Update Syntrax decoder with speed improvements.

CQTexperiment
Christopher Snowhill 2017-03-12 21:15:16 -07:00
parent d963710c28
commit fce57925c0
3 changed files with 61 additions and 75 deletions

View File

@ -62,11 +62,10 @@ static void gen_sinc( double rolloff, int width, double offset, double spacing,
} }
enum { width = 32 }; enum { width = 32 };
enum { stereo = 2 };
enum { max_res = 512 }; enum { max_res = 512 };
enum { min_width = (width < 4 ? 4 : width) }; enum { min_width = (width < 4 ? 4 : width) };
enum { adj_width = min_width / 4 * 4 + 2 }; enum { adj_width = min_width / 4 * 4 + 2 };
enum { write_offset = adj_width * stereo }; enum { write_offset = adj_width };
enum { buffer_size = 128 }; enum { buffer_size = 128 };
@ -83,8 +82,8 @@ typedef struct _resampler
imp_t const* imp; imp_t const* imp;
imp_t impulses [max_res * (adj_width + 2 * (sizeof(imp_off_t) / sizeof(imp_t)))]; imp_t impulses [max_res * (adj_width + 2 * (sizeof(imp_off_t) / sizeof(imp_t)))];
sample_t buffer_in[buffer_size * stereo * 2]; sample_t buffer_in[buffer_size * 2];
sample_t buffer_out[buffer_size * stereo]; sample_t buffer_out[buffer_size];
} resampler; } resampler;
void * resampler_create() void * resampler_create()
@ -172,7 +171,7 @@ void resampler_set_rate( void *_r, double new_factor )
rs->rate_ = ratio_; rs->rate_ = ratio_;
/* how much of input is used for each output sample */ /* how much of input is used for each output sample */
step = stereo * (int) floor( ratio_ ); step = (int) floor( ratio_ );
fraction = fmod( ratio_, 1.0 ); fraction = fmod( ratio_, 1.0 );
filter = (ratio_ < 1.0) ? 1.0 : 1.0 / ratio_; filter = (ratio_ < 1.0) ? 1.0 : 1.0 / ratio_;
@ -193,10 +192,10 @@ void resampler_set_rate( void *_r, double new_factor )
if ( pos >= 0.9999999 ) if ( pos >= 0.9999999 )
{ {
pos -= 1.0; pos -= 1.0;
cur_step += stereo; cur_step += 1;
} }
((imp_off_t*)out)[0] = (cur_step - rs->width_ * 2 + 4) * sizeof (sample_t); ((imp_off_t*)out)[0] = (cur_step - rs->width_ + 2) * sizeof (sample_t);
((imp_off_t*)out)[1] = 2 * sizeof (imp_t) + 2 * sizeof (imp_off_t); ((imp_off_t*)out)[1] = 2 * sizeof (imp_t) + 2 * sizeof (imp_off_t);
out += 2 * (sizeof(imp_off_t) / sizeof(imp_t)); out += 2 * (sizeof(imp_off_t) / sizeof(imp_t));
/*input_per_cycle += cur_step;*/ /*input_per_cycle += cur_step;*/
@ -210,19 +209,19 @@ void resampler_set_rate( void *_r, double new_factor )
int resampler_get_free(void *_r) int resampler_get_free(void *_r)
{ {
resampler *r = (resampler *)_r; resampler *r = (resampler *)_r;
return buffer_size * stereo - r->infilled; return buffer_size - r->infilled;
} }
int resampler_get_min_fill(void *_r) int resampler_get_min_fill(void *_r)
{ {
resampler *r = (resampler *)_r; resampler *r = (resampler *)_r;
const int min_needed = write_offset + stereo; const int min_needed = write_offset + 1;
const int latency = r->latency ? 0 : adj_width; const int latency = r->latency ? 0 : adj_width;
int min_free = min_needed - r->infilled - latency; int min_free = min_needed - r->infilled - latency;
return min_free < 0 ? 0 : min_free; return min_free < 0 ? 0 : min_free;
} }
void resampler_write_pair(void *_r, sample_t ls, sample_t rs) void resampler_write_sample(void *_r, sample_t s)
{ {
resampler *r = (resampler *)_r; resampler *r = (resampler *)_r;
@ -231,24 +230,20 @@ void resampler_write_pair(void *_r, sample_t ls, sample_t rs)
int i; int i;
for ( i = 0; i < adj_width / 2; ++i) for ( i = 0; i < adj_width / 2; ++i)
{ {
r->buffer_in[r->inptr + 0] = 0; r->buffer_in[r->inptr] = 0;
r->buffer_in[r->inptr + 1] = 0; r->buffer_in[buffer_size + r->inptr] = 0;
r->buffer_in[buffer_size * stereo + r->inptr + 0] = 0; r->inptr = (r->inptr + 1) % (buffer_size);
r->buffer_in[buffer_size * stereo + r->inptr + 1] = 0; r->infilled += 1;
r->inptr = (r->inptr + stereo) % (buffer_size * stereo);
r->infilled += stereo;
} }
r->latency = 1; r->latency = 1;
} }
if (r->infilled < buffer_size * stereo) if (r->infilled < buffer_size)
{ {
r->buffer_in[r->inptr + 0] = ls; r->buffer_in[r->inptr] = s;
r->buffer_in[r->inptr + 1] = rs; r->buffer_in[buffer_size + r->inptr + 0] = s;
r->buffer_in[buffer_size * stereo + r->inptr + 0] = ls; r->inptr = (r->inptr + 1) % (buffer_size);
r->buffer_in[buffer_size * stereo + r->inptr + 1] = rs; r->infilled += 1;
r->inptr = (r->inptr + stereo) % (buffer_size * stereo);
r->infilled += stereo;
} }
} }
@ -271,35 +266,30 @@ static const sample_t * resampler_inner_loop( resampler *r, sample_t** out_,
int n; int n;
/* accumulate in extended precision*/ /* accumulate in extended precision*/
int pt = imp [0]; int pt = imp [0];
intermediate_t l = (intermediate_t)pt * (intermediate_t)(in [0]); intermediate_t s = (intermediate_t)pt * (intermediate_t)(in [0]);
intermediate_t r = (intermediate_t)pt * (intermediate_t)(in [1]);
if ( out >= out_end ) if ( out >= out_end )
break; break;
for ( n = (adj_width - 2) / 2; n; --n ) for ( n = (adj_width - 2) / 2; n; --n )
{ {
pt = imp [1]; pt = imp [1];
l += (intermediate_t)pt * (intermediate_t)(in [2]); s += (intermediate_t)pt * (intermediate_t)(in [1]);
r += (intermediate_t)pt * (intermediate_t)(in [3]);
/* pre-increment more efficient on some RISC processors*/ /* pre-increment more efficient on some RISC processors*/
imp += 2; imp += 2;
pt = imp [0]; pt = imp [0];
r += (intermediate_t)pt * (intermediate_t)(in [5]); s += (intermediate_t)pt * (intermediate_t)(in [2]);
in += 4; in += 2;
l += (intermediate_t)pt * (intermediate_t)(in [0]);
} }
pt = imp [1]; pt = imp [1];
l += (intermediate_t)pt * (intermediate_t)(in [2]); s += (intermediate_t)pt * (intermediate_t)(in [1]);
r += (intermediate_t)pt * (intermediate_t)(in [3]);
/* these two "samples" after the end of the impulse give the /* these two "samples" after the end of the impulse give the
* proper offsets to the next input sample and next impulse */ * proper offsets to the next input sample and next impulse */
in = (sample_t const*) ((char const*) in + ((imp_off_t*)(&imp [2]))[0]); /* some negative value */ in = (sample_t const*) ((char const*) in + ((imp_off_t*)(&imp [2]))[0]); /* some negative value */
imp = (imp_t const*) ((char const*) imp + ((imp_off_t*)(&imp [2]))[1]); /* small positive or large negative */ imp = (imp_t const*) ((char const*) imp + ((imp_off_t*)(&imp [2]))[1]); /* small positive or large negative */
out [0] = (sample_t) (l >> 15); out [0] = (sample_t) (s >> 15);
out [1] = (sample_t) (r >> 15); out += 1;
out += 2;
} }
while ( in < in_end ); while ( in < in_end );
@ -315,9 +305,9 @@ static int resampler_wrapper( resampler *r, sample_t out [], int* out_size,
sample_t const in [], int in_size ) sample_t const in [], int in_size )
{ {
sample_t* out_ = out; sample_t* out_ = out;
int result = (int)(resampler_inner_loop( r, &out_, out + *out_size, in, in_size ) - in); int result = resampler_inner_loop( r, &out_, out + *out_size, in, in_size ) - in;
*out_size = (int)(out_ - out); *out_size = out_ - out;
return result; return result;
} }
@ -327,11 +317,11 @@ static void resampler_fill( resampler *r )
{ {
int inread; int inread;
int writepos = ( r->outptr + r->outfilled ) % (buffer_size * stereo); int writepos = ( r->outptr + r->outfilled ) % (buffer_size);
int writesize = (buffer_size * stereo) - writepos; int writesize = (buffer_size) - writepos;
if ( writesize > ( buffer_size * stereo - r->outfilled ) ) if ( writesize > ( buffer_size - r->outfilled ) )
writesize = buffer_size * stereo - r->outfilled; writesize = buffer_size - r->outfilled;
inread = resampler_wrapper(r, &r->buffer_out[writepos], &writesize, &r->buffer_in[buffer_size * stereo + r->inptr - r->infilled], r->infilled); inread = resampler_wrapper(r, &r->buffer_out[writepos], &writesize, &r->buffer_in[buffer_size + r->inptr - r->infilled], r->infilled);
r->infilled -= inread; r->infilled -= inread;
r->outfilled += writesize; r->outfilled += writesize;
if (!inread) if (!inread)
@ -342,38 +332,36 @@ static void resampler_fill( resampler *r )
int resampler_get_avail(void *_r) int resampler_get_avail(void *_r)
{ {
resampler *r = (resampler *)_r; resampler *r = (resampler *)_r;
if (r->outfilled < stereo && r->infilled >= r->width_) if (r->outfilled < 1 && r->infilled >= r->width_)
resampler_fill( r ); resampler_fill( r );
return r->outfilled; return r->outfilled;
} }
static void resampler_read_pair_internal( resampler *r, sample_t *ls, sample_t *rs, int advance ) static void resampler_read_sample_internal( resampler *r, sample_t *s, int advance )
{ {
if (r->outfilled < stereo) if (r->outfilled < 1)
resampler_fill( r ); resampler_fill( r );
if (r->outfilled < stereo) if (r->outfilled < 1)
{ {
*ls = 0; *s = 0;
*rs = 0;
return; return;
} }
*ls = r->buffer_out[r->outptr + 0]; *s = r->buffer_out[r->outptr];
*rs = r->buffer_out[r->outptr + 1];
if (advance) if (advance)
{ {
r->outptr = (r->outptr + 2) % (buffer_size * stereo); r->outptr = (r->outptr + 1) % (buffer_size);
r->outfilled -= stereo; r->outfilled -= 1;
} }
} }
void resampler_read_pair( void *_r, sample_t *ls, sample_t *rs ) void resampler_read_sample( void *_r, sample_t *s )
{ {
resampler *r = (resampler *)_r; resampler *r = (resampler *)_r;
resampler_read_pair_internal(r, ls, rs, 1); resampler_read_sample_internal(r, s, 1);
} }
void resampler_peek_pair( void *_r, sample_t *ls, sample_t *rs ) void resampler_peek_sample( void *_r, sample_t *s )
{ {
resampler *r = (resampler *)_r; resampler *r = (resampler *)_r;
resampler_read_pair_internal(r, ls, rs, 0); resampler_read_sample_internal(r, s, 0);
} }

View File

@ -61,12 +61,12 @@ void resampler_set_rate( void *, double new_factor );
int resampler_get_free(void *); int resampler_get_free(void *);
int resampler_get_min_fill(void *); int resampler_get_min_fill(void *);
void resampler_write_pair(void *, sample_t ls, sample_t rs); void resampler_write_sample(void *, sample_t s);
int resampler_get_avail(void *); int resampler_get_avail(void *);
void resampler_read_pair( void *, sample_t *ls, sample_t *rs ); void resampler_read_sample( void *, sample_t *s );
void resampler_peek_pair( void *, sample_t *ls, sample_t *rs ); void resampler_peek_sample( void *, sample_t *s );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -134,11 +134,11 @@ void playerDestroy(Player *p)
Player * playerCreate(int SAMPLEFREQUENCY) Player * playerCreate(int SAMPLEFREQUENCY)
{ {
int i/*, j*/; int i, j;
Player* p; Player* p;
srand((unsigned int)time(NULL)); srand(time(NULL));
p = (Player *) calloc(1, sizeof(Player)); p = (Player *) calloc(1, sizeof(Player));
if (!p) return NULL; if (!p) return NULL;
@ -241,7 +241,7 @@ static void instrEffect(Player *p, int chanNum)
int _local38; int _local38;
int _local39; int _local39;
int _local40; int _local40;
/*int _local43;*/ int _local43;
int butt, ron, pat, buf2, buf1; int butt, ron, pat, buf2, buf1;
TuneChannel *tc = &p->tuneChannels[chanNum]; TuneChannel *tc = &p->tuneChannels[chanNum];
@ -1666,7 +1666,7 @@ static void ABH(Player *p)
_local4 = 0; _local4 = 0;
} }
_local2 = _local3[_local4].patLen; _local2 = _local3[_local4].patLen;
if ((((tc->LJHG == _local2)) || ((tc->EQMIWERPIF == 0xFF)))){ if ((((tc->LJHG == _local2)) || ((tc->EQMIWERPIF == -1)))){
tc->LJHG = 0; tc->LJHG = 0;
tc->EQMIWERPIF++; tc->EQMIWERPIF++;
p->curSubsong.mutedChans[i] = p->mutedChans[i]; p->curSubsong.mutedChans[i] = p->mutedChans[i];
@ -1744,10 +1744,10 @@ void mixChunk(Player *p, int16_t *outBuff, uint playbackBufferSize)
{ {
int i, j; int i, j;
uint sampleNum; uint sampleNum;
int amp, smp/*, pos*/; int amp, smp, pos;
int32_t audioMainR, audioMainL; int32_t audioMainR, audioMainL;
int32_t audioDelayR, audioDelayL; int32_t audioDelayR, audioDelayL;
uint otherDelayTime = 1; uint otherDelayTime;
Voice *v; Voice *v;
TuneChannel *tc; TuneChannel *tc;
int insNum; int insNum;
@ -1850,8 +1850,6 @@ void mixChunk(Player *p, int16_t *outBuff, uint playbackBufferSize)
{ {
//amp = word_6632B964; //amp = word_6632B964;
//otherDelayTime = word_6632BB24; //otherDelayTime = word_6632BB24;
amp = 0;
otherDelayTime = 1;
} }
else else
{ {
@ -1882,7 +1880,7 @@ void mixChunk(Player *p, int16_t *outBuff, uint playbackBufferSize)
while ( v->sampPos != -1 && resampler_get_min_fill(v->resampler[0]) ) while ( v->sampPos != -1 && resampler_get_min_fill(v->resampler[0]) )
{ {
s = v->waveBuff[v->sampPos]; s = v->waveBuff[v->sampPos];
resampler_write_pair(v->resampler[0], s, s); resampler_write_sample(v->resampler[0], s);
if ( v->isPlayingBackward ) if ( v->isPlayingBackward )
{ {
v->sampPos--; v->sampPos--;
@ -1919,7 +1917,7 @@ void mixChunk(Player *p, int16_t *outBuff, uint playbackBufferSize)
} }
//smp = intp->interpSamp(v); //smp = intp->interpSamp(v);
resampler_read_pair(v->resampler[0], &s, &s); resampler_read_sample(v->resampler[0], &s);
smp = s; smp = s;
audioMainR += (smp * v->gainRight) >> 8; audioMainR += (smp * v->gainRight) >> 8;
@ -1936,11 +1934,11 @@ void mixChunk(Player *p, int16_t *outBuff, uint playbackBufferSize)
while ( resampler_get_min_fill(v->resampler[0]) ) while ( resampler_get_min_fill(v->resampler[0]) )
{ {
s = v->waveBuff[v->synthPos]; s = v->waveBuff[v->synthPos];
resampler_write_pair(v->resampler[0], s, s); resampler_write_sample(v->resampler[0], s);
v->synthPos++; v->synthPos++;
v->synthPos &= v->wavelength; v->synthPos &= v->wavelength;
} }
resampler_read_pair(v->resampler[0], &s, &s); resampler_read_sample(v->resampler[0], &s);
smp = s; smp = s;
audioMainR += (smp * v->gainRight) >> 8; audioMainR += (smp * v->gainRight) >> 8;
@ -2028,7 +2026,7 @@ void mixChunk(Player *p, int16_t *outBuff, uint playbackBufferSize)
while ( v->sampPos != -1 && resampler_get_min_fill(v->resampler[1]) ) while ( v->sampPos != -1 && resampler_get_min_fill(v->resampler[1]) )
{ {
s = v->waveBuff[v->sampPos]; s = v->waveBuff[v->sampPos];
resampler_write_pair(v->resampler[1], s, s); resampler_write_sample(v->resampler[1], s);
if ( v->isPlayingBackward ) if ( v->isPlayingBackward )
{ {
v->sampPos--; v->sampPos--;
@ -2063,7 +2061,7 @@ void mixChunk(Player *p, int16_t *outBuff, uint playbackBufferSize)
} }
} }
} }
resampler_read_pair(v->resampler[1], &s, &s); resampler_read_sample(v->resampler[1], &s);
smp = s; smp = s;
audioMainR += (smp * v->gainRight) >> 8; audioMainR += (smp * v->gainRight) >> 8;
@ -2080,11 +2078,11 @@ void mixChunk(Player *p, int16_t *outBuff, uint playbackBufferSize)
while ( resampler_get_min_fill(v->resampler[1]) ) while ( resampler_get_min_fill(v->resampler[1]) )
{ {
s = v->waveBuff[v->synthPos]; s = v->waveBuff[v->synthPos];
resampler_write_pair(v->resampler[1], s, s); resampler_write_sample(v->resampler[1], s);
v->synthPos++; v->synthPos++;
v->synthPos &= v->wavelength; v->synthPos &= v->wavelength;
} }
resampler_read_pair(v->resampler[1], &s, &s); resampler_read_sample(v->resampler[1], &s);
smp = s; smp = s;
audioMainR += (smp * v->gainRight) >> 8; audioMainR += (smp * v->gainRight) >> 8;