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 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 float oldSample = ((Interpolate*)object)->fOldSample; 52 53 #define SRC *(const inType*)(src) 54 55 while (count--) { 56 float tmp = (gain * (oldSample + (SRC - oldSample) * current - inMiddle) 57 + outMiddle); 58 if (tmp <= min) 59 *(outType *)dest = min; 60 else if (tmp >= max) 61 *(outType *)dest = max; 62 else 63 *(outType *)dest = (outType)tmp; 64 65 dest += destSampleOffset; 66 current += delta; 67 if (current >= 1.0f) { 68 double ipart; 69 current = modf(current, &ipart); 70 oldSample = SRC; 71 src += srcSampleOffset * (int)ipart; 72 } 73 } 74 75 ((Interpolate*)object)->fOldSample = oldSample; 76 } 77 78 79 Interpolate::Interpolate(uint32 src_format, uint32 dst_format) 80 : 81 Resampler(), 82 fOldSample(0) 83 { 84 if (src_format == media_raw_audio_format::B_AUDIO_UCHAR) 85 fOldSample = 128; 86 87 if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) { 88 switch (src_format) { 89 case media_raw_audio_format::B_AUDIO_FLOAT: 90 fFunc = &kernel<float, float, 1, 1, 0, 0, -1, 1>; 91 return; 92 case media_raw_audio_format::B_AUDIO_INT: 93 fFunc = &kernel<int32, float, 1, INT32_MAX, 0, 0, -1, 1>; 94 return; 95 case media_raw_audio_format::B_AUDIO_SHORT: 96 fFunc = &kernel<int16, float, 1, INT16_MAX, 0, 0, -1, 1>; 97 return; 98 case media_raw_audio_format::B_AUDIO_CHAR: 99 fFunc = &kernel<int8, float, 1, INT8_MAX, 0, 0, -1, 1>; 100 return; 101 case media_raw_audio_format::B_AUDIO_UCHAR: 102 fFunc = &kernel<uint8, float, 2, UINT8_MAX, 128, 0, -1, 1>; 103 return; 104 default: 105 ERROR("Resampler::Resampler: unknown source format 0x%x\n", 106 src_format); 107 return; 108 } 109 } 110 111 if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) { 112 switch (dst_format) { 113 // float=>float already handled above 114 case media_raw_audio_format::B_AUDIO_INT: 115 fFunc = &kernel<float, int32, INT32_MAX, 1, 0, 0, 116 INT32_MIN, INT32_MAX>; 117 return; 118 case media_raw_audio_format::B_AUDIO_SHORT: 119 fFunc = &kernel<float, int16, INT16_MAX, 1, 0, 0, 120 INT16_MIN, INT16_MAX>; 121 return; 122 case media_raw_audio_format::B_AUDIO_CHAR: 123 fFunc = &kernel<float, int8, INT8_MAX, 1, 0, 0, 124 INT8_MIN, INT8_MAX>; 125 return; 126 case media_raw_audio_format::B_AUDIO_UCHAR: 127 fFunc = &kernel<float, uint8, UINT8_MAX, 2, 0, 128, 128 0, UINT8_MAX>; 129 return; 130 default: 131 ERROR("Resampler::Resampler: unknown destination format 0x%x\n", 132 dst_format); 133 return; 134 } 135 } 136 137 ERROR("Resampler::Resampler: source or destination format must be " 138 "B_AUDIO_FLOAT\n"); 139 } 140 141 142