2 * Copyright 2008 Stephan Aßmus <superstippi@gmx.de>
3 * All Rights Reserved. Distributed under the terms of the MIT license.
7 #include "ProxyAudioSupplier.h"
17 #include "AudioTrackSupplier.h"
18 #include "AudioAdapter.h"
19 #include "AudioVolumeConverter.h"
20 #include "PlaybackManager.h"
26 //#define TRACE_PROXY_AUDIO_SUPPLIER
27 #ifdef TRACE_PROXY_AUDIO_SUPPLIER
28 # define TRACE(x...) printf("ProxyAudioSupplier::"); printf(x)
29 # define ERROR(x...) fprintf(stderr, "ProxyAudioSupplier::"); fprintf(stderr, x)
32 # define ERROR(x...) fprintf(stderr, "ProxyAudioSupplier::"); fprintf(stderr, x)
36 struct PlayingInterval
{
37 PlayingInterval(bigtime_t startTime
, bigtime_t endTime
)
39 start_time(startTime
),
46 bigtime_t x_start_time
;
52 ProxyAudioSupplier::ProxyAudioSupplier(PlaybackManager
* playbackManager
)
54 fSupplierLock("audio supplier lock"),
56 fPlaybackManager(playbackManager
),
57 fVideoFrameRate(25.0),
62 fVolumeConverter(NULL
),
65 TRACE("ProxyAudioSupplier()\n");
69 ProxyAudioSupplier::~ProxyAudioSupplier()
71 TRACE("~ProxyAudioSupplier()\n");
73 delete fVolumeConverter
;
78 ProxyAudioSupplier::InitialLatency() const
80 BAutolock
_(fSupplierLock
);
82 if (fSupplier
== NULL
)
85 return fSupplier
->InitialLatency();
90 ProxyAudioSupplier::GetFrames(void* buffer
, int64 frameCount
,
91 bigtime_t startTime
, bigtime_t endTime
)
93 TRACE("GetFrames(%p, frameCount: %" B_PRId64
", time interval: %"
94 B_PRIdBIGTIME
" - %" B_PRIdBIGTIME
")\n",
95 buffer
, frameCount
, startTime
, endTime
);
97 // Create a list of playing intervals which compose the supplied
98 // performance time interval.
99 BList playingIntervals
;
100 status_t error
= fPlaybackManager
->LockWithTimeout(10000);
102 bigtime_t intervalStartTime
= startTime
;
103 while (intervalStartTime
< endTime
) {
104 PlayingInterval
* interval
105 = new (nothrow
) PlayingInterval(intervalStartTime
, endTime
);
110 fPlaybackManager
->GetPlaylistTimeInterval(
111 interval
->start_time
, interval
->end_time
,
112 interval
->x_start_time
, interval
->x_end_time
,
114 if (intervalStartTime
== interval
->end_time
) {
117 ERROR("GetFrames() - zero duration audio interval! start "
118 "time: %" B_PRIdBIGTIME
"\n", intervalStartTime
);
121 if (!playingIntervals
.AddItem(interval
)) {
124 ERROR("GetFrames() - Out of memory\n");
127 intervalStartTime
= interval
->end_time
;
129 fPlaybackManager
->SetCurrentAudioTime(endTime
);
130 fPlaybackManager
->Unlock();
131 } else if (error
== B_TIMED_OUT
) {
132 TRACE("GetFrames() - LOCKING THE PLAYBACK MANAGER TIMED OUT!!!\n");
135 BAutolock
_(fSupplierLock
);
140 // retrieve the audio data for each interval.
141 #ifdef TRACE_PROXY_AUDIO_SUPPLIER
142 int32 intervalIndex
= 0;
145 int64 framesRead
= 0;
146 while (!playingIntervals
.IsEmpty()) {
147 PlayingInterval
* interval
148 = (PlayingInterval
*)playingIntervals
.RemoveItem((int32
)0);
154 // get playing direction
155 int32 playingDirection
= 0;
156 if (interval
->speed
> 0)
157 playingDirection
= 1;
158 else if (interval
->speed
< 0)
159 playingDirection
= -1;
160 float absSpeed
= interval
->speed
* playingDirection
;
161 int64 framesToRead
= _AudioFrameForTime(interval
->end_time
)
162 - _AudioFrameForTime(interval
->start_time
);
164 TRACE("GetFrames() - interval (%ld) [%lld, %lld]: [%lld, %lld], "
165 "frames: %lld\n", intervalIndex
,
166 interval
->start_time
, interval
->end_time
,
167 interval
->x_start_time
, interval
->x_end_time
,
172 _ReadSilence(buffer
, framesToRead
);
175 fAudioResampler
.SetInOffset(
176 _AudioFrameForTime(interval
->x_start_time
));
177 fAudioResampler
.SetTimeScale(absSpeed
);
178 error
= fAudioResampler
.Read(buffer
, 0, framesToRead
);
179 // backwards -> reverse frames
180 if (error
== B_OK
&& interval
->speed
< 0)
181 _ReverseFrames(buffer
, framesToRead
);
183 // read silence on error
185 _ReadSilence(buffer
, framesToRead
);
188 framesRead
+= framesToRead
;
189 buffer
= _SkipFrames(buffer
, framesToRead
);
192 #ifdef TRACE_PROXY_AUDIO_SUPPLIER
196 // read silence on error
198 _ReadSilence(buffer
, frameCount
);
202 TRACE("GetFrames() done\n");
209 ProxyAudioSupplier::SetFormat(const media_format
& format
)
211 //printf("ProxyAudioSupplier::SetFormat()\n");
212 #ifdef TRACE_PROXY_AUDIO_SUPPLIER
214 string_for_format(format
, string
, 256);
215 TRACE("SetFormat(%s)\n", string
);
218 BAutolock
_(fSupplierLock
);
220 fAudioResampler
.SetFormat(format
);
222 // In case SetSupplier was called before, we need
223 // to adapt to the new format, or maybe the format
224 // was still invalid.
225 SetSupplier(fSupplier
, fVideoFrameRate
);
230 ProxyAudioSupplier::Format() const
232 return fAudioResampler
.Format();
237 ProxyAudioSupplier::InitCheck() const
239 status_t ret
= AudioSupplier::InitCheck();
247 ProxyAudioSupplier::SetSupplier(AudioTrackSupplier
* supplier
,
248 float videoFrameRate
)
250 //printf("ProxyAudioSupplier::SetSupplier(%p, %.1f)\n", supplier,
252 TRACE("SetSupplier(%p, %.1f)\n", supplier
, videoFrameRate
);
254 BAutolock
_(fSupplierLock
);
256 fSupplier
= supplier
;
257 fVideoFrameRate
= videoFrameRate
;
260 delete fVolumeConverter
;
262 fAdapter
= new AudioAdapter(fSupplier
, Format());
263 fVolumeConverter
= new AudioVolumeConverter(fAdapter
, fVolume
);
265 fAudioResampler
.SetSource(fVolumeConverter
);
270 ProxyAudioSupplier::SetVolume(float volume
)
272 BAutolock
_(fSupplierLock
);
274 if (fVolumeConverter
)
275 fVolumeConverter
->SetVolume(volume
);
280 ProxyAudioSupplier::Volume()
282 BAutolock
_(fSupplierLock
);
287 // #pragma mark - audio/video/frame/time conversion
291 ProxyAudioSupplier::_AudioFrameForVideoFrame(int64 frame
) const
294 return (int64
)((double)frame
* Format().u
.raw_audio
.frame_rate
297 const media_format
& format
= fSupplier
->Format();
298 return (int64
)((double)frame
* format
.u
.raw_audio
.frame_rate
304 ProxyAudioSupplier::_VideoFrameForAudioFrame(int64 frame
) const
307 return (int64
)((double)frame
* fVideoFrameRate
308 / Format().u
.raw_audio
.frame_rate
);
311 const media_format
& format
= fSupplier
->Format();
312 return (int64
)((double)frame
* fVideoFrameRate
313 / format
.u
.raw_audio
.frame_rate
);
318 ProxyAudioSupplier::_AudioFrameForTime(bigtime_t time
) const
320 return (int64
)((double)time
* Format().u
.raw_audio
.frame_rate
326 ProxyAudioSupplier::_VideoFrameForTime(bigtime_t time
) const
328 return (int64
)((double)time
* fVideoFrameRate
/ 1000000.0);
332 // #pragma mark - utility
336 ProxyAudioSupplier::_ReadSilence(void* buffer
, int64 frames
) const
338 memset(buffer
, 0, (char*)_SkipFrames(buffer
, frames
) - (char*)buffer
);
343 ProxyAudioSupplier::_ReverseFrames(void* buffer
, int64 frames
) const
345 int32 sampleSize
= Format().u
.raw_audio
.format
346 & media_raw_audio_format::B_AUDIO_SIZE_MASK
;
347 int32 frameSize
= sampleSize
* Format().u
.raw_audio
.channel_count
;
348 char* front
= (char*)buffer
;
349 char* back
= (char*)buffer
+ (frames
- 1) * frameSize
;
350 while (front
< back
) {
351 for (int32 i
= 0; i
< frameSize
; i
++)
352 swap(front
[i
], back
[i
]);
360 ProxyAudioSupplier::_SkipFrames(void* buffer
, int64 frames
) const
362 int32 sampleSize
= Format().u
.raw_audio
.format
363 & media_raw_audio_format::B_AUDIO_SIZE_MASK
;
364 int32 frameSize
= sampleSize
* Format().u
.raw_audio
.channel_count
;
365 return (char*)buffer
+ frames
* frameSize
;