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 = {
|
||||
|
||||
/* 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 */; };
|
||||
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 */; };
|
||||
83A0F4D61816CF9500119DB4 /* playptmod.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A0F4D21816CF9500119DB4 /* playptmod.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
/* End PBXBuildFile 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; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
83A0F4D21816CF9500119DB4 /* playptmod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = playptmod.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
@ -70,8 +70,8 @@
|
|||
83A0F4A11816CEAD00119DB4 /* playptmod */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
83A0F4CF1816CF9500119DB4 /* blip_buf.c */,
|
||||
83A0F4D01816CF9500119DB4 /* blip_buf.h */,
|
||||
83304C991A5F9A1C0066CDDA /* pt_blep.c */,
|
||||
83304C9A1A5F9A1C0066CDDA /* pt_blep.h */,
|
||||
83A0F4D11816CF9500119DB4 /* playptmod.c */,
|
||||
83A0F4D21816CF9500119DB4 /* playptmod.h */,
|
||||
83A0F4A21816CEAD00119DB4 /* Supporting Files */,
|
||||
|
@ -95,8 +95,8 @@
|
|||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
83A0F4D41816CF9500119DB4 /* blip_buf.h in Headers */,
|
||||
83A0F4D61816CF9500119DB4 /* playptmod.h in Headers */,
|
||||
83304C9C1A5F9A1C0066CDDA /* pt_blep.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -163,8 +163,8 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
83304C9B1A5F9A1C0066CDDA /* pt_blep.c in Sources */,
|
||||
83A0F4D51816CF9500119DB4 /* playptmod.c in Sources */,
|
||||
83A0F4D31816CF9500119DB4 /* blip_buf.c in Sources */,
|
||||
);
|
||||
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
|
||||
|
||||
#include "playptmod.h"
|
||||
#include "blip_buf.h"
|
||||
#include "pt_blep.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h> // memcpy()
|
||||
#include <stdlib.h> // malloc(), calloc(), free()
|
||||
#include <limits.h> // INT_MAX, INT_MIN
|
||||
#include <math.h> // floorf(), sinf()
|
||||
|
||||
#define HI_NYBBLE(x) ((x) >> 4)
|
||||
|
@ -240,8 +241,8 @@ typedef struct
|
|||
FilterC filterC;
|
||||
float *mixBufferL;
|
||||
float *mixBufferR;
|
||||
blip_t blep[MAX_CHANNELS];
|
||||
blip_t blepVol[MAX_CHANNELS];
|
||||
BLEP blep[MAX_CHANNELS];
|
||||
BLEP blepVol[MAX_CHANNELS];
|
||||
unsigned int orderPlayed[256];
|
||||
MODULE *source;
|
||||
} player;
|
||||
|
@ -524,8 +525,8 @@ static void mixerCutChannels(player *p)
|
|||
memset(p->v, 0, sizeof (p->v));
|
||||
for (i = 0; i < MAX_CHANNELS; ++i)
|
||||
{
|
||||
ptm_blip_clear(&p->blep[i]);
|
||||
ptm_blip_clear(&p->blepVol[i]);
|
||||
memset(&p->blep[i], 0, sizeof(BLEP));
|
||||
memset(&p->blepVol[i], 0, sizeof(BLEP));
|
||||
}
|
||||
|
||||
memset(&p->filter, 0, sizeof (p->filter));
|
||||
|
@ -564,8 +565,8 @@ static void outputAudio(player *p, int *target, int numSamples)
|
|||
float downscale;
|
||||
|
||||
Voice *v;
|
||||
blip_t *bSmp;
|
||||
blip_t *bVol;
|
||||
BLEP *bSmp;
|
||||
BLEP *bVol;
|
||||
|
||||
memset(p->mixBufferL, 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)
|
||||
v->frac -= 1.0f;
|
||||
|
||||
t_vol += ptm_blip_read_sample(bVol);
|
||||
t_smp += ptm_blip_read_sample(bSmp);
|
||||
t_vol += blepRun(bVol);
|
||||
t_smp += blepRun(bSmp);
|
||||
|
||||
t_smp *= t_vol;
|
||||
i_smp = (signed int)t_smp;
|
||||
|
@ -609,18 +610,18 @@ static void outputAudio(player *p, int *target, int numSamples)
|
|||
if (j >= numSamples)
|
||||
break;
|
||||
|
||||
if (tempSample != bSmp->last_value)
|
||||
if (tempSample != bSmp->lastInput && v->frac >= 0.0f && v->frac < 1.0f)
|
||||
{
|
||||
delta = tempSample - bSmp->last_value;
|
||||
bSmp->last_value = tempSample;
|
||||
ptm_blip_add_delta(bSmp, v->frac, delta);
|
||||
delta = tempSample - bSmp->lastInput;
|
||||
bSmp->lastInput = tempSample;
|
||||
blepAdd(bSmp, v->frac, delta);
|
||||
}
|
||||
|
||||
if (tempVolume != bVol->last_value)
|
||||
if (tempVolume != bVol->lastInput)
|
||||
{
|
||||
delta = tempVolume - bVol->last_value;
|
||||
bVol->last_value = tempVolume;
|
||||
ptm_blip_add_delta(bVol, 0, delta);
|
||||
delta = tempVolume - bVol->lastInput;
|
||||
bVol->lastInput = tempVolume;
|
||||
blepAdd(bVol, 0, delta);
|
||||
}
|
||||
|
||||
if (v->data)
|
||||
|
@ -696,11 +697,11 @@ static void outputAudio(player *p, int *target, int numSamples)
|
|||
{
|
||||
for (; j < numSamples; ++j)
|
||||
{
|
||||
tempVolume = bVol->last_value;
|
||||
tempSample = bSmp->last_value;
|
||||
tempVolume = 0.0f;
|
||||
tempSample = 0.0f;
|
||||
|
||||
tempVolume += ptm_blip_read_sample(bVol);
|
||||
tempSample += ptm_blip_read_sample(bSmp);
|
||||
tempVolume += blepRun(bVol);
|
||||
tempSample += blepRun(bSmp);
|
||||
|
||||
tempSample *= tempVolume;
|
||||
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