1/* 2 * Copyright 2008 Stephan Aßmus <superstippi@gmx.de> 3 * All Rights Reserved. Distributed under the terms of the MIT license. 4 */ 5 6 7#include "ProxyAudioSupplier.h" 8 9#include <algorithm> 10#include <new> 11#include <stdio.h> 12#include <string.h> 13 14#include <Autolock.h> 15#include <List.h> 16 17#include "AudioTrackSupplier.h" 18#include "AudioAdapter.h" 19#include "AudioVolumeConverter.h" 20#include "PlaybackManager.h" 21 22using std::nothrow; 23using std::swap; 24 25 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) 30#else 31# define TRACE(x...) 32# define ERROR(x...) fprintf(stderr, "ProxyAudioSupplier::"); fprintf(stderr, x) 33#endif 34 35 36struct PlayingInterval { 37 PlayingInterval(bigtime_t startTime, bigtime_t endTime) 38 : 39 start_time(startTime), 40 end_time(endTime) 41 { 42 } 43 44 bigtime_t start_time; 45 bigtime_t end_time; 46 bigtime_t x_start_time; 47 bigtime_t x_end_time; 48 float speed; 49}; 50 51 52ProxyAudioSupplier::ProxyAudioSupplier(PlaybackManager* playbackManager) 53 : 54 fSupplierLock("audio supplier lock"), 55 56 fPlaybackManager(playbackManager), 57 fVideoFrameRate(25.0), 58 fVolume(1.0), 59 60 fSupplier(NULL), 61 fAdapter(NULL), 62 fVolumeConverter(NULL), 63 fAudioResampler() 64{ 65 TRACE("ProxyAudioSupplier()\n"); 66} 67 68 69ProxyAudioSupplier::~ProxyAudioSupplier() 70{ 71 TRACE("~ProxyAudioSupplier()\n"); 72 delete fAdapter; 73 delete fVolumeConverter; 74} 75 76 77bigtime_t 78ProxyAudioSupplier::InitialLatency() const 79{ 80 BAutolock _(fSupplierLock); 81 82 if (fSupplier == NULL) 83 return 0; 84 85 return fSupplier->InitialLatency(); 86} 87 88 89status_t 90ProxyAudioSupplier::GetFrames(void* buffer, int64 frameCount, 91 bigtime_t startTime, bigtime_t endTime) 92{ 93 TRACE("GetFrames(%p, frameCount: %" B_PRId64 ", time interval: %" 94 B_PRIdBIGTIME " - %" B_PRIdBIGTIME ")\n", 95 buffer, frameCount, startTime, endTime); 96 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); 101 if (error == B_OK) { 102 bigtime_t intervalStartTime = startTime; 103 while (intervalStartTime < endTime) { 104 PlayingInterval* interval 105 = new (nothrow) PlayingInterval(intervalStartTime, endTime); 106 if (!interval) { 107 error = B_NO_MEMORY; 108 break; 109 } 110 fPlaybackManager->GetPlaylistTimeInterval( 111 interval->start_time, interval->end_time, 112 interval->x_start_time, interval->x_end_time, 113 interval->speed); 114 if (intervalStartTime == interval->end_time) { 115 delete interval; 116 error = B_ERROR; 117 ERROR("GetFrames() - zero duration audio interval! start " 118 "time: %" B_PRIdBIGTIME "\n", intervalStartTime); 119 break; 120 } 121 if (!playingIntervals.AddItem(interval)) { 122 delete interval; 123 error = B_NO_MEMORY; 124 ERROR("GetFrames() - Out of memory\n"); 125 break; 126 } 127 intervalStartTime = interval->end_time; 128 } 129 fPlaybackManager->SetCurrentAudioTime(endTime); 130 fPlaybackManager->Unlock(); 131 } else if (error == B_TIMED_OUT) { 132 TRACE("GetFrames() - LOCKING THE PLAYBACK MANAGER TIMED OUT!!!\n"); 133 } 134 135 BAutolock _(fSupplierLock); 136 137 if (!fSupplier) 138 return B_ERROR; 139 140 // retrieve the audio data for each interval. 141 #ifdef TRACE_PROXY_AUDIO_SUPPLIER 142 int32 intervalIndex = 0; 143 #endif 144 145 int64 framesRead = 0; 146 while (!playingIntervals.IsEmpty()) { 147 PlayingInterval* interval 148 = (PlayingInterval*)playingIntervals.RemoveItem((int32)0); 149 if (error != B_OK) { 150 delete interval; 151 continue; 152 } 153 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); 163 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, 168 framesToRead); 169 170 // not playing 171 if (absSpeed == 0) 172 _ReadSilence(buffer, framesToRead); 173 // playing 174 else { 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); 182 } 183 // read silence on error 184 if (error != B_OK) { 185 _ReadSilence(buffer, framesToRead); 186 error = B_OK; 187 } 188 framesRead += framesToRead; 189 buffer = _SkipFrames(buffer, framesToRead); 190 delete interval; 191 192 #ifdef TRACE_PROXY_AUDIO_SUPPLIER 193 intervalIndex++; 194 #endif 195 } 196 // read silence on error 197 if (error != B_OK) { 198 _ReadSilence(buffer, frameCount); 199 error = B_OK; 200 } 201 202 TRACE("GetFrames() done\n"); 203 204 return error; 205} 206 207 208void 209ProxyAudioSupplier::SetFormat(const media_format& format) 210{ 211//printf("ProxyAudioSupplier::SetFormat()\n"); 212 #ifdef TRACE_PROXY_AUDIO_SUPPLIER 213 char string[256]; 214 string_for_format(format, string, 256); 215 TRACE("SetFormat(%s)\n", string); 216 #endif 217 218 BAutolock _(fSupplierLock); 219 220 fAudioResampler.SetFormat(format); 221 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); 226} 227 228 229const media_format& 230ProxyAudioSupplier::Format() const 231{ 232 return fAudioResampler.Format(); 233} 234 235 236status_t 237ProxyAudioSupplier::InitCheck() const 238{ 239 status_t ret = AudioSupplier::InitCheck(); 240 if (ret < B_OK) 241 return ret; 242 return B_OK; 243} 244 245 246void 247ProxyAudioSupplier::SetSupplier(AudioTrackSupplier* supplier, 248 float videoFrameRate) 249{ 250//printf("ProxyAudioSupplier::SetSupplier(%p, %.1f)\n", supplier, 251//videoFrameRate); 252 TRACE("SetSupplier(%p, %.1f)\n", supplier, videoFrameRate); 253 254 BAutolock _(fSupplierLock); 255 256 fSupplier = supplier; 257 fVideoFrameRate = videoFrameRate; 258 259 delete fAdapter; 260 delete fVolumeConverter; 261 262 fAdapter = new AudioAdapter(fSupplier, Format()); 263 fVolumeConverter = new AudioVolumeConverter(fAdapter, fVolume); 264 265 fAudioResampler.SetSource(fVolumeConverter); 266} 267 268 269void 270ProxyAudioSupplier::SetVolume(float volume) 271{ 272 BAutolock _(fSupplierLock); 273 fVolume = volume; 274 if (fVolumeConverter) 275 fVolumeConverter->SetVolume(volume); 276} 277 278 279float 280ProxyAudioSupplier::Volume() 281{ 282 BAutolock _(fSupplierLock); 283 return fVolume; 284} 285 286 287// #pragma mark - audio/video/frame/time conversion 288 289 290int64 291ProxyAudioSupplier::_AudioFrameForVideoFrame(int64 frame) const 292{ 293 if (!fSupplier) { 294 return (int64)((double)frame * Format().u.raw_audio.frame_rate 295 / fVideoFrameRate); 296 } 297 const media_format& format = fSupplier->Format(); 298 return (int64)((double)frame * format.u.raw_audio.frame_rate 299 / fVideoFrameRate); 300} 301 302 303int64 304ProxyAudioSupplier::_VideoFrameForAudioFrame(int64 frame) const 305{ 306 if (!fSupplier) { 307 return (int64)((double)frame * fVideoFrameRate 308 / Format().u.raw_audio.frame_rate); 309 } 310 311 const media_format& format = fSupplier->Format(); 312 return (int64)((double)frame * fVideoFrameRate 313 / format.u.raw_audio.frame_rate); 314} 315 316 317int64 318ProxyAudioSupplier::_AudioFrameForTime(bigtime_t time) const 319{ 320 return (int64)((double)time * Format().u.raw_audio.frame_rate 321 / 1000000.0); 322} 323 324 325int64 326ProxyAudioSupplier::_VideoFrameForTime(bigtime_t time) const 327{ 328 return (int64)((double)time * fVideoFrameRate / 1000000.0); 329} 330 331 332// #pragma mark - utility 333 334 335void 336ProxyAudioSupplier::_ReadSilence(void* buffer, int64 frames) const 337{ 338 memset(buffer, 0, (char*)_SkipFrames(buffer, frames) - (char*)buffer); 339} 340 341 342void 343ProxyAudioSupplier::_ReverseFrames(void* buffer, int64 frames) const 344{ 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]); 353 front += frameSize; 354 back -= frameSize; 355 } 356} 357 358 359void* 360ProxyAudioSupplier::_SkipFrames(void* buffer, int64 frames) const 361{ 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; 366} 367 368