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 22cfe72209SMáximo Castañeda template<typename inType, typename outType, int gnum, int gden, 23cfe72209SMáximo Castañeda int inMiddle, int outMiddle, int32 min, int32 max> static void 2427606daeSAdrien Destugues kernel(Resampler* object, const void *_src, int32 srcSampleOffset, 2527606daeSAdrien Destugues int32 srcSampleCount, void *_dest, int32 destSampleOffset, 2627606daeSAdrien Destugues int32 destSampleCount, float _gain) 2727606daeSAdrien Destugues { 28*95080923SMichael Brumbelow const char * src = (const char *)_src; 29*95080923SMichael Brumbelow char * dest = (char *)_dest; 30*95080923SMichael Brumbelow int32 count = destSampleCount; 31*95080923SMichael Brumbelow float gain = _gain * gnum / gden; 3227606daeSAdrien Destugues 3327606daeSAdrien Destugues if (srcSampleCount == destSampleCount) { 3427606daeSAdrien Destugues // optimized case for no resampling 3527606daeSAdrien Destugues while (count--) { 36cfe72209SMáximo Castañeda float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle; 372e68fbd2SMáximo Castañeda if (tmp <= min) 382e68fbd2SMáximo Castañeda *(outType *)dest = min; 392e68fbd2SMáximo Castañeda else if (tmp >= max) 402e68fbd2SMáximo Castañeda *(outType *)dest = max; 412e68fbd2SMáximo Castañeda else 4227606daeSAdrien Destugues *(outType *)dest = (outType)tmp; 4327606daeSAdrien Destugues src += srcSampleOffset; 4427606daeSAdrien Destugues dest += destSampleOffset; 4527606daeSAdrien Destugues } 4627606daeSAdrien Destugues return; 4727606daeSAdrien Destugues } 4827606daeSAdrien Destugues 49*95080923SMichael Brumbelow float delta = float(srcSampleCount) / float(destSampleCount); 50*95080923SMichael Brumbelow float current = 0.0f; 5127606daeSAdrien Destugues 5227606daeSAdrien Destugues // downsample 5327606daeSAdrien Destugues while (count--) { 54cfe72209SMáximo Castañeda float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle; 552e68fbd2SMáximo Castañeda if (tmp <= min) 562e68fbd2SMáximo Castañeda *(outType *)dest = min; 572e68fbd2SMáximo Castañeda else if (tmp >= max) 582e68fbd2SMáximo Castañeda *(outType *)dest = max; 592e68fbd2SMáximo Castañeda else 6027606daeSAdrien Destugues *(outType *)dest = (outType)tmp; 6127606daeSAdrien Destugues 6227606daeSAdrien Destugues dest += destSampleOffset; 6327606daeSAdrien Destugues current += delta; 64*95080923SMichael Brumbelow int32 skipcount = (int32)current; 6527606daeSAdrien Destugues current -= skipcount; 6627606daeSAdrien Destugues src += skipcount * srcSampleOffset; 6727606daeSAdrien Destugues } 6827606daeSAdrien Destugues } 6927606daeSAdrien Destugues 7027606daeSAdrien Destugues 71f0a85f97SJérôme Duval Resampler::Resampler(uint32 src_format, uint32 dst_format) 72a9cf57cfSAxel Dörfler : 7378341a93SJohn Scipione fFunc(0) 74575526ffSbeveloper { 75575526ffSbeveloper if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) { 76575526ffSbeveloper switch (src_format) { 77575526ffSbeveloper case media_raw_audio_format::B_AUDIO_FLOAT: 78cfe72209SMáximo Castañeda fFunc = &kernel<float, float, 1, 1, 0, 0, -1, 1>; 79575526ffSbeveloper return; 80575526ffSbeveloper case media_raw_audio_format::B_AUDIO_INT: 81cfe72209SMáximo Castañeda fFunc = &kernel<int32, float, 1, INT32_MAX, 0, 0, -1, 1>; 82575526ffSbeveloper return; 83575526ffSbeveloper case media_raw_audio_format::B_AUDIO_SHORT: 84cfe72209SMáximo Castañeda fFunc = &kernel<int16, float, 1, INT16_MAX, 0, 0, -1, 1>; 85575526ffSbeveloper return; 86575526ffSbeveloper case media_raw_audio_format::B_AUDIO_CHAR: 87cfe72209SMáximo Castañeda fFunc = &kernel<int8, float, 1, INT8_MAX, 0, 0, -1, 1>; 88575526ffSbeveloper return; 89575526ffSbeveloper case media_raw_audio_format::B_AUDIO_UCHAR: 90cfe72209SMáximo Castañeda fFunc = &kernel<uint8, float, 2, UINT8_MAX, 128, 0, -1, 1>; 91575526ffSbeveloper return; 92575526ffSbeveloper default: 93a9cf57cfSAxel Dörfler ERROR("Resampler::Resampler: unknown source format 0x%x\n", 94a9cf57cfSAxel Dörfler src_format); 95575526ffSbeveloper return; 96575526ffSbeveloper } 97575526ffSbeveloper } 98575526ffSbeveloper 99575526ffSbeveloper if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) { 100575526ffSbeveloper switch (dst_format) { 101575526ffSbeveloper // float=>float already handled above 102575526ffSbeveloper case media_raw_audio_format::B_AUDIO_INT: 103cfe72209SMáximo Castañeda fFunc = &kernel<float, int32, INT32_MAX, 1, 0, 0, 10427606daeSAdrien Destugues INT32_MIN, INT32_MAX>; 105575526ffSbeveloper return; 106575526ffSbeveloper case media_raw_audio_format::B_AUDIO_SHORT: 107cfe72209SMáximo Castañeda fFunc = &kernel<float, int16, INT16_MAX, 1, 0, 0, 10827606daeSAdrien Destugues INT16_MIN, INT16_MAX>; 109575526ffSbeveloper return; 110575526ffSbeveloper case media_raw_audio_format::B_AUDIO_CHAR: 111cfe72209SMáximo Castañeda fFunc = &kernel<float, int8, INT8_MAX, 1, 0, 0, 11227606daeSAdrien Destugues INT8_MIN, INT8_MAX>; 113575526ffSbeveloper return; 114575526ffSbeveloper case media_raw_audio_format::B_AUDIO_UCHAR: 115cfe72209SMáximo Castañeda fFunc = &kernel<float, uint8, UINT8_MAX, 2, 0, 128, 11627606daeSAdrien Destugues 0, UINT8_MAX>; 117575526ffSbeveloper return; 118575526ffSbeveloper default: 11927606daeSAdrien Destugues ERROR("Resampler::Resampler: unknown destination format 0x%x\n", 12027606daeSAdrien Destugues dst_format); 121575526ffSbeveloper return; 122575526ffSbeveloper } 123575526ffSbeveloper } 124575526ffSbeveloper 125a9cf57cfSAxel Dörfler ERROR("Resampler::Resampler: source or destination format must be " 126a9cf57cfSAxel Dörfler "B_AUDIO_FLOAT\n"); 127575526ffSbeveloper } 128575526ffSbeveloper 129a9cf57cfSAxel Dörfler 13027606daeSAdrien Destugues Resampler::Resampler() 13127606daeSAdrien Destugues : 13227606daeSAdrien Destugues fFunc(0) 133575526ffSbeveloper { 134575526ffSbeveloper } 135575526ffSbeveloper 136a9cf57cfSAxel Dörfler 137