1575526ffSbeveloper /* Copyright (C) 2003 Marcus Overhagen 2575526ffSbeveloper * Released under terms of the MIT license. 3575526ffSbeveloper * 4575526ffSbeveloper * A simple resampling class for the audio mixer. 5c6a2e89fSStefano Ceccherini * You pick the conversion function on object creation, 6575526ffSbeveloper * and then call the Resample() function, specifying data pointer, 7575526ffSbeveloper * offset (in bytes) to the next sample, and count of samples for 8575526ffSbeveloper * both source and destination. 9575526ffSbeveloper * 10575526ffSbeveloper */ 11575526ffSbeveloper 12fb71d3a9Sbeveloper #include <MediaDefs.h> 13575526ffSbeveloper #include "Resampler.h" 14*f916862cSMarcus Overhagen #include "MixerDebug.h" 15575526ffSbeveloper 16ff14d245SJérôme Duval Resampler::Resampler(uint32 src_format, uint32 dst_format, int16 dst_valid_bits) 17575526ffSbeveloper : fFunc(0) 18575526ffSbeveloper { 19575526ffSbeveloper if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) { 20575526ffSbeveloper switch (src_format) { 21575526ffSbeveloper case media_raw_audio_format::B_AUDIO_FLOAT: 22575526ffSbeveloper fFunc = &Resampler::float_to_float; 23575526ffSbeveloper return; 24575526ffSbeveloper case media_raw_audio_format::B_AUDIO_INT: 25575526ffSbeveloper fFunc = &Resampler::int32_to_float; 26575526ffSbeveloper return; 27575526ffSbeveloper case media_raw_audio_format::B_AUDIO_SHORT: 28575526ffSbeveloper fFunc = &Resampler::int16_to_float; 29575526ffSbeveloper return; 30575526ffSbeveloper case media_raw_audio_format::B_AUDIO_CHAR: 31575526ffSbeveloper fFunc = &Resampler::int8_to_float; 32575526ffSbeveloper return; 33575526ffSbeveloper case media_raw_audio_format::B_AUDIO_UCHAR: 34575526ffSbeveloper fFunc = &Resampler::uint8_to_float; 35575526ffSbeveloper return; 36575526ffSbeveloper default: 37e6c7c99fSbeveloper ERROR("Resampler::Resampler: unknown source format 0x%x\n", src_format); 38575526ffSbeveloper return; 39575526ffSbeveloper } 40575526ffSbeveloper } 41575526ffSbeveloper 42575526ffSbeveloper if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) { 43575526ffSbeveloper switch (dst_format) { 44575526ffSbeveloper // float=>float already handled above 45575526ffSbeveloper case media_raw_audio_format::B_AUDIO_INT: 46ff14d245SJérôme Duval fFunc = &Resampler::float_to_int32_32; 47ff14d245SJérôme Duval if (dst_valid_bits == 24) 48ff14d245SJérôme Duval fFunc = &Resampler::float_to_int32_24; 49ebc67ddeSJérôme Duval else if (dst_valid_bits == 20) 50ebc67ddeSJérôme Duval fFunc = &Resampler::float_to_int32_20; 51575526ffSbeveloper return; 52575526ffSbeveloper case media_raw_audio_format::B_AUDIO_SHORT: 53575526ffSbeveloper fFunc = &Resampler::float_to_int16; 54575526ffSbeveloper return; 55575526ffSbeveloper case media_raw_audio_format::B_AUDIO_CHAR: 56575526ffSbeveloper fFunc = &Resampler::float_to_int8; 57575526ffSbeveloper return; 58575526ffSbeveloper case media_raw_audio_format::B_AUDIO_UCHAR: 59575526ffSbeveloper fFunc = &Resampler::float_to_uint8; 60575526ffSbeveloper return; 61575526ffSbeveloper default: 62e6c7c99fSbeveloper ERROR("Resampler::Resampler: unknown destination format 0x%x\n", dst_format); 63575526ffSbeveloper return; 64575526ffSbeveloper } 65575526ffSbeveloper } 66575526ffSbeveloper 67e6c7c99fSbeveloper ERROR("Resampler::Resampler: source or destination format must be B_AUDIO_FLOAT\n"); 68575526ffSbeveloper } 69575526ffSbeveloper 70575526ffSbeveloper Resampler::~Resampler() 71575526ffSbeveloper { 72575526ffSbeveloper } 73575526ffSbeveloper 74575526ffSbeveloper status_t 75575526ffSbeveloper Resampler::InitCheck() 76575526ffSbeveloper { 77575526ffSbeveloper return (fFunc != 0) ? B_OK : B_ERROR; 78575526ffSbeveloper } 79575526ffSbeveloper 80575526ffSbeveloper void 817ca83dacSbeveloper Resampler::float_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 827ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 837ca83dacSbeveloper { 847ca83dacSbeveloper register const char * src = (const char *) _src; 857ca83dacSbeveloper register char * dst = (char *) _dst; 867ca83dacSbeveloper register int32 count = dst_sample_count; 877ca83dacSbeveloper register float gain = _gain; 887ca83dacSbeveloper 897ca83dacSbeveloper if (src_sample_count == dst_sample_count) { 907ca83dacSbeveloper // optimized case for no resampling 917ca83dacSbeveloper while (count--) { 927ca83dacSbeveloper *(float *)dst = *(const float *)src * gain; 937ca83dacSbeveloper src += src_sample_offset; 947ca83dacSbeveloper dst += dst_sample_offset; 957ca83dacSbeveloper } 967ca83dacSbeveloper return; 977ca83dacSbeveloper } 987ca83dacSbeveloper 99fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 1007ca83dacSbeveloper register float current = 0.0f; 1017ca83dacSbeveloper 1027ca83dacSbeveloper if (delta < 1.0) { 1037ca83dacSbeveloper // upsample 1047ca83dacSbeveloper while (count--) { 1057ca83dacSbeveloper *(float *)dst = *(const float *)src * gain; 1067ca83dacSbeveloper dst += dst_sample_offset; 1077ca83dacSbeveloper current += delta; 1086b5e1508Sbeveloper if (current >= 1.0f) { 1097ca83dacSbeveloper current -= 1.0f; 1107ca83dacSbeveloper src += src_sample_offset; 1117ca83dacSbeveloper } 1127ca83dacSbeveloper } 1137ca83dacSbeveloper } else { 1147ca83dacSbeveloper // downsample 1157ca83dacSbeveloper while (count--) { 1167ca83dacSbeveloper *(float *)dst = *(const float *)src * gain; 1177ca83dacSbeveloper dst += dst_sample_offset; 1186b5e1508Sbeveloper current += delta; 1196b5e1508Sbeveloper register int32 skipcount = (int32)current; 1206b5e1508Sbeveloper current -= skipcount; 1216b5e1508Sbeveloper src += skipcount * src_sample_offset; 1227ca83dacSbeveloper } 1237ca83dacSbeveloper } 1247ca83dacSbeveloper } 1257ca83dacSbeveloper 1267ca83dacSbeveloper void 1277ca83dacSbeveloper Resampler::int32_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 1287ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 129575526ffSbeveloper { 13088e430cbSbeveloper register const char * src = (const char *) _src; 13188e430cbSbeveloper register char * dst = (char *) _dst; 13288e430cbSbeveloper register int32 count = dst_sample_count; 13388e430cbSbeveloper register float gain = _gain / 2147483647.0; 13488e430cbSbeveloper 13588e430cbSbeveloper if (src_sample_count == dst_sample_count) { 13688e430cbSbeveloper // optimized case for no resampling 13788e430cbSbeveloper while (count--) { 13888e430cbSbeveloper *(float *)dst = *(const int32 *)src * gain; 13988e430cbSbeveloper src += src_sample_offset; 14088e430cbSbeveloper dst += dst_sample_offset; 14188e430cbSbeveloper } 14288e430cbSbeveloper return; 14388e430cbSbeveloper } 14488e430cbSbeveloper 145fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 14688e430cbSbeveloper register float current = 0.0f; 14788e430cbSbeveloper 14888e430cbSbeveloper if (delta < 1.0) { 14988e430cbSbeveloper // upsample 15088e430cbSbeveloper while (count--) { 15188e430cbSbeveloper *(float *)dst = *(const int32 *)src * gain; 15288e430cbSbeveloper dst += dst_sample_offset; 15388e430cbSbeveloper current += delta; 1546b5e1508Sbeveloper if (current >= 1.0f) { 15588e430cbSbeveloper current -= 1.0f; 15688e430cbSbeveloper src += src_sample_offset; 15788e430cbSbeveloper } 15888e430cbSbeveloper } 15988e430cbSbeveloper } else { 16088e430cbSbeveloper // downsample 16188e430cbSbeveloper while (count--) { 16288e430cbSbeveloper *(float *)dst = *(const int32 *)src * gain; 16388e430cbSbeveloper dst += dst_sample_offset; 1646b5e1508Sbeveloper current += delta; 1656b5e1508Sbeveloper register int32 skipcount = (int32)current; 1666b5e1508Sbeveloper current -= skipcount; 1676b5e1508Sbeveloper src += skipcount * src_sample_offset; 16888e430cbSbeveloper } 16988e430cbSbeveloper } 170575526ffSbeveloper } 171575526ffSbeveloper 172575526ffSbeveloper void 1737ca83dacSbeveloper Resampler::int16_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 1747ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 175575526ffSbeveloper { 17688e430cbSbeveloper register const char * src = (const char *) _src; 17788e430cbSbeveloper register char * dst = (char *) _dst; 17888e430cbSbeveloper register int32 count = dst_sample_count; 17988e430cbSbeveloper register float gain = _gain / 32767.0; 18088e430cbSbeveloper 18188e430cbSbeveloper if (src_sample_count == dst_sample_count) { 18288e430cbSbeveloper // optimized case for no resampling 18388e430cbSbeveloper while (count--) { 18488e430cbSbeveloper *(float *)dst = *(const int16 *)src * gain; 18588e430cbSbeveloper src += src_sample_offset; 18688e430cbSbeveloper dst += dst_sample_offset; 18788e430cbSbeveloper } 18888e430cbSbeveloper return; 18988e430cbSbeveloper } 19088e430cbSbeveloper 191fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 19288e430cbSbeveloper register float current = 0.0f; 19388e430cbSbeveloper 19488e430cbSbeveloper if (delta < 1.0) { 19588e430cbSbeveloper // upsample 19688e430cbSbeveloper while (count--) { 19788e430cbSbeveloper *(float *)dst = *(const int16 *)src * gain; 19888e430cbSbeveloper dst += dst_sample_offset; 19988e430cbSbeveloper current += delta; 2006b5e1508Sbeveloper if (current >= 1.0f) { 20188e430cbSbeveloper current -= 1.0f; 20288e430cbSbeveloper src += src_sample_offset; 20388e430cbSbeveloper } 20488e430cbSbeveloper } 20588e430cbSbeveloper } else { 20688e430cbSbeveloper // downsample 20788e430cbSbeveloper while (count--) { 20888e430cbSbeveloper *(float *)dst = *(const int16 *)src * gain; 20988e430cbSbeveloper dst += dst_sample_offset; 2106b5e1508Sbeveloper current += delta; 2116b5e1508Sbeveloper register int32 skipcount = (int32)current; 2126b5e1508Sbeveloper current -= skipcount; 2136b5e1508Sbeveloper src += skipcount * src_sample_offset; 21488e430cbSbeveloper } 21588e430cbSbeveloper } 216575526ffSbeveloper } 217575526ffSbeveloper 218575526ffSbeveloper void 2197ca83dacSbeveloper Resampler::int8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 2207ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 221575526ffSbeveloper { 22288e430cbSbeveloper register const char * src = (const char *) _src; 22388e430cbSbeveloper register char * dst = (char *) _dst; 22488e430cbSbeveloper register int32 count = dst_sample_count; 22588e430cbSbeveloper register float gain = _gain / 127.0; 22688e430cbSbeveloper 22788e430cbSbeveloper if (src_sample_count == dst_sample_count) { 22888e430cbSbeveloper // optimized case for no resampling 22988e430cbSbeveloper while (count--) { 23088e430cbSbeveloper *(float *)dst = *(const int8 *)src * gain; 23188e430cbSbeveloper src += src_sample_offset; 23288e430cbSbeveloper dst += dst_sample_offset; 23388e430cbSbeveloper } 23488e430cbSbeveloper return; 23588e430cbSbeveloper } 23688e430cbSbeveloper 237fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 23888e430cbSbeveloper register float current = 0.0f; 23988e430cbSbeveloper 24088e430cbSbeveloper if (delta < 1.0) { 24188e430cbSbeveloper // upsample 24288e430cbSbeveloper while (count--) { 24388e430cbSbeveloper *(float *)dst = *(const int8 *)src * gain; 24488e430cbSbeveloper dst += dst_sample_offset; 24588e430cbSbeveloper current += delta; 2466b5e1508Sbeveloper if (current >= 1.0f) { 24788e430cbSbeveloper current -= 1.0f; 24888e430cbSbeveloper src += src_sample_offset; 24988e430cbSbeveloper } 25088e430cbSbeveloper } 25188e430cbSbeveloper } else { 25288e430cbSbeveloper // downsample 25388e430cbSbeveloper while (count--) { 25488e430cbSbeveloper *(float *)dst = *(const int8 *)src * gain; 25588e430cbSbeveloper dst += dst_sample_offset; 2566b5e1508Sbeveloper current += delta; 2576b5e1508Sbeveloper register int32 skipcount = (int32)current; 2586b5e1508Sbeveloper current -= skipcount; 2596b5e1508Sbeveloper src += skipcount * src_sample_offset; 26088e430cbSbeveloper } 26188e430cbSbeveloper } 262575526ffSbeveloper } 263575526ffSbeveloper 264575526ffSbeveloper void 2657ca83dacSbeveloper Resampler::uint8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 2667ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 267575526ffSbeveloper { 26888e430cbSbeveloper register const char * src = (const char *) _src; 26988e430cbSbeveloper register char * dst = (char *) _dst; 27088e430cbSbeveloper register int32 count = dst_sample_count; 27188e430cbSbeveloper register float gain = _gain / 127.0; 27288e430cbSbeveloper 27388e430cbSbeveloper if (src_sample_count == dst_sample_count) { 27488e430cbSbeveloper // optimized case for no resampling 27588e430cbSbeveloper while (count--) { 27688e430cbSbeveloper *(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; 27788e430cbSbeveloper src += src_sample_offset; 27888e430cbSbeveloper dst += dst_sample_offset; 27988e430cbSbeveloper } 28088e430cbSbeveloper return; 28188e430cbSbeveloper } 28288e430cbSbeveloper 283fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 28488e430cbSbeveloper register float current = 0.0f; 28588e430cbSbeveloper 28688e430cbSbeveloper if (delta < 1.0) { 28788e430cbSbeveloper // upsample 28888e430cbSbeveloper while (count--) { 28988e430cbSbeveloper *(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; 29088e430cbSbeveloper dst += dst_sample_offset; 29188e430cbSbeveloper current += delta; 2926b5e1508Sbeveloper if (current >= 1.0f) { 29388e430cbSbeveloper current -= 1.0f; 29488e430cbSbeveloper src += src_sample_offset; 29588e430cbSbeveloper } 29688e430cbSbeveloper } 29788e430cbSbeveloper } else { 29888e430cbSbeveloper // downsample 29988e430cbSbeveloper while (count--) { 30088e430cbSbeveloper *(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; 30188e430cbSbeveloper dst += dst_sample_offset; 3026b5e1508Sbeveloper current += delta; 3036b5e1508Sbeveloper register int32 skipcount = (int32)current; 3046b5e1508Sbeveloper current -= skipcount; 3056b5e1508Sbeveloper src += skipcount * src_sample_offset; 30688e430cbSbeveloper } 30788e430cbSbeveloper } 308575526ffSbeveloper } 309575526ffSbeveloper 310575526ffSbeveloper void 311ff14d245SJérôme Duval Resampler::float_to_int32_32(const void *_src, int32 src_sample_offset, int32 src_sample_count, 3127ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 313575526ffSbeveloper { 3149b875fbaSbeveloper register const char * src = (const char *) _src; 3159b875fbaSbeveloper register char * dst = (char *) _dst; 3169b875fbaSbeveloper register int32 count = dst_sample_count; 3179b875fbaSbeveloper register float gain = _gain * 2147483647.0; 3189b875fbaSbeveloper 3199b875fbaSbeveloper if (src_sample_count == dst_sample_count) { 3209b875fbaSbeveloper // optimized case for no resampling 3219b875fbaSbeveloper while (count--) { 3229b875fbaSbeveloper register float sample = *(const float *)src * gain; 3239b875fbaSbeveloper if (sample > 2147483647.0f) 3249b875fbaSbeveloper *(int32 *)dst = 2147483647L; 3259b875fbaSbeveloper else if (sample < -2147483647.0f) 3269b875fbaSbeveloper *(int32 *)dst = -2147483647L; 3279b875fbaSbeveloper else 3289b875fbaSbeveloper *(int32 *)dst = (int32)sample; 3299b875fbaSbeveloper src += src_sample_offset; 3309b875fbaSbeveloper dst += dst_sample_offset; 3319b875fbaSbeveloper } 3329b875fbaSbeveloper return; 3339b875fbaSbeveloper } 3349b875fbaSbeveloper 335fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 3369b875fbaSbeveloper register float current = 0.0f; 3379b875fbaSbeveloper 3389b875fbaSbeveloper if (delta < 1.0) { 3399b875fbaSbeveloper // upsample 3409b875fbaSbeveloper while (count--) { 3419b875fbaSbeveloper register float sample = *(const float *)src * gain; 3429b875fbaSbeveloper if (sample > 2147483647.0f) 3439b875fbaSbeveloper *(int32 *)dst = 2147483647L; 3449b875fbaSbeveloper else if (sample < -2147483647.0f) 3459b875fbaSbeveloper *(int32 *)dst = -2147483647L; 3469b875fbaSbeveloper else 3479b875fbaSbeveloper *(int32 *)dst = (int32)sample; 3489b875fbaSbeveloper dst += dst_sample_offset; 3499b875fbaSbeveloper current += delta; 3506b5e1508Sbeveloper if (current >= 1.0f) { 3519b875fbaSbeveloper current -= 1.0f; 3529b875fbaSbeveloper src += src_sample_offset; 3539b875fbaSbeveloper } 3549b875fbaSbeveloper } 3559b875fbaSbeveloper } else { 3569b875fbaSbeveloper // downsample 3579b875fbaSbeveloper while (count--) { 3589b875fbaSbeveloper register float sample = *(const float *)src * gain; 3599b875fbaSbeveloper if (sample > 2147483647.0f) 3609b875fbaSbeveloper *(int32 *)dst = 2147483647L; 3619b875fbaSbeveloper else if (sample < -2147483647.0f) 3629b875fbaSbeveloper *(int32 *)dst = -2147483647L; 3639b875fbaSbeveloper else 3649b875fbaSbeveloper *(int32 *)dst = (int32)sample; 3659b875fbaSbeveloper dst += dst_sample_offset; 3666b5e1508Sbeveloper current += delta; 3676b5e1508Sbeveloper register int32 skipcount = (int32)current; 3686b5e1508Sbeveloper current -= skipcount; 3696b5e1508Sbeveloper src += skipcount * src_sample_offset; 3709b875fbaSbeveloper } 3719b875fbaSbeveloper } 372575526ffSbeveloper } 373575526ffSbeveloper 374ff14d245SJérôme Duval 375ff14d245SJérôme Duval void 376ff14d245SJérôme Duval Resampler::float_to_int32_24(const void *_src, int32 src_sample_offset, int32 src_sample_count, 377ff14d245SJérôme Duval void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 378ff14d245SJérôme Duval { 379ff14d245SJérôme Duval register const char * src = (const char *) _src; 380ff14d245SJérôme Duval register char * dst = (char *) _dst; 381ff14d245SJérôme Duval register int32 count = dst_sample_count; 382ff14d245SJérôme Duval register float gain = _gain * 8388607.0; 383ff14d245SJérôme Duval 384ff14d245SJérôme Duval if (src_sample_count == dst_sample_count) { 385ff14d245SJérôme Duval // optimized case for no resampling 386ff14d245SJérôme Duval while (count--) { 387ff14d245SJérôme Duval register float sample = *(const float *)src * gain; 388ff14d245SJérôme Duval if (sample > 8388607.0f) 389ff14d245SJérôme Duval *(int32 *)dst = 8388607L; 390ebc67ddeSJérôme Duval else if (sample < -8388607.0f) 391ff14d245SJérôme Duval *(int32 *)dst = -8388607L; 392ff14d245SJérôme Duval else 393ff14d245SJérôme Duval *(int32 *)dst = (int32)sample; 394ff14d245SJérôme Duval src += src_sample_offset; 395ff14d245SJérôme Duval dst += dst_sample_offset; 396ff14d245SJérôme Duval } 397ff14d245SJérôme Duval return; 398ff14d245SJérôme Duval } 399ff14d245SJérôme Duval 400ff14d245SJérôme Duval register float delta = float(src_sample_count) / float(dst_sample_count); 401ff14d245SJérôme Duval register float current = 0.0f; 402ff14d245SJérôme Duval 403ff14d245SJérôme Duval if (delta < 1.0) { 404ff14d245SJérôme Duval // upsample 405ff14d245SJérôme Duval while (count--) { 406ff14d245SJérôme Duval register float sample = *(const float *)src * gain; 407ff14d245SJérôme Duval if (sample > 8388607.0f) 408ff14d245SJérôme Duval *(int32 *)dst = 8388607L; 409ff14d245SJérôme Duval else if (sample < -8388607.0f) 410ff14d245SJérôme Duval *(int32 *)dst = -8388607L; 411ff14d245SJérôme Duval else 412ff14d245SJérôme Duval *(int32 *)dst = (int32)sample; 413ff14d245SJérôme Duval dst += dst_sample_offset; 414ff14d245SJérôme Duval current += delta; 415ff14d245SJérôme Duval if (current >= 1.0f) { 416ff14d245SJérôme Duval current -= 1.0f; 417ff14d245SJérôme Duval src += src_sample_offset; 418ff14d245SJérôme Duval } 419ff14d245SJérôme Duval } 420ff14d245SJérôme Duval } else { 421ff14d245SJérôme Duval // downsample 422ff14d245SJérôme Duval while (count--) { 423ff14d245SJérôme Duval register float sample = *(const float *)src * gain; 424ff14d245SJérôme Duval if (sample > 8388607.0f) 425ff14d245SJérôme Duval *(int32 *)dst = 8388607L; 426ff14d245SJérôme Duval else if (sample < -8388607.0f) 427ff14d245SJérôme Duval *(int32 *)dst = -8388607L; 428ff14d245SJérôme Duval else 429ff14d245SJérôme Duval *(int32 *)dst = (int32)sample; 430ff14d245SJérôme Duval dst += dst_sample_offset; 431ff14d245SJérôme Duval current += delta; 432ff14d245SJérôme Duval register int32 skipcount = (int32)current; 433ff14d245SJérôme Duval current -= skipcount; 434ff14d245SJérôme Duval src += skipcount * src_sample_offset; 435ff14d245SJérôme Duval } 436ff14d245SJérôme Duval } 437ff14d245SJérôme Duval } 438ff14d245SJérôme Duval 439ff14d245SJérôme Duval 440575526ffSbeveloper void 441ebc67ddeSJérôme Duval Resampler::float_to_int32_20(const void *_src, int32 src_sample_offset, int32 src_sample_count, 442ebc67ddeSJérôme Duval void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 443ebc67ddeSJérôme Duval { 444ebc67ddeSJérôme Duval register const char * src = (const char *) _src; 445ebc67ddeSJérôme Duval register char * dst = (char *) _dst; 446ebc67ddeSJérôme Duval register int32 count = dst_sample_count; 447ebc67ddeSJérôme Duval register float gain = _gain * 524287.0; 448ebc67ddeSJérôme Duval 449ebc67ddeSJérôme Duval if (src_sample_count == dst_sample_count) { 450ebc67ddeSJérôme Duval // optimized case for no resampling 451ebc67ddeSJérôme Duval while (count--) { 452ebc67ddeSJérôme Duval register float sample = *(const float *)src * gain; 453ebc67ddeSJérôme Duval if (sample > 524287.0f) 454ebc67ddeSJérôme Duval *(int32 *)dst = 524287L; 455ebc67ddeSJérôme Duval else if (sample < -524287.0f) 456ebc67ddeSJérôme Duval *(int32 *)dst = -524287L; 457ebc67ddeSJérôme Duval else 458ebc67ddeSJérôme Duval *(int32 *)dst = (int32)sample; 459ebc67ddeSJérôme Duval src += src_sample_offset; 460ebc67ddeSJérôme Duval dst += dst_sample_offset; 461ebc67ddeSJérôme Duval } 462ebc67ddeSJérôme Duval return; 463ebc67ddeSJérôme Duval } 464ebc67ddeSJérôme Duval 465ebc67ddeSJérôme Duval register float delta = float(src_sample_count) / float(dst_sample_count); 466ebc67ddeSJérôme Duval register float current = 0.0f; 467ebc67ddeSJérôme Duval 468ebc67ddeSJérôme Duval if (delta < 1.0) { 469ebc67ddeSJérôme Duval // upsample 470ebc67ddeSJérôme Duval while (count--) { 471ebc67ddeSJérôme Duval register float sample = *(const float *)src * gain; 472ebc67ddeSJérôme Duval if (sample > 524287.0f) 473ebc67ddeSJérôme Duval *(int32 *)dst = 524287L; 474ebc67ddeSJérôme Duval else if (sample < -524287.0f) 475ebc67ddeSJérôme Duval *(int32 *)dst = -524287L; 476ebc67ddeSJérôme Duval else 477ebc67ddeSJérôme Duval *(int32 *)dst = (int32)sample; 478ebc67ddeSJérôme Duval dst += dst_sample_offset; 479ebc67ddeSJérôme Duval current += delta; 480ebc67ddeSJérôme Duval if (current >= 1.0f) { 481ebc67ddeSJérôme Duval current -= 1.0f; 482ebc67ddeSJérôme Duval src += src_sample_offset; 483ebc67ddeSJérôme Duval } 484ebc67ddeSJérôme Duval } 485ebc67ddeSJérôme Duval } else { 486ebc67ddeSJérôme Duval // downsample 487ebc67ddeSJérôme Duval while (count--) { 488ebc67ddeSJérôme Duval register float sample = *(const float *)src * gain; 489ebc67ddeSJérôme Duval if (sample > 524287.0f) 490ebc67ddeSJérôme Duval *(int32 *)dst = 524287L; 491ebc67ddeSJérôme Duval else if (sample < -524287.0f) 492ebc67ddeSJérôme Duval *(int32 *)dst = -524287L; 493ebc67ddeSJérôme Duval else 494ebc67ddeSJérôme Duval *(int32 *)dst = (int32)sample; 495ebc67ddeSJérôme Duval dst += dst_sample_offset; 496ebc67ddeSJérôme Duval current += delta; 497ebc67ddeSJérôme Duval register int32 skipcount = (int32)current; 498ebc67ddeSJérôme Duval current -= skipcount; 499ebc67ddeSJérôme Duval src += skipcount * src_sample_offset; 500ebc67ddeSJérôme Duval } 501ebc67ddeSJérôme Duval } 502ebc67ddeSJérôme Duval } 503ebc67ddeSJérôme Duval 504ebc67ddeSJérôme Duval 505ebc67ddeSJérôme Duval void 5067ca83dacSbeveloper Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_sample_count, 5077ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 508575526ffSbeveloper { 5099b875fbaSbeveloper register const char * src = (const char *) _src; 5109b875fbaSbeveloper register char * dst = (char *) _dst; 5119b875fbaSbeveloper register int32 count = dst_sample_count; 5129b875fbaSbeveloper register float gain = _gain * 32767.0; 5139b875fbaSbeveloper 5149b875fbaSbeveloper if (src_sample_count == dst_sample_count) { 5159b875fbaSbeveloper // optimized case for no resampling 5169b875fbaSbeveloper while (count--) { 5179b875fbaSbeveloper register float sample = *(const float *)src * gain; 5189b875fbaSbeveloper if (sample > 32767.0f) 5199b875fbaSbeveloper *(int16 *)dst = 32767; 5209b875fbaSbeveloper else if (sample < -32767.0f) 5219b875fbaSbeveloper *(int16 *)dst = -32767; 5229b875fbaSbeveloper else 5239b875fbaSbeveloper *(int16 *)dst = (int16)sample; 5249b875fbaSbeveloper src += src_sample_offset; 5259b875fbaSbeveloper dst += dst_sample_offset; 5269b875fbaSbeveloper } 5279b875fbaSbeveloper return; 5289b875fbaSbeveloper } 5299b875fbaSbeveloper 530fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 5319b875fbaSbeveloper register float current = 0.0f; 5329b875fbaSbeveloper 5339b875fbaSbeveloper if (delta < 1.0) { 5349b875fbaSbeveloper // upsample 5359b875fbaSbeveloper while (count--) { 5369b875fbaSbeveloper register float sample = *(const float *)src * gain; 5379b875fbaSbeveloper if (sample > 32767.0f) 5389b875fbaSbeveloper *(int16 *)dst = 32767; 5399b875fbaSbeveloper else if (sample < -32767.0f) 5409b875fbaSbeveloper *(int16 *)dst = -32767; 5419b875fbaSbeveloper else 5429b875fbaSbeveloper *(int16 *)dst = (int16)sample; 5439b875fbaSbeveloper dst += dst_sample_offset; 5449b875fbaSbeveloper current += delta; 5456b5e1508Sbeveloper if (current >= 1.0f) { 5469b875fbaSbeveloper current -= 1.0f; 5479b875fbaSbeveloper src += src_sample_offset; 5489b875fbaSbeveloper } 5499b875fbaSbeveloper } 5509b875fbaSbeveloper } else { 5519b875fbaSbeveloper // downsample 5529b875fbaSbeveloper while (count--) { 5539b875fbaSbeveloper register float sample = *(const float *)src * gain; 5549b875fbaSbeveloper if (sample > 32767.0f) 5559b875fbaSbeveloper *(int16 *)dst = 32767; 5569b875fbaSbeveloper else if (sample < -32767.0f) 5579b875fbaSbeveloper *(int16 *)dst = -32767; 5589b875fbaSbeveloper else 5599b875fbaSbeveloper *(int16 *)dst = (int16)sample; 5609b875fbaSbeveloper dst += dst_sample_offset; 5616b5e1508Sbeveloper current += delta; 5626b5e1508Sbeveloper register int32 skipcount = (int32)current; 5636b5e1508Sbeveloper current -= skipcount; 5646b5e1508Sbeveloper src += skipcount * src_sample_offset; 5659b875fbaSbeveloper } 5669b875fbaSbeveloper } 567575526ffSbeveloper } 568575526ffSbeveloper 569575526ffSbeveloper void 5709b875fbaSbeveloper Resampler::float_to_int8(const void *_src, int32 src_sample_offset, int32 src_sample_count, 5717ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 572575526ffSbeveloper { 5739b875fbaSbeveloper register const char * src = (const char *) _src; 5749b875fbaSbeveloper register char * dst = (char *) _dst; 5759b875fbaSbeveloper register int32 count = dst_sample_count; 5769b875fbaSbeveloper register float gain = _gain * 127.0; 5779b875fbaSbeveloper 5789b875fbaSbeveloper if (src_sample_count == dst_sample_count) { 5799b875fbaSbeveloper // optimized case for no resampling 5809b875fbaSbeveloper while (count--) { 5819b875fbaSbeveloper register float sample = *(const float *)src * gain; 5829b875fbaSbeveloper if (sample > 127.0f) 5839b875fbaSbeveloper *(int8 *)dst = 127; 5849b875fbaSbeveloper else if (sample < -127.0f) 5859b875fbaSbeveloper *(int8 *)dst = -127; 5869b875fbaSbeveloper else 5879b875fbaSbeveloper *(int8 *)dst = (int8)sample; 5889b875fbaSbeveloper src += src_sample_offset; 5899b875fbaSbeveloper dst += dst_sample_offset; 5909b875fbaSbeveloper } 5919b875fbaSbeveloper return; 5929b875fbaSbeveloper } 5939b875fbaSbeveloper 594fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 5959b875fbaSbeveloper register float current = 0.0f; 5969b875fbaSbeveloper 5979b875fbaSbeveloper if (delta < 1.0) { 5989b875fbaSbeveloper // upsample 5999b875fbaSbeveloper while (count--) { 6009b875fbaSbeveloper register float sample = *(const float *)src * gain; 6019b875fbaSbeveloper if (sample > 127.0f) 6029b875fbaSbeveloper *(int8 *)dst = 127; 6039b875fbaSbeveloper else if (sample < -127.0f) 6049b875fbaSbeveloper *(int8 *)dst = -127; 6059b875fbaSbeveloper else 6069b875fbaSbeveloper *(int8 *)dst = (int8)sample; 6079b875fbaSbeveloper dst += dst_sample_offset; 6089b875fbaSbeveloper current += delta; 6096b5e1508Sbeveloper if (current >= 1.0f) { 6109b875fbaSbeveloper current -= 1.0f; 6119b875fbaSbeveloper src += src_sample_offset; 6129b875fbaSbeveloper } 6139b875fbaSbeveloper } 6149b875fbaSbeveloper } else { 6159b875fbaSbeveloper // downsample 6169b875fbaSbeveloper while (count--) { 6179b875fbaSbeveloper register float sample = *(const float *)src * gain; 6189b875fbaSbeveloper if (sample > 127.0f) 6199b875fbaSbeveloper *(int8 *)dst = 127; 6209b875fbaSbeveloper else if (sample < -127.0f) 6219b875fbaSbeveloper *(int8 *)dst = -127; 6229b875fbaSbeveloper else 6239b875fbaSbeveloper *(int8 *)dst = (int8)sample; 6249b875fbaSbeveloper dst += dst_sample_offset; 6256b5e1508Sbeveloper current += delta; 6266b5e1508Sbeveloper register int32 skipcount = (int32)current; 6276b5e1508Sbeveloper current -= skipcount; 6286b5e1508Sbeveloper src += skipcount * src_sample_offset; 6299b875fbaSbeveloper } 6309b875fbaSbeveloper } 631575526ffSbeveloper } 632575526ffSbeveloper 633575526ffSbeveloper void 6347ca83dacSbeveloper Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_sample_count, 6357ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 636575526ffSbeveloper { 6379b875fbaSbeveloper register const char * src = (const char *) _src; 6389b875fbaSbeveloper register char * dst = (char *) _dst; 6399b875fbaSbeveloper register int32 count = dst_sample_count; 6409b875fbaSbeveloper register float gain = _gain * 127.0; 6419b875fbaSbeveloper 6429b875fbaSbeveloper if (src_sample_count == dst_sample_count) { 6439b875fbaSbeveloper // optimized case for no resampling 6449b875fbaSbeveloper while (count--) { 6459b875fbaSbeveloper register float sample = 128.0f + *(const float *)src * gain; 6469b875fbaSbeveloper if (sample > 255.0f) 6479b875fbaSbeveloper *(uint8 *)dst = 255; 6489b875fbaSbeveloper else if (sample < 1.0f) 6499b875fbaSbeveloper *(uint8 *)dst = 1; 6509b875fbaSbeveloper else 6519b875fbaSbeveloper *(uint8 *)dst = (uint8)sample; 6529b875fbaSbeveloper src += src_sample_offset; 6539b875fbaSbeveloper dst += dst_sample_offset; 654575526ffSbeveloper } 6559b875fbaSbeveloper return; 6569b875fbaSbeveloper } 6579b875fbaSbeveloper 658fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 6599b875fbaSbeveloper register float current = 0.0f; 6609b875fbaSbeveloper 6619b875fbaSbeveloper if (delta < 1.0) { 6629b875fbaSbeveloper // upsample 6639b875fbaSbeveloper while (count--) { 6649b875fbaSbeveloper register float sample = 128.0f + *(const float *)src * gain; 6659b875fbaSbeveloper if (sample > 255.0f) 6669b875fbaSbeveloper *(uint8 *)dst = 255; 6679b875fbaSbeveloper else if (sample < 1.0f) 6689b875fbaSbeveloper *(uint8 *)dst = 1; 6699b875fbaSbeveloper else 6709b875fbaSbeveloper *(uint8 *)dst = (uint8)sample; 6719b875fbaSbeveloper dst += dst_sample_offset; 6729b875fbaSbeveloper current += delta; 6736b5e1508Sbeveloper if (current >= 1.0f) { 6749b875fbaSbeveloper current -= 1.0f; 6759b875fbaSbeveloper src += src_sample_offset; 6769b875fbaSbeveloper } 6779b875fbaSbeveloper } 6789b875fbaSbeveloper } else { 6799b875fbaSbeveloper // downsample 6809b875fbaSbeveloper while (count--) { 6819b875fbaSbeveloper register float sample = 128.0f + *(const float *)src * gain; 6829b875fbaSbeveloper if (sample > 255.0f) 6839b875fbaSbeveloper *(uint8 *)dst = 255; 6849b875fbaSbeveloper else if (sample < 1.0f) 6859b875fbaSbeveloper *(uint8 *)dst = 1; 6869b875fbaSbeveloper else 6879b875fbaSbeveloper *(uint8 *)dst = (uint8)sample; 6889b875fbaSbeveloper dst += dst_sample_offset; 6896b5e1508Sbeveloper current += delta; 6906b5e1508Sbeveloper register int32 skipcount = (int32)current; 6916b5e1508Sbeveloper current -= skipcount; 6926b5e1508Sbeveloper src += skipcount * src_sample_offset; 6939b875fbaSbeveloper } 6949b875fbaSbeveloper } 6959b875fbaSbeveloper } 696