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" 14f916862cSMarcus Overhagen #include "MixerDebug.h" 15575526ffSbeveloper 16*f0a85f97SJérôme Duval Resampler::Resampler(uint32 src_format, uint32 dst_format) 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: 46*f0a85f97SJérôme Duval fFunc = &Resampler::float_to_int32; 47575526ffSbeveloper return; 48575526ffSbeveloper case media_raw_audio_format::B_AUDIO_SHORT: 49575526ffSbeveloper fFunc = &Resampler::float_to_int16; 50575526ffSbeveloper return; 51575526ffSbeveloper case media_raw_audio_format::B_AUDIO_CHAR: 52575526ffSbeveloper fFunc = &Resampler::float_to_int8; 53575526ffSbeveloper return; 54575526ffSbeveloper case media_raw_audio_format::B_AUDIO_UCHAR: 55575526ffSbeveloper fFunc = &Resampler::float_to_uint8; 56575526ffSbeveloper return; 57575526ffSbeveloper default: 58e6c7c99fSbeveloper ERROR("Resampler::Resampler: unknown destination format 0x%x\n", dst_format); 59575526ffSbeveloper return; 60575526ffSbeveloper } 61575526ffSbeveloper } 62575526ffSbeveloper 63e6c7c99fSbeveloper ERROR("Resampler::Resampler: source or destination format must be B_AUDIO_FLOAT\n"); 64575526ffSbeveloper } 65575526ffSbeveloper 66575526ffSbeveloper Resampler::~Resampler() 67575526ffSbeveloper { 68575526ffSbeveloper } 69575526ffSbeveloper 70575526ffSbeveloper status_t 71575526ffSbeveloper Resampler::InitCheck() 72575526ffSbeveloper { 73575526ffSbeveloper return (fFunc != 0) ? B_OK : B_ERROR; 74575526ffSbeveloper } 75575526ffSbeveloper 76575526ffSbeveloper void 777ca83dacSbeveloper Resampler::float_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 787ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 797ca83dacSbeveloper { 807ca83dacSbeveloper register const char * src = (const char *) _src; 817ca83dacSbeveloper register char * dst = (char *) _dst; 827ca83dacSbeveloper register int32 count = dst_sample_count; 837ca83dacSbeveloper register float gain = _gain; 847ca83dacSbeveloper 857ca83dacSbeveloper if (src_sample_count == dst_sample_count) { 867ca83dacSbeveloper // optimized case for no resampling 877ca83dacSbeveloper while (count--) { 887ca83dacSbeveloper *(float *)dst = *(const float *)src * gain; 897ca83dacSbeveloper src += src_sample_offset; 907ca83dacSbeveloper dst += dst_sample_offset; 917ca83dacSbeveloper } 927ca83dacSbeveloper return; 937ca83dacSbeveloper } 947ca83dacSbeveloper 95fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 967ca83dacSbeveloper register float current = 0.0f; 977ca83dacSbeveloper 987ca83dacSbeveloper if (delta < 1.0) { 997ca83dacSbeveloper // upsample 1007ca83dacSbeveloper while (count--) { 1017ca83dacSbeveloper *(float *)dst = *(const float *)src * gain; 1027ca83dacSbeveloper dst += dst_sample_offset; 1037ca83dacSbeveloper current += delta; 1046b5e1508Sbeveloper if (current >= 1.0f) { 1057ca83dacSbeveloper current -= 1.0f; 1067ca83dacSbeveloper src += src_sample_offset; 1077ca83dacSbeveloper } 1087ca83dacSbeveloper } 1097ca83dacSbeveloper } else { 1107ca83dacSbeveloper // downsample 1117ca83dacSbeveloper while (count--) { 1127ca83dacSbeveloper *(float *)dst = *(const float *)src * gain; 1137ca83dacSbeveloper dst += dst_sample_offset; 1146b5e1508Sbeveloper current += delta; 1156b5e1508Sbeveloper register int32 skipcount = (int32)current; 1166b5e1508Sbeveloper current -= skipcount; 1176b5e1508Sbeveloper src += skipcount * src_sample_offset; 1187ca83dacSbeveloper } 1197ca83dacSbeveloper } 1207ca83dacSbeveloper } 1217ca83dacSbeveloper 1227ca83dacSbeveloper void 1237ca83dacSbeveloper Resampler::int32_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 1247ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 125575526ffSbeveloper { 12688e430cbSbeveloper register const char * src = (const char *) _src; 12788e430cbSbeveloper register char * dst = (char *) _dst; 12888e430cbSbeveloper register int32 count = dst_sample_count; 12988e430cbSbeveloper register float gain = _gain / 2147483647.0; 13088e430cbSbeveloper 13188e430cbSbeveloper if (src_sample_count == dst_sample_count) { 13288e430cbSbeveloper // optimized case for no resampling 13388e430cbSbeveloper while (count--) { 13488e430cbSbeveloper *(float *)dst = *(const int32 *)src * gain; 13588e430cbSbeveloper src += src_sample_offset; 13688e430cbSbeveloper dst += dst_sample_offset; 13788e430cbSbeveloper } 13888e430cbSbeveloper return; 13988e430cbSbeveloper } 14088e430cbSbeveloper 141fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 14288e430cbSbeveloper register float current = 0.0f; 14388e430cbSbeveloper 14488e430cbSbeveloper if (delta < 1.0) { 14588e430cbSbeveloper // upsample 14688e430cbSbeveloper while (count--) { 14788e430cbSbeveloper *(float *)dst = *(const int32 *)src * gain; 14888e430cbSbeveloper dst += dst_sample_offset; 14988e430cbSbeveloper current += delta; 1506b5e1508Sbeveloper if (current >= 1.0f) { 15188e430cbSbeveloper current -= 1.0f; 15288e430cbSbeveloper src += src_sample_offset; 15388e430cbSbeveloper } 15488e430cbSbeveloper } 15588e430cbSbeveloper } else { 15688e430cbSbeveloper // downsample 15788e430cbSbeveloper while (count--) { 15888e430cbSbeveloper *(float *)dst = *(const int32 *)src * gain; 15988e430cbSbeveloper dst += dst_sample_offset; 1606b5e1508Sbeveloper current += delta; 1616b5e1508Sbeveloper register int32 skipcount = (int32)current; 1626b5e1508Sbeveloper current -= skipcount; 1636b5e1508Sbeveloper src += skipcount * src_sample_offset; 16488e430cbSbeveloper } 16588e430cbSbeveloper } 166575526ffSbeveloper } 167575526ffSbeveloper 168575526ffSbeveloper void 1697ca83dacSbeveloper Resampler::int16_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 1707ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 171575526ffSbeveloper { 17288e430cbSbeveloper register const char * src = (const char *) _src; 17388e430cbSbeveloper register char * dst = (char *) _dst; 17488e430cbSbeveloper register int32 count = dst_sample_count; 17588e430cbSbeveloper register float gain = _gain / 32767.0; 17688e430cbSbeveloper 17788e430cbSbeveloper if (src_sample_count == dst_sample_count) { 17888e430cbSbeveloper // optimized case for no resampling 17988e430cbSbeveloper while (count--) { 18088e430cbSbeveloper *(float *)dst = *(const int16 *)src * gain; 18188e430cbSbeveloper src += src_sample_offset; 18288e430cbSbeveloper dst += dst_sample_offset; 18388e430cbSbeveloper } 18488e430cbSbeveloper return; 18588e430cbSbeveloper } 18688e430cbSbeveloper 187fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 18888e430cbSbeveloper register float current = 0.0f; 18988e430cbSbeveloper 19088e430cbSbeveloper if (delta < 1.0) { 19188e430cbSbeveloper // upsample 19288e430cbSbeveloper while (count--) { 19388e430cbSbeveloper *(float *)dst = *(const int16 *)src * gain; 19488e430cbSbeveloper dst += dst_sample_offset; 19588e430cbSbeveloper current += delta; 1966b5e1508Sbeveloper if (current >= 1.0f) { 19788e430cbSbeveloper current -= 1.0f; 19888e430cbSbeveloper src += src_sample_offset; 19988e430cbSbeveloper } 20088e430cbSbeveloper } 20188e430cbSbeveloper } else { 20288e430cbSbeveloper // downsample 20388e430cbSbeveloper while (count--) { 20488e430cbSbeveloper *(float *)dst = *(const int16 *)src * gain; 20588e430cbSbeveloper dst += dst_sample_offset; 2066b5e1508Sbeveloper current += delta; 2076b5e1508Sbeveloper register int32 skipcount = (int32)current; 2086b5e1508Sbeveloper current -= skipcount; 2096b5e1508Sbeveloper src += skipcount * src_sample_offset; 21088e430cbSbeveloper } 21188e430cbSbeveloper } 212575526ffSbeveloper } 213575526ffSbeveloper 214575526ffSbeveloper void 2157ca83dacSbeveloper Resampler::int8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 2167ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 217575526ffSbeveloper { 21888e430cbSbeveloper register const char * src = (const char *) _src; 21988e430cbSbeveloper register char * dst = (char *) _dst; 22088e430cbSbeveloper register int32 count = dst_sample_count; 22188e430cbSbeveloper register float gain = _gain / 127.0; 22288e430cbSbeveloper 22388e430cbSbeveloper if (src_sample_count == dst_sample_count) { 22488e430cbSbeveloper // optimized case for no resampling 22588e430cbSbeveloper while (count--) { 22688e430cbSbeveloper *(float *)dst = *(const int8 *)src * gain; 22788e430cbSbeveloper src += src_sample_offset; 22888e430cbSbeveloper dst += dst_sample_offset; 22988e430cbSbeveloper } 23088e430cbSbeveloper return; 23188e430cbSbeveloper } 23288e430cbSbeveloper 233fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 23488e430cbSbeveloper register float current = 0.0f; 23588e430cbSbeveloper 23688e430cbSbeveloper if (delta < 1.0) { 23788e430cbSbeveloper // upsample 23888e430cbSbeveloper while (count--) { 23988e430cbSbeveloper *(float *)dst = *(const int8 *)src * gain; 24088e430cbSbeveloper dst += dst_sample_offset; 24188e430cbSbeveloper current += delta; 2426b5e1508Sbeveloper if (current >= 1.0f) { 24388e430cbSbeveloper current -= 1.0f; 24488e430cbSbeveloper src += src_sample_offset; 24588e430cbSbeveloper } 24688e430cbSbeveloper } 24788e430cbSbeveloper } else { 24888e430cbSbeveloper // downsample 24988e430cbSbeveloper while (count--) { 25088e430cbSbeveloper *(float *)dst = *(const int8 *)src * gain; 25188e430cbSbeveloper dst += dst_sample_offset; 2526b5e1508Sbeveloper current += delta; 2536b5e1508Sbeveloper register int32 skipcount = (int32)current; 2546b5e1508Sbeveloper current -= skipcount; 2556b5e1508Sbeveloper src += skipcount * src_sample_offset; 25688e430cbSbeveloper } 25788e430cbSbeveloper } 258575526ffSbeveloper } 259575526ffSbeveloper 260575526ffSbeveloper void 2617ca83dacSbeveloper Resampler::uint8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 2627ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 263575526ffSbeveloper { 26488e430cbSbeveloper register const char * src = (const char *) _src; 26588e430cbSbeveloper register char * dst = (char *) _dst; 26688e430cbSbeveloper register int32 count = dst_sample_count; 26788e430cbSbeveloper register float gain = _gain / 127.0; 26888e430cbSbeveloper 26988e430cbSbeveloper if (src_sample_count == dst_sample_count) { 27088e430cbSbeveloper // optimized case for no resampling 27188e430cbSbeveloper while (count--) { 27288e430cbSbeveloper *(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; 27388e430cbSbeveloper src += src_sample_offset; 27488e430cbSbeveloper dst += dst_sample_offset; 27588e430cbSbeveloper } 27688e430cbSbeveloper return; 27788e430cbSbeveloper } 27888e430cbSbeveloper 279fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 28088e430cbSbeveloper register float current = 0.0f; 28188e430cbSbeveloper 28288e430cbSbeveloper if (delta < 1.0) { 28388e430cbSbeveloper // upsample 28488e430cbSbeveloper while (count--) { 28588e430cbSbeveloper *(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; 28688e430cbSbeveloper dst += dst_sample_offset; 28788e430cbSbeveloper current += delta; 2886b5e1508Sbeveloper if (current >= 1.0f) { 28988e430cbSbeveloper current -= 1.0f; 29088e430cbSbeveloper src += src_sample_offset; 29188e430cbSbeveloper } 29288e430cbSbeveloper } 29388e430cbSbeveloper } else { 29488e430cbSbeveloper // downsample 29588e430cbSbeveloper while (count--) { 29688e430cbSbeveloper *(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; 29788e430cbSbeveloper dst += dst_sample_offset; 2986b5e1508Sbeveloper current += delta; 2996b5e1508Sbeveloper register int32 skipcount = (int32)current; 3006b5e1508Sbeveloper current -= skipcount; 3016b5e1508Sbeveloper src += skipcount * src_sample_offset; 30288e430cbSbeveloper } 30388e430cbSbeveloper } 304575526ffSbeveloper } 305575526ffSbeveloper 306575526ffSbeveloper void 307*f0a85f97SJérôme Duval Resampler::float_to_int32(const void *_src, int32 src_sample_offset, int32 src_sample_count, 3087ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 309575526ffSbeveloper { 3109b875fbaSbeveloper register const char * src = (const char *) _src; 3119b875fbaSbeveloper register char * dst = (char *) _dst; 3129b875fbaSbeveloper register int32 count = dst_sample_count; 3139b875fbaSbeveloper register float gain = _gain * 2147483647.0; 3149b875fbaSbeveloper 3159b875fbaSbeveloper if (src_sample_count == dst_sample_count) { 3169b875fbaSbeveloper // optimized case for no resampling 3179b875fbaSbeveloper while (count--) { 3189b875fbaSbeveloper register float sample = *(const float *)src * gain; 3199b875fbaSbeveloper if (sample > 2147483647.0f) 3209b875fbaSbeveloper *(int32 *)dst = 2147483647L; 3219b875fbaSbeveloper else if (sample < -2147483647.0f) 3229b875fbaSbeveloper *(int32 *)dst = -2147483647L; 3239b875fbaSbeveloper else 3249b875fbaSbeveloper *(int32 *)dst = (int32)sample; 3259b875fbaSbeveloper src += src_sample_offset; 3269b875fbaSbeveloper dst += dst_sample_offset; 3279b875fbaSbeveloper } 3289b875fbaSbeveloper return; 3299b875fbaSbeveloper } 3309b875fbaSbeveloper 331fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 3329b875fbaSbeveloper register float current = 0.0f; 3339b875fbaSbeveloper 3349b875fbaSbeveloper if (delta < 1.0) { 3359b875fbaSbeveloper // upsample 3369b875fbaSbeveloper while (count--) { 3379b875fbaSbeveloper register float sample = *(const float *)src * gain; 3389b875fbaSbeveloper if (sample > 2147483647.0f) 3399b875fbaSbeveloper *(int32 *)dst = 2147483647L; 3409b875fbaSbeveloper else if (sample < -2147483647.0f) 3419b875fbaSbeveloper *(int32 *)dst = -2147483647L; 3429b875fbaSbeveloper else 3439b875fbaSbeveloper *(int32 *)dst = (int32)sample; 3449b875fbaSbeveloper dst += dst_sample_offset; 3459b875fbaSbeveloper current += delta; 3466b5e1508Sbeveloper if (current >= 1.0f) { 3479b875fbaSbeveloper current -= 1.0f; 3489b875fbaSbeveloper src += src_sample_offset; 3499b875fbaSbeveloper } 3509b875fbaSbeveloper } 3519b875fbaSbeveloper } else { 3529b875fbaSbeveloper // downsample 3539b875fbaSbeveloper while (count--) { 3549b875fbaSbeveloper register float sample = *(const float *)src * gain; 3559b875fbaSbeveloper if (sample > 2147483647.0f) 3569b875fbaSbeveloper *(int32 *)dst = 2147483647L; 3579b875fbaSbeveloper else if (sample < -2147483647.0f) 3589b875fbaSbeveloper *(int32 *)dst = -2147483647L; 3599b875fbaSbeveloper else 3609b875fbaSbeveloper *(int32 *)dst = (int32)sample; 3619b875fbaSbeveloper dst += dst_sample_offset; 3626b5e1508Sbeveloper current += delta; 3636b5e1508Sbeveloper register int32 skipcount = (int32)current; 3646b5e1508Sbeveloper current -= skipcount; 3656b5e1508Sbeveloper src += skipcount * src_sample_offset; 3669b875fbaSbeveloper } 3679b875fbaSbeveloper } 368575526ffSbeveloper } 369575526ffSbeveloper 370ff14d245SJérôme Duval 371ff14d245SJérôme Duval void 3727ca83dacSbeveloper Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_sample_count, 3737ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 374575526ffSbeveloper { 3759b875fbaSbeveloper register const char * src = (const char *) _src; 3769b875fbaSbeveloper register char * dst = (char *) _dst; 3779b875fbaSbeveloper register int32 count = dst_sample_count; 3789b875fbaSbeveloper register float gain = _gain * 32767.0; 3799b875fbaSbeveloper 3809b875fbaSbeveloper if (src_sample_count == dst_sample_count) { 3819b875fbaSbeveloper // optimized case for no resampling 3829b875fbaSbeveloper while (count--) { 3839b875fbaSbeveloper register float sample = *(const float *)src * gain; 3849b875fbaSbeveloper if (sample > 32767.0f) 3859b875fbaSbeveloper *(int16 *)dst = 32767; 3869b875fbaSbeveloper else if (sample < -32767.0f) 3879b875fbaSbeveloper *(int16 *)dst = -32767; 3889b875fbaSbeveloper else 3899b875fbaSbeveloper *(int16 *)dst = (int16)sample; 3909b875fbaSbeveloper src += src_sample_offset; 3919b875fbaSbeveloper dst += dst_sample_offset; 3929b875fbaSbeveloper } 3939b875fbaSbeveloper return; 3949b875fbaSbeveloper } 3959b875fbaSbeveloper 396fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 3979b875fbaSbeveloper register float current = 0.0f; 3989b875fbaSbeveloper 3999b875fbaSbeveloper if (delta < 1.0) { 4009b875fbaSbeveloper // upsample 4019b875fbaSbeveloper while (count--) { 4029b875fbaSbeveloper register float sample = *(const float *)src * gain; 4039b875fbaSbeveloper if (sample > 32767.0f) 4049b875fbaSbeveloper *(int16 *)dst = 32767; 4059b875fbaSbeveloper else if (sample < -32767.0f) 4069b875fbaSbeveloper *(int16 *)dst = -32767; 4079b875fbaSbeveloper else 4089b875fbaSbeveloper *(int16 *)dst = (int16)sample; 4099b875fbaSbeveloper dst += dst_sample_offset; 4109b875fbaSbeveloper current += delta; 4116b5e1508Sbeveloper if (current >= 1.0f) { 4129b875fbaSbeveloper current -= 1.0f; 4139b875fbaSbeveloper src += src_sample_offset; 4149b875fbaSbeveloper } 4159b875fbaSbeveloper } 4169b875fbaSbeveloper } else { 4179b875fbaSbeveloper // downsample 4189b875fbaSbeveloper while (count--) { 4199b875fbaSbeveloper register float sample = *(const float *)src * gain; 4209b875fbaSbeveloper if (sample > 32767.0f) 4219b875fbaSbeveloper *(int16 *)dst = 32767; 4229b875fbaSbeveloper else if (sample < -32767.0f) 4239b875fbaSbeveloper *(int16 *)dst = -32767; 4249b875fbaSbeveloper else 4259b875fbaSbeveloper *(int16 *)dst = (int16)sample; 4269b875fbaSbeveloper dst += dst_sample_offset; 4276b5e1508Sbeveloper current += delta; 4286b5e1508Sbeveloper register int32 skipcount = (int32)current; 4296b5e1508Sbeveloper current -= skipcount; 4306b5e1508Sbeveloper src += skipcount * src_sample_offset; 4319b875fbaSbeveloper } 4329b875fbaSbeveloper } 433575526ffSbeveloper } 434575526ffSbeveloper 435575526ffSbeveloper void 4369b875fbaSbeveloper Resampler::float_to_int8(const void *_src, int32 src_sample_offset, int32 src_sample_count, 4377ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 438575526ffSbeveloper { 4399b875fbaSbeveloper register const char * src = (const char *) _src; 4409b875fbaSbeveloper register char * dst = (char *) _dst; 4419b875fbaSbeveloper register int32 count = dst_sample_count; 4429b875fbaSbeveloper register float gain = _gain * 127.0; 4439b875fbaSbeveloper 4449b875fbaSbeveloper if (src_sample_count == dst_sample_count) { 4459b875fbaSbeveloper // optimized case for no resampling 4469b875fbaSbeveloper while (count--) { 4479b875fbaSbeveloper register float sample = *(const float *)src * gain; 4489b875fbaSbeveloper if (sample > 127.0f) 4499b875fbaSbeveloper *(int8 *)dst = 127; 4509b875fbaSbeveloper else if (sample < -127.0f) 4519b875fbaSbeveloper *(int8 *)dst = -127; 4529b875fbaSbeveloper else 4539b875fbaSbeveloper *(int8 *)dst = (int8)sample; 4549b875fbaSbeveloper src += src_sample_offset; 4559b875fbaSbeveloper dst += dst_sample_offset; 4569b875fbaSbeveloper } 4579b875fbaSbeveloper return; 4589b875fbaSbeveloper } 4599b875fbaSbeveloper 460fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 4619b875fbaSbeveloper register float current = 0.0f; 4629b875fbaSbeveloper 4639b875fbaSbeveloper if (delta < 1.0) { 4649b875fbaSbeveloper // upsample 4659b875fbaSbeveloper while (count--) { 4669b875fbaSbeveloper register float sample = *(const float *)src * gain; 4679b875fbaSbeveloper if (sample > 127.0f) 4689b875fbaSbeveloper *(int8 *)dst = 127; 4699b875fbaSbeveloper else if (sample < -127.0f) 4709b875fbaSbeveloper *(int8 *)dst = -127; 4719b875fbaSbeveloper else 4729b875fbaSbeveloper *(int8 *)dst = (int8)sample; 4739b875fbaSbeveloper dst += dst_sample_offset; 4749b875fbaSbeveloper current += delta; 4756b5e1508Sbeveloper if (current >= 1.0f) { 4769b875fbaSbeveloper current -= 1.0f; 4779b875fbaSbeveloper src += src_sample_offset; 4789b875fbaSbeveloper } 4799b875fbaSbeveloper } 4809b875fbaSbeveloper } else { 4819b875fbaSbeveloper // downsample 4829b875fbaSbeveloper while (count--) { 4839b875fbaSbeveloper register float sample = *(const float *)src * gain; 4849b875fbaSbeveloper if (sample > 127.0f) 4859b875fbaSbeveloper *(int8 *)dst = 127; 4869b875fbaSbeveloper else if (sample < -127.0f) 4879b875fbaSbeveloper *(int8 *)dst = -127; 4889b875fbaSbeveloper else 4899b875fbaSbeveloper *(int8 *)dst = (int8)sample; 4909b875fbaSbeveloper dst += dst_sample_offset; 4916b5e1508Sbeveloper current += delta; 4926b5e1508Sbeveloper register int32 skipcount = (int32)current; 4936b5e1508Sbeveloper current -= skipcount; 4946b5e1508Sbeveloper src += skipcount * src_sample_offset; 4959b875fbaSbeveloper } 4969b875fbaSbeveloper } 497575526ffSbeveloper } 498575526ffSbeveloper 499575526ffSbeveloper void 5007ca83dacSbeveloper Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_sample_count, 5017ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 502575526ffSbeveloper { 5039b875fbaSbeveloper register const char * src = (const char *) _src; 5049b875fbaSbeveloper register char * dst = (char *) _dst; 5059b875fbaSbeveloper register int32 count = dst_sample_count; 5069b875fbaSbeveloper register float gain = _gain * 127.0; 5079b875fbaSbeveloper 5089b875fbaSbeveloper if (src_sample_count == dst_sample_count) { 5099b875fbaSbeveloper // optimized case for no resampling 5109b875fbaSbeveloper while (count--) { 5119b875fbaSbeveloper register float sample = 128.0f + *(const float *)src * gain; 5129b875fbaSbeveloper if (sample > 255.0f) 5139b875fbaSbeveloper *(uint8 *)dst = 255; 5149b875fbaSbeveloper else if (sample < 1.0f) 5159b875fbaSbeveloper *(uint8 *)dst = 1; 5169b875fbaSbeveloper else 5179b875fbaSbeveloper *(uint8 *)dst = (uint8)sample; 5189b875fbaSbeveloper src += src_sample_offset; 5199b875fbaSbeveloper dst += dst_sample_offset; 520575526ffSbeveloper } 5219b875fbaSbeveloper return; 5229b875fbaSbeveloper } 5239b875fbaSbeveloper 524fb71d3a9Sbeveloper register float delta = float(src_sample_count) / float(dst_sample_count); 5259b875fbaSbeveloper register float current = 0.0f; 5269b875fbaSbeveloper 5279b875fbaSbeveloper if (delta < 1.0) { 5289b875fbaSbeveloper // upsample 5299b875fbaSbeveloper while (count--) { 5309b875fbaSbeveloper register float sample = 128.0f + *(const float *)src * gain; 5319b875fbaSbeveloper if (sample > 255.0f) 5329b875fbaSbeveloper *(uint8 *)dst = 255; 5339b875fbaSbeveloper else if (sample < 1.0f) 5349b875fbaSbeveloper *(uint8 *)dst = 1; 5359b875fbaSbeveloper else 5369b875fbaSbeveloper *(uint8 *)dst = (uint8)sample; 5379b875fbaSbeveloper dst += dst_sample_offset; 5389b875fbaSbeveloper current += delta; 5396b5e1508Sbeveloper if (current >= 1.0f) { 5409b875fbaSbeveloper current -= 1.0f; 5419b875fbaSbeveloper src += src_sample_offset; 5429b875fbaSbeveloper } 5439b875fbaSbeveloper } 5449b875fbaSbeveloper } else { 5459b875fbaSbeveloper // downsample 5469b875fbaSbeveloper while (count--) { 5479b875fbaSbeveloper register float sample = 128.0f + *(const float *)src * gain; 5489b875fbaSbeveloper if (sample > 255.0f) 5499b875fbaSbeveloper *(uint8 *)dst = 255; 5509b875fbaSbeveloper else if (sample < 1.0f) 5519b875fbaSbeveloper *(uint8 *)dst = 1; 5529b875fbaSbeveloper else 5539b875fbaSbeveloper *(uint8 *)dst = (uint8)sample; 5549b875fbaSbeveloper dst += dst_sample_offset; 5556b5e1508Sbeveloper current += delta; 5566b5e1508Sbeveloper register int32 skipcount = (int32)current; 5576b5e1508Sbeveloper current -= skipcount; 5586b5e1508Sbeveloper src += skipcount * src_sample_offset; 5599b875fbaSbeveloper } 5609b875fbaSbeveloper } 5619b875fbaSbeveloper } 562