Updated playptmod
This commit is contained in:
parent
3e885e5ca7
commit
9c54354c44
6 changed files with 178 additions and 297 deletions
|
@ -7,19 +7,19 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
83304C9B1A5F9A1C0066CDDA /* pt_blep.c in Sources */ = {isa = PBXBuildFile; fileRef = 83304C991A5F9A1C0066CDDA /* pt_blep.c */; };
|
||||||
|
83304C9C1A5F9A1C0066CDDA /* pt_blep.h in Headers */ = {isa = PBXBuildFile; fileRef = 83304C9A1A5F9A1C0066CDDA /* pt_blep.h */; };
|
||||||
83A0F4A61816CEAD00119DB4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 83A0F4A41816CEAD00119DB4 /* InfoPlist.strings */; };
|
83A0F4A61816CEAD00119DB4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 83A0F4A41816CEAD00119DB4 /* InfoPlist.strings */; };
|
||||||
83A0F4D31816CF9500119DB4 /* blip_buf.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A0F4CF1816CF9500119DB4 /* blip_buf.c */; };
|
|
||||||
83A0F4D41816CF9500119DB4 /* blip_buf.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A0F4D01816CF9500119DB4 /* blip_buf.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
83A0F4D51816CF9500119DB4 /* playptmod.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A0F4D11816CF9500119DB4 /* playptmod.c */; };
|
83A0F4D51816CF9500119DB4 /* playptmod.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A0F4D11816CF9500119DB4 /* playptmod.c */; };
|
||||||
83A0F4D61816CF9500119DB4 /* playptmod.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A0F4D21816CF9500119DB4 /* playptmod.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
83A0F4D61816CF9500119DB4 /* playptmod.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A0F4D21816CF9500119DB4 /* playptmod.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
83304C991A5F9A1C0066CDDA /* pt_blep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pt_blep.c; sourceTree = "<group>"; };
|
||||||
|
83304C9A1A5F9A1C0066CDDA /* pt_blep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pt_blep.h; sourceTree = "<group>"; };
|
||||||
83A0F4981816CEAD00119DB4 /* playptmod.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = playptmod.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
83A0F4981816CEAD00119DB4 /* playptmod.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = playptmod.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
83A0F4A31816CEAD00119DB4 /* playptmod-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "playptmod-Info.plist"; sourceTree = "<group>"; };
|
83A0F4A31816CEAD00119DB4 /* playptmod-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "playptmod-Info.plist"; sourceTree = "<group>"; };
|
||||||
83A0F4A51816CEAD00119DB4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
83A0F4A51816CEAD00119DB4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
83A0F4CF1816CF9500119DB4 /* blip_buf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blip_buf.c; sourceTree = "<group>"; };
|
|
||||||
83A0F4D01816CF9500119DB4 /* blip_buf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blip_buf.h; sourceTree = "<group>"; };
|
|
||||||
83A0F4D11816CF9500119DB4 /* playptmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = playptmod.c; sourceTree = "<group>"; };
|
83A0F4D11816CF9500119DB4 /* playptmod.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = playptmod.c; sourceTree = "<group>"; };
|
||||||
83A0F4D21816CF9500119DB4 /* playptmod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = playptmod.h; sourceTree = "<group>"; };
|
83A0F4D21816CF9500119DB4 /* playptmod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = playptmod.h; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
@ -70,8 +70,8 @@
|
||||||
83A0F4A11816CEAD00119DB4 /* playptmod */ = {
|
83A0F4A11816CEAD00119DB4 /* playptmod */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
83A0F4CF1816CF9500119DB4 /* blip_buf.c */,
|
83304C991A5F9A1C0066CDDA /* pt_blep.c */,
|
||||||
83A0F4D01816CF9500119DB4 /* blip_buf.h */,
|
83304C9A1A5F9A1C0066CDDA /* pt_blep.h */,
|
||||||
83A0F4D11816CF9500119DB4 /* playptmod.c */,
|
83A0F4D11816CF9500119DB4 /* playptmod.c */,
|
||||||
83A0F4D21816CF9500119DB4 /* playptmod.h */,
|
83A0F4D21816CF9500119DB4 /* playptmod.h */,
|
||||||
83A0F4A21816CEAD00119DB4 /* Supporting Files */,
|
83A0F4A21816CEAD00119DB4 /* Supporting Files */,
|
||||||
|
@ -95,8 +95,8 @@
|
||||||
isa = PBXHeadersBuildPhase;
|
isa = PBXHeadersBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
83A0F4D41816CF9500119DB4 /* blip_buf.h in Headers */,
|
|
||||||
83A0F4D61816CF9500119DB4 /* playptmod.h in Headers */,
|
83A0F4D61816CF9500119DB4 /* playptmod.h in Headers */,
|
||||||
|
83304C9C1A5F9A1C0066CDDA /* pt_blep.h in Headers */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -163,8 +163,8 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
83304C9B1A5F9A1C0066CDDA /* pt_blep.c in Sources */,
|
||||||
83A0F4D51816CF9500119DB4 /* playptmod.c in Sources */,
|
83A0F4D51816CF9500119DB4 /* playptmod.c in Sources */,
|
||||||
83A0F4D31816CF9500119DB4 /* blip_buf.c in Sources */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,196 +0,0 @@
|
||||||
/* blip_buf 1.1.0. http://www.slack.net/~ant/ */
|
|
||||||
|
|
||||||
#include "blip_buf.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/* Library Copyright (C) 2003-2009 Shay Green. This library is free software;
|
|
||||||
you can redistribute it and/or modify it under the terms of the GNU Lesser
|
|
||||||
General Public License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version. This
|
|
||||||
library is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
||||||
details. You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this module; if not, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
||||||
|
|
||||||
#if defined (BLARGG_TEST) && BLARGG_TEST
|
|
||||||
#include "blargg_test.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum { time_bits = pre_shift + 20 };
|
|
||||||
|
|
||||||
static fixed_t const time_unit = (fixed_t) 1 << time_bits;
|
|
||||||
|
|
||||||
enum { bass_shift = 9 }; /* affects high-pass filter breakpoint frequency */
|
|
||||||
enum { end_frame_extra = 2 }; /* allows deltas slightly after frame length */
|
|
||||||
|
|
||||||
enum { half_width = 8 };
|
|
||||||
enum { buf_extra = half_width*2 + end_frame_extra };
|
|
||||||
enum { phase_bits = 5 };
|
|
||||||
enum { phase_count = 1 << phase_bits };
|
|
||||||
enum { delta_bits = 15 };
|
|
||||||
enum { delta_unit = 1 << delta_bits };
|
|
||||||
enum { frac_bits = time_bits - pre_shift };
|
|
||||||
|
|
||||||
/* We could eliminate avail and encode whole samples in offset, but that would
|
|
||||||
limit the total buffered samples to blip_max_frame. That could only be
|
|
||||||
increased by decreasing time_bits, which would reduce resample ratio accuracy.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* probably not totally portable */
|
|
||||||
#define SAMPLES( buf ) (buf->samples)
|
|
||||||
|
|
||||||
/* Arithmetic (sign-preserving) right shift */
|
|
||||||
#define ARITH_SHIFT( n, shift ) \
|
|
||||||
((n) >> (shift))
|
|
||||||
|
|
||||||
enum { max_sample = +32767 };
|
|
||||||
enum { min_sample = -32768 };
|
|
||||||
|
|
||||||
#define CLAMP( n ) \
|
|
||||||
{\
|
|
||||||
if ( (short) n != n )\
|
|
||||||
n = ARITH_SHIFT( n, 16 ) ^ max_sample;\
|
|
||||||
}
|
|
||||||
|
|
||||||
void ptm_blip_clear( blip_t* m )
|
|
||||||
{
|
|
||||||
/* We could set offset to 0, factor/2, or factor-1. 0 is suitable if
|
|
||||||
factor is rounded up. factor-1 is suitable if factor is rounded down.
|
|
||||||
Since we don't know rounding direction, factor/2 accommodates either,
|
|
||||||
with the slight loss of showing an error in half the time. Since for
|
|
||||||
a 64-bit factor this is years, the halving isn't a problem. */
|
|
||||||
|
|
||||||
m->offset = time_unit / 2;
|
|
||||||
m->index = 0;
|
|
||||||
m->integrator = 0;
|
|
||||||
m->last_value = 0;
|
|
||||||
memset( SAMPLES( m ), 0, 128 * sizeof (buf_t) );
|
|
||||||
}
|
|
||||||
|
|
||||||
int ptm_blip_read_sample( blip_t* m )
|
|
||||||
{
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
{
|
|
||||||
buf_t * in = SAMPLES( m ) + m->index;
|
|
||||||
int sum = m->integrator;
|
|
||||||
{
|
|
||||||
/* Eliminate fraction */
|
|
||||||
int s = ARITH_SHIFT( sum, delta_bits );
|
|
||||||
|
|
||||||
sum += *in;
|
|
||||||
|
|
||||||
retval = s;
|
|
||||||
}
|
|
||||||
m->integrator = sum;
|
|
||||||
|
|
||||||
*in = 0;
|
|
||||||
|
|
||||||
m->index = ( m->index + 1 ) % 128;
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Things that didn't help performance on x86:
|
|
||||||
__attribute__((aligned(128)))
|
|
||||||
#define short int
|
|
||||||
restrict
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int const bl_step [phase_count + 1] [half_width] =
|
|
||||||
{
|
|
||||||
{ 0, 0, 0, 0, 0, 0, 0,32768},
|
|
||||||
{ -1, 9, -30, 79, -178, 380, -923,32713},
|
|
||||||
{ -2, 17, -58, 153, -346, 739,-1775,32549},
|
|
||||||
{ -3, 24, -83, 221, -503, 1073,-2555,32277},
|
|
||||||
{ -4, 30, -107, 284, -647, 1382,-3259,31898},
|
|
||||||
{ -5, 36, -127, 340, -778, 1662,-3887,31415},
|
|
||||||
{ -5, 40, -145, 390, -895, 1913,-4439,30832},
|
|
||||||
{ -6, 44, -160, 433, -998, 2133,-4914,30151},
|
|
||||||
{ -6, 47, -172, 469,-1085, 2322,-5313,29377},
|
|
||||||
{ -6, 49, -181, 499,-1158, 2479,-5636,28515},
|
|
||||||
{ -6, 50, -188, 521,-1215, 2604,-5885,27570},
|
|
||||||
{ -5, 51, -193, 537,-1257, 2697,-6063,26548},
|
|
||||||
{ -5, 51, -195, 547,-1285, 2760,-6172,25455},
|
|
||||||
{ -5, 50, -195, 550,-1298, 2792,-6214,24298},
|
|
||||||
{ -4, 49, -192, 548,-1298, 2795,-6193,23084},
|
|
||||||
{ -4, 47, -188, 540,-1284, 2770,-6112,21820},
|
|
||||||
{ -3, 45, -182, 526,-1258, 2719,-5976,20513},
|
|
||||||
{ -3, 42, -175, 508,-1221, 2643,-5788,19172},
|
|
||||||
{ -2, 39, -166, 486,-1173, 2544,-5554,17805},
|
|
||||||
{ -2, 36, -156, 460,-1116, 2425,-5277,16418},
|
|
||||||
{ -1, 33, -145, 431,-1050, 2287,-4963,15020},
|
|
||||||
{ -1, 30, -133, 399, -977, 2132,-4615,13618},
|
|
||||||
{ -1, 26, -120, 365, -898, 1963,-4240,12221},
|
|
||||||
{ 0, 23, -107, 329, -813, 1783,-3843,10836},
|
|
||||||
{ 0, 20, -94, 292, -725, 1593,-3427, 9470},
|
|
||||||
{ 0, 17, -81, 254, -633, 1396,-2998, 8131},
|
|
||||||
{ 0, 14, -68, 215, -540, 1194,-2560, 6824},
|
|
||||||
{ 0, 11, -56, 177, -446, 989,-2119, 5556},
|
|
||||||
{ 0, 8, -43, 139, -353, 784,-1678, 4334},
|
|
||||||
{ 0, 6, -31, 102, -260, 581,-1242, 3162},
|
|
||||||
{ 0, 3, -20, 66, -170, 381, -814, 2046},
|
|
||||||
{ 0, 1, -9, 32, -83, 187, -399, 991},
|
|
||||||
{ 0, 0, 0, 0, 0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Shifting by pre_shift allows calculation using unsigned int rather than
|
|
||||||
possibly-wider fixed_t. On 32-bit platforms, this is likely more efficient.
|
|
||||||
And by having pre_shift 32, a 32-bit platform can easily do the shift by
|
|
||||||
simply ignoring the low half. */
|
|
||||||
|
|
||||||
void ptm_blip_add_delta( blip_t* m, float time, int delta )
|
|
||||||
{
|
|
||||||
unsigned fixed = (unsigned) ((int)(time * time_unit + m->offset) >> pre_shift);
|
|
||||||
buf_t* out = SAMPLES( m ) + (m->index + (fixed >> frac_bits)) % 128;
|
|
||||||
buf_t* end = SAMPLES( m ) + 128;
|
|
||||||
|
|
||||||
int const phase_shift = frac_bits - phase_bits;
|
|
||||||
int phase = fixed >> phase_shift & (phase_count - 1);
|
|
||||||
int const* in = bl_step [phase];
|
|
||||||
int const* rev = bl_step [phase_count - phase];
|
|
||||||
|
|
||||||
int interp = fixed >> (phase_shift - delta_bits) & (delta_unit - 1);
|
|
||||||
int delta2 = (delta * interp) >> delta_bits;
|
|
||||||
delta -= delta2;
|
|
||||||
|
|
||||||
*out++ += in[0]*delta + in[half_width+0]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[1]*delta + in[half_width+1]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[2]*delta + in[half_width+2]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[3]*delta + in[half_width+3]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[4]*delta + in[half_width+4]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[5]*delta + in[half_width+5]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[6]*delta + in[half_width+6]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[7]*delta + in[half_width+7]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
|
|
||||||
in = rev;
|
|
||||||
*out++ += in[7]*delta + in[7-half_width]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[6]*delta + in[6-half_width]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[5]*delta + in[5-half_width]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[4]*delta + in[4-half_width]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[3]*delta + in[3-half_width]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[2]*delta + in[2-half_width]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[1]*delta + in[1-half_width]*delta2;
|
|
||||||
if (out >= end) out = SAMPLES( m );
|
|
||||||
*out++ += in[0]*delta + in[0-half_width]*delta2;
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/** \file
|
|
||||||
Sample buffer that resamples from input clock rate to output sample rate */
|
|
||||||
|
|
||||||
/* blip_buf 1.1.0 */
|
|
||||||
#ifndef BLIP_BUF_H
|
|
||||||
#define BLIP_BUF_H
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
/* Equivalent to ULONG_MAX >= 0xFFFFFFFF00000000.
|
|
||||||
Avoids constants that don't fit in 32 bits. */
|
|
||||||
#if ULONG_MAX/0xFFFFFFFF > 0xFFFFFFFF
|
|
||||||
typedef unsigned long fixed_t;
|
|
||||||
enum { pre_shift = 32 };
|
|
||||||
|
|
||||||
#elif defined(ULLONG_MAX)
|
|
||||||
typedef unsigned long long fixed_t;
|
|
||||||
enum { pre_shift = 32 };
|
|
||||||
|
|
||||||
#else
|
|
||||||
typedef unsigned fixed_t;
|
|
||||||
enum { pre_shift = 0 };
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef int buf_t;
|
|
||||||
|
|
||||||
/** Sample buffer that resamples to output rate and accumulates samples
|
|
||||||
until they're read out */
|
|
||||||
struct blip_t
|
|
||||||
{
|
|
||||||
fixed_t offset;
|
|
||||||
int index;
|
|
||||||
int avail;
|
|
||||||
int size;
|
|
||||||
int integrator;
|
|
||||||
int last_value;
|
|
||||||
buf_t samples[128];
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** First parameter of most functions is blip_t*, or const blip_t* if nothing
|
|
||||||
is changed. */
|
|
||||||
typedef struct blip_t blip_t;
|
|
||||||
|
|
||||||
/** Clears entire buffer. Afterwards, blip_samples_avail() == 0. */
|
|
||||||
void ptm_blip_clear( blip_t* );
|
|
||||||
|
|
||||||
/** Adds positive/negative delta into buffer at specified clock time. */
|
|
||||||
void ptm_blip_add_delta( blip_t*, float clock_time, int delta );
|
|
||||||
|
|
||||||
/** Number of buffered samples available for reading. */
|
|
||||||
int ptm_blip_samples_avail( const blip_t* );
|
|
||||||
|
|
||||||
/** Reads and removes at most 'count' samples and writes them to 'out'. If
|
|
||||||
'stereo' is true, writes output to every other element of 'out', allowing easy
|
|
||||||
interleaving of two buffers into a stereo sample stream. Outputs 16-bit signed
|
|
||||||
samples. Returns number of samples actually read. */
|
|
||||||
int ptm_blip_read_sample( blip_t* );
|
|
||||||
|
|
||||||
|
|
||||||
/* Deprecated */
|
|
||||||
typedef blip_t blip_buffer_t;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -29,11 +29,12 @@
|
||||||
#define _USE_MATH_DEFINES // visual studio
|
#define _USE_MATH_DEFINES // visual studio
|
||||||
|
|
||||||
#include "playptmod.h"
|
#include "playptmod.h"
|
||||||
#include "blip_buf.h"
|
#include "pt_blep.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h> // memcpy()
|
#include <string.h> // memcpy()
|
||||||
#include <stdlib.h> // malloc(), calloc(), free()
|
#include <stdlib.h> // malloc(), calloc(), free()
|
||||||
|
#include <limits.h> // INT_MAX, INT_MIN
|
||||||
#include <math.h> // floorf(), sinf()
|
#include <math.h> // floorf(), sinf()
|
||||||
|
|
||||||
#define HI_NYBBLE(x) ((x) >> 4)
|
#define HI_NYBBLE(x) ((x) >> 4)
|
||||||
|
@ -240,8 +241,8 @@ typedef struct
|
||||||
FilterC filterC;
|
FilterC filterC;
|
||||||
float *mixBufferL;
|
float *mixBufferL;
|
||||||
float *mixBufferR;
|
float *mixBufferR;
|
||||||
blip_t blep[MAX_CHANNELS];
|
BLEP blep[MAX_CHANNELS];
|
||||||
blip_t blepVol[MAX_CHANNELS];
|
BLEP blepVol[MAX_CHANNELS];
|
||||||
unsigned int orderPlayed[256];
|
unsigned int orderPlayed[256];
|
||||||
MODULE *source;
|
MODULE *source;
|
||||||
} player;
|
} player;
|
||||||
|
@ -524,8 +525,8 @@ static void mixerCutChannels(player *p)
|
||||||
memset(p->v, 0, sizeof (p->v));
|
memset(p->v, 0, sizeof (p->v));
|
||||||
for (i = 0; i < MAX_CHANNELS; ++i)
|
for (i = 0; i < MAX_CHANNELS; ++i)
|
||||||
{
|
{
|
||||||
ptm_blip_clear(&p->blep[i]);
|
memset(&p->blep[i], 0, sizeof(BLEP));
|
||||||
ptm_blip_clear(&p->blepVol[i]);
|
memset(&p->blepVol[i], 0, sizeof(BLEP));
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&p->filter, 0, sizeof (p->filter));
|
memset(&p->filter, 0, sizeof (p->filter));
|
||||||
|
@ -564,8 +565,8 @@ static void outputAudio(player *p, int *target, int numSamples)
|
||||||
float downscale;
|
float downscale;
|
||||||
|
|
||||||
Voice *v;
|
Voice *v;
|
||||||
blip_t *bSmp;
|
BLEP *bSmp;
|
||||||
blip_t *bVol;
|
BLEP *bVol;
|
||||||
|
|
||||||
memset(p->mixBufferL, 0, numSamples * sizeof (float));
|
memset(p->mixBufferL, 0, numSamples * sizeof (float));
|
||||||
memset(p->mixBufferR, 0, numSamples * sizeof (float));
|
memset(p->mixBufferR, 0, numSamples * sizeof (float));
|
||||||
|
@ -594,8 +595,8 @@ static void outputAudio(player *p, int *target, int numSamples)
|
||||||
if (v->data)
|
if (v->data)
|
||||||
v->frac -= 1.0f;
|
v->frac -= 1.0f;
|
||||||
|
|
||||||
t_vol += ptm_blip_read_sample(bVol);
|
t_vol += blepRun(bVol);
|
||||||
t_smp += ptm_blip_read_sample(bSmp);
|
t_smp += blepRun(bSmp);
|
||||||
|
|
||||||
t_smp *= t_vol;
|
t_smp *= t_vol;
|
||||||
i_smp = (signed int)t_smp;
|
i_smp = (signed int)t_smp;
|
||||||
|
@ -609,18 +610,18 @@ static void outputAudio(player *p, int *target, int numSamples)
|
||||||
if (j >= numSamples)
|
if (j >= numSamples)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (tempSample != bSmp->last_value)
|
if (tempSample != bSmp->lastInput && v->frac >= 0.0f && v->frac < 1.0f)
|
||||||
{
|
{
|
||||||
delta = tempSample - bSmp->last_value;
|
delta = tempSample - bSmp->lastInput;
|
||||||
bSmp->last_value = tempSample;
|
bSmp->lastInput = tempSample;
|
||||||
ptm_blip_add_delta(bSmp, v->frac, delta);
|
blepAdd(bSmp, v->frac, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tempVolume != bVol->last_value)
|
if (tempVolume != bVol->lastInput)
|
||||||
{
|
{
|
||||||
delta = tempVolume - bVol->last_value;
|
delta = tempVolume - bVol->lastInput;
|
||||||
bVol->last_value = tempVolume;
|
bVol->lastInput = tempVolume;
|
||||||
ptm_blip_add_delta(bVol, 0, delta);
|
blepAdd(bVol, 0, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v->data)
|
if (v->data)
|
||||||
|
@ -696,11 +697,11 @@ static void outputAudio(player *p, int *target, int numSamples)
|
||||||
{
|
{
|
||||||
for (; j < numSamples; ++j)
|
for (; j < numSamples; ++j)
|
||||||
{
|
{
|
||||||
tempVolume = bVol->last_value;
|
tempVolume = 0.0f;
|
||||||
tempSample = bSmp->last_value;
|
tempSample = 0.0f;
|
||||||
|
|
||||||
tempVolume += ptm_blip_read_sample(bVol);
|
tempVolume += blepRun(bVol);
|
||||||
tempSample += ptm_blip_read_sample(bSmp);
|
tempSample += blepRun(bSmp);
|
||||||
|
|
||||||
tempSample *= tempVolume;
|
tempSample *= tempVolume;
|
||||||
i_smp = (signed int)tempSample;
|
i_smp = (signed int)tempSample;
|
||||||
|
|
93
Frameworks/playptmod/playptmod/pt_blep.c
Normal file
93
Frameworks/playptmod/playptmod/pt_blep.c
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
** This file is part of the ProTracker 2.3D port/clone
|
||||||
|
** project by Olav "8bitbubsy" Sorensen.
|
||||||
|
**
|
||||||
|
** It contains unstructured and unclean code, but I care
|
||||||
|
** more about how the program works than how the source
|
||||||
|
** code looks. Although, I do respect coders that can
|
||||||
|
** master the art of writing clean and structured code.
|
||||||
|
** I know I can't.
|
||||||
|
**
|
||||||
|
** All of the files are considered 'public domain',
|
||||||
|
** do whatever you want with it.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "pt_blep.h"
|
||||||
|
|
||||||
|
#define _LERP(I, F) ((I[0]) + ((I[1]) - (I[0])) * (F))
|
||||||
|
|
||||||
|
static const uint32_t blepData[48] =
|
||||||
|
{
|
||||||
|
0x3F7FE1F1, 0x3F7FD548, 0x3F7FD6A3, 0x3F7FD4E3,
|
||||||
|
0x3F7FAD85, 0x3F7F2152, 0x3F7DBFAE, 0x3F7ACCDF,
|
||||||
|
0x3F752F1E, 0x3F6B7384, 0x3F5BFBCB, 0x3F455CF2,
|
||||||
|
0x3F26E524, 0x3F0128C4, 0x3EACC7DC, 0x3E29E86B,
|
||||||
|
0x3C1C1D29, 0xBDE4BBE6, 0xBE3AAE04, 0xBE48DEDD,
|
||||||
|
0xBE22AD7E, 0xBDB2309A, 0xBB82B620, 0x3D881411,
|
||||||
|
0x3DDADBF3, 0x3DE2C81D, 0x3DAAA01F, 0x3D1E769A,
|
||||||
|
0xBBC116D7, 0xBD1402E8, 0xBD38A069, 0xBD0C53BB,
|
||||||
|
0xBC3FFB8C, 0x3C465FD2, 0x3CEA5764, 0x3D0A51D6,
|
||||||
|
0x3CEAE2D5, 0x3C92AC5A, 0x3BE4CBF7, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||||
|
};
|
||||||
|
|
||||||
|
void blepAdd(BLEP *b, float offset, float amplitude)
|
||||||
|
{
|
||||||
|
int8_t n;
|
||||||
|
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
const float *src;
|
||||||
|
float f;
|
||||||
|
float a;
|
||||||
|
|
||||||
|
float k[NS];
|
||||||
|
|
||||||
|
n = NS;
|
||||||
|
i = (uint32_t)(offset * SP);
|
||||||
|
src = (const float *)(blepData) + i + OS;
|
||||||
|
f = (offset * SP) - i;
|
||||||
|
i = b->index;
|
||||||
|
a = 0.0f;
|
||||||
|
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
a += k[n] = _LERP(src, f);
|
||||||
|
src += SP;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = NS;
|
||||||
|
a = 1.0f / a;
|
||||||
|
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
b->buffer[i] += (amplitude * k[n]) * a;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
i &= RNS;
|
||||||
|
}
|
||||||
|
|
||||||
|
b->samplesLeft = NS;
|
||||||
|
}
|
||||||
|
|
||||||
|
float blepRun(BLEP *b)
|
||||||
|
{
|
||||||
|
float output;
|
||||||
|
|
||||||
|
output = b->buffer[b->index];
|
||||||
|
b->buffer[b->index] = 0.0f;
|
||||||
|
|
||||||
|
b->index++;
|
||||||
|
b->index &= RNS;
|
||||||
|
|
||||||
|
b->samplesLeft--;
|
||||||
|
|
||||||
|
output += b->lastOutput;
|
||||||
|
b->lastOutput = output;
|
||||||
|
|
||||||
|
return (output);
|
||||||
|
}
|
||||||
|
|
55
Frameworks/playptmod/playptmod/pt_blep.h
Normal file
55
Frameworks/playptmod/playptmod/pt_blep.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
** This file is part of the ProTracker 2.3D port/clone
|
||||||
|
** project by Olav "8bitbubsy" Sorensen.
|
||||||
|
**
|
||||||
|
** It contains unstructured and unclean code, but I care
|
||||||
|
** more about how the program works than how the source
|
||||||
|
** code looks. Although, I do respect coders that can
|
||||||
|
** master the art of writing clean and structured code.
|
||||||
|
** I know I can't.
|
||||||
|
**
|
||||||
|
** All of the files are considered 'public domain',
|
||||||
|
** do whatever you want with it.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PT_BLEP_H
|
||||||
|
#define __PT_BLEP_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// thanks to aciddose/ad/adejr for the blep/cutoff/filter stuff!
|
||||||
|
|
||||||
|
// information on blep variables
|
||||||
|
//
|
||||||
|
// ZC = zero crossings, the number of ripples in the impulse
|
||||||
|
// OS = oversampling, how many samples per zero crossing are taken
|
||||||
|
// SP = step size per output sample, used to lower the cutoff (play the impulse slower)
|
||||||
|
// NS = number of samples of impulse to insert
|
||||||
|
// RNS = the lowest power of two greater than NS, minus one (used to wrap output buffer)
|
||||||
|
//
|
||||||
|
// ZC and OS are here only for reference, they depend upon the data in the table and can't be changed.
|
||||||
|
// SP, the step size can be any number lower or equal to OS, as long as the result NS remains an integer.
|
||||||
|
// for example, if ZC=8,OS=5, you can set SP=1, the result is NS=40, and RNS must then be 63.
|
||||||
|
// the result of that is the filter cutoff is set at nyquist * (SP/OS), in this case nyquist/5.
|
||||||
|
|
||||||
|
#define ZC 8
|
||||||
|
#define OS 5
|
||||||
|
#define SP 5
|
||||||
|
#define NS (ZC * OS / SP)
|
||||||
|
#define RNS 7 // RNS = (2^ > NS) - 1
|
||||||
|
|
||||||
|
typedef struct blep_data
|
||||||
|
{
|
||||||
|
int32_t index;
|
||||||
|
int32_t samplesLeft;
|
||||||
|
float buffer[RNS + 1];
|
||||||
|
float lastInput;
|
||||||
|
float lastOutput;
|
||||||
|
} BLEP;
|
||||||
|
|
||||||
|
void blepAdd(BLEP *b, float offset, float amplitude);
|
||||||
|
float blepRun(BLEP *b);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue