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 22 using std::nothrow; 23 using 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 36 struct 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 52 ProxyAudioSupplier::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 69 ProxyAudioSupplier::~ProxyAudioSupplier() 70 { 71 TRACE("~ProxyAudioSupplier()\n"); 72 delete fAdapter; 73 delete fVolumeConverter; 74 } 75 76 77 bigtime_t 78 ProxyAudioSupplier::InitialLatency() const 79 { 80 BAutolock _(fSupplierLock); 81 82 if (fSupplier == NULL) 83 return 0; 84 85 return fSupplier->InitialLatency(); 86 } 87 88 89 status_t 90 ProxyAudioSupplier::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 208 void 209 ProxyAudioSupplier::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 229 const media_format& 230 ProxyAudioSupplier::Format() const 231 { 232 return fAudioResampler.Format(); 233 } 234 235 236 status_t 237 ProxyAudioSupplier::InitCheck() const 238 { 239 status_t ret = AudioSupplier::InitCheck(); 240 if (ret < B_OK) 241 return ret; 242 return B_OK; 243 } 244 245 246 void 247 ProxyAudioSupplier::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 269 void 270 ProxyAudioSupplier::SetVolume(float volume) 271 { 272 BAutolock _(fSupplierLock); 273 fVolume = volume; 274 if (fVolumeConverter) 275 fVolumeConverter->SetVolume(volume); 276 } 277 278 279 float 280 ProxyAudioSupplier::Volume() 281 { 282 BAutolock _(fSupplierLock); 283 return fVolume; 284 } 285 286 287 // #pragma mark - audio/video/frame/time conversion 288 289 290 int64 291 ProxyAudioSupplier::_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 303 int64 304 ProxyAudioSupplier::_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 317 int64 318 ProxyAudioSupplier::_AudioFrameForTime(bigtime_t time) const 319 { 320 return (int64)((double)time * Format().u.raw_audio.frame_rate 321 / 1000000.0); 322 } 323 324 325 int64 326 ProxyAudioSupplier::_VideoFrameForTime(bigtime_t time) const 327 { 328 return (int64)((double)time * fVideoFrameRate / 1000000.0); 329 } 330 331 332 // #pragma mark - utility 333 334 335 void 336 ProxyAudioSupplier::_ReadSilence(void* buffer, int64 frames) const 337 { 338 memset(buffer, 0, (char*)_SkipFrames(buffer, frames) - (char*)buffer); 339 } 340 341 342 void 343 ProxyAudioSupplier::_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 359 void* 360 ProxyAudioSupplier::_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