Update Syntrax decoder with speed improvements.
parent
d963710c28
commit
fce57925c0
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue