Updated playptmod

CQTexperiment
Chris Moeller 2015-01-08 21:10:38 -08:00
parent 3e885e5ca7
commit 9c54354c44
6 changed files with 178 additions and 297 deletions

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View 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);
}

View 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