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