Updated st3play

CQTexperiment
Chris Moeller 2014-03-18 23:04:26 -07:00
parent e4d76dd1ca
commit 38d287ac75
4 changed files with 81 additions and 44 deletions

View File

@ -17,7 +17,7 @@ static double lanczos_lut[LANCZOS_SAMPLES + 1];
enum { lanczos_buffer_size = LANCZOS_WIDTH * 4 }; enum { lanczos_buffer_size = LANCZOS_WIDTH * 4 };
int fEqual(const double b, const double a) static int fEqual(const double b, const double a)
{ {
return fabs(a - b) < 1.0e-6; return fabs(a - b) < 1.0e-6;
} }
@ -27,12 +27,12 @@ static double sinc(double x)
return fEqual(x, 0.0) ? 1.0 : sin(x * M_PI) / (x * M_PI); return fEqual(x, 0.0) ? 1.0 : sin(x * M_PI) / (x * M_PI);
} }
void lanczos_init() void lanczos_init(void)
{ {
unsigned i; unsigned i;
double dx = (double)(LANCZOS_WIDTH) / LANCZOS_SAMPLES, x = 0.0; double dx = (double)(LANCZOS_WIDTH) / LANCZOS_SAMPLES, x = 0.0;
for (i = 0; i < LANCZOS_SAMPLES + 1; ++i, x += dx) for (i = 0; i < LANCZOS_SAMPLES + 1; ++i, x += dx)
lanczos_lut[i] = abs(x) < LANCZOS_WIDTH ? sinc(x) * sinc(x / LANCZOS_WIDTH) : 0.0; lanczos_lut[i] = fabs(x) < LANCZOS_WIDTH ? sinc(x) * sinc(x / LANCZOS_WIDTH) : 0.0;
} }
typedef struct lanczos_resampler typedef struct lanczos_resampler
@ -45,7 +45,7 @@ typedef struct lanczos_resampler
float buffer_out[lanczos_buffer_size]; float buffer_out[lanczos_buffer_size];
} lanczos_resampler; } lanczos_resampler;
void * lanczos_resampler_create() void * lanczos_resampler_create(void)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) malloc( sizeof(lanczos_resampler) ); lanczos_resampler * r = ( lanczos_resampler * ) malloc( sizeof(lanczos_resampler) );
if ( !r ) return 0; if ( !r ) return 0;
@ -164,7 +164,7 @@ static int lanczos_resampler_run(lanczos_resampler * r, float ** out_, float * o
} }
for (sample = 0, i = 0; i < LANCZOS_WIDTH * 2; ++i) for (sample = 0, i = 0; i < LANCZOS_WIDTH * 2; ++i)
sample += in[i] * kernel[i]; sample += in[i] * kernel[i];
*out++ = sample / kernel_sum * 256.0; *out++ = (float)(sample / kernel_sum * 256.0);
phase += phase_inc; phase += phase_inc;
@ -174,7 +174,7 @@ static int lanczos_resampler_run(lanczos_resampler * r, float ** out_, float * o
} }
while ( in < in_end ); while ( in < in_end );
r->phase = phase; r->phase = (unsigned short) phase;
*out_ = out; *out_ = out;
used = (int)(in - in_); used = (int)(in - in_);

View File

@ -1,9 +1,27 @@
#ifndef _LANCZOS_RESAMPLER_H_ #ifndef _LANCZOS_RESAMPLER_H_
#define _LANCZOS_RESAMPLER_H_ #define _LANCZOS_RESAMPLER_H_
void lanczos_init(); // Ugglay
#ifdef LANCZOS_DECORATE
#define PASTE(a,b) a ## b
#define EVALUATE(a,b) PASTE(a,b)
#define lanczos_init EVALUATE(LANCZOS_DECORATE,_lanczos_init)
#define lanczos_resampler_create EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_create)
#define lanczos_resampler_delete EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_delete)
#define lanczos_resampler_dup EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_dup)
#define lanczos_resampler_get_free_count EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_get_free_count)
#define lanczos_resampler_write_sample EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_write_sample)
#define lanczos_resampler_set_rate EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_set_rate)
#define lanczos_resampler_ready EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_ready)
#define lanczos_resampler_clear EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_clear)
#define lanczos_resampler_get_sample_count EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_get_sample_count)
#define lanczos_resampler_get_sample EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_get_sample)
#define lanczos_resampler_remove_sample EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_remove_sample)
#endif
void * lanczos_resampler_create(); void lanczos_init(void);
void * lanczos_resampler_create(void);
void lanczos_resampler_delete(void *); void lanczos_resampler_delete(void *);
void * lanczos_resampler_dup(void *); void * lanczos_resampler_dup(void *);

View File

@ -1,4 +1,4 @@
/* /*
** ST3PLAY v0.43a ** ST3PLAY v0.43a
** ============== ** ==============
** **
@ -173,7 +173,7 @@ typedef struct
chn_t chn[32]; chn_t chn[32];
uint8_t mixingVolume; uint8_t mixingVolume;
uint32_t soundBufferSize; int32_t soundBufferSize;
uint32_t outputFreq; uint32_t outputFreq;
VOICE voice[32]; VOICE voice[32];
@ -453,7 +453,7 @@ void * st3play_Alloc(uint32_t outputFreq, int8_t interpolation)
{ {
int i; int i;
PLAYER * p = calloc(1, sizeof(PLAYER)); PLAYER * p = (PLAYER *) calloc(1, sizeof(PLAYER));
if ( !p ) if ( !p )
return 0; return 0;
@ -525,7 +525,7 @@ static inline uint16_t get_le16(const void *_p)
static inline void set_le16(void *_p, uint16_t v) static inline void set_le16(void *_p, uint16_t v)
{ {
uint8_t * p = (uint8_t *)_p; uint8_t * p = (uint8_t *)_p;
p[0] = v; p[0] = (uint8_t)v;
p[1] = v >> 8; p[1] = v >> 8;
} }
@ -537,6 +537,7 @@ static inline uint32_t get_le32(const void *_p)
static inline void getlastnfo(PLAYER *p, chn_t *ch) static inline void getlastnfo(PLAYER *p, chn_t *ch)
{ {
(void)p;
if (!ch->info) if (!ch->info)
ch->info = ch->alastnfo; ch->info = ch->alastnfo;
} }
@ -785,7 +786,7 @@ static inline uint8_t getnote(PLAYER *p)
return (255); return (255);
i = p->np_patoff; i = p->np_patoff;
while (1) for (;;)
{ {
dat = p->mseg[p->np_patseg + i++]; dat = p->mseg[p->np_patseg + i++];
if (!dat) // end of row if (!dat) // end of row
@ -836,6 +837,7 @@ static inline void doamiga(PLAYER *p, uint8_t ch)
uint32_t inslen; uint32_t inslen;
uint32_t insrepbeg; uint32_t insrepbeg;
uint32_t insrepend; uint32_t insrepend;
int8_t shift;
if (p->chn[ch].ins) if (p->chn[ch].ins)
{ {
@ -860,7 +862,18 @@ static inline void doamiga(PLAYER *p, uint8_t ch)
insoffs = (uint32_t)(((uint32_t)(insdat[0x0D])<<16)|((uint16_t)(insdat[0x0F])<<8)|insdat[0x0E])<<4; insoffs = (uint32_t)(((uint32_t)(insdat[0x0D])<<16)|((uint16_t)(insdat[0x0F])<<8)|insdat[0x0E])<<4;
if (insoffs > p->mseg_len)
insoffs = p->mseg_len;
inslen = get_le32(&insdat[0x10]); inslen = get_le32(&insdat[0x10]);
shift = 0;
if (insdat[0x1F] & 2) shift++;
if (insdat[0x1F] & 4) shift++;
if (insoffs + (inslen << shift) > p->mseg_len)
inslen = (p->mseg_len - insoffs) >> shift;
insrepbeg = get_le32(&insdat[0x14]); insrepbeg = get_le32(&insdat[0x14]);
insrepend = get_le32(&insdat[0x18]); insrepend = get_le32(&insdat[0x18]);
@ -1000,7 +1013,7 @@ static inline void donotes(PLAYER *p)
seekpat(p); seekpat(p);
while (1) for (;;)
{ {
ch = getnote(p); ch = getnote(p);
if (ch == 255) break; // end of row/channels if (ch == 255) break; // end of row/channels
@ -1270,6 +1283,9 @@ static void loadheaderparms(PLAYER *p)
if (insoff && (insdat[0] == 1)) if (insoff && (insdat[0] == 1))
{ {
if (insoff > p->mseg_len)
insoff = p->mseg_len;
inslen = get_le32(&insdat[0x10]); inslen = get_le32(&insdat[0x10]);
if (insdat[0x1E] == 4) // modplug packed if (insdat[0x1E] == 4) // modplug packed
@ -1280,12 +1296,16 @@ static void loadheaderparms(PLAYER *p)
if (insdat[0x1F] & 4) if (insdat[0x1F] & 4)
{ {
// 16-bit // 16-bit
if (insoff + inslen * 2 > p->mseg_len)
inslen = (p->mseg_len - insoff) / 2;
for (j = 0; j < inslen; ++j) for (j = 0; j < inslen; ++j)
set_le16(&p->mseg[insoff + (j << 1)], get_le16(&p->mseg[insoff + (j << 1)]) - 0x8000); set_le16(&p->mseg[insoff + (j << 1)], get_le16(&p->mseg[insoff + (j << 1)]) - 0x8000);
} }
else else
{ {
// 8-bit // 8-bit
if (insoff + inslen > p->mseg_len)
inslen = p->mseg_len - insoff;
for (j = 0; j < inslen; ++j) for (j = 0; j < inslen; ++j)
p->mseg[insoff + j] = p->mseg[insoff + j] - 0x80; p->mseg[insoff + j] = p->mseg[insoff + j] - 0x80;
} }
@ -2595,7 +2615,6 @@ static inline void mix8b(PLAYER *p, uint8_t ch, uint32_t samples)
int32_t samplingInterpolation; int32_t samplingInterpolation;
int32_t interpolating; int32_t interpolating;
int32_t oversampleCount; int32_t oversampleCount;
int32_t i;
uint32_t j; uint32_t j;
float volume; float volume;
float sample; float sample;
@ -2626,10 +2645,10 @@ static inline void mix8b(PLAYER *p, uint8_t ch, uint32_t samples)
while (interpolating && lanczos_resampler_get_free_count(resampler)) while (interpolating && lanczos_resampler_get_free_count(resampler))
{ {
for (i = oversampleCount; i < samplingInterpolation && lanczos_resampler_get_free_count(resampler); ++i) for (; oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler); ++oversampleCount)
lanczos_resampler_write_sample(resampler, sampleData[samplePosition] * 256); lanczos_resampler_write_sample(resampler, sampleData[samplePosition] * 256);
if (i < samplingInterpolation) if (oversampleCount < samplingInterpolation)
break; break;
samplePosition++; samplePosition++;
@ -2651,8 +2670,8 @@ static inline void mix8b(PLAYER *p, uint8_t ch, uint32_t samples)
} }
p->voice[ch].samplePosition = samplePosition; p->voice[ch].samplePosition = samplePosition;
p->voice[ch].interpolating = interpolating; p->voice[ch].interpolating = (int8_t)interpolating;
p->voice[ch].oversampleCount = oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
if ( !lanczos_resampler_ready(resampler) ) if ( !lanczos_resampler_ready(resampler) )
{ {
@ -2681,7 +2700,6 @@ static inline void mix8bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
int32_t samplingInterpolation; int32_t samplingInterpolation;
int32_t interpolating; int32_t interpolating;
int32_t oversampleCount; int32_t oversampleCount;
int32_t i;
uint32_t j; uint32_t j;
float volume; float volume;
float sampleL; float sampleL;
@ -2715,13 +2733,13 @@ static inline void mix8bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
while (interpolating && lanczos_resampler_get_free_count(resampler[0])) while (interpolating && lanczos_resampler_get_free_count(resampler[0]))
{ {
for (i = oversampleCount; i < samplingInterpolation && lanczos_resampler_get_free_count(resampler[0]); ++i) for (; oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler[0]); ++oversampleCount)
{ {
lanczos_resampler_write_sample(resampler[0], sampleData[samplePosition] * 256); lanczos_resampler_write_sample(resampler[0], sampleData[samplePosition] * 256);
lanczos_resampler_write_sample(resampler[1], sampleData[sampleLength + samplePosition] * 256); lanczos_resampler_write_sample(resampler[1], sampleData[sampleLength + samplePosition] * 256);
} }
if (i < samplingInterpolation) if (oversampleCount < samplingInterpolation)
break; break;
samplePosition++; samplePosition++;
@ -2743,8 +2761,8 @@ static inline void mix8bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
} }
p->voice[ch].samplePosition = samplePosition; p->voice[ch].samplePosition = samplePosition;
p->voice[ch].interpolating = interpolating; p->voice[ch].interpolating = (int8_t)interpolating;
p->voice[ch].oversampleCount = oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
if ( !lanczos_resampler_ready(resampler[0]) ) if ( !lanczos_resampler_ready(resampler[0]) )
{ {
@ -2776,7 +2794,6 @@ static inline void mix16b(PLAYER *p, uint8_t ch, uint32_t samples)
int32_t samplingInterpolation; int32_t samplingInterpolation;
int32_t interpolating; int32_t interpolating;
int32_t oversampleCount; int32_t oversampleCount;
int32_t i;
uint32_t j; uint32_t j;
float volume; float volume;
float sample; float sample;
@ -2807,10 +2824,10 @@ static inline void mix16b(PLAYER *p, uint8_t ch, uint32_t samples)
while (interpolating && lanczos_resampler_get_free_count(resampler)) while (interpolating && lanczos_resampler_get_free_count(resampler))
{ {
for (i = oversampleCount; i < samplingInterpolation && lanczos_resampler_get_free_count(resampler); ++i) for (; oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler); ++oversampleCount)
lanczos_resampler_write_sample(resampler, get_le16(&sampleData[samplePosition])); lanczos_resampler_write_sample(resampler, get_le16(&sampleData[samplePosition]));
if (i < samplingInterpolation) if (oversampleCount < samplingInterpolation)
break; break;
samplePosition++; samplePosition++;
@ -2832,8 +2849,8 @@ static inline void mix16b(PLAYER *p, uint8_t ch, uint32_t samples)
} }
p->voice[ch].samplePosition = samplePosition; p->voice[ch].samplePosition = samplePosition;
p->voice[ch].interpolating = interpolating; p->voice[ch].interpolating = (int8_t)interpolating;
p->voice[ch].oversampleCount = oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
if ( !lanczos_resampler_ready(resampler) ) if ( !lanczos_resampler_ready(resampler) )
{ {
@ -2862,7 +2879,6 @@ static inline void mix16bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
int32_t samplingInterpolation; int32_t samplingInterpolation;
int32_t interpolating; int32_t interpolating;
int32_t oversampleCount; int32_t oversampleCount;
int32_t i;
uint32_t j; uint32_t j;
float volume; float volume;
float sampleL; float sampleL;
@ -2896,13 +2912,13 @@ static inline void mix16bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
while (interpolating && lanczos_resampler_get_free_count(resampler[0])) while (interpolating && lanczos_resampler_get_free_count(resampler[0]))
{ {
for (i = oversampleCount; i < samplingInterpolation && lanczos_resampler_get_free_count(resampler[0]); ++i) for (; oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler[0]); ++oversampleCount)
{ {
lanczos_resampler_write_sample(resampler[0], get_le16(&sampleData[samplePosition])); lanczos_resampler_write_sample(resampler[0], get_le16(&sampleData[samplePosition]));
lanczos_resampler_write_sample(resampler[1], get_le16(&sampleData[sampleLength + samplePosition])); lanczos_resampler_write_sample(resampler[1], get_le16(&sampleData[sampleLength + samplePosition]));
} }
if (i < samplingInterpolation) if (oversampleCount < samplingInterpolation)
break; break;
samplePosition++; samplePosition++;
@ -2924,8 +2940,8 @@ static inline void mix16bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
} }
p->voice[ch].samplePosition = samplePosition; p->voice[ch].samplePosition = samplePosition;
p->voice[ch].interpolating = interpolating; p->voice[ch].interpolating = (int8_t)interpolating;
p->voice[ch].oversampleCount = oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
if ( !lanczos_resampler_ready(resampler[0]) ) if ( !lanczos_resampler_ready(resampler[0]) )
{ {
@ -2966,7 +2982,6 @@ static inline void mixadpcm(PLAYER *p, uint8_t ch, uint32_t samples)
int8_t lastDelta; int8_t lastDelta;
int32_t interpolating; int32_t interpolating;
int32_t oversampleCount; int32_t oversampleCount;
int32_t i;
uint32_t j; uint32_t j;
float volume; float volume;
float sample; float sample;
@ -3010,10 +3025,10 @@ static inline void mixadpcm(PLAYER *p, uint8_t ch, uint32_t samples)
int8_t nextDelta = lastDelta; int8_t nextDelta = lastDelta;
int16_t sample = get_adpcm_sample(sampleDictionary, sampleData, samplePosition, &nextDelta) * 256; int16_t sample = get_adpcm_sample(sampleDictionary, sampleData, samplePosition, &nextDelta) * 256;
for (i = oversampleCount; i < samplingInterpolation && lanczos_resampler_get_free_count(resampler); ++i) for (; oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler); ++oversampleCount)
lanczos_resampler_write_sample(resampler, sample); lanczos_resampler_write_sample(resampler, sample);
if (i < samplingInterpolation) if (oversampleCount < samplingInterpolation)
break; break;
lastDelta = nextDelta; lastDelta = nextDelta;
@ -3044,8 +3059,8 @@ static inline void mixadpcm(PLAYER *p, uint8_t ch, uint32_t samples)
p->voice[ch].samplePosition = samplePosition; p->voice[ch].samplePosition = samplePosition;
p->voice[ch].lastSamplePosition = samplePosition; p->voice[ch].lastSamplePosition = samplePosition;
p->voice[ch].interpolating = interpolating; p->voice[ch].interpolating = (int8_t)interpolating;
p->voice[ch].oversampleCount = oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
p->voice[ch].lastDelta = lastDelta; p->voice[ch].lastDelta = lastDelta;
if ( !lanczos_resampler_ready(resampler) ) if ( !lanczos_resampler_ready(resampler) )
@ -3208,6 +3223,8 @@ void st3play_GetInfo(void *_p, st3_info *info)
info->order = p->x_np_ord - 1; info->order = p->x_np_ord - 1;
info->pattern = p->x_np_pat; info->pattern = p->x_np_pat;
info->row = p->x_np_row; info->row = p->x_np_row;
info->speed = p->musicmax;
info->tempo = p->tempo;
channels_playing = 0; channels_playing = 0;
if (p->isMixing) if (p->isMixing)
{ {
@ -3217,7 +3234,7 @@ void st3play_GetInfo(void *_p, st3_info *info)
++channels_playing; ++channels_playing;
} }
} }
info->channels_playing = channels_playing; info->channels_playing = (int8_t)channels_playing;
} }
// EOF // EOF

View File

@ -20,10 +20,12 @@ void st3play_Render16(void *, int16_t *buffer, int32_t count);
typedef struct typedef struct
{ {
int16_t order; uint16_t order;
int16_t pattern; uint16_t pattern;
int16_t row; uint16_t row;
int8_t channels_playing; uint8_t speed;
uint8_t tempo;
uint8_t channels_playing;
} st3_info; } st3_info;
void st3play_GetInfo(void *, st3_info *); void st3play_GetInfo(void *, st3_info *);