2 * Copyright 2000-2006 Ingo Weinhold <ingo_weinhold@gmx.de>
3 * All rights reserved. Distributed under the terms of the MIT licensce.
7 #include "AudioResampler.h"
11 #include "SampleBuffer.h"
14 //#define TRACE_AUDIO_RESAMPLER
15 #ifdef TRACE_AUDIO_RESAMPLER
16 # define TRACE(x...) printf(x)
22 //! Calculates the greatest common divider of /a/ and /b/.
23 template<typename T
> inline
36 template<typename Buffer
>
38 resample_linear(void* _inBuffer
, void* _outBuffer
, uint32 channelCount
,
39 double inFrameRate
, double outFrameRate
, int32 frames
)
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
;
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
63 outFrameBuf
.WriteSample((timeDiff2
* inFrameBuf1
.ReadSample()
64 + timeDiff1
* inFrameBuf2
.ReadSample()) / timeDiff
);
73 AudioResampler::AudioResampler()
83 AudioResampler::AudioResampler(AudioReader
* source
, float frameRate
,
88 fTimeScale(timeScale
),
93 fFormat
.u
.raw_audio
.frame_rate
= frameRate
;
97 AudioResampler::~AudioResampler()
103 AudioResampler::InitialLatency() const
105 return fSource
->InitialLatency();
110 AudioResampler::Read(void* buffer
, int64 pos
, int64 frames
)
112 TRACE("AudioResampler::Read(%p, %Ld, %Ld)\n", buffer
, pos
, frames
);
114 status_t error
= InitCheck();
116 TRACE("AudioResampler::Read() done1\n");
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
);
127 if (sourceFrames
== 0) {
128 ReadSilence(buffer
, frames
);
129 TRACE("AudioResampler::Read() done3\n");
132 // check, if playing backwards
133 bool backward
= false;
134 if (sourceFrames
< 0) {
135 sourceFrames
= -sourceFrames
;
136 sourcePos
-= sourceFrames
;
140 // we need at least two frames to interpolate
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
);
147 TRACE("AudioResampler::_ReadLinear() done4\n");
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
);
159 case media_raw_audio_format::B_AUDIO_INT
:
160 resample_linear
< IntSampleBuffer
<double> >(inBuffer
, buffer
,
161 channelCount
, inFrameRate
, outFrameRate
, (int32
)frames
);
163 case media_raw_audio_format::B_AUDIO_SHORT
:
164 resample_linear
< ShortSampleBuffer
<double> >(inBuffer
, buffer
,
165 channelCount
, inFrameRate
, outFrameRate
, (int32
)frames
);
167 case media_raw_audio_format::B_AUDIO_UCHAR
:
168 resample_linear
< UCharSampleBuffer
<double> >(inBuffer
, buffer
,
169 channelCount
, inFrameRate
, outFrameRate
, (int32
)frames
);
171 case media_raw_audio_format::B_AUDIO_CHAR
:
172 resample_linear
< CharSampleBuffer
<double> >(inBuffer
, buffer
,
173 channelCount
, inFrameRate
, outFrameRate
, (int32
)frames
);
176 // reverse the frame order if reading backwards
178 ReverseFrames(buffer
, frames
);
180 TRACE("AudioResampler::Read() done\n");
186 AudioResampler::InitCheck() const
188 status_t error
= AudioReader::InitCheck();
189 if (error
== B_OK
&& !fSource
)
196 AudioResampler::SetSource(AudioReader
* source
)
199 TRACE("AudioResampler::SetSource() - NULL source\n");
203 if (source
->Format().type
!= B_MEDIA_RAW_AUDIO
) {
204 TRACE("AudioResampler::SetSource() - not B_MEDIA_RAW_AUDIO\n");
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");
215 float frameRate
= FrameRate();
216 // don't overwrite previous audio frame rate
218 fFormat
= source
->Format();
219 fFormat
.u
.raw_audio
.frame_rate
= frameRate
;
224 AudioResampler::SetFrameRate(float frameRate
)
226 fFormat
.u
.raw_audio
.frame_rate
= frameRate
;
231 AudioResampler::SetTimeScale(float timeScale
)
233 fTimeScale
= timeScale
;
238 AudioResampler::Source() const
245 AudioResampler::FrameRate() const
247 return fFormat
.u
.raw_audio
.frame_rate
;
252 AudioResampler::TimeScale() const
259 AudioResampler::SetInOffset(int64 offset
)
266 AudioResampler::InOffset() const
273 AudioResampler::ConvertFromSource(int64 pos
) const
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
;
283 AudioResampler::ConvertToSource(int64 pos
) const
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
;