1 /* 2 * Copyright 2010, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2000-2010, Stephan Aßmus <superstippi@gmx.de>, 4 * Copyright 2000-2008, Ingo Weinhold <ingo_weinhold@gmx.de>, 5 * All Rights Reserved. Distributed under the terms of the MIT license. 6 * 7 * Copyright (c) 1998-99, Be Incorporated, All Rights Reserved. 8 * Distributed under the terms of the Be Sample Code license. 9 */ 10 11 12 #include "AudioProducer.h" 13 14 #include <math.h> 15 #include <string.h> 16 #include <stdio.h> 17 18 #include <BufferGroup.h> 19 #include <Buffer.h> 20 #include <MediaDefs.h> 21 #include <ParameterWeb.h> 22 #include <TimeSource.h> 23 24 #include "AudioSupplier.h" 25 #include "EventQueue.h" 26 #include "MessageEvent.h" 27 28 #define DEBUG_TO_FILE 0 29 30 #if DEBUG_TO_FILE 31 # include <Entry.h> 32 # include <MediaFormats.h> 33 # include <MediaFile.h> 34 # include <MediaTrack.h> 35 #endif // DEBUG_TO_FILE 36 37 38 // debugging 39 //#define TRACE_AUDIO_PRODUCER 40 #ifdef TRACE_AUDIO_PRODUCER 41 # define TRACE(x...) printf(x) 42 # define TRACE_BUFFER(x...) 43 # define ERROR(x...) fprintf(stderr, x) 44 #else 45 # define TRACE(x...) 46 # define TRACE_BUFFER(x...) 47 # define ERROR(x...) fprintf(stderr, x) 48 #endif 49 50 51 const static bigtime_t kMaxLatency = 150000; 52 // 150 ms is the maximum latency we publish 53 54 55 #if DEBUG_TO_FILE 56 static BMediaFile* 57 init_media_file(media_format format, BMediaTrack** _track) 58 { 59 static BMediaFile* file = NULL; 60 static BMediaTrack* track = NULL; 61 if (file == NULL) { 62 entry_ref ref; 63 get_ref_for_path("/boot/home/Desktop/test.wav", &ref); 64 65 media_file_format fileFormat; 66 int32 cookie = 0; 67 while (get_next_file_format(&cookie, &fileFormat) == B_OK) { 68 if (strcmp(fileFormat.short_name, "wav") == 0) 69 break; 70 } 71 file = new BMediaFile(&ref, &fileFormat); 72 73 media_codec_info info; 74 cookie = 0; 75 while (get_next_encoder(&cookie, &info) == B_OK) { 76 if (strcmp(info.short_name, "raw-audio") == 0 77 || strcmp(info.short_name, "pcm") == 0) { 78 break; 79 } 80 } 81 82 track = file->CreateTrack(&format, &info); 83 if (track == NULL) 84 printf("failed to create track\n"); 85 86 file->CommitHeader(); 87 } 88 *_track = track; 89 return track != NULL ? file : NULL; 90 } 91 #endif // DEBUG_TO_FILE 92 93 94 static bigtime_t 95 estimate_internal_latency(const media_format& format) 96 { 97 bigtime_t startTime = system_time(); 98 // calculate the number of samples per buffer 99 int32 sampleSize = format.u.raw_audio.format 100 & media_raw_audio_format::B_AUDIO_SIZE_MASK; 101 int32 sampleCount = format.u.raw_audio.buffer_size / sampleSize; 102 // alloc float buffers of this size 103 const int bufferCount = 10; // number of input buffers 104 float* buffers[bufferCount + 1]; 105 for (int32 i = 0; i < bufferCount + 1; i++) 106 buffers[i] = new float[sampleCount]; 107 float* outBuffer = buffers[bufferCount]; 108 // fill all buffers save the last one with arbitrary data and merge them 109 // into the last one 110 for (int32 i = 0; i < bufferCount; i++) { 111 for (int32 k = 0; k < sampleCount; k++) { 112 buffers[i][k] = ((float)i * (float)k) 113 / float(bufferCount * sampleCount); 114 } 115 } 116 for (int32 k = 0; k < sampleCount; k++) { 117 outBuffer[k] = 0; 118 for (int32 i = 0; i < bufferCount; i++) 119 outBuffer[k] += buffers[i][k]; 120 outBuffer[k] /= bufferCount; 121 } 122 // cleanup 123 for (int32 i = 0; i < bufferCount + 1; i++) 124 delete[] buffers[i]; 125 return system_time() - startTime; 126 } 127 128 129 // #pragma mark - 130 131 132 AudioProducer::AudioProducer(const char* name, AudioSupplier* supplier, 133 bool lowLatency) 134 : 135 BMediaNode(name), 136 BBufferProducer(B_MEDIA_RAW_AUDIO), 137 BMediaEventLooper(), 138 139 fBufferGroup(NULL), 140 fLatency(0), 141 fInternalLatency(0), 142 fLastLateNotice(0), 143 fNextScheduledBuffer(0), 144 fLowLatency(lowLatency), 145 fOutputEnabled(true), 146 fFramesSent(0), 147 fStartTime(0), 148 fSupplier(supplier), 149 150 fPeakListener(NULL) 151 { 152 TRACE("%p->AudioProducer::AudioProducer(%s, %p, %d)\n", this, name, 153 supplier, lowLatency); 154 155 // initialize our preferred format object 156 fPreferredFormat.type = B_MEDIA_RAW_AUDIO; 157 fPreferredFormat.u.raw_audio.format 158 = media_raw_audio_format::B_AUDIO_FLOAT; 159 // = media_raw_audio_format::B_AUDIO_SHORT; 160 fPreferredFormat.u.raw_audio.byte_order 161 = (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN; 162 #if 0 163 fPreferredFormat.u.raw_audio.channel_count = 2; 164 fPreferredFormat.u.raw_audio.frame_rate = 44100.0; 165 166 // NOTE: the (buffer_size * 1000000) needs to be dividable by 167 // fPreferredFormat.u.raw_audio.frame_rate! 168 fPreferredFormat.u.raw_audio.buffer_size = 441 * 4 169 * (fPreferredFormat.u.raw_audio.format 170 & media_raw_audio_format::B_AUDIO_SIZE_MASK); 171 172 if (!fLowLatency) 173 fPreferredFormat.u.raw_audio.buffer_size *= 3; 174 #else 175 fPreferredFormat.u.raw_audio.channel_count = 0; 176 fPreferredFormat.u.raw_audio.frame_rate = 0.0; 177 fPreferredFormat.u.raw_audio.buffer_size = 0; 178 #endif 179 180 // we're not connected yet 181 fOutput.destination = media_destination::null; 182 fOutput.format = fPreferredFormat; 183 184 // init the audio supplier 185 if (fSupplier != NULL) { 186 fSupplier->SetAudioProducer(this); 187 SetInitialLatency(fSupplier->InitialLatency()); 188 } 189 } 190 191 192 AudioProducer::~AudioProducer() 193 { 194 TRACE("%p->AudioProducer::~AudioProducer()\n", this); 195 196 #if DEBUG_TO_FILE 197 BMediaTrack* track; 198 if (BMediaFile* file = init_media_file(fPreferredFormat, &track)) { 199 printf("deleting file...\n"); 200 track->Flush(); 201 file->ReleaseTrack(track); 202 file->CloseFile(); 203 delete file; 204 } 205 #endif // DEBUG_TO_FILE 206 207 // Stop the BMediaEventLooper thread 208 Quit(); 209 TRACE("AudioProducer::~AudioProducer() done\n"); 210 } 211 212 213 BMediaAddOn* 214 AudioProducer::AddOn(int32* internalId) const 215 { 216 return NULL; 217 } 218 219 220 status_t 221 AudioProducer::FormatSuggestionRequested(media_type type, int32 quality, 222 media_format* _format) 223 { 224 TRACE("%p->AudioProducer::FormatSuggestionRequested()\n", this); 225 226 if (!_format) 227 return B_BAD_VALUE; 228 229 // This is the format we'll be returning (our preferred format) 230 *_format = fPreferredFormat; 231 232 // A wildcard type is okay; we can specialize it, otherwise only raw audio 233 // is supported 234 if (type != B_MEDIA_UNKNOWN_TYPE && type != B_MEDIA_RAW_AUDIO) 235 return B_MEDIA_BAD_FORMAT; 236 237 return B_OK; 238 } 239 240 status_t 241 AudioProducer::FormatProposal(const media_source& output, media_format* format) 242 { 243 TRACE("%p->AudioProducer::FormatProposal()\n", this); 244 245 // is this a proposal for our one output? 246 if (output != fOutput.source) { 247 TRACE(" -> B_MEDIA_BAD_SOURCE\n"); 248 return B_MEDIA_BAD_SOURCE; 249 } 250 251 // Raw audio or wildcard type, either is okay by us. If the format is 252 // anything else, overwrite it with our preferred format. Also, we only support 253 // floating point audio in the host native byte order at the moment. 254 if ((format->type != B_MEDIA_UNKNOWN_TYPE 255 && format->type != B_MEDIA_RAW_AUDIO) 256 || (format->u.raw_audio.format 257 != media_raw_audio_format::wildcard.format 258 && format->u.raw_audio.format 259 != fPreferredFormat.u.raw_audio.format) 260 || (format->u.raw_audio.byte_order 261 != media_raw_audio_format::wildcard.byte_order 262 && format->u.raw_audio.byte_order 263 != fPreferredFormat.u.raw_audio.byte_order)) { 264 TRACE(" -> B_MEDIA_BAD_FORMAT\n"); 265 *format = fPreferredFormat; 266 return B_MEDIA_BAD_FORMAT; 267 } 268 269 format->type = B_MEDIA_RAW_AUDIO; 270 format->u.raw_audio.format = fPreferredFormat.u.raw_audio.format; 271 format->u.raw_audio.byte_order = fPreferredFormat.u.raw_audio.byte_order; 272 273 return B_OK; 274 } 275 276 277 status_t 278 AudioProducer::FormatChangeRequested(const media_source& source, 279 const media_destination& destination, media_format* ioFormat, 280 int32* _deprecated_) 281 { 282 TRACE("%p->AudioProducer::FormatChangeRequested()\n", this); 283 284 if (destination != fOutput.destination) { 285 TRACE(" -> B_MEDIA_BAD_DESTINATION\n"); 286 return B_MEDIA_BAD_DESTINATION; 287 } 288 289 if (source != fOutput.source) { 290 TRACE(" -> B_MEDIA_BAD_SOURCE\n"); 291 return B_MEDIA_BAD_SOURCE; 292 } 293 294 // TODO: Maybe we are supposed to specialize here only and not actually change yet? 295 // status_t ret = _SpecializeFormat(ioFormat); 296 297 return ChangeFormat(ioFormat); 298 } 299 300 301 status_t 302 AudioProducer::GetNextOutput(int32* cookie, media_output* _output) 303 { 304 TRACE("%p->AudioProducer::GetNextOutput(%ld)\n", this, *cookie); 305 306 // we have only a single output; if we supported multiple outputs, we'd 307 // iterate over whatever data structure we were using to keep track of 308 // them. 309 if (0 == *cookie) { 310 *_output = fOutput; 311 *cookie += 1; 312 return B_OK; 313 } 314 315 return B_BAD_INDEX; 316 } 317 318 319 status_t 320 AudioProducer::DisposeOutputCookie(int32 cookie) 321 { 322 // do nothing because we don't use the cookie for anything special 323 return B_OK; 324 } 325 326 327 status_t 328 AudioProducer::SetBufferGroup(const media_source& forSource, 329 BBufferGroup* newGroup) 330 { 331 TRACE("%p->AudioProducer::SetBufferGroup()\n", this); 332 333 if (forSource != fOutput.source) 334 return B_MEDIA_BAD_SOURCE; 335 336 if (newGroup == fBufferGroup) 337 return B_OK; 338 339 if (fUsingOurBuffers && fBufferGroup) 340 delete fBufferGroup; // waits for all buffers to recycle 341 342 if (newGroup != NULL) { 343 // we were given a valid group; just use that one from now on 344 fBufferGroup = newGroup; 345 fUsingOurBuffers = false; 346 } else { 347 // we were passed a NULL group pointer; that means we construct 348 // our own buffer group to use from now on 349 size_t size = fOutput.format.u.raw_audio.buffer_size; 350 int32 count = int32(fLatency / BufferDuration() + 1 + 1); 351 fBufferGroup = new BBufferGroup(size, count); 352 fUsingOurBuffers = true; 353 } 354 355 return B_OK; 356 } 357 358 359 status_t 360 AudioProducer::GetLatency(bigtime_t* _latency) 361 { 362 TRACE("%p->AudioProducer::GetLatency()\n", this); 363 364 // report our *total* latency: internal plus downstream plus scheduling 365 *_latency = EventLatency() + SchedulingLatency(); 366 return B_OK; 367 } 368 369 370 status_t 371 AudioProducer::PrepareToConnect(const media_source& what, 372 const media_destination& where, media_format* format, 373 media_source* _source, char* _name) 374 { 375 TRACE("%p->AudioProducer::PrepareToConnect()\n", this); 376 377 // trying to connect something that isn't our source? 378 if (what != fOutput.source) { 379 TRACE(" -> B_MEDIA_BAD_SOURCE\n"); 380 return B_MEDIA_BAD_SOURCE; 381 } 382 383 // are we already connected? 384 if (fOutput.destination != media_destination::null) { 385 TRACE(" -> B_MEDIA_ALREADY_CONNECTED\n"); 386 return B_MEDIA_ALREADY_CONNECTED; 387 } 388 389 status_t ret = _SpecializeFormat(format); 390 if (ret != B_OK) { 391 TRACE(" -> format error: %s\n", strerror(ret)); 392 return ret; 393 } 394 395 // Now reserve the connection, and return information about it 396 fOutput.destination = where; 397 fOutput.format = *format; 398 399 if (fSupplier != NULL) 400 fSupplier->SetFormat(fOutput.format); 401 402 *_source = fOutput.source; 403 strncpy(_name, fOutput.name, B_MEDIA_NAME_LENGTH); 404 TRACE(" -> B_OK\n"); 405 return B_OK; 406 } 407 408 409 void 410 AudioProducer::Connect(status_t error, const media_source& source, 411 const media_destination& destination, const media_format& format, 412 char* _name) 413 { 414 TRACE("AudioProducer::Connect(%s)\n", strerror(error)); 415 416 // If something earlier failed, Connect() might still be called, but with 417 // a non-zero error code. When that happens we simply unreserve the 418 // connection and do nothing else. 419 if (error != B_OK) { 420 fOutput.destination = media_destination::null; 421 fOutput.format = fPreferredFormat; 422 return; 423 } 424 425 // Okay, the connection has been confirmed. Record the destination and 426 // format that we agreed on, and report our connection name again. 427 fOutput.destination = destination; 428 fOutput.format = format; 429 strncpy(_name, fOutput.name, B_MEDIA_NAME_LENGTH); 430 431 // tell our audio supplier about the format 432 if (fSupplier) { 433 TRACE("AudioProducer::Connect() fSupplier->SetFormat()\n"); 434 fSupplier->SetFormat(fOutput.format); 435 } 436 437 TRACE("AudioProducer::Connect() FindLatencyFor()\n"); 438 439 // Now that we're connected, we can determine our downstream latency. 440 // Do so, then make sure we get our events early enough. 441 media_node_id id; 442 FindLatencyFor(fOutput.destination, &fLatency, &id); 443 444 // Use a dry run to see how long it takes me to fill a buffer of data 445 size_t sampleSize = fOutput.format.u.raw_audio.format 446 & media_raw_audio_format::B_AUDIO_SIZE_MASK; 447 size_t samplesPerBuffer 448 = fOutput.format.u.raw_audio.buffer_size / sampleSize; 449 fInternalLatency = estimate_internal_latency(fOutput.format); 450 if (!fLowLatency) 451 fInternalLatency *= 32; 452 SetEventLatency(fLatency + fInternalLatency); 453 454 // reset our buffer duration, etc. to avoid later calculations 455 bigtime_t duration = bigtime_t(1000000) 456 * samplesPerBuffer / bigtime_t(fOutput.format.u.raw_audio.frame_rate 457 * fOutput.format.u.raw_audio.channel_count); 458 TRACE("AudioProducer::Connect() SetBufferDuration(%lld)\n", duration); 459 SetBufferDuration(duration); 460 461 TRACE("AudioProducer::Connect() _AllocateBuffers()\n"); 462 463 // Set up the buffer group for our connection, as long as nobody handed 464 // us a buffer group (via SetBufferGroup()) prior to this. That can 465 // happen, for example, if the consumer calls SetOutputBuffersFor() on 466 // us from within its Connected() method. 467 if (fBufferGroup == NULL) 468 _AllocateBuffers(fOutput.format); 469 470 TRACE("AudioProducer::Connect() done\n"); 471 } 472 473 474 void 475 AudioProducer::Disconnect(const media_source& what, 476 const media_destination& where) 477 { 478 TRACE("%p->AudioProducer::Disconnect()\n", this); 479 480 // Make sure that our connection is the one being disconnected 481 if (where == fOutput.destination && what == fOutput.source) { 482 fOutput.destination = media_destination::null; 483 fOutput.format = fPreferredFormat; 484 TRACE("AudioProducer: deleting buffer group...\n"); 485 // Always delete the buffer group, even if it is not ours. 486 // (See BeBook::SetBufferGroup()). 487 delete fBufferGroup; 488 TRACE("AudioProducer: buffer group deleted\n"); 489 fBufferGroup = NULL; 490 } 491 492 TRACE("%p->AudioProducer::Disconnect() done\n", this); 493 } 494 495 496 void 497 AudioProducer::LateNoticeReceived(const media_source& what, bigtime_t howMuch, 498 bigtime_t performanceTime) 499 { 500 TRACE("%p->AudioProducer::LateNoticeReceived(%lld, %lld)\n", this, howMuch, 501 performanceTime); 502 // If we're late, we need to catch up. Respond in a manner appropriate 503 // to our current run mode. 504 if (what == fOutput.source) { 505 // Ignore the notices for buffers we already send out (or scheduled 506 // their event) before we processed the last notice 507 if (fLastLateNotice > performanceTime) 508 return; 509 510 fLastLateNotice = fNextScheduledBuffer; 511 512 if (RunMode() == B_RECORDING) { 513 // ... 514 } else if (RunMode() == B_INCREASE_LATENCY) { 515 fInternalLatency += howMuch; 516 517 // At some point a too large latency can get annoying 518 if (fInternalLatency > kMaxLatency) 519 fInternalLatency = kMaxLatency; 520 521 SetEventLatency(fLatency + fInternalLatency); 522 } else { 523 // Skip one buffer ahead in the audio data. 524 size_t sampleSize 525 = fOutput.format.u.raw_audio.format 526 & media_raw_audio_format::B_AUDIO_SIZE_MASK; 527 size_t samplesPerBuffer 528 = fOutput.format.u.raw_audio.buffer_size / sampleSize; 529 size_t framesPerBuffer 530 = samplesPerBuffer / fOutput.format.u.raw_audio.channel_count; 531 fFramesSent += framesPerBuffer; 532 } 533 } 534 } 535 536 537 void 538 AudioProducer::EnableOutput(const media_source& what, bool enabled, 539 int32* _deprecated_) 540 { 541 TRACE("%p->AudioProducer::EnableOutput(%d)\n", this, enabled); 542 543 if (what == fOutput.source) 544 fOutputEnabled = enabled; 545 } 546 547 548 status_t 549 AudioProducer::SetPlayRate(int32 numer, int32 denom) 550 { 551 return B_ERROR; 552 } 553 554 555 status_t 556 AudioProducer::HandleMessage(int32 message, const void *data, size_t size) 557 { 558 TRACE("%p->AudioProducer::HandleMessage()\n", this); 559 return B_ERROR; 560 } 561 562 563 void 564 AudioProducer::AdditionalBufferRequested(const media_source& source, 565 media_buffer_id prevBuffer, bigtime_t prevTime, 566 const media_seek_tag *prevTag) 567 { 568 TRACE("%p->AudioProducer::AdditionalBufferRequested()\n", this); 569 } 570 571 572 void 573 AudioProducer::LatencyChanged(const media_source& source, 574 const media_destination& destination, bigtime_t newLatency, uint32 flags) 575 { 576 TRACE("%p->AudioProducer::LatencyChanged(%lld)\n", this, newLatency); 577 578 if (source == fOutput.source && destination == fOutput.destination) { 579 fLatency = newLatency; 580 SetEventLatency(fLatency + fInternalLatency); 581 } 582 } 583 584 585 void 586 AudioProducer::NodeRegistered() 587 { 588 TRACE("%p->AudioProducer::NodeRegistered()\n", this); 589 590 // set up as much information about our output as we can 591 fOutput.source.port = ControlPort(); 592 fOutput.source.id = 0; 593 fOutput.node = Node(); 594 ::strcpy(fOutput.name, Name()); 595 596 // Start the BMediaEventLooper thread 597 SetPriority(B_REAL_TIME_PRIORITY); 598 Run(); 599 } 600 601 602 void 603 AudioProducer::SetRunMode(run_mode mode) 604 { 605 TRACE("%p->AudioProducer::SetRunMode()\n", this); 606 607 if (B_OFFLINE == mode) 608 ReportError(B_NODE_FAILED_SET_RUN_MODE); 609 else 610 BBufferProducer::SetRunMode(mode); 611 } 612 613 614 void 615 AudioProducer::HandleEvent(const media_timed_event* event, bigtime_t lateness, 616 bool realTimeEvent) 617 { 618 TRACE_BUFFER("%p->AudioProducer::HandleEvent()\n", this); 619 620 switch (event->type) { 621 case BTimedEventQueue::B_START: 622 TRACE("AudioProducer::HandleEvent(B_START)\n"); 623 if (RunState() != B_STARTED) { 624 fFramesSent = 0; 625 fStartTime = event->event_time + fSupplier->InitialLatency(); 626 media_timed_event firstBufferEvent( 627 fStartTime - fSupplier->InitialLatency(), 628 BTimedEventQueue::B_HANDLE_BUFFER); 629 EventQueue()->AddEvent(firstBufferEvent); 630 } 631 TRACE("AudioProducer::HandleEvent(B_START) done\n"); 632 break; 633 634 case BTimedEventQueue::B_STOP: 635 TRACE("AudioProducer::HandleEvent(B_STOP)\n"); 636 EventQueue()->FlushEvents(0, BTimedEventQueue::B_ALWAYS, true, 637 BTimedEventQueue::B_HANDLE_BUFFER); 638 TRACE("AudioProducer::HandleEvent(B_STOP) done\n"); 639 break; 640 641 case BTimedEventQueue::B_HANDLE_BUFFER: 642 { 643 TRACE_BUFFER("AudioProducer::HandleEvent(B_HANDLE_BUFFER)\n"); 644 if (RunState() == BMediaEventLooper::B_STARTED 645 && fOutput.destination != media_destination::null) { 646 BBuffer* buffer = _FillNextBuffer(event->event_time); 647 if (buffer != NULL) { 648 status_t err = B_ERROR; 649 if (fOutputEnabled) { 650 err = SendBuffer(buffer, fOutput.source, 651 fOutput.destination); 652 } 653 if (err != B_OK) 654 buffer->Recycle(); 655 } 656 size_t sampleSize = fOutput.format.u.raw_audio.format 657 & media_raw_audio_format::B_AUDIO_SIZE_MASK; 658 659 size_t nFrames = fOutput.format.u.raw_audio.buffer_size 660 / (sampleSize * fOutput.format.u.raw_audio.channel_count); 661 fFramesSent += nFrames; 662 663 fNextScheduledBuffer = fStartTime 664 + bigtime_t(double(fFramesSent) * 1000000.0 665 / double(fOutput.format.u.raw_audio.frame_rate)); 666 media_timed_event nextBufferEvent(fNextScheduledBuffer, 667 BTimedEventQueue::B_HANDLE_BUFFER); 668 EventQueue()->AddEvent(nextBufferEvent); 669 } else { 670 ERROR("B_HANDLE_BUFFER, but not started!\n"); 671 } 672 TRACE_BUFFER("AudioProducer::HandleEvent(B_HANDLE_BUFFER) done\n"); 673 break; 674 } 675 default: 676 break; 677 } 678 } 679 680 681 void 682 AudioProducer::SetPeakListener(BHandler* handler) 683 { 684 fPeakListener = handler; 685 } 686 687 688 status_t 689 AudioProducer::ChangeFormat(media_format* format) 690 { 691 TRACE("AudioProducer::ChangeFormat()\n"); 692 693 format->u.raw_audio.buffer_size 694 = media_raw_audio_format::wildcard.buffer_size; 695 696 status_t ret = _SpecializeFormat(format); 697 if (ret != B_OK) { 698 TRACE(" _SpecializeFormat(): %s\n", strerror(ret)); 699 return ret; 700 } 701 702 ret = BBufferProducer::ProposeFormatChange(format, fOutput.destination); 703 if (ret != B_OK) { 704 TRACE(" ProposeFormatChange(): %s\n", strerror(ret)); 705 return ret; 706 } 707 708 ret = BBufferProducer::ChangeFormat(fOutput.source, fOutput.destination, 709 format); 710 if (ret != B_OK) { 711 TRACE(" ChangeFormat(): %s\n", strerror(ret)); 712 return ret; 713 } 714 715 return _ChangeFormat(*format); 716 } 717 718 719 // #pragma mark - 720 721 722 status_t 723 AudioProducer::_SpecializeFormat(media_format* format) 724 { 725 // the format may not yet be fully specialized (the consumer might have 726 // passed back some wildcards). Finish specializing it now, and return an 727 // error if we don't support the requested format. 728 if (format->type != B_MEDIA_RAW_AUDIO) { 729 TRACE(" not raw audio\n"); 730 return B_MEDIA_BAD_FORMAT; 731 // TODO: we might want to support different audio formats 732 } else if (format->u.raw_audio.format 733 != fPreferredFormat.u.raw_audio.format) { 734 TRACE(" format does not match\n"); 735 return B_MEDIA_BAD_FORMAT; 736 } 737 738 if (format->u.raw_audio.channel_count 739 == media_raw_audio_format::wildcard.channel_count) { 740 format->u.raw_audio.channel_count = 2; 741 TRACE(" -> adjusting channel count, it was wildcard\n"); 742 } 743 744 if (format->u.raw_audio.frame_rate 745 == media_raw_audio_format::wildcard.frame_rate) { 746 format->u.raw_audio.frame_rate = 44100.0; 747 TRACE(" -> adjusting frame rate, it was wildcard\n"); 748 } 749 750 // check the buffer size, which may still be wildcarded 751 if (format->u.raw_audio.buffer_size 752 == media_raw_audio_format::wildcard.buffer_size) { 753 // pick something comfortable to suggest 754 TRACE(" -> adjusting buffer size, it was wildcard\n"); 755 756 // NOTE: the (buffer_size * 1000000) needs to be dividable by 757 // format->u.raw_audio.frame_rate! (We assume frame rate is a multiple of 758 // 25, which it usually is.) 759 format->u.raw_audio.buffer_size 760 = uint32(format->u.raw_audio.frame_rate / 25.0) 761 * format->u.raw_audio.channel_count 762 * (format->u.raw_audio.format 763 & media_raw_audio_format::B_AUDIO_SIZE_MASK); 764 765 if (!fLowLatency) 766 format->u.raw_audio.buffer_size *= 3; 767 } 768 769 return B_OK; 770 } 771 772 773 status_t 774 AudioProducer::_ChangeFormat(const media_format& format) 775 { 776 fOutput.format = format; 777 778 // notify our audio supplier of the format change 779 if (fSupplier) 780 fSupplier->SetFormat(format); 781 782 return _AllocateBuffers(format); 783 } 784 785 786 status_t 787 AudioProducer::_AllocateBuffers(const media_format& format) 788 { 789 TRACE("%p->AudioProducer::_AllocateBuffers()\n", this); 790 791 if (fBufferGroup && fUsingOurBuffers) { 792 delete fBufferGroup; 793 fBufferGroup = NULL; 794 } 795 size_t size = format.u.raw_audio.buffer_size; 796 int32 bufferDuration = BufferDuration(); 797 int32 count = 0; 798 if (bufferDuration > 0) { 799 count = (int32)((fLatency + fInternalLatency) 800 / bufferDuration + 2); 801 } 802 803 fBufferGroup = new BBufferGroup(size, count); 804 fUsingOurBuffers = true; 805 return fBufferGroup->InitCheck(); 806 } 807 808 809 BBuffer* 810 AudioProducer::_FillNextBuffer(bigtime_t eventTime) 811 { 812 fBufferGroup->WaitForBuffers(); 813 BBuffer* buffer = fBufferGroup->RequestBuffer( 814 fOutput.format.u.raw_audio.buffer_size, BufferDuration()); 815 816 if (buffer == NULL) { 817 static bool errorPrinted = false; 818 if (!errorPrinted) { 819 ERROR("AudioProducer::_FillNextBuffer() - no buffer " 820 "(size: %" B_PRIuSIZE ", duration: %" B_PRIiBIGTIME ")\n", 821 fOutput.format.u.raw_audio.buffer_size, BufferDuration()); 822 errorPrinted = true; 823 } 824 return NULL; 825 } 826 827 size_t sampleSize = fOutput.format.u.raw_audio.format 828 & media_raw_audio_format::B_AUDIO_SIZE_MASK; 829 size_t numSamples = fOutput.format.u.raw_audio.buffer_size / sampleSize; 830 // number of sample in the buffer 831 832 // fill in the buffer header 833 media_header* header = buffer->Header(); 834 header->type = B_MEDIA_RAW_AUDIO; 835 header->time_source = TimeSource()->ID(); 836 buffer->SetSizeUsed(fOutput.format.u.raw_audio.buffer_size); 837 838 // fill in data from audio supplier 839 int64 frameCount = numSamples / fOutput.format.u.raw_audio.channel_count; 840 bigtime_t startTime = bigtime_t(double(fFramesSent) 841 * 1000000.0 / fOutput.format.u.raw_audio.frame_rate); 842 bigtime_t endTime = bigtime_t(double(fFramesSent + frameCount) 843 * 1000000.0 / fOutput.format.u.raw_audio.frame_rate); 844 845 if (fSupplier == NULL || fSupplier->InitCheck() != B_OK 846 || fSupplier->GetFrames(buffer->Data(), frameCount, startTime, 847 endTime) != B_OK) { 848 ERROR("AudioProducer::_FillNextBuffer() - supplier error -> silence\n"); 849 memset(buffer->Data(), 0, buffer->SizeUsed()); 850 } 851 852 // stamp buffer 853 if (RunMode() == B_RECORDING) 854 header->start_time = eventTime; 855 else 856 header->start_time = fStartTime + startTime; 857 858 #if DEBUG_TO_FILE 859 BMediaTrack* track; 860 if (init_media_file(fOutput.format, &track) != NULL) 861 track->WriteFrames(buffer->Data(), frameCount); 862 #endif // DEBUG_TO_FILE 863 864 if (fPeakListener 865 && fOutput.format.u.raw_audio.format 866 == media_raw_audio_format::B_AUDIO_FLOAT) { 867 // TODO: extend the peak notifier for other sample formats 868 int32 channels = fOutput.format.u.raw_audio.channel_count; 869 float max[channels]; 870 float min[channels]; 871 for (int32 i = 0; i < channels; i++) { 872 max[i] = -1.0; 873 min[i] = 1.0; 874 } 875 float* sample = (float*)buffer->Data(); 876 for (uint32 i = 0; i < frameCount; i++) { 877 for (int32 k = 0; k < channels; k++) { 878 if (*sample < min[k]) 879 min[k] = *sample; 880 if (*sample > max[k]) 881 max[k] = *sample; 882 sample++; 883 } 884 } 885 BMessage message(MSG_PEAK_NOTIFICATION); 886 for (int32 i = 0; i < channels; i++) { 887 float maxAbs = max_c(fabs(min[i]), fabs(max[i])); 888 message.AddFloat("max", maxAbs); 889 } 890 bigtime_t realTime = TimeSource()->RealTimeFor( 891 fStartTime + startTime, 0); 892 MessageEvent* event = new (std::nothrow) MessageEvent(realTime, 893 fPeakListener, message); 894 if (event != NULL) 895 EventQueue::Default().AddEvent(event); 896 } 897 898 return buffer; 899 } 900 901