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: %lld, time interval: %lld - %lld)\n", 94 buffer, frameCount, startTime, endTime); 95 96 // Create a list of playing intervals which compose the supplied 97 // performance time interval. 98 BList playingIntervals; 99 status_t error = fPlaybackManager->LockWithTimeout(10000); 100 if (error == B_OK) { 101 bigtime_t intervalStartTime = startTime; 102 while (intervalStartTime < endTime) { 103 PlayingInterval* interval 104 = new (nothrow) PlayingInterval(intervalStartTime, endTime); 105 if (!interval) { 106 error = B_NO_MEMORY; 107 break; 108 } 109 fPlaybackManager->GetPlaylistTimeInterval( 110 interval->start_time, interval->end_time, 111 interval->x_start_time, interval->x_end_time, 112 interval->speed); 113 if (intervalStartTime == interval->end_time) { 114 delete interval; 115 error = B_ERROR; 116 ERROR("GetFrames() - zero duration audio interval! start " 117 "time: %lld\n", intervalStartTime); 118 break; 119 } 120 if (!playingIntervals.AddItem(interval)) { 121 delete interval; 122 error = B_NO_MEMORY; 123 ERROR("GetFrames() - Out of memory\n"); 124 break; 125 } 126 intervalStartTime = interval->end_time; 127 } 128 fPlaybackManager->SetCurrentAudioTime(endTime); 129 fPlaybackManager->Unlock(); 130 } else if (error == B_TIMED_OUT) { 131 TRACE("GetFrames() - LOCKING THE PLAYBACK MANAGER TIMED OUT!!!\n"); 132 } 133 134 BAutolock _(fSupplierLock); 135 136 if (!fSupplier) 137 return B_ERROR; 138 139 // retrieve the audio data for each interval. 140 #ifdef TRACE_PROXY_AUDIO_SUPPLIER 141 int32 intervalIndex = 0; 142 #endif 143 144 int64 framesRead = 0; 145 while (!playingIntervals.IsEmpty()) { 146 PlayingInterval* interval 147 = (PlayingInterval*)playingIntervals.RemoveItem(0L); 148 if (error != B_OK) { 149 delete interval; 150 continue; 151 } 152 153 // get playing direction 154 int32 playingDirection = 0; 155 if (interval->speed > 0) 156 playingDirection = 1; 157 else if (interval->speed < 0) 158 playingDirection = -1; 159 float absSpeed = interval->speed * playingDirection; 160 int64 framesToRead = _AudioFrameForTime(interval->end_time) 161 - _AudioFrameForTime(interval->start_time); 162 163 TRACE("GetFrames() - interval (%ld) [%lld, %lld]: [%lld, %lld], " 164 "frames: %lld\n", intervalIndex, 165 interval->start_time, interval->end_time, 166 interval->x_start_time, interval->x_end_time, 167 framesToRead); 168 169 // not playing 170 if (absSpeed == 0) 171 _ReadSilence(buffer, framesToRead); 172 // playing 173 else { 174 fAudioResampler.SetInOffset( 175 _AudioFrameForTime(interval->x_start_time)); 176 fAudioResampler.SetTimeScale(absSpeed); 177 error = fAudioResampler.Read(buffer, 0, framesToRead); 178 // backwards -> reverse frames 179 if (error == B_OK && interval->speed < 0) 180 _ReverseFrames(buffer, framesToRead); 181 } 182 // read silence on error 183 if (error != B_OK) { 184 _ReadSilence(buffer, framesToRead); 185 error = B_OK; 186 } 187 framesRead += framesToRead; 188 buffer = _SkipFrames(buffer, framesToRead); 189 delete interval; 190 191 #ifdef TRACE_PROXY_AUDIO_SUPPLIER 192 intervalIndex++; 193 #endif 194 } 195 // read silence on error 196 if (error != B_OK) { 197 _ReadSilence(buffer, frameCount); 198 error = B_OK; 199 } 200 201 TRACE("GetFrames() done\n"); 202 203 return error; 204 } 205 206 207 void 208 ProxyAudioSupplier::SetFormat(const media_format& format) 209 { 210 //printf("ProxyAudioSupplier::SetFormat()\n"); 211 #ifdef TRACE_PROXY_AUDIO_SUPPLIER 212 char string[256]; 213 string_for_format(format, string, 256); 214 TRACE("SetFormat(%s)\n", string); 215 #endif 216 217 BAutolock _(fSupplierLock); 218 219 fAudioResampler.SetFormat(format); 220 221 // In case SetSupplier was called before, we need 222 // to adapt to the new format, or maybe the format 223 // was still invalid. 224 SetSupplier(fSupplier, fVideoFrameRate); 225 } 226 227 228 const media_format& 229 ProxyAudioSupplier::Format() const 230 { 231 return fAudioResampler.Format(); 232 } 233 234 235 status_t 236 ProxyAudioSupplier::InitCheck() const 237 { 238 status_t ret = AudioSupplier::InitCheck(); 239 if (ret < B_OK) 240 return ret; 241 return B_OK; 242 } 243 244 245 void 246 ProxyAudioSupplier::SetSupplier(AudioTrackSupplier* supplier, 247 float videoFrameRate) 248 { 249 //printf("ProxyAudioSupplier::SetSupplier(%p, %.1f)\n", supplier, 250 //videoFrameRate); 251 TRACE("SetSupplier(%p, %.1f)\n", supplier, videoFrameRate); 252 253 BAutolock _(fSupplierLock); 254 255 fSupplier = supplier; 256 fVideoFrameRate = videoFrameRate; 257 258 delete fAdapter; 259 delete fVolumeConverter; 260 261 fAdapter = new AudioAdapter(fSupplier, Format()); 262 fVolumeConverter = new AudioVolumeConverter(fAdapter, fVolume); 263 264 fAudioResampler.SetSource(fVolumeConverter); 265 } 266 267 268 void 269 ProxyAudioSupplier::SetVolume(float volume) 270 { 271 BAutolock _(fSupplierLock); 272 fVolume = volume; 273 if (fVolumeConverter) 274 fVolumeConverter->SetVolume(volume); 275 } 276 277 278 float 279 ProxyAudioSupplier::Volume() 280 { 281 BAutolock _(fSupplierLock); 282 return fVolume; 283 } 284 285 286 // #pragma mark - audio/video/frame/time conversion 287 288 289 int64 290 ProxyAudioSupplier::_AudioFrameForVideoFrame(int64 frame) const 291 { 292 if (!fSupplier) { 293 return (int64)((double)frame * Format().u.raw_audio.frame_rate 294 / fVideoFrameRate); 295 } 296 const media_format& format = fSupplier->Format(); 297 return (int64)((double)frame * format.u.raw_audio.frame_rate 298 / fVideoFrameRate); 299 } 300 301 302 int64 303 ProxyAudioSupplier::_VideoFrameForAudioFrame(int64 frame) const 304 { 305 if (!fSupplier) { 306 return (int64)((double)frame * fVideoFrameRate 307 / Format().u.raw_audio.frame_rate); 308 } 309 310 const media_format& format = fSupplier->Format(); 311 return (int64)((double)frame * fVideoFrameRate 312 / format.u.raw_audio.frame_rate); 313 } 314 315 316 int64 317 ProxyAudioSupplier::_AudioFrameForTime(bigtime_t time) const 318 { 319 return (int64)((double)time * Format().u.raw_audio.frame_rate 320 / 1000000.0); 321 } 322 323 324 int64 325 ProxyAudioSupplier::_VideoFrameForTime(bigtime_t time) const 326 { 327 return (int64)((double)time * fVideoFrameRate / 1000000.0); 328 } 329 330 331 // #pragma mark - utility 332 333 334 void 335 ProxyAudioSupplier::_ReadSilence(void* buffer, int64 frames) const 336 { 337 memset(buffer, 0, (char*)_SkipFrames(buffer, frames) - (char*)buffer); 338 } 339 340 341 void 342 ProxyAudioSupplier::_ReverseFrames(void* buffer, int64 frames) const 343 { 344 int32 sampleSize = Format().u.raw_audio.format 345 & media_raw_audio_format::B_AUDIO_SIZE_MASK; 346 int32 frameSize = sampleSize * Format().u.raw_audio.channel_count; 347 char* front = (char*)buffer; 348 char* back = (char*)buffer + (frames - 1) * frameSize; 349 while (front < back) { 350 for (int32 i = 0; i < frameSize; i++) 351 swap(front[i], back[i]); 352 front += frameSize; 353 back -= frameSize; 354 } 355 } 356 357 358 void* 359 ProxyAudioSupplier::_SkipFrames(void* buffer, int64 frames) const 360 { 361 int32 sampleSize = Format().u.raw_audio.format 362 & media_raw_audio_format::B_AUDIO_SIZE_MASK; 363 int32 frameSize = sampleSize * Format().u.raw_audio.channel_count; 364 return (char*)buffer + frames * frameSize; 365 } 366 367