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*cfe72209SMáximo Castañeda template<typename inType, typename outType, int gnum, int gden, 23*cfe72209SMá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 { 2827606daeSAdrien Destugues register const char * src = (const char *)_src; 2927606daeSAdrien Destugues register char * dest = (char *)_dest; 3027606daeSAdrien Destugues register int32 count = destSampleCount; 3127606daeSAdrien Destugues register float gain = _gain * gnum / gden; 3227606daeSAdrien Destugues 3327606daeSAdrien Destugues if (srcSampleCount == destSampleCount) { 3427606daeSAdrien Destugues // optimized case for no resampling 3527606daeSAdrien Destugues while (count--) { 36*cfe72209SMáximo Castañeda float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle; 3727606daeSAdrien Destugues if (tmp < min) tmp = min; 3827606daeSAdrien Destugues if (tmp > max) tmp = max; 3927606daeSAdrien Destugues *(outType *)dest = (outType)tmp; 4027606daeSAdrien Destugues src += srcSampleOffset; 4127606daeSAdrien Destugues dest += destSampleOffset; 4227606daeSAdrien Destugues } 4327606daeSAdrien Destugues return; 4427606daeSAdrien Destugues } 4527606daeSAdrien Destugues 4627606daeSAdrien Destugues register float delta = float(srcSampleCount) / float(destSampleCount); 4727606daeSAdrien Destugues register float current = 0.0f; 4827606daeSAdrien Destugues 4927606daeSAdrien Destugues // downsample 5027606daeSAdrien Destugues while (count--) { 51*cfe72209SMáximo Castañeda float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle; 5227606daeSAdrien Destugues if (tmp < min) tmp = min; 5327606daeSAdrien Destugues if (tmp > max) tmp = max; 5427606daeSAdrien Destugues *(outType *)dest = (outType)tmp; 5527606daeSAdrien Destugues 5627606daeSAdrien Destugues dest += destSampleOffset; 5727606daeSAdrien Destugues current += delta; 5827606daeSAdrien Destugues register int32 skipcount = (int32)current; 5927606daeSAdrien Destugues current -= skipcount; 6027606daeSAdrien Destugues src += skipcount * srcSampleOffset; 6127606daeSAdrien Destugues } 6227606daeSAdrien Destugues } 6327606daeSAdrien Destugues 6427606daeSAdrien 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*cfe72209SMáximo Castañeda fFunc = &kernel<float, float, 1, 1, 0, 0, -1, 1>; 73575526ffSbeveloper return; 74575526ffSbeveloper case media_raw_audio_format::B_AUDIO_INT: 75*cfe72209SMáximo Castañeda fFunc = &kernel<int32, float, 1, INT32_MAX, 0, 0, -1, 1>; 76575526ffSbeveloper return; 77575526ffSbeveloper case media_raw_audio_format::B_AUDIO_SHORT: 78*cfe72209SMáximo Castañeda fFunc = &kernel<int16, float, 1, INT16_MAX, 0, 0, -1, 1>; 79575526ffSbeveloper return; 80575526ffSbeveloper case media_raw_audio_format::B_AUDIO_CHAR: 81*cfe72209SMáximo Castañeda fFunc = &kernel<int8, float, 1, INT8_MAX, 0, 0, -1, 1>; 82575526ffSbeveloper return; 83575526ffSbeveloper case media_raw_audio_format::B_AUDIO_UCHAR: 84*cfe72209SMáximo Castañeda fFunc = &kernel<uint8, float, 2, UINT8_MAX, 128, 0, -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*cfe72209SMáximo Castañeda fFunc = &kernel<float, int32, INT32_MAX, 1, 0, 0, 9827606daeSAdrien Destugues INT32_MIN, INT32_MAX>; 99575526ffSbeveloper return; 100575526ffSbeveloper case media_raw_audio_format::B_AUDIO_SHORT: 101*cfe72209SMáximo Castañeda fFunc = &kernel<float, int16, INT16_MAX, 1, 0, 0, 10227606daeSAdrien Destugues INT16_MIN, INT16_MAX>; 103575526ffSbeveloper return; 104575526ffSbeveloper case media_raw_audio_format::B_AUDIO_CHAR: 105*cfe72209SMáximo Castañeda fFunc = &kernel<float, int8, INT8_MAX, 1, 0, 0, 10627606daeSAdrien Destugues INT8_MIN, INT8_MAX>; 107575526ffSbeveloper return; 108575526ffSbeveloper case media_raw_audio_format::B_AUDIO_UCHAR: 109*cfe72209SMáximo Castañeda fFunc = &kernel<float, uint8, UINT8_MAX, 2, 0, 128, 11027606daeSAdrien Destugues 0, UINT8_MAX>; 111575526ffSbeveloper return; 112575526ffSbeveloper default: 11327606daeSAdrien Destugues ERROR("Resampler::Resampler: unknown destination format 0x%x\n", 11427606daeSAdrien 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 12427606daeSAdrien Destugues Resampler::Resampler() 12527606daeSAdrien Destugues : 12627606daeSAdrien Destugues fFunc(0) 127575526ffSbeveloper { 128575526ffSbeveloper } 129575526ffSbeveloper 130a9cf57cfSAxel Dörfler 131