1575526ffSbeveloper /* Copyright (C) 2003 Marcus Overhagen 2575526ffSbeveloper * Released under terms of the MIT license. 3575526ffSbeveloper * 4575526ffSbeveloper * A simple resampling class for the audio mixer. 5575526ffSbeveloper * You pick the conversation 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 12575526ffSbeveloper #include "Resampler.h" 13575526ffSbeveloper #include "debug.h" 14575526ffSbeveloper 15575526ffSbeveloper Resampler::Resampler(uint32 src_format, uint32 dst_format) 16575526ffSbeveloper : fFunc(0) 17575526ffSbeveloper { 18575526ffSbeveloper if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) { 19575526ffSbeveloper switch (src_format) { 20575526ffSbeveloper case media_raw_audio_format::B_AUDIO_FLOAT: 21575526ffSbeveloper fFunc = &Resampler::float_to_float; 22575526ffSbeveloper return; 23575526ffSbeveloper case media_raw_audio_format::B_AUDIO_INT: 24575526ffSbeveloper fFunc = &Resampler::int32_to_float; 25575526ffSbeveloper return; 26575526ffSbeveloper case media_raw_audio_format::B_AUDIO_SHORT: 27575526ffSbeveloper fFunc = &Resampler::int16_to_float; 28575526ffSbeveloper return; 29575526ffSbeveloper case media_raw_audio_format::B_AUDIO_CHAR: 30575526ffSbeveloper fFunc = &Resampler::int8_to_float; 31575526ffSbeveloper return; 32575526ffSbeveloper case media_raw_audio_format::B_AUDIO_UCHAR: 33575526ffSbeveloper fFunc = &Resampler::uint8_to_float; 34575526ffSbeveloper return; 35575526ffSbeveloper default: 36575526ffSbeveloper FATAL("Resampler::Resampler: unknown source format 0x%x\n", src_format); 37575526ffSbeveloper return; 38575526ffSbeveloper } 39575526ffSbeveloper } 40575526ffSbeveloper 41575526ffSbeveloper if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) { 42575526ffSbeveloper switch (dst_format) { 43575526ffSbeveloper // float=>float already handled above 44575526ffSbeveloper case media_raw_audio_format::B_AUDIO_INT: 45575526ffSbeveloper fFunc = &Resampler::float_to_int32; 46575526ffSbeveloper return; 47575526ffSbeveloper case media_raw_audio_format::B_AUDIO_SHORT: 48575526ffSbeveloper fFunc = &Resampler::float_to_int16; 49575526ffSbeveloper return; 50575526ffSbeveloper case media_raw_audio_format::B_AUDIO_CHAR: 51575526ffSbeveloper fFunc = &Resampler::float_to_int8; 52575526ffSbeveloper return; 53575526ffSbeveloper case media_raw_audio_format::B_AUDIO_UCHAR: 54575526ffSbeveloper fFunc = &Resampler::float_to_uint8; 55575526ffSbeveloper return; 56575526ffSbeveloper default: 57575526ffSbeveloper FATAL("Resampler::Resampler: unknown destination format 0x%x\n", dst_format); 58575526ffSbeveloper return; 59575526ffSbeveloper } 60575526ffSbeveloper } 61575526ffSbeveloper 62575526ffSbeveloper FATAL("Resampler::Resampler: source or destination format must be B_AUDIO_FLOAT\n"); 63575526ffSbeveloper } 64575526ffSbeveloper 65575526ffSbeveloper Resampler::~Resampler() 66575526ffSbeveloper { 67575526ffSbeveloper } 68575526ffSbeveloper 69575526ffSbeveloper status_t 70575526ffSbeveloper Resampler::InitCheck() 71575526ffSbeveloper { 72575526ffSbeveloper return (fFunc != 0) ? B_OK : B_ERROR; 73575526ffSbeveloper } 74575526ffSbeveloper 75575526ffSbeveloper void 767ca83dacSbeveloper Resampler::float_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 777ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 787ca83dacSbeveloper { 797ca83dacSbeveloper register const char * src = (const char *) _src; 807ca83dacSbeveloper register char * dst = (char *) _dst; 817ca83dacSbeveloper register int32 count = dst_sample_count; 827ca83dacSbeveloper register float gain = _gain; 837ca83dacSbeveloper 847ca83dacSbeveloper if (src_sample_count == dst_sample_count) { 857ca83dacSbeveloper // optimized case for no resampling 867ca83dacSbeveloper while (count--) { 877ca83dacSbeveloper *(float *)dst = *(const float *)src * gain; 887ca83dacSbeveloper src += src_sample_offset; 897ca83dacSbeveloper dst += dst_sample_offset; 907ca83dacSbeveloper } 917ca83dacSbeveloper return; 927ca83dacSbeveloper } 937ca83dacSbeveloper 94*88e430cbSbeveloper register float delta = float(src_sample_count) / float(dst_sample_offset); 957ca83dacSbeveloper register float current = 0.0f; 967ca83dacSbeveloper 977ca83dacSbeveloper if (delta < 1.0) { 987ca83dacSbeveloper // upsample 997ca83dacSbeveloper while (count--) { 1007ca83dacSbeveloper *(float *)dst = *(const float *)src * gain; 1017ca83dacSbeveloper dst += dst_sample_offset; 1027ca83dacSbeveloper current += delta; 1037ca83dacSbeveloper if (current > 1.0f) { 1047ca83dacSbeveloper current -= 1.0f; 1057ca83dacSbeveloper src += src_sample_offset; 1067ca83dacSbeveloper } 1077ca83dacSbeveloper } 1087ca83dacSbeveloper } else { 1097ca83dacSbeveloper // downsample 1107ca83dacSbeveloper while (count--) { 1117ca83dacSbeveloper *(float *)dst = *(const float *)src * gain; 1127ca83dacSbeveloper src += src_sample_offset; 1137ca83dacSbeveloper current += delta; // delta is always > 1.0 1147ca83dacSbeveloper if (current < 2.0f) { 1157ca83dacSbeveloper current -= 1.0f; 1167ca83dacSbeveloper dst += dst_sample_offset; 1177ca83dacSbeveloper } else { 1187ca83dacSbeveloper int32 inc_count = (int32) current; 1197ca83dacSbeveloper current -= (float) inc_count; 1207ca83dacSbeveloper dst += inc_count * dst_sample_offset; 1217ca83dacSbeveloper } 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 { 130*88e430cbSbeveloper register const char * src = (const char *) _src; 131*88e430cbSbeveloper register char * dst = (char *) _dst; 132*88e430cbSbeveloper register int32 count = dst_sample_count; 133*88e430cbSbeveloper register float gain = _gain / 2147483647.0; 134*88e430cbSbeveloper 135*88e430cbSbeveloper if (src_sample_count == dst_sample_count) { 136*88e430cbSbeveloper // optimized case for no resampling 137*88e430cbSbeveloper while (count--) { 138*88e430cbSbeveloper *(float *)dst = *(const int32 *)src * gain; 139*88e430cbSbeveloper src += src_sample_offset; 140*88e430cbSbeveloper dst += dst_sample_offset; 141*88e430cbSbeveloper } 142*88e430cbSbeveloper return; 143*88e430cbSbeveloper } 144*88e430cbSbeveloper 145*88e430cbSbeveloper register float delta = float(src_sample_count) / float(dst_sample_offset); 146*88e430cbSbeveloper register float current = 0.0f; 147*88e430cbSbeveloper 148*88e430cbSbeveloper if (delta < 1.0) { 149*88e430cbSbeveloper // upsample 150*88e430cbSbeveloper while (count--) { 151*88e430cbSbeveloper *(float *)dst = *(const int32 *)src * gain; 152*88e430cbSbeveloper dst += dst_sample_offset; 153*88e430cbSbeveloper current += delta; 154*88e430cbSbeveloper if (current > 1.0f) { 155*88e430cbSbeveloper current -= 1.0f; 156*88e430cbSbeveloper src += src_sample_offset; 157*88e430cbSbeveloper } 158*88e430cbSbeveloper } 159*88e430cbSbeveloper } else { 160*88e430cbSbeveloper // downsample 161*88e430cbSbeveloper while (count--) { 162*88e430cbSbeveloper *(float *)dst = *(const int32 *)src * gain; 163*88e430cbSbeveloper src += src_sample_offset; 164*88e430cbSbeveloper current += delta; // delta is always > 1.0 165*88e430cbSbeveloper if (current < 2.0f) { 166*88e430cbSbeveloper current -= 1.0f; 167*88e430cbSbeveloper dst += dst_sample_offset; 168*88e430cbSbeveloper } else { 169*88e430cbSbeveloper int32 inc_count = (int32) current; 170*88e430cbSbeveloper current -= (float) inc_count; 171*88e430cbSbeveloper dst += inc_count * dst_sample_offset; 172*88e430cbSbeveloper } 173*88e430cbSbeveloper } 174*88e430cbSbeveloper } 175575526ffSbeveloper } 176575526ffSbeveloper 177575526ffSbeveloper void 1787ca83dacSbeveloper Resampler::int16_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 1797ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 180575526ffSbeveloper { 181*88e430cbSbeveloper register const char * src = (const char *) _src; 182*88e430cbSbeveloper register char * dst = (char *) _dst; 183*88e430cbSbeveloper register int32 count = dst_sample_count; 184*88e430cbSbeveloper register float gain = _gain / 32767.0; 185*88e430cbSbeveloper 186*88e430cbSbeveloper if (src_sample_count == dst_sample_count) { 187*88e430cbSbeveloper // optimized case for no resampling 188*88e430cbSbeveloper while (count--) { 189*88e430cbSbeveloper *(float *)dst = *(const int16 *)src * gain; 190*88e430cbSbeveloper src += src_sample_offset; 191*88e430cbSbeveloper dst += dst_sample_offset; 192*88e430cbSbeveloper } 193*88e430cbSbeveloper return; 194*88e430cbSbeveloper } 195*88e430cbSbeveloper 196*88e430cbSbeveloper register float delta = float(src_sample_count) / float(dst_sample_offset); 197*88e430cbSbeveloper register float current = 0.0f; 198*88e430cbSbeveloper 199*88e430cbSbeveloper if (delta < 1.0) { 200*88e430cbSbeveloper // upsample 201*88e430cbSbeveloper while (count--) { 202*88e430cbSbeveloper *(float *)dst = *(const int16 *)src * gain; 203*88e430cbSbeveloper dst += dst_sample_offset; 204*88e430cbSbeveloper current += delta; 205*88e430cbSbeveloper if (current > 1.0f) { 206*88e430cbSbeveloper current -= 1.0f; 207*88e430cbSbeveloper src += src_sample_offset; 208*88e430cbSbeveloper } 209*88e430cbSbeveloper } 210*88e430cbSbeveloper } else { 211*88e430cbSbeveloper // downsample 212*88e430cbSbeveloper while (count--) { 213*88e430cbSbeveloper *(float *)dst = *(const int16 *)src * gain; 214*88e430cbSbeveloper src += src_sample_offset; 215*88e430cbSbeveloper current += delta; // delta is always > 1.0 216*88e430cbSbeveloper if (current < 2.0f) { 217*88e430cbSbeveloper current -= 1.0f; 218*88e430cbSbeveloper dst += dst_sample_offset; 219*88e430cbSbeveloper } else { 220*88e430cbSbeveloper int32 inc_count = (int32) current; 221*88e430cbSbeveloper current -= (float) inc_count; 222*88e430cbSbeveloper dst += inc_count * dst_sample_offset; 223*88e430cbSbeveloper } 224*88e430cbSbeveloper } 225*88e430cbSbeveloper } 226575526ffSbeveloper } 227575526ffSbeveloper 228575526ffSbeveloper void 2297ca83dacSbeveloper Resampler::int8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 2307ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 231575526ffSbeveloper { 232*88e430cbSbeveloper register const char * src = (const char *) _src; 233*88e430cbSbeveloper register char * dst = (char *) _dst; 234*88e430cbSbeveloper register int32 count = dst_sample_count; 235*88e430cbSbeveloper register float gain = _gain / 127.0; 236*88e430cbSbeveloper 237*88e430cbSbeveloper if (src_sample_count == dst_sample_count) { 238*88e430cbSbeveloper // optimized case for no resampling 239*88e430cbSbeveloper while (count--) { 240*88e430cbSbeveloper *(float *)dst = *(const int8 *)src * gain; 241*88e430cbSbeveloper src += src_sample_offset; 242*88e430cbSbeveloper dst += dst_sample_offset; 243*88e430cbSbeveloper } 244*88e430cbSbeveloper return; 245*88e430cbSbeveloper } 246*88e430cbSbeveloper 247*88e430cbSbeveloper register float delta = float(src_sample_count) / float(dst_sample_offset); 248*88e430cbSbeveloper register float current = 0.0f; 249*88e430cbSbeveloper 250*88e430cbSbeveloper if (delta < 1.0) { 251*88e430cbSbeveloper // upsample 252*88e430cbSbeveloper while (count--) { 253*88e430cbSbeveloper *(float *)dst = *(const int8 *)src * gain; 254*88e430cbSbeveloper dst += dst_sample_offset; 255*88e430cbSbeveloper current += delta; 256*88e430cbSbeveloper if (current > 1.0f) { 257*88e430cbSbeveloper current -= 1.0f; 258*88e430cbSbeveloper src += src_sample_offset; 259*88e430cbSbeveloper } 260*88e430cbSbeveloper } 261*88e430cbSbeveloper } else { 262*88e430cbSbeveloper // downsample 263*88e430cbSbeveloper while (count--) { 264*88e430cbSbeveloper *(float *)dst = *(const int8 *)src * gain; 265*88e430cbSbeveloper src += src_sample_offset; 266*88e430cbSbeveloper current += delta; // delta is always > 1.0 267*88e430cbSbeveloper if (current < 2.0f) { 268*88e430cbSbeveloper current -= 1.0f; 269*88e430cbSbeveloper dst += dst_sample_offset; 270*88e430cbSbeveloper } else { 271*88e430cbSbeveloper int32 inc_count = (int32) current; 272*88e430cbSbeveloper current -= (float) inc_count; 273*88e430cbSbeveloper dst += inc_count * dst_sample_offset; 274*88e430cbSbeveloper } 275*88e430cbSbeveloper } 276*88e430cbSbeveloper } 277575526ffSbeveloper } 278575526ffSbeveloper 279575526ffSbeveloper void 2807ca83dacSbeveloper Resampler::uint8_to_float(const void *_src, int32 src_sample_offset, int32 src_sample_count, 2817ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 282575526ffSbeveloper { 283*88e430cbSbeveloper register const char * src = (const char *) _src; 284*88e430cbSbeveloper register char * dst = (char *) _dst; 285*88e430cbSbeveloper register int32 count = dst_sample_count; 286*88e430cbSbeveloper register float gain = _gain / 127.0; 287*88e430cbSbeveloper 288*88e430cbSbeveloper if (src_sample_count == dst_sample_count) { 289*88e430cbSbeveloper // optimized case for no resampling 290*88e430cbSbeveloper while (count--) { 291*88e430cbSbeveloper *(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; 292*88e430cbSbeveloper src += src_sample_offset; 293*88e430cbSbeveloper dst += dst_sample_offset; 294*88e430cbSbeveloper } 295*88e430cbSbeveloper return; 296*88e430cbSbeveloper } 297*88e430cbSbeveloper 298*88e430cbSbeveloper register float delta = float(src_sample_count) / float(dst_sample_offset); 299*88e430cbSbeveloper register float current = 0.0f; 300*88e430cbSbeveloper 301*88e430cbSbeveloper if (delta < 1.0) { 302*88e430cbSbeveloper // upsample 303*88e430cbSbeveloper while (count--) { 304*88e430cbSbeveloper *(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; 305*88e430cbSbeveloper dst += dst_sample_offset; 306*88e430cbSbeveloper current += delta; 307*88e430cbSbeveloper if (current > 1.0f) { 308*88e430cbSbeveloper current -= 1.0f; 309*88e430cbSbeveloper src += src_sample_offset; 310*88e430cbSbeveloper } 311*88e430cbSbeveloper } 312*88e430cbSbeveloper } else { 313*88e430cbSbeveloper // downsample 314*88e430cbSbeveloper while (count--) { 315*88e430cbSbeveloper *(float *)dst = (((int32) *(const uint8 *)src) - 128) * gain; 316*88e430cbSbeveloper src += src_sample_offset; 317*88e430cbSbeveloper current += delta; // delta is always > 1.0 318*88e430cbSbeveloper if (current < 2.0f) { 319*88e430cbSbeveloper current -= 1.0f; 320*88e430cbSbeveloper dst += dst_sample_offset; 321*88e430cbSbeveloper } else { 322*88e430cbSbeveloper int32 inc_count = (int32) current; 323*88e430cbSbeveloper current -= (float) inc_count; 324*88e430cbSbeveloper dst += inc_count * dst_sample_offset; 325*88e430cbSbeveloper } 326*88e430cbSbeveloper } 327*88e430cbSbeveloper } 328575526ffSbeveloper } 329575526ffSbeveloper 330575526ffSbeveloper void 3317ca83dacSbeveloper Resampler::float_to_int32(const void *_src, int32 src_sample_offset, int32 src_sample_count, 3327ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 333575526ffSbeveloper { 334575526ffSbeveloper } 335575526ffSbeveloper 336575526ffSbeveloper void 3377ca83dacSbeveloper Resampler::float_to_int16(const void *_src, int32 src_sample_offset, int32 src_sample_count, 3387ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 339575526ffSbeveloper { 340575526ffSbeveloper } 341575526ffSbeveloper 342575526ffSbeveloper void 343575526ffSbeveloper Resampler::float_to_int8(const void *src, int32 src_sample_offset, int32 src_sample_count, 3447ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 345575526ffSbeveloper { 346575526ffSbeveloper } 347575526ffSbeveloper 348575526ffSbeveloper void 3497ca83dacSbeveloper Resampler::float_to_uint8(const void *_src, int32 src_sample_offset, int32 src_sample_count, 3507ca83dacSbeveloper void *_dst, int32 dst_sample_offset, int32 dst_sample_count, float _gain) 351575526ffSbeveloper { 352575526ffSbeveloper } 353575526ffSbeveloper 354