1a9cf57cfSAxel Dörfler /* 2a9cf57cfSAxel Dörfler * Copyright 2003 Marcus Overhagen 3a9cf57cfSAxel Dörfler * Distributed under the terms of the MIT License. 4575526ffSbeveloper */ 5575526ffSbeveloper 6a9cf57cfSAxel Dörfler 7575526ffSbeveloper #include "Resampler.h" 8a9cf57cfSAxel Dörfler 9a9cf57cfSAxel Dörfler #include <MediaDefs.h> 10a9cf57cfSAxel Dörfler 11f916862cSMarcus Overhagen #include "MixerDebug.h" 12575526ffSbeveloper 13a9cf57cfSAxel Dörfler 14a9cf57cfSAxel Dörfler /*! A simple resampling class for the audio mixer. 15a9cf57cfSAxel Dörfler You pick the conversion function on object creation, 16a9cf57cfSAxel Dörfler and then call the Resample() function, specifying data pointer, 17a9cf57cfSAxel Dörfler offset (in bytes) to the next sample, and count of samples for 18a9cf57cfSAxel Dörfler both source and destination. 19a9cf57cfSAxel Dörfler */ 20a9cf57cfSAxel Dörfler 21a9cf57cfSAxel Dörfler 22*27606daeSAdrien Destugues template<typename inType, typename outType, int gnum, int gden, int offset, 23*27606daeSAdrien Destugues int32 min, int32 max> static void 24*27606daeSAdrien Destugues kernel(Resampler* object, const void *_src, int32 srcSampleOffset, 25*27606daeSAdrien Destugues int32 srcSampleCount, void *_dest, int32 destSampleOffset, 26*27606daeSAdrien Destugues int32 destSampleCount, float _gain) 27*27606daeSAdrien Destugues { 28*27606daeSAdrien Destugues register const char * src = (const char *)_src; 29*27606daeSAdrien Destugues register char * dest = (char *)_dest; 30*27606daeSAdrien Destugues register int32 count = destSampleCount; 31*27606daeSAdrien Destugues register float gain = _gain * gnum / gden; 32*27606daeSAdrien Destugues 33*27606daeSAdrien Destugues if (srcSampleCount == destSampleCount) { 34*27606daeSAdrien Destugues // optimized case for no resampling 35*27606daeSAdrien Destugues while (count--) { 36*27606daeSAdrien Destugues float tmp = *(const inType*)src * gain + offset; 37*27606daeSAdrien Destugues if (tmp < min) tmp = min; 38*27606daeSAdrien Destugues if (tmp > max) tmp = max; 39*27606daeSAdrien Destugues *(outType *)dest = (outType)tmp; 40*27606daeSAdrien Destugues src += srcSampleOffset; 41*27606daeSAdrien Destugues dest += destSampleOffset; 42*27606daeSAdrien Destugues } 43*27606daeSAdrien Destugues return; 44*27606daeSAdrien Destugues } 45*27606daeSAdrien Destugues 46*27606daeSAdrien Destugues register float delta = float(srcSampleCount) / float(destSampleCount); 47*27606daeSAdrien Destugues register float current = 0.0f; 48*27606daeSAdrien Destugues 49*27606daeSAdrien Destugues // downsample 50*27606daeSAdrien Destugues while (count--) { 51*27606daeSAdrien Destugues float tmp = *(const inType*)src * gain + offset; 52*27606daeSAdrien Destugues if (tmp < min) tmp = min; 53*27606daeSAdrien Destugues if (tmp > max) tmp = max; 54*27606daeSAdrien Destugues *(outType *)dest = (outType)tmp; 55*27606daeSAdrien Destugues 56*27606daeSAdrien Destugues dest += destSampleOffset; 57*27606daeSAdrien Destugues current += delta; 58*27606daeSAdrien Destugues register int32 skipcount = (int32)current; 59*27606daeSAdrien Destugues current -= skipcount; 60*27606daeSAdrien Destugues src += skipcount * srcSampleOffset; 61*27606daeSAdrien Destugues } 62*27606daeSAdrien Destugues } 63*27606daeSAdrien Destugues 64*27606daeSAdrien Destugues 65f0a85f97SJérôme Duval Resampler::Resampler(uint32 src_format, uint32 dst_format) 66a9cf57cfSAxel Dörfler : 6778341a93SJohn Scipione fFunc(0) 68575526ffSbeveloper { 69575526ffSbeveloper if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) { 70575526ffSbeveloper switch (src_format) { 71575526ffSbeveloper case media_raw_audio_format::B_AUDIO_FLOAT: 72*27606daeSAdrien Destugues fFunc = &kernel<float, float, 1, 1, 0, -1, 1>; 73575526ffSbeveloper return; 74575526ffSbeveloper case media_raw_audio_format::B_AUDIO_INT: 75*27606daeSAdrien Destugues fFunc = &kernel<int32, float, 1, INT32_MAX, 0, -1, 1>; 76575526ffSbeveloper return; 77575526ffSbeveloper case media_raw_audio_format::B_AUDIO_SHORT: 78*27606daeSAdrien Destugues fFunc = &kernel<int16, float, 1, INT16_MAX, 0, -1, 1>; 79575526ffSbeveloper return; 80575526ffSbeveloper case media_raw_audio_format::B_AUDIO_CHAR: 81*27606daeSAdrien Destugues fFunc = &kernel<int8, float, 1, INT8_MAX, 0, -1, 1>; 82575526ffSbeveloper return; 83575526ffSbeveloper case media_raw_audio_format::B_AUDIO_UCHAR: 84*27606daeSAdrien Destugues fFunc = &kernel<uint8, float, 2, UINT8_MAX, -128, -1, 1>; 85575526ffSbeveloper return; 86575526ffSbeveloper default: 87a9cf57cfSAxel Dörfler ERROR("Resampler::Resampler: unknown source format 0x%x\n", 88a9cf57cfSAxel Dörfler src_format); 89575526ffSbeveloper return; 90575526ffSbeveloper } 91575526ffSbeveloper } 92575526ffSbeveloper 93575526ffSbeveloper if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) { 94575526ffSbeveloper switch (dst_format) { 95575526ffSbeveloper // float=>float already handled above 96575526ffSbeveloper case media_raw_audio_format::B_AUDIO_INT: 97*27606daeSAdrien Destugues fFunc = &kernel<float, int32, INT32_MAX, 1, 0, 98*27606daeSAdrien Destugues INT32_MIN, INT32_MAX>; 99575526ffSbeveloper return; 100575526ffSbeveloper case media_raw_audio_format::B_AUDIO_SHORT: 101*27606daeSAdrien Destugues fFunc = &kernel<float, int16, INT16_MAX, 1, 0, 102*27606daeSAdrien Destugues INT16_MIN, INT16_MAX>; 103575526ffSbeveloper return; 104575526ffSbeveloper case media_raw_audio_format::B_AUDIO_CHAR: 105*27606daeSAdrien Destugues fFunc = &kernel<float, int8, INT8_MAX, 1, 0, 106*27606daeSAdrien Destugues INT8_MIN, INT8_MAX>; 107575526ffSbeveloper return; 108575526ffSbeveloper case media_raw_audio_format::B_AUDIO_UCHAR: 109*27606daeSAdrien Destugues fFunc = &kernel<float, uint8, UINT8_MAX, 2, 1, 110*27606daeSAdrien Destugues 0, UINT8_MAX>; 111575526ffSbeveloper return; 112575526ffSbeveloper default: 113*27606daeSAdrien Destugues ERROR("Resampler::Resampler: unknown destination format 0x%x\n", 114*27606daeSAdrien Destugues dst_format); 115575526ffSbeveloper return; 116575526ffSbeveloper } 117575526ffSbeveloper } 118575526ffSbeveloper 119a9cf57cfSAxel Dörfler ERROR("Resampler::Resampler: source or destination format must be " 120a9cf57cfSAxel Dörfler "B_AUDIO_FLOAT\n"); 121575526ffSbeveloper } 122575526ffSbeveloper 123a9cf57cfSAxel Dörfler 124*27606daeSAdrien Destugues Resampler::Resampler() 125*27606daeSAdrien Destugues : 126*27606daeSAdrien Destugues fFunc(0) 127575526ffSbeveloper { 128575526ffSbeveloper } 129575526ffSbeveloper 130a9cf57cfSAxel Dörfler 131