1 /* 2 * Copyright © 2000-2006 Ingo Weinhold <ingo_weinhold@gmx.de> 3 * All rights reserved. Distributed under the terms of the MIT licensce. 4 */ 5 #include "AudioResampler.h" 6 7 #include <stdio.h> 8 9 #include "SampleBuffer.h" 10 11 12 //#define TRACE_AUDIO_RESAMPLER 13 #ifdef TRACE_AUDIO_RESAMPLER 14 # define TRACE(x...) printf(x) 15 #else 16 # define TRACE(x...) 17 #endif 18 19 20 AudioResampler::AudioResampler() 21 : AudioReader(), 22 fSource(NULL), 23 fTimeScale(1.0), 24 fInOffset(0) 25 { 26 } 27 28 29 AudioResampler::AudioResampler(AudioReader* source, float frameRate, 30 float timeScale) 31 : AudioReader(), 32 fSource(NULL), 33 fTimeScale(timeScale), 34 fInOffset(0) 35 { 36 SetSource(source); 37 if (fSource) 38 fFormat.u.raw_audio.frame_rate = frameRate; 39 } 40 41 42 AudioResampler::~AudioResampler() 43 { 44 } 45 46 47 //! Calculates the greatest common divider of /a/ and /b/. 48 template<typename T> inline 49 T 50 gcd(T a, T b) 51 { 52 while (b != 0) { 53 T r = a % b; 54 a = b; 55 b = r; 56 } 57 return a; 58 } 59 60 61 template<typename Buffer> 62 static void 63 resample_linear(void* _inBuffer, void* _outBuffer, uint32 channelCount, 64 double inFrameRate, double outFrameRate, int32 frames) 65 { 66 typedef double sample_t; 67 Buffer inBuffer(_inBuffer); 68 Buffer outFrameBuf(_outBuffer); 69 for (sample_t outFrame = 0; outFrame < frames; outFrame++) { 70 // time of the out sample 71 sample_t outTime = outFrame / outFrameRate; 72 // first in frame 73 int64 inFrame = int64(outTime * inFrameRate); 74 // time of the first and the second in frame 75 sample_t inTime1 = (sample_t)inFrame / inFrameRate; 76 sample_t inTime2 = (sample_t)(inFrame + 1) / inFrameRate; 77 // differences between the out frame time and the in frame times 78 sample_t timeDiff1 = outTime - inTime1; 79 sample_t timeDiff2 = inTime2 - outTime; 80 sample_t timeDiff = timeDiff1 + timeDiff2; 81 // pointer to the first and second in frame 82 Buffer inFrameBuf1 = inBuffer + inFrame * channelCount; 83 Buffer inFrameBuf2 = inFrameBuf1 + channelCount; 84 for (uint32 c = 0; c < channelCount; 85 c++, inFrameBuf1++, inFrameBuf2++, outFrameBuf++) { 86 // sum weighted according to the distance to the respective other 87 // in frame 88 outFrameBuf.WriteSample((timeDiff2 * inFrameBuf1.ReadSample() 89 + timeDiff1 * inFrameBuf2.ReadSample()) / timeDiff); 90 } 91 } 92 } 93 94 95 status_t 96 AudioResampler::Read(void* buffer, int64 pos, int64 frames) 97 { 98 TRACE("AudioResampler::Read(%p, %Ld, %Ld)\n", buffer, pos, frames); 99 100 status_t error = InitCheck(); 101 if (error != B_OK) { 102 TRACE("AudioResampler::Read() done1\n"); 103 return error; 104 } 105 // calculate position and frames in the source data 106 int64 sourcePos = ConvertToSource(pos); 107 int64 sourceFrames = ConvertToSource(pos + frames) - sourcePos; 108 // check the frame counts 109 if (sourceFrames == frames) { 110 TRACE("AudioResampler::Read() done2\n"); 111 return fSource->Read(buffer, sourcePos, sourceFrames); 112 } 113 if (sourceFrames == 0) { 114 ReadSilence(buffer, frames); 115 TRACE("AudioResampler::Read() done3\n"); 116 return B_OK; 117 } 118 // check, if playing backwards 119 bool backward = false; 120 if (sourceFrames < 0) { 121 sourceFrames = -sourceFrames; 122 sourcePos -= sourceFrames; 123 backward = true; 124 } 125 126 // we need at least two frames to interpolate 127 sourceFrames += 2; 128 int32 sampleSize = media_raw_audio_format::B_AUDIO_SIZE_MASK; 129 uint32 channelCount = fFormat.u.raw_audio.channel_count; 130 char* inBuffer = new char[sourceFrames * channelCount * sampleSize]; 131 error = fSource->Read(inBuffer, sourcePos, sourceFrames); 132 if (error != B_OK) { 133 TRACE("AudioResampler::_ReadLinear() done4\n"); 134 return error; 135 } 136 double inFrameRate = fSource->Format().u.raw_audio.frame_rate; 137 double outFrameRate = (double)fFormat.u.raw_audio.frame_rate 138 / (double)fTimeScale; 139 // choose the sample buffer to be used 140 switch (fFormat.u.raw_audio.format) { 141 case media_raw_audio_format::B_AUDIO_FLOAT: 142 resample_linear< FloatSampleBuffer<double> >(inBuffer, buffer, 143 channelCount, inFrameRate, outFrameRate, (int32)frames); 144 break; 145 case media_raw_audio_format::B_AUDIO_INT: 146 resample_linear< IntSampleBuffer<double> >(inBuffer, buffer, 147 channelCount, inFrameRate, outFrameRate, (int32)frames); 148 break; 149 case media_raw_audio_format::B_AUDIO_SHORT: 150 resample_linear< ShortSampleBuffer<double> >(inBuffer, buffer, 151 channelCount, inFrameRate, outFrameRate, (int32)frames); 152 break; 153 case media_raw_audio_format::B_AUDIO_UCHAR: 154 resample_linear< UCharSampleBuffer<double> >(inBuffer, buffer, 155 channelCount, inFrameRate, outFrameRate, (int32)frames); 156 break; 157 case media_raw_audio_format::B_AUDIO_CHAR: 158 resample_linear< CharSampleBuffer<double> >(inBuffer, buffer, 159 channelCount, inFrameRate, outFrameRate, (int32)frames); 160 break; 161 } 162 // reverse the frame order if reading backwards 163 if (backward) 164 ReverseFrames(buffer, frames); 165 delete[] inBuffer; 166 TRACE("AudioResampler::Read() done\n"); 167 return B_OK; 168 } 169 170 171 status_t 172 AudioResampler::InitCheck() const 173 { 174 status_t error = AudioReader::InitCheck(); 175 if (error == B_OK && !fSource) 176 error = B_NO_INIT; 177 return error; 178 } 179 180 181 void 182 AudioResampler::SetSource(AudioReader* source) 183 { 184 if (!source) { 185 TRACE("AudioResampler::SetSource() - NULL source\n"); 186 return; 187 } 188 189 if (source->Format().type != B_MEDIA_RAW_AUDIO) { 190 TRACE("AudioResampler::SetSource() - not B_MEDIA_RAW_AUDIO\n"); 191 return; 192 } 193 194 uint32 hostByteOrder 195 = (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN; 196 if (source->Format().u.raw_audio.byte_order != hostByteOrder) { 197 TRACE("AudioResampler::SetSource() - not host byte order\n"); 198 return; 199 } 200 201 float frameRate = FrameRate(); 202 // don't overwrite previous audio frame rate 203 fSource = source; 204 fFormat = source->Format(); 205 fFormat.u.raw_audio.frame_rate = frameRate; 206 } 207 208 209 void 210 AudioResampler::SetFrameRate(float frameRate) 211 { 212 fFormat.u.raw_audio.frame_rate = frameRate; 213 } 214 215 216 void 217 AudioResampler::SetTimeScale(float timeScale) 218 { 219 fTimeScale = timeScale; 220 } 221 222 223 AudioReader* 224 AudioResampler::Source() const 225 { 226 return fSource; 227 } 228 229 230 float 231 AudioResampler::FrameRate() const 232 { 233 return fFormat.u.raw_audio.frame_rate; 234 } 235 236 237 float 238 AudioResampler::TimeScale() const 239 { 240 return fTimeScale; 241 } 242 243 244 void 245 AudioResampler::SetInOffset(int64 offset) 246 { 247 fInOffset = offset; 248 } 249 250 251 int64 252 AudioResampler::InOffset() const 253 { 254 return fInOffset; 255 } 256 257 258 int64 259 AudioResampler::ConvertFromSource(int64 pos) const 260 { 261 double inFrameRate = fSource->Format().u.raw_audio.frame_rate; 262 double outFrameRate = fFormat.u.raw_audio.frame_rate; 263 return (int64)((double)(pos - fInOffset) * outFrameRate / inFrameRate 264 / (double)fTimeScale) - fOutOffset; 265 } 266 267 268 int64 269 AudioResampler::ConvertToSource(int64 pos) const 270 { 271 double inFrameRate = fSource->Format().u.raw_audio.frame_rate; 272 double outFrameRate = fFormat.u.raw_audio.frame_rate; 273 return (int64)((double)(pos + fOutOffset) * inFrameRate / outFrameRate 274 * (double)fTimeScale) + fInOffset; 275 } 276 277