diff --git a/Frameworks/Dumb/dumb/include/internal/resampler.h b/Frameworks/Dumb/dumb/include/internal/resampler.h index 4d409efef..90a98714f 100644 --- a/Frameworks/Dumb/dumb/include/internal/resampler.h +++ b/Frameworks/Dumb/dumb/include/internal/resampler.h @@ -13,11 +13,13 @@ #define resampler_set_quality EVALUATE(RESAMPLER_DECORATE,_resampler_set_quality) #define resampler_get_free_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_free_count) #define resampler_write_sample EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample) +#define resampler_write_sample_fixed EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample_fixed) #define resampler_set_rate EVALUATE(RESAMPLER_DECORATE,_resampler_set_rate) #define resampler_ready EVALUATE(RESAMPLER_DECORATE,_resampler_ready) #define resampler_clear EVALUATE(RESAMPLER_DECORATE,_resampler_clear) #define resampler_get_sample_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_count) #define resampler_get_sample EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample) +#define resampler_get_sample_float EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_float) #define resampler_remove_sample EVALUATE(RESAMPLER_DECORATE,_resampler_remove_sample) #endif @@ -43,11 +45,13 @@ void resampler_set_quality(void *, int quality); int resampler_get_free_count(void *); void resampler_write_sample(void *, short sample); +void resampler_write_sample_fixed(void *, int sample, unsigned char depth); void resampler_set_rate( void *, double new_factor ); int resampler_ready(void *); void resampler_clear(void *); int resampler_get_sample_count(void *); int resampler_get_sample(void *); +float resampler_get_sample_float(void *); void resampler_remove_sample(void *); #endif diff --git a/Frameworks/Dumb/dumb/src/helpers/resampler.c b/Frameworks/Dumb/dumb/src/helpers/resampler.c index 90b01a4ef..697261be7 100644 --- a/Frameworks/Dumb/dumb/src/helpers/resampler.c +++ b/Frameworks/Dumb/dumb/src/helpers/resampler.c @@ -20,7 +20,9 @@ #include "internal/resampler.h" enum { RESAMPLER_SHIFT = 10 }; +enum { RESAMPLER_SHIFT_EXTRA = 8 }; enum { RESAMPLER_RESOLUTION = 1 << RESAMPLER_SHIFT }; +enum { RESAMPLER_RESOLUTION_EXTRA = 1 << (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA) }; enum { SINC_WIDTH = 16 }; enum { SINC_SAMPLES = RESAMPLER_RESOLUTION * SINC_WIDTH }; enum { CUBIC_SAMPLES = RESAMPLER_RESOLUTION * 4 }; @@ -324,9 +326,9 @@ void resampler_clear(void *_r) void resampler_set_rate(void *_r, double new_factor) { resampler * r = ( resampler * ) _r; - r->phase_inc = (int)( new_factor * RESAMPLER_RESOLUTION ); + r->phase_inc = (int)( new_factor * RESAMPLER_RESOLUTION_EXTRA ); new_factor = 1.0 / new_factor; - r->inv_phase_inc = (int)( new_factor * RESAMPLER_RESOLUTION ); + r->inv_phase_inc = (int)( new_factor * RESAMPLER_RESOLUTION_EXTRA ); } void resampler_write_sample(void *_r, short s) @@ -403,13 +405,13 @@ static int resampler_run_zoh(resampler * r, float ** out_, float * out_end) phase += phase_inc; - in += phase >> RESAMPLER_SHIFT; + in += phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - phase &= RESAMPLER_RESOLUTION-1; + phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); - r->phase = (unsigned short) phase; + r->phase = phase; *out_ = out; used = (int)(in - in_); @@ -440,6 +442,7 @@ static int resampler_run_blep(resampler * r, float ** out_, float * out_end) do { float kernel[SINC_WIDTH * 2], kernel_sum = 0.0; + int phase_reduced = inv_phase >> RESAMPLER_SHIFT_EXTRA; int i = SINC_WIDTH; float sample; @@ -449,7 +452,7 @@ static int resampler_run_blep(resampler * r, float ** out_, float * out_end) for (; i >= -SINC_WIDTH + 1; --i) { int pos = i * step; - int abs_pos = abs(inv_phase - pos); + int abs_pos = abs(phase_reduced - pos); kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs_pos] * window_lut[abs_pos]; } sample = *in++ - last_amp; @@ -460,9 +463,9 @@ static int resampler_run_blep(resampler * r, float ** out_, float * out_end) inv_phase += inv_phase_inc; - out += inv_phase >> RESAMPLER_SHIFT; + out += inv_phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - inv_phase &= RESAMPLER_RESOLUTION-1; + inv_phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -505,6 +508,7 @@ static int resampler_run_blep_sse(resampler * r, float ** out_, float * out_end) __m128 samplex; float sample; float *kernelf = (float*)(&kernel); + int phase_reduced = inv_phase >> RESAMPLER_SHIFT_EXTRA; int i = SINC_WIDTH; if ( out + SINC_WIDTH * 2 > out_end ) @@ -513,7 +517,7 @@ static int resampler_run_blep_sse(resampler * r, float ** out_, float * out_end) for (; i >= -SINC_WIDTH + 1; --i) { int pos = i * step; - int abs_pos = abs(inv_phase - pos); + int abs_pos = abs(phase_reduced - pos); kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs_pos] * window_lut[abs_pos]; } sample = *in++ - last_amp; @@ -531,9 +535,9 @@ static int resampler_run_blep_sse(resampler * r, float ** out_, float * out_end) inv_phase += inv_phase_inc; - out += inv_phase >> RESAMPLER_SHIFT; + out += inv_phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - inv_phase &= RESAMPLER_RESOLUTION - 1; + inv_phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -571,14 +575,14 @@ static int resampler_run_linear(resampler * r, float ** out_, float * out_end) if ( out >= out_end ) break; - sample = in[0] + (in[1] - in[0]) * ((float)phase / RESAMPLER_RESOLUTION); + sample = in[0] + (in[1] - in[0]) * ((float)phase / RESAMPLER_RESOLUTION_EXTRA); *out++ = sample; phase += phase_inc; - in += phase >> RESAMPLER_SHIFT; + in += phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - phase &= RESAMPLER_RESOLUTION-1; + phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -616,7 +620,7 @@ static int resampler_run_cubic(resampler * r, float ** out_, float * out_end) if ( out >= out_end ) break; - kernel = cubic_lut + phase * 4; + kernel = cubic_lut + (phase >> RESAMPLER_SHIFT_EXTRA) * 4; for (sample = 0, i = 0; i < 4; ++i) sample += in[i] * kernel[i]; @@ -624,9 +628,9 @@ static int resampler_run_cubic(resampler * r, float ** out_, float * out_end) phase += phase_inc; - in += phase >> RESAMPLER_SHIFT; + in += phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - phase &= RESAMPLER_RESOLUTION-1; + phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -665,7 +669,7 @@ static int resampler_run_cubic_sse(resampler * r, float ** out_, float * out_end break; temp1 = _mm_loadu_ps( (const float *)( in ) ); - temp2 = _mm_load_ps( (const float *)( cubic_lut + phase * 4 ) ); + temp2 = _mm_load_ps( (const float *)( cubic_lut + (phase >> RESAMPLER_SHIFT_EXTRA) * 4 ) ); temp1 = _mm_mul_ps( temp1, temp2 ); samplex = _mm_add_ps( samplex, temp1 ); temp1 = _mm_movehl_ps( temp1, samplex ); @@ -678,9 +682,9 @@ static int resampler_run_cubic_sse(resampler * r, float ** out_, float * out_end phase += phase_inc; - in += phase >> RESAMPLER_SHIFT; + in += phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - phase &= RESAMPLER_RESOLUTION - 1; + phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -710,14 +714,15 @@ static int resampler_run_sinc(resampler * r, float ** out_, float * out_end) int phase = r->phase; int phase_inc = r->phase_inc; - int step = phase_inc > RESAMPLER_RESOLUTION ? RESAMPLER_RESOLUTION * RESAMPLER_RESOLUTION / phase_inc : RESAMPLER_RESOLUTION; + int step = phase_inc > RESAMPLER_RESOLUTION_EXTRA ? RESAMPLER_RESOLUTION * RESAMPLER_RESOLUTION_EXTRA / phase_inc : RESAMPLER_RESOLUTION; int window_step = RESAMPLER_RESOLUTION; do { float kernel[SINC_WIDTH * 2], kernel_sum = 0.0; int i = SINC_WIDTH; - int phase_adj = phase * step / RESAMPLER_RESOLUTION; + int phase_reduced = phase >> RESAMPLER_SHIFT_EXTRA; + int phase_adj = phase_reduced * step / RESAMPLER_RESOLUTION; float sample; if ( out >= out_end ) @@ -727,7 +732,7 @@ static int resampler_run_sinc(resampler * r, float ** out_, float * out_end) { int pos = i * step; int window_pos = i * window_step; - kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase - window_pos)]; + kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase_reduced - window_pos)]; } for (sample = 0, i = 0; i < SINC_WIDTH * 2; ++i) sample += in[i] * kernel[i]; @@ -735,9 +740,9 @@ static int resampler_run_sinc(resampler * r, float ** out_, float * out_end) phase += phase_inc; - in += phase >> RESAMPLER_SHIFT; + in += phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - phase &= RESAMPLER_RESOLUTION-1; + phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -767,7 +772,7 @@ static int resampler_run_sinc_sse(resampler * r, float ** out_, float * out_end) int phase = r->phase; int phase_inc = r->phase_inc; - int step = phase_inc > RESAMPLER_RESOLUTION ? RESAMPLER_RESOLUTION * RESAMPLER_RESOLUTION / phase_inc : RESAMPLER_RESOLUTION; + int step = phase_inc > RESAMPLER_RESOLUTION_EXTRA ? RESAMPLER_RESOLUTION * RESAMPLER_RESOLUTION_EXTRA / phase_inc : RESAMPLER_RESOLUTION; int window_step = RESAMPLER_RESOLUTION; do @@ -779,7 +784,8 @@ static int resampler_run_sinc_sse(resampler * r, float ** out_, float * out_end) __m128 samplex = _mm_setzero_ps(); float *kernelf = (float*)(&kernel); int i = SINC_WIDTH; - int phase_adj = phase * step / RESAMPLER_RESOLUTION; + int phase_reduced = phase >> RESAMPLER_SHIFT_EXTRA; + int phase_adj = phase_reduced * step / RESAMPLER_RESOLUTION; if ( out >= out_end ) break; @@ -788,7 +794,7 @@ static int resampler_run_sinc_sse(resampler * r, float ** out_, float * out_end) { int pos = i * step; int window_pos = i * window_step; - kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase - window_pos)]; + kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase_reduced - window_pos)]; } for (i = 0; i < SINC_WIDTH / 2; ++i) { @@ -810,9 +816,9 @@ static int resampler_run_sinc_sse(resampler * r, float ** out_, float * out_end) phase += phase_inc; - in += phase >> RESAMPLER_SHIFT; + in += phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - phase &= RESAMPLER_RESOLUTION - 1; + phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -924,6 +930,19 @@ int resampler_get_sample(void *_r) return (int)r->buffer_out[ r->read_pos ]; } +float resampler_get_sample_float(void *_r) +{ + resampler * r = ( resampler * ) _r; + if ( r->read_filled < 1 && r->phase_inc) + resampler_fill_and_remove_delay( r ); + if ( r->read_filled < 1 ) + return 0; + if ( r->quality == RESAMPLER_QUALITY_BLEP ) + return r->buffer_out[ r->read_pos ] + r->accumulator; + else + return r->buffer_out[ r->read_pos ]; +} + void resampler_remove_sample(void *_r) { resampler * r = ( resampler * ) _r; diff --git a/Frameworks/modplay/modplay/ft2play.c b/Frameworks/modplay/modplay/ft2play.c index 0c61905a9..532af0b8b 100644 --- a/Frameworks/modplay/modplay/ft2play.c +++ b/Frameworks/modplay/modplay/ft2play.c @@ -2402,7 +2402,10 @@ static int8_t LoadInstrSample(PLAYER *p, MEM *f, uint16_t i) return (0); } - mread(s->Pek, adpcm ? adpcm : l, 1, f); + if (s->Typ & 16) + mread_swap(s->Pek, l, 1, f, 0, 1); // byte swap 16 bit sample on big endian system, which by definition cannot be an adpcm sample + else + mread(s->Pek, adpcm ? adpcm : l, 1, f); if (!adpcm) Delta2Samp(s->Pek, l, s->Typ); else @@ -2911,7 +2914,7 @@ static inline void mix8b(PLAYER *p, uint32_t ch, uint32_t samples) while (interpolating && resampler_get_free_count(resampler)) { - resampler_write_sample(resampler, sampleData[samplePosition] * 256); + resampler_write_sample_fixed(resampler, sampleData[samplePosition], 8); if (loopDir == 1) --samplePosition; @@ -2962,7 +2965,7 @@ static inline void mix8b(PLAYER *p, uint32_t ch, uint32_t samples) break; } - sample = resampler_get_sample(resampler); + sample = resampler_get_sample_float(resampler); resampler_remove_sample(resampler); sample *= p->voice[ch].volume; @@ -3075,8 +3078,8 @@ static inline void mix8bstereo(PLAYER *p, uint32_t ch, uint32_t samples) while (interpolating && resampler_get_free_count(resampler[0])) { - resampler_write_sample(resampler[0], sampleData[samplePosition] * 256); - resampler_write_sample(resampler[1], sampleData[sampleLength + samplePosition] * 256); + resampler_write_sample_fixed(resampler[0], sampleData[samplePosition], 8); + resampler_write_sample_fixed(resampler[1], sampleData[sampleLength + samplePosition], 8); if (loopDir == 1) --samplePosition; @@ -3127,8 +3130,8 @@ static inline void mix8bstereo(PLAYER *p, uint32_t ch, uint32_t samples) break; } - sampleL = resampler_get_sample(resampler[0]); - sampleR = resampler_get_sample(resampler[1]); + sampleL = resampler_get_sample_float(resampler[0]); + sampleR = resampler_get_sample_float(resampler[1]); resampler_remove_sample(resampler[0]); resampler_remove_sample(resampler[1]); @@ -3238,7 +3241,7 @@ static inline void mix16b(PLAYER *p, uint32_t ch, uint32_t samples) while (interpolating && resampler_get_free_count(resampler)) { - resampler_write_sample(resampler, sampleData[samplePosition]); + resampler_write_sample_fixed(resampler, sampleData[samplePosition], 16); if (loopDir == 1) --samplePosition; @@ -3289,7 +3292,7 @@ static inline void mix16b(PLAYER *p, uint32_t ch, uint32_t samples) break; } - sample = resampler_get_sample(resampler); + sample = resampler_get_sample_float(resampler); resampler_remove_sample(resampler); sample *= p->voice[ch].volume; @@ -3402,8 +3405,8 @@ static inline void mix16bstereo(PLAYER *p, uint32_t ch, uint32_t samples) while (interpolating && resampler_get_free_count(resampler[0])) { - resampler_write_sample(resampler[0], sampleData[samplePosition]); - resampler_write_sample(resampler[1], sampleData[sampleLength + samplePosition]); + resampler_write_sample_fixed(resampler[0], sampleData[samplePosition], 16); + resampler_write_sample_fixed(resampler[1], sampleData[sampleLength + samplePosition], 16); if (loopDir == 1) --samplePosition; @@ -3454,8 +3457,8 @@ static inline void mix16bstereo(PLAYER *p, uint32_t ch, uint32_t samples) break; } - sampleL = resampler_get_sample(resampler[0]); - sampleR = resampler_get_sample(resampler[1]); + sampleL = resampler_get_sample_float(resampler[0]); + sampleR = resampler_get_sample_float(resampler[1]); resampler_remove_sample(resampler[0]); resampler_remove_sample(resampler[1]); diff --git a/Frameworks/modplay/modplay/resampler.c b/Frameworks/modplay/modplay/resampler.c index 2d5e9884c..05a7c2741 100644 --- a/Frameworks/modplay/modplay/resampler.c +++ b/Frameworks/modplay/modplay/resampler.c @@ -20,7 +20,9 @@ #include "resampler.h" enum { RESAMPLER_SHIFT = 10 }; +enum { RESAMPLER_SHIFT_EXTRA = 8 }; enum { RESAMPLER_RESOLUTION = 1 << RESAMPLER_SHIFT }; +enum { RESAMPLER_RESOLUTION_EXTRA = 1 << (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA) }; enum { SINC_WIDTH = 16 }; enum { SINC_SAMPLES = RESAMPLER_RESOLUTION * SINC_WIDTH }; enum { CUBIC_SAMPLES = RESAMPLER_RESOLUTION * 4 }; @@ -324,9 +326,9 @@ void resampler_clear(void *_r) void resampler_set_rate(void *_r, double new_factor) { resampler * r = ( resampler * ) _r; - r->phase_inc = (int)( new_factor * RESAMPLER_RESOLUTION ); + r->phase_inc = (int)( new_factor * RESAMPLER_RESOLUTION_EXTRA ); new_factor = 1.0 / new_factor; - r->inv_phase_inc = (int)( new_factor * RESAMPLER_RESOLUTION ); + r->inv_phase_inc = (int)( new_factor * RESAMPLER_RESOLUTION_EXTRA ); } void resampler_write_sample(void *_r, short s) @@ -342,7 +344,7 @@ void resampler_write_sample(void *_r, short s) if ( r->write_filled < resampler_buffer_size ) { float s32 = s; - s32 *= (1.0 / 32768.0); + s32 *= 256.0; r->buffer_in[ r->write_pos ] = s32; r->buffer_in[ r->write_pos + resampler_buffer_size ] = s32; @@ -403,13 +405,13 @@ static int resampler_run_zoh(resampler * r, float ** out_, float * out_end) phase += phase_inc; - in += phase >> RESAMPLER_SHIFT; + in += phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - phase &= RESAMPLER_RESOLUTION-1; + phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); - r->phase = (unsigned short) phase; + r->phase = phase; *out_ = out; used = (int)(in - in_); @@ -440,6 +442,7 @@ static int resampler_run_blep(resampler * r, float ** out_, float * out_end) do { float kernel[SINC_WIDTH * 2], kernel_sum = 0.0; + int phase_reduced = inv_phase >> RESAMPLER_SHIFT_EXTRA; int i = SINC_WIDTH; float sample; @@ -449,7 +452,7 @@ static int resampler_run_blep(resampler * r, float ** out_, float * out_end) for (; i >= -SINC_WIDTH + 1; --i) { int pos = i * step; - int abs_pos = abs(inv_phase - pos); + int abs_pos = abs(phase_reduced - pos); kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs_pos] * window_lut[abs_pos]; } sample = *in++ - last_amp; @@ -460,9 +463,9 @@ static int resampler_run_blep(resampler * r, float ** out_, float * out_end) inv_phase += inv_phase_inc; - out += inv_phase >> RESAMPLER_SHIFT; + out += inv_phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - inv_phase &= RESAMPLER_RESOLUTION-1; + inv_phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -505,6 +508,7 @@ static int resampler_run_blep_sse(resampler * r, float ** out_, float * out_end) __m128 samplex; float sample; float *kernelf = (float*)(&kernel); + int phase_reduced = inv_phase >> RESAMPLER_SHIFT_EXTRA; int i = SINC_WIDTH; if ( out + SINC_WIDTH * 2 > out_end ) @@ -513,7 +517,7 @@ static int resampler_run_blep_sse(resampler * r, float ** out_, float * out_end) for (; i >= -SINC_WIDTH + 1; --i) { int pos = i * step; - int abs_pos = abs(inv_phase - pos); + int abs_pos = abs(phase_reduced - pos); kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs_pos] * window_lut[abs_pos]; } sample = *in++ - last_amp; @@ -531,9 +535,9 @@ static int resampler_run_blep_sse(resampler * r, float ** out_, float * out_end) inv_phase += inv_phase_inc; - out += inv_phase >> RESAMPLER_SHIFT; + out += inv_phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - inv_phase &= RESAMPLER_RESOLUTION - 1; + inv_phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -571,14 +575,14 @@ static int resampler_run_linear(resampler * r, float ** out_, float * out_end) if ( out >= out_end ) break; - sample = in[0] + (in[1] - in[0]) * ((float)phase / RESAMPLER_RESOLUTION); + sample = in[0] + (in[1] - in[0]) * ((float)phase / RESAMPLER_RESOLUTION_EXTRA); *out++ = sample; phase += phase_inc; - in += phase >> RESAMPLER_SHIFT; + in += phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - phase &= RESAMPLER_RESOLUTION-1; + phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -616,7 +620,7 @@ static int resampler_run_cubic(resampler * r, float ** out_, float * out_end) if ( out >= out_end ) break; - kernel = cubic_lut + phase * 4; + kernel = cubic_lut + (phase >> RESAMPLER_SHIFT_EXTRA) * 4; for (sample = 0, i = 0; i < 4; ++i) sample += in[i] * kernel[i]; @@ -624,9 +628,9 @@ static int resampler_run_cubic(resampler * r, float ** out_, float * out_end) phase += phase_inc; - in += phase >> RESAMPLER_SHIFT; + in += phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - phase &= RESAMPLER_RESOLUTION-1; + phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -665,7 +669,7 @@ static int resampler_run_cubic_sse(resampler * r, float ** out_, float * out_end break; temp1 = _mm_loadu_ps( (const float *)( in ) ); - temp2 = _mm_load_ps( (const float *)( cubic_lut + phase * 4 ) ); + temp2 = _mm_load_ps( (const float *)( cubic_lut + (phase >> RESAMPLER_SHIFT_EXTRA) * 4 ) ); temp1 = _mm_mul_ps( temp1, temp2 ); samplex = _mm_add_ps( samplex, temp1 ); temp1 = _mm_movehl_ps( temp1, samplex ); @@ -678,9 +682,9 @@ static int resampler_run_cubic_sse(resampler * r, float ** out_, float * out_end phase += phase_inc; - in += phase >> RESAMPLER_SHIFT; + in += phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - phase &= RESAMPLER_RESOLUTION - 1; + phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -710,14 +714,15 @@ static int resampler_run_sinc(resampler * r, float ** out_, float * out_end) int phase = r->phase; int phase_inc = r->phase_inc; - int step = phase_inc > RESAMPLER_RESOLUTION ? RESAMPLER_RESOLUTION * RESAMPLER_RESOLUTION / phase_inc : RESAMPLER_RESOLUTION; + int step = phase_inc > RESAMPLER_RESOLUTION_EXTRA ? RESAMPLER_RESOLUTION * RESAMPLER_RESOLUTION_EXTRA / phase_inc : RESAMPLER_RESOLUTION; int window_step = RESAMPLER_RESOLUTION; do { float kernel[SINC_WIDTH * 2], kernel_sum = 0.0; int i = SINC_WIDTH; - int phase_adj = phase * step / RESAMPLER_RESOLUTION; + int phase_reduced = phase >> RESAMPLER_SHIFT_EXTRA; + int phase_adj = phase_reduced * step / RESAMPLER_RESOLUTION; float sample; if ( out >= out_end ) @@ -727,7 +732,7 @@ static int resampler_run_sinc(resampler * r, float ** out_, float * out_end) { int pos = i * step; int window_pos = i * window_step; - kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase - window_pos)]; + kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase_reduced - window_pos)]; } for (sample = 0, i = 0; i < SINC_WIDTH * 2; ++i) sample += in[i] * kernel[i]; @@ -735,9 +740,9 @@ static int resampler_run_sinc(resampler * r, float ** out_, float * out_end) phase += phase_inc; - in += phase >> RESAMPLER_SHIFT; + in += phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - phase &= RESAMPLER_RESOLUTION-1; + phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -767,7 +772,7 @@ static int resampler_run_sinc_sse(resampler * r, float ** out_, float * out_end) int phase = r->phase; int phase_inc = r->phase_inc; - int step = phase_inc > RESAMPLER_RESOLUTION ? RESAMPLER_RESOLUTION * RESAMPLER_RESOLUTION / phase_inc : RESAMPLER_RESOLUTION; + int step = phase_inc > RESAMPLER_RESOLUTION_EXTRA ? RESAMPLER_RESOLUTION * RESAMPLER_RESOLUTION_EXTRA / phase_inc : RESAMPLER_RESOLUTION; int window_step = RESAMPLER_RESOLUTION; do @@ -779,7 +784,8 @@ static int resampler_run_sinc_sse(resampler * r, float ** out_, float * out_end) __m128 samplex = _mm_setzero_ps(); float *kernelf = (float*)(&kernel); int i = SINC_WIDTH; - int phase_adj = phase * step / RESAMPLER_RESOLUTION; + int phase_reduced = phase >> RESAMPLER_SHIFT_EXTRA; + int phase_adj = phase_reduced * step / RESAMPLER_RESOLUTION; if ( out >= out_end ) break; @@ -788,7 +794,7 @@ static int resampler_run_sinc_sse(resampler * r, float ** out_, float * out_end) { int pos = i * step; int window_pos = i * window_step; - kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase - window_pos)]; + kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase_reduced - window_pos)]; } for (i = 0; i < SINC_WIDTH / 2; ++i) { @@ -810,9 +816,9 @@ static int resampler_run_sinc_sse(resampler * r, float ** out_, float * out_end) phase += phase_inc; - in += phase >> RESAMPLER_SHIFT; + in += phase >> (RESAMPLER_SHIFT + RESAMPLER_SHIFT_EXTRA); - phase &= RESAMPLER_RESOLUTION - 1; + phase &= RESAMPLER_RESOLUTION_EXTRA - 1; } while ( in < in_end ); @@ -911,7 +917,20 @@ int resampler_get_sample_count(void *_r) return r->read_filled; } -float resampler_get_sample(void *_r) +int resampler_get_sample(void *_r) +{ + resampler * r = ( resampler * ) _r; + if ( r->read_filled < 1 && r->phase_inc) + resampler_fill_and_remove_delay( r ); + if ( r->read_filled < 1 ) + return 0; + if ( r->quality == RESAMPLER_QUALITY_BLEP ) + return (int)(r->buffer_out[ r->read_pos ] + r->accumulator); + else + return (int)r->buffer_out[ r->read_pos ]; +} + +float resampler_get_sample_float(void *_r) { resampler * r = ( resampler * ) _r; if ( r->read_filled < 1 && r->phase_inc) diff --git a/Frameworks/modplay/modplay/resampler.h b/Frameworks/modplay/modplay/resampler.h index a725f7dd9..90a98714f 100644 --- a/Frameworks/modplay/modplay/resampler.h +++ b/Frameworks/modplay/modplay/resampler.h @@ -19,6 +19,7 @@ #define resampler_clear EVALUATE(RESAMPLER_DECORATE,_resampler_clear) #define resampler_get_sample_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_count) #define resampler_get_sample EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample) +#define resampler_get_sample_float EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_float) #define resampler_remove_sample EVALUATE(RESAMPLER_DECORATE,_resampler_remove_sample) #endif @@ -49,7 +50,8 @@ void resampler_set_rate( void *, double new_factor ); int resampler_ready(void *); void resampler_clear(void *); int resampler_get_sample_count(void *); -float resampler_get_sample(void *); +int resampler_get_sample(void *); +float resampler_get_sample_float(void *); void resampler_remove_sample(void *); #endif diff --git a/Frameworks/modplay/modplay/st3play.c b/Frameworks/modplay/modplay/st3play.c index 1aaa7ca8d..6de1a0a60 100644 --- a/Frameworks/modplay/modplay/st3play.c +++ b/Frameworks/modplay/modplay/st3play.c @@ -2961,7 +2961,7 @@ static inline void mix8b(PLAYER *p, uint8_t ch, uint32_t samples) while (interpolating && resampler_get_free_count(resampler)) { - resampler_write_sample(resampler, sampleData[samplePosition] * 256); + resampler_write_sample_fixed(resampler, sampleData[samplePosition], 8); ++samplePosition; @@ -2986,7 +2986,7 @@ static inline void mix8b(PLAYER *p, uint8_t ch, uint32_t samples) break; } - sample = resampler_get_sample(resampler); + sample = resampler_get_sample_float(resampler); resampler_remove_sample(resampler); sample *= volume; @@ -3102,8 +3102,8 @@ static inline void mix8bstereo(PLAYER *p, uint8_t ch, uint32_t samples) while (interpolating && resampler_get_free_count(resampler[0])) { - resampler_write_sample(resampler[0], sampleData[samplePosition] * 256); - resampler_write_sample(resampler[1], sampleData[sampleLength + samplePosition] * 256); + resampler_write_sample_fixed(resampler[0], sampleData[samplePosition], 8); + resampler_write_sample_fixed(resampler[1], sampleData[sampleLength + samplePosition], 8); ++samplePosition; @@ -3128,8 +3128,8 @@ static inline void mix8bstereo(PLAYER *p, uint8_t ch, uint32_t samples) break; } - sampleL = resampler_get_sample(resampler[0]); - sampleR = resampler_get_sample(resampler[1]); + sampleL = resampler_get_sample_float(resampler[0]); + sampleR = resampler_get_sample_float(resampler[1]); resampler_remove_sample(resampler[0]); resampler_remove_sample(resampler[1]); @@ -3240,7 +3240,7 @@ static inline void mix16b(PLAYER *p, uint8_t ch, uint32_t samples) while (interpolating && resampler_get_free_count(resampler)) { - resampler_write_sample(resampler, get_le16(&sampleData[samplePosition])); + resampler_write_sample_fixed(resampler, get_le16(&sampleData[samplePosition]), 16); ++samplePosition; @@ -3265,7 +3265,7 @@ static inline void mix16b(PLAYER *p, uint8_t ch, uint32_t samples) break; } - sample = resampler_get_sample(resampler); + sample = resampler_get_sample_float(resampler); resampler_remove_sample(resampler); sample *= volume; @@ -3381,8 +3381,8 @@ static inline void mix16bstereo(PLAYER *p, uint8_t ch, uint32_t samples) while (interpolating && resampler_get_free_count(resampler[0])) { - resampler_write_sample(resampler[0], get_le16(&sampleData[samplePosition])); - resampler_write_sample(resampler[1], get_le16(&sampleData[sampleLength + samplePosition])); + resampler_write_sample_fixed(resampler[0], get_le16(&sampleData[samplePosition]), 16); + resampler_write_sample_fixed(resampler[1], get_le16(&sampleData[sampleLength + samplePosition]), 16); ++samplePosition; @@ -3407,8 +3407,8 @@ static inline void mix16bstereo(PLAYER *p, uint8_t ch, uint32_t samples) break; } - sampleL = resampler_get_sample(resampler[0]); - sampleR = resampler_get_sample(resampler[1]); + sampleL = resampler_get_sample_float(resampler[0]); + sampleR = resampler_get_sample_float(resampler[1]); resampler_remove_sample(resampler[0]); resampler_remove_sample(resampler[1]); @@ -3539,9 +3539,9 @@ static inline void mixadpcm(PLAYER *p, uint8_t ch, uint32_t samples) while (interpolating && resampler_get_free_count(resampler)) { 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); - resampler_write_sample(resampler, sample); + resampler_write_sample_fixed(resampler, sample, 8); lastDelta = nextDelta; @@ -3576,7 +3576,7 @@ static inline void mixadpcm(PLAYER *p, uint8_t ch, uint32_t samples) break; } - sample = resampler_get_sample(resampler); + sample = resampler_get_sample_float(resampler); resampler_remove_sample(resampler); sample *= volume; @@ -3727,7 +3727,7 @@ static void st3play_AdlibMix(PLAYER *p, float *buffer, int32_t count) for (i = 0; i < outbuffer_avail; ++i) { - float sample = resampler_get_sample( p->fmResampler ); + float sample = resampler_get_sample_float( p->fmResampler ); resampler_remove_sample( p->fmResampler ); buffer[i * 2 + 0] += sample;