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