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