1 /* 2 * Copyright 2003 Marcus Overhagen 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "Resampler.h" 8 9 #include <MediaDefs.h> 10 11 #include "MixerDebug.h" 12 13 14 /*! A simple resampling class for the audio mixer. 15 You pick the conversion function on object creation, 16 and then call the Resample() function, specifying data pointer, 17 offset (in bytes) to the next sample, and count of samples for 18 both source and destination. 19 */ 20 21 22 template<typename inType, typename outType, int gnum, int gden, 23 int inMiddle, int outMiddle, int32 min, int32 max> static void 24 kernel(Resampler* object, const void *_src, int32 srcSampleOffset, 25 int32 srcSampleCount, void *_dest, int32 destSampleOffset, 26 int32 destSampleCount, float _gain) 27 { 28 const char * src = (const char *)_src; 29 char * dest = (char *)_dest; 30 int32 count = destSampleCount; 31 float gain = _gain * gnum / gden; 32 33 if (srcSampleCount == destSampleCount) { 34 // optimized case for no resampling 35 while (count--) { 36 float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle; 37 if (tmp <= min) 38 *(outType *)dest = min; 39 else if (tmp >= max) 40 *(outType *)dest = max; 41 else 42 *(outType *)dest = (outType)tmp; 43 src += srcSampleOffset; 44 dest += destSampleOffset; 45 } 46 return; 47 } 48 49 float delta = float(srcSampleCount) / float(destSampleCount); 50 float current = 0.0f; 51 52 // downsample 53 while (count--) { 54 float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle; 55 if (tmp <= min) 56 *(outType *)dest = min; 57 else if (tmp >= max) 58 *(outType *)dest = max; 59 else 60 *(outType *)dest = (outType)tmp; 61 62 dest += destSampleOffset; 63 current += delta; 64 int32 skipcount = (int32)current; 65 current -= skipcount; 66 src += skipcount * srcSampleOffset; 67 } 68 } 69 70 71 Resampler::Resampler(uint32 src_format, uint32 dst_format) 72 : 73 fFunc(0) 74 { 75 if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) { 76 switch (src_format) { 77 case media_raw_audio_format::B_AUDIO_FLOAT: 78 fFunc = &kernel<float, float, 1, 1, 0, 0, -1, 1>; 79 return; 80 case media_raw_audio_format::B_AUDIO_INT: 81 fFunc = &kernel<int32, float, 1, INT32_MAX, 0, 0, -1, 1>; 82 return; 83 case media_raw_audio_format::B_AUDIO_SHORT: 84 fFunc = &kernel<int16, float, 1, INT16_MAX, 0, 0, -1, 1>; 85 return; 86 case media_raw_audio_format::B_AUDIO_CHAR: 87 fFunc = &kernel<int8, float, 1, INT8_MAX, 0, 0, -1, 1>; 88 return; 89 case media_raw_audio_format::B_AUDIO_UCHAR: 90 fFunc = &kernel<uint8, float, 2, UINT8_MAX, 128, 0, -1, 1>; 91 return; 92 default: 93 ERROR("Resampler::Resampler: unknown source format 0x%x\n", 94 src_format); 95 return; 96 } 97 } 98 99 if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) { 100 switch (dst_format) { 101 // float=>float already handled above 102 case media_raw_audio_format::B_AUDIO_INT: 103 fFunc = &kernel<float, int32, INT32_MAX, 1, 0, 0, 104 INT32_MIN, INT32_MAX>; 105 return; 106 case media_raw_audio_format::B_AUDIO_SHORT: 107 fFunc = &kernel<float, int16, INT16_MAX, 1, 0, 0, 108 INT16_MIN, INT16_MAX>; 109 return; 110 case media_raw_audio_format::B_AUDIO_CHAR: 111 fFunc = &kernel<float, int8, INT8_MAX, 1, 0, 0, 112 INT8_MIN, INT8_MAX>; 113 return; 114 case media_raw_audio_format::B_AUDIO_UCHAR: 115 fFunc = &kernel<float, uint8, UINT8_MAX, 2, 0, 128, 116 0, UINT8_MAX>; 117 return; 118 default: 119 ERROR("Resampler::Resampler: unknown destination format 0x%x\n", 120 dst_format); 121 return; 122 } 123 } 124 125 ERROR("Resampler::Resampler: source or destination format must be " 126 "B_AUDIO_FLOAT\n"); 127 } 128 129 130 Resampler::Resampler() 131 : 132 fFunc(0) 133 { 134 } 135 136 137