1 /* 2 * Copyright 2010-2014 Haiku, inc. 3 * Distributed under the terms of the MIT Licence. 4 * 5 * Author: Adrien Destugues <pulkomandy@pulkomandy.tk> 6 */ 7 8 9 #include "Interpolate.h" 10 11 #include <cmath> 12 13 #include <MediaDefs.h> 14 15 #include "MixerDebug.h" 16 17 18 /*! Resampling class doing linear interpolation. 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 register const char * src = (const char *)_src; 29 register char * dest = (char *)_dest; 30 register int32 count = destSampleCount; 31 register 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) tmp = min; 38 if (tmp > max) tmp = max; 39 *(outType *)dest = (outType)tmp; 40 src += srcSampleOffset; 41 dest += destSampleOffset; 42 } 43 return; 44 } 45 46 register float delta = float(srcSampleCount) / float(destSampleCount); 47 register float current = 0.0f; 48 float oldSample = ((Interpolate*)object)->fOldSample; 49 50 #define SRC *(const inType*)(src) 51 52 while (count--) { 53 float tmp = (gain * (oldSample + (SRC - oldSample) * current - inMiddle) 54 + outMiddle); 55 if (tmp < min) tmp = min; 56 if (tmp > max) tmp = max; 57 *(outType *)dest = (outType)tmp; 58 59 dest += destSampleOffset; 60 current += delta; 61 if (current >= 1.0f) { 62 double ipart; 63 current = modf(current, &ipart); 64 oldSample = SRC; 65 src += srcSampleOffset * (int)ipart; 66 } 67 } 68 69 ((Interpolate*)object)->fOldSample = oldSample; 70 } 71 72 73 Interpolate::Interpolate(uint32 src_format, uint32 dst_format) 74 : 75 Resampler(), 76 fOldSample(0) 77 { 78 if (src_format == media_raw_audio_format::B_AUDIO_UCHAR) 79 fOldSample = 128; 80 81 if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) { 82 switch (src_format) { 83 case media_raw_audio_format::B_AUDIO_FLOAT: 84 fFunc = &kernel<float, float, 1, 1, 0, 0, -1, 1>; 85 return; 86 case media_raw_audio_format::B_AUDIO_INT: 87 fFunc = &kernel<int32, float, 1, INT32_MAX, 0, 0, -1, 1>; 88 return; 89 case media_raw_audio_format::B_AUDIO_SHORT: 90 fFunc = &kernel<int16, float, 1, INT16_MAX, 0, 0, -1, 1>; 91 return; 92 case media_raw_audio_format::B_AUDIO_CHAR: 93 fFunc = &kernel<int8, float, 1, INT8_MAX, 0, 0, -1, 1>; 94 return; 95 case media_raw_audio_format::B_AUDIO_UCHAR: 96 fFunc = &kernel<uint8, float, 2, UINT8_MAX, 128, 0, -1, 1>; 97 return; 98 default: 99 ERROR("Resampler::Resampler: unknown source format 0x%x\n", 100 src_format); 101 return; 102 } 103 } 104 105 if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) { 106 switch (dst_format) { 107 // float=>float already handled above 108 case media_raw_audio_format::B_AUDIO_INT: 109 fFunc = &kernel<float, int32, INT32_MAX, 1, 0, 0, 110 INT32_MIN, INT32_MAX>; 111 return; 112 case media_raw_audio_format::B_AUDIO_SHORT: 113 fFunc = &kernel<float, int16, INT16_MAX, 1, 0, 0, 114 INT16_MIN, INT16_MAX>; 115 return; 116 case media_raw_audio_format::B_AUDIO_CHAR: 117 fFunc = &kernel<float, int8, INT8_MAX, 1, 0, 0, 118 INT8_MIN, INT8_MAX>; 119 return; 120 case media_raw_audio_format::B_AUDIO_UCHAR: 121 fFunc = &kernel<float, uint8, UINT8_MAX, 2, 0, 128, 122 0, UINT8_MAX>; 123 return; 124 default: 125 ERROR("Resampler::Resampler: unknown destination format 0x%x\n", 126 dst_format); 127 return; 128 } 129 } 130 131 ERROR("Resampler::Resampler: source or destination format must be " 132 "B_AUDIO_FLOAT\n"); 133 } 134 135 136