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, %lld, %lld, %lld)\n", buffer, frameCount, 94 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 int64 framesRead = 0; 141 while (!playingIntervals.IsEmpty()) { 142 PlayingInterval* interval 143 = (PlayingInterval*)playingIntervals.RemoveItem(0L); 144 if (error != B_OK) { 145 delete interval; 146 continue; 147 } 148 149 TRACE("GetFrames() - interval [%lld, %lld]: [%lld, %lld]\n", 150 interval->start_time, interval->end_time, 151 interval->x_start_time, interval->x_end_time); 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 // not playing 163 if (absSpeed == 0) 164 _ReadSilence(buffer, framesToRead); 165 // playing 166 else { 167 fAudioResampler.SetInOffset( 168 _AudioFrameForTime(interval->x_start_time)); 169 fAudioResampler.SetTimeScale(absSpeed); 170 error = fAudioResampler.Read(buffer, 0, framesToRead); 171 // backwards -> reverse frames 172 if (error == B_OK && interval->speed < 0) 173 _ReverseFrames(buffer, framesToRead); 174 } 175 // read silence on error 176 if (error != B_OK) { 177 _ReadSilence(buffer, framesToRead); 178 error = B_OK; 179 } 180 framesRead += framesToRead; 181 buffer = _SkipFrames(buffer, framesToRead); 182 delete interval; 183 } 184 // read silence on error 185 if (error != B_OK) { 186 _ReadSilence(buffer, frameCount); 187 error = B_OK; 188 } 189 190 TRACE("GetFrames() done\n"); 191 192 return error; 193 } 194 195 196 void 197 ProxyAudioSupplier::SetFormat(const media_format& format) 198 { 199 //printf("ProxyAudioSupplier::SetFormat()\n"); 200 #ifdef TRACE_PROXY_AUDIO_SUPPLIER 201 char string[256]; 202 string_for_format(format, string, 256); 203 TRACE("SetFormat(%s)\n", string); 204 #endif 205 206 BAutolock _(fSupplierLock); 207 208 fAudioResampler.SetFormat(format); 209 210 // In case SetSupplier was called before, we need 211 // to adapt to the new format, or maybe the format 212 // was still invalid. 213 SetSupplier(fSupplier, fVideoFrameRate); 214 } 215 216 217 const media_format& 218 ProxyAudioSupplier::Format() const 219 { 220 return fAudioResampler.Format(); 221 } 222 223 224 status_t 225 ProxyAudioSupplier::InitCheck() const 226 { 227 status_t ret = AudioSupplier::InitCheck(); 228 if (ret < B_OK) 229 return ret; 230 return B_OK; 231 } 232 233 234 void 235 ProxyAudioSupplier::SetSupplier(AudioTrackSupplier* supplier, 236 float videoFrameRate) 237 { 238 //printf("ProxyAudioSupplier::SetSupplier(%p, %.1f)\n", supplier, 239 //videoFrameRate); 240 TRACE("SetSupplier(%p, %.1f)\n", supplier, videoFrameRate); 241 242 BAutolock _(fSupplierLock); 243 244 fSupplier = supplier; 245 fVideoFrameRate = videoFrameRate; 246 247 delete fAdapter; 248 delete fVolumeConverter; 249 250 fAdapter = new AudioAdapter(fSupplier, Format()); 251 fVolumeConverter = new AudioVolumeConverter(fAdapter, fVolume); 252 253 fAudioResampler.SetSource(fVolumeConverter); 254 } 255 256 257 void 258 ProxyAudioSupplier::SetVolume(float volume) 259 { 260 BAutolock _(fSupplierLock); 261 fVolume = volume; 262 if (fVolumeConverter) 263 fVolumeConverter->SetVolume(volume); 264 } 265 266 267 float 268 ProxyAudioSupplier::Volume() 269 { 270 BAutolock _(fSupplierLock); 271 return fVolume; 272 } 273 274 275 // #pragma mark - audio/video/frame/time conversion 276 277 278 int64 279 ProxyAudioSupplier::_AudioFrameForVideoFrame(int64 frame) const 280 { 281 if (!fSupplier) { 282 return (int64)((double)frame * Format().u.raw_audio.frame_rate 283 / fVideoFrameRate); 284 } 285 const media_format& format = fSupplier->Format(); 286 return (int64)((double)frame * format.u.raw_audio.frame_rate 287 / fVideoFrameRate); 288 } 289 290 291 int64 292 ProxyAudioSupplier::_VideoFrameForAudioFrame(int64 frame) const 293 { 294 if (!fSupplier) { 295 return (int64)((double)frame * fVideoFrameRate 296 / Format().u.raw_audio.frame_rate); 297 } 298 299 const media_format& format = fSupplier->Format(); 300 return (int64)((double)frame * fVideoFrameRate 301 / format.u.raw_audio.frame_rate); 302 } 303 304 305 int64 306 ProxyAudioSupplier::_AudioFrameForTime(bigtime_t time) const 307 { 308 return (int64)((double)time * Format().u.raw_audio.frame_rate 309 / 1000000.0); 310 } 311 312 313 int64 314 ProxyAudioSupplier::_VideoFrameForTime(bigtime_t time) const 315 { 316 return (int64)((double)time * fVideoFrameRate / 1000000.0); 317 } 318 319 320 // #pragma mark - utility 321 322 323 void 324 ProxyAudioSupplier::_ReadSilence(void* buffer, int64 frames) const 325 { 326 memset(buffer, 0, (char*)_SkipFrames(buffer, frames) - (char*)buffer); 327 } 328 329 330 void 331 ProxyAudioSupplier::_ReverseFrames(void* buffer, int64 frames) const 332 { 333 int32 sampleSize = Format().u.raw_audio.format 334 & media_raw_audio_format::B_AUDIO_SIZE_MASK; 335 int32 frameSize = sampleSize * Format().u.raw_audio.channel_count; 336 char* front = (char*)buffer; 337 char* back = (char*)buffer + (frames - 1) * frameSize; 338 while (front < back) { 339 for (int32 i = 0; i < frameSize; i++) 340 swap(front[i], back[i]); 341 front += frameSize; 342 back -= frameSize; 343 } 344 } 345 346 347 void* 348 ProxyAudioSupplier::_SkipFrames(void* buffer, int64 frames) const 349 { 350 int32 sampleSize = Format().u.raw_audio.format 351 & media_raw_audio_format::B_AUDIO_SIZE_MASK; 352 int32 frameSize = sampleSize * Format().u.raw_audio.channel_count; 353 return (char*)buffer + frames * frameSize; 354 } 355 356