1 /* 2 * Copyright 2012, Gerasim Troeglazov (3dEyes**), 3dEyes@gmail.com. 3 * All rights reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 #include <ByteOrder.h> 8 #include <Buffer.h> 9 #include <BufferGroup.h> 10 #include <TimeSource.h> 11 #include <ParameterWeb.h> 12 #include <String.h> 13 14 #include <stdio.h> 15 #include <string.h> 16 17 #include "EqualizerNode.h" 18 19 //EqualizerNode 20 EqualizerNode::~EqualizerNode() 21 { 22 Quit(); 23 } 24 25 26 EqualizerNode::EqualizerNode(BMediaAddOn* addon) 27 : 28 BMediaNode("10 Band Equalizer"), 29 BBufferConsumer(B_MEDIA_RAW_AUDIO), 30 BBufferProducer(B_MEDIA_RAW_AUDIO), 31 BControllable(), 32 BMediaEventLooper(), 33 fAddOn(addon), 34 fProcessLatency(0), 35 fDownstreamLatency(0), 36 fOutputMediaEnabled(true) 37 { 38 } 39 40 41 //BMediaNode 42 BMediaAddOn* 43 EqualizerNode::AddOn(int32* id) const 44 { 45 if (fAddOn) 46 *id = 0; 47 return fAddOn; 48 } 49 50 51 status_t 52 EqualizerNode::HandleMessage(int32 message, const void *data, size_t size) 53 { 54 if ((BControllable::HandleMessage(message, data, size) != B_OK) && 55 (BBufferConsumer::HandleMessage(message, data, size) != B_OK) && 56 (BBufferProducer::HandleMessage(message, data, size) != B_OK) && 57 (BControllable::HandleMessage(message, data, size) != B_OK)) { 58 BMediaNode::HandleMessage(message, data, size); 59 return B_OK; 60 } 61 BMediaNode::HandleBadMessage(message, data, size); 62 return B_ERROR; 63 } 64 65 66 void 67 EqualizerNode::NodeRegistered() 68 { 69 fPreferredFormat.type = B_MEDIA_RAW_AUDIO; 70 fPreferredFormat.u.raw_audio.buffer_size = BUFF_SIZE; 71 fPreferredFormat.u.raw_audio = media_raw_audio_format::wildcard; 72 fPreferredFormat.u.raw_audio.channel_count = 73 media_raw_audio_format::wildcard.channel_count; 74 fPreferredFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; 75 76 fFormat.type = B_MEDIA_RAW_AUDIO; 77 fFormat.u.raw_audio = media_raw_audio_format::wildcard; 78 79 fInputMedia.destination.port = ControlPort(); 80 fInputMedia.destination.id = ID_AUDIO_INPUT; 81 fInputMedia.node = Node(); 82 fInputMedia.source = media_source::null; 83 fInputMedia.format = fFormat; 84 strncpy(fInputMedia.name, "Audio Input", B_MEDIA_NAME_LENGTH); 85 86 fOutputMedia.source.port = ControlPort(); 87 fOutputMedia.source.id = ID_AUDIO_OUTPUT; 88 fOutputMedia.node = Node(); 89 fOutputMedia.destination = media_destination::null; 90 fOutputMedia.format = fFormat; 91 strncpy(fOutputMedia.name, "Audio Output", B_MEDIA_NAME_LENGTH); 92 93 InitParameterValues(); 94 InitParameterWeb(); 95 96 SetPriority(B_REAL_TIME_PRIORITY); 97 Run(); 98 } 99 100 101 //BControllable 102 status_t 103 EqualizerNode::GetParameterValue(int32 id, bigtime_t* lastChangeTime, 104 void* value, size_t* size) 105 { 106 if (*size < sizeof(float)) 107 return B_NO_MEMORY; 108 109 if (id == P_MUTE) { 110 *(int32*)value = fMute; 111 *lastChangeTime = fMuteLastChanged; 112 *size = sizeof(int32); 113 } else if (id == P_BYPASS) { 114 *(int32*)value = fByPass; 115 *lastChangeTime = fByPassLastChanged; 116 *size = sizeof(int32); 117 } else if (id == P_PREAMP) { 118 *(float*)value = (float)fEqualizer.PreAmp(); 119 *lastChangeTime = fPreAmpLastChanged; 120 *size = sizeof(float); 121 } else if (id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount()) { 122 int band = id - P_BANDS; 123 *(float*)value = (float)fEqualizer.Band(band); 124 *lastChangeTime = fBandsLastChanged[band]; 125 *size = sizeof(float); 126 } else 127 return B_ERROR; 128 return B_OK; 129 } 130 131 132 void 133 EqualizerNode::SetParameterValue(int32 id, bigtime_t time, const void* value, 134 size_t size) 135 { 136 if (id == P_PREAMP || id == P_BYPASS || id == P_MUTE 137 || (id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount())) { 138 media_timed_event ev(time, BTimedEventQueue::B_PARAMETER, (void*)value, 139 BTimedEventQueue::B_NO_CLEANUP, size, id, (char*)"EQ"); 140 //dirty hack for parameter processing (mediakit bug????) 141 ParameterEventProcessing(&ev); 142 EventQueue()->AddEvent(ev); 143 } 144 } 145 146 147 //BBufferConsumer 148 void 149 EqualizerNode::BufferReceived(BBuffer* buffer) 150 { 151 if (buffer->Header()->destination != fInputMedia.destination.id) { 152 buffer->Recycle(); 153 return; 154 } 155 156 if (fOutputMedia.destination == media_destination::null 157 || !fOutputMediaEnabled) { 158 buffer->Recycle(); 159 return; 160 } 161 162 FilterBuffer(buffer); 163 164 status_t err = SendBuffer(buffer, fOutputMedia.source, 165 fOutputMedia.destination); 166 if (err < B_OK) 167 buffer->Recycle(); 168 } 169 170 171 status_t 172 EqualizerNode::AcceptFormat(const media_destination &dst, media_format* format) 173 { 174 if (dst != fInputMedia.destination) 175 return B_MEDIA_BAD_DESTINATION; 176 177 if (format->type != B_MEDIA_RAW_AUDIO) 178 return B_MEDIA_BAD_FORMAT; 179 180 ValidateFormat((fFormat.u.raw_audio.format 181 != media_raw_audio_format::wildcard.format) ? 182 fFormat : fPreferredFormat, *format); 183 184 return B_OK; 185 } 186 187 188 status_t 189 EqualizerNode::GetNextInput(int32* cookie, media_input* input) 190 { 191 if (*cookie) 192 return B_BAD_INDEX; 193 194 ++*cookie; 195 *input = fInputMedia; 196 return B_OK; 197 } 198 199 200 void 201 EqualizerNode::DisposeInputCookie(int32 cookie) 202 { 203 } 204 205 206 status_t 207 EqualizerNode::FormatChanged(const media_source &src, 208 const media_destination &dst, int32 changeTag, const media_format &format) 209 { 210 return B_MEDIA_BAD_FORMAT; 211 } 212 213 214 void 215 EqualizerNode::ProducerDataStatus(const media_destination &dst, int32 status, 216 bigtime_t when) 217 { 218 if (fOutputMedia.destination != media_destination::null) 219 SendDataStatus(status, fOutputMedia.destination, when); 220 } 221 222 223 status_t 224 EqualizerNode::GetLatencyFor(const media_destination &dst, bigtime_t* latency, 225 media_node_id* outTimeSource) 226 { 227 228 if (dst != fInputMedia.destination) 229 return B_MEDIA_BAD_DESTINATION; 230 231 *latency = fDownstreamLatency + fProcessLatency; 232 *outTimeSource = TimeSource()->ID(); 233 return B_OK; 234 } 235 236 237 status_t 238 EqualizerNode::Connected(const media_source& source, 239 const media_destination& destination, const media_format& format, 240 media_input* poInput) 241 { 242 if (destination != fInputMedia.destination) 243 return B_MEDIA_BAD_DESTINATION; 244 245 if (fInputMedia.source != media_source::null) 246 return B_MEDIA_ALREADY_CONNECTED; 247 248 fInputMedia.source = source; 249 fInputMedia.format = format; 250 *poInput = fInputMedia; 251 fFormat = format; 252 253 return B_OK; 254 } 255 256 257 void 258 EqualizerNode::Disconnected(const media_source &src, 259 const media_destination &dst) 260 { 261 if (fInputMedia.source != src || dst != fInputMedia.destination) 262 return; 263 264 fInputMedia.source = media_source::null; 265 266 if (fOutputMedia.destination == media_destination::null) 267 fFormat.u.raw_audio = media_raw_audio_format::wildcard; 268 269 fInputMedia.format = fFormat; 270 } 271 272 273 //BBufferProducer 274 status_t 275 EqualizerNode::FormatSuggestionRequested(media_type type, int32 quality, 276 media_format* format) 277 { 278 if (type != B_MEDIA_RAW_AUDIO) 279 return B_MEDIA_BAD_FORMAT; 280 281 if (fFormat.u.raw_audio.format != media_raw_audio_format::wildcard.format) 282 *format = fFormat; 283 else 284 *format = fPreferredFormat; 285 return B_OK; 286 } 287 288 289 status_t 290 EqualizerNode::FormatProposal(const media_source &src, media_format* format) 291 { 292 if (src != fOutputMedia.source) 293 return B_MEDIA_BAD_SOURCE; 294 295 if (format->type != B_MEDIA_RAW_AUDIO) 296 return B_MEDIA_BAD_FORMAT; 297 298 ValidateFormat((fFormat.u.raw_audio.format 299 != media_raw_audio_format::wildcard.format) ? 300 fFormat:fPreferredFormat, *format); 301 302 return B_OK; 303 } 304 305 306 status_t 307 EqualizerNode::FormatChangeRequested(const media_source &src, 308 const media_destination &dst, media_format* format, int32* _deprecated_) 309 { 310 return B_MEDIA_BAD_FORMAT; 311 } 312 313 314 void 315 EqualizerNode::LateNoticeReceived(const media_source &src, bigtime_t late, 316 bigtime_t when) 317 { 318 if (src != fOutputMedia.source || fInputMedia.source == media_source::null) 319 return; 320 321 NotifyLateProducer(fInputMedia.source, late, when); 322 } 323 324 325 status_t 326 EqualizerNode::GetNextOutput(int32* cookie, media_output* output) 327 { 328 if (*cookie) 329 return B_BAD_INDEX; 330 331 ++*cookie; 332 *output = fOutputMedia; 333 return B_OK; 334 } 335 336 337 status_t 338 EqualizerNode::DisposeOutputCookie(int32 cookie) 339 { 340 return B_OK; 341 } 342 343 344 status_t 345 EqualizerNode::SetBufferGroup(const media_source &src, BBufferGroup* group) 346 { 347 int32 changeTag; 348 status_t ret = B_OK; 349 350 if (src != fOutputMedia.source) 351 return B_MEDIA_BAD_SOURCE; 352 353 if (fInputMedia.source == media_source::null) 354 return B_ERROR; 355 356 ret = SetOutputBuffersFor(fInputMedia.source, fInputMedia.destination, 357 group, 0, &changeTag); 358 return ret; 359 } 360 361 362 status_t 363 EqualizerNode::PrepareToConnect(const media_source &src, 364 const media_destination &dst, media_format* format, media_source* outSource, 365 char* outName) 366 { 367 if (src != fOutputMedia.source) 368 return B_MEDIA_BAD_SOURCE; 369 370 if (format->type != B_MEDIA_RAW_AUDIO) 371 return B_MEDIA_BAD_FORMAT; 372 373 if (fOutputMedia.destination != media_destination::null) 374 return B_MEDIA_ALREADY_CONNECTED; 375 376 status_t err = ValidateFormat((fFormat.u.raw_audio.format 377 != media_raw_audio_format::wildcard.format) ? fFormat 378 : fPreferredFormat, *format); 379 380 if (err < B_OK) 381 return err; 382 383 SetOutputFormat(*format); 384 385 fOutputMedia.destination = dst; 386 fOutputMedia.format = *format; 387 388 *outSource = fOutputMedia.source; 389 strncpy(outName, fOutputMedia.name, B_MEDIA_NAME_LENGTH); 390 391 return B_OK; 392 } 393 394 395 void 396 EqualizerNode::Connect(status_t status, const media_source &src, 397 const media_destination &dst, const media_format &format, char* name) 398 { 399 if (status < B_OK) { 400 fOutputMedia.destination = media_destination::null; 401 return; 402 } 403 404 strncpy(name, fOutputMedia.name, B_MEDIA_NAME_LENGTH); 405 fOutputMedia.destination = dst; 406 fFormat = format; 407 408 media_node_id timeSource; 409 FindLatencyFor(fOutputMedia.destination, &fDownstreamLatency, &timeSource); 410 411 InitFilter(); 412 413 fProcessLatency = GetFilterLatency(); 414 SetEventLatency(fDownstreamLatency + fProcessLatency); 415 416 if (fInputMedia.source != media_source::null) { 417 SendLatencyChange(fInputMedia.source, fInputMedia.destination, 418 EventLatency() + SchedulingLatency()); 419 } 420 421 bigtime_t duration = 0; 422 423 int sample_size = (fFormat.u.raw_audio.format & 0xf) 424 * fFormat.u.raw_audio.channel_count; 425 426 if (fFormat.u.raw_audio.buffer_size > 0 427 && fFormat.u.raw_audio.frame_rate > 0 && sample_size > 0) { 428 duration = (bigtime_t)(((fFormat.u.raw_audio.buffer_size / sample_size) 429 / fFormat.u.raw_audio.frame_rate) * 1000000.0); 430 } 431 432 SetBufferDuration(duration); 433 } 434 435 436 void 437 EqualizerNode::Disconnect(const media_source &src, const media_destination &dst) 438 { 439 if (src != fOutputMedia.source) 440 return; 441 442 if (dst != fOutputMedia.destination) 443 return; 444 445 fOutputMedia.destination = media_destination::null; 446 447 if (fInputMedia.source == media_source::null) 448 fFormat.u.raw_audio = media_raw_audio_format::wildcard; 449 450 fOutputMedia.format = fFormat; 451 } 452 453 454 void 455 EqualizerNode::EnableOutput(const media_source &src, bool enabled, 456 int32* _deprecated_) 457 { 458 if (src != fOutputMedia.source) 459 return; 460 fOutputMediaEnabled = enabled; 461 } 462 463 464 status_t 465 EqualizerNode::GetLatency(bigtime_t* latency) 466 { 467 *latency = EventLatency() + SchedulingLatency(); 468 return B_OK; 469 } 470 471 472 void 473 EqualizerNode::LatencyChanged(const media_source &src, 474 const media_destination &dst, bigtime_t latency, uint32 flags) 475 { 476 if (src != fOutputMedia.source || dst != fOutputMedia.destination) 477 return; 478 479 fDownstreamLatency = latency; 480 SetEventLatency(fDownstreamLatency + fProcessLatency); 481 482 if (fInputMedia.source != media_source::null) { 483 SendLatencyChange(fInputMedia.source, 484 fInputMedia.destination,EventLatency() + SchedulingLatency()); 485 } 486 } 487 488 489 //BMediaEventLooper 490 bigtime_t 491 EqualizerNode::OfflineTime() 492 { 493 return 0LL; 494 } 495 496 497 //EqualizerNode 498 void 499 EqualizerNode::HandleEvent(const media_timed_event* event, bigtime_t late, 500 bool realTime) 501 { 502 if (event->type == BTimedEventQueue::B_PARAMETER) 503 ParameterEventProcessing(event); 504 } 505 506 507 void 508 EqualizerNode::ParameterEventProcessing(const media_timed_event* event) 509 { 510 float value = 0.0; 511 int32 value32 = 0; 512 513 int32 id = event->bigdata; 514 size_t size = event->data; 515 bigtime_t now = TimeSource()->Now(); 516 517 type_code v_type = B_FLOAT_TYPE; 518 519 BParameter* web_param; 520 521 for (int i = 0; i < fWeb->CountParameters(); i++) { 522 web_param = fWeb->ParameterAt(i); 523 if (web_param->ID() == id) { 524 v_type=web_param->ValueType(); 525 break; 526 } 527 } 528 529 if (v_type == B_FLOAT_TYPE) 530 value = *((float*)event->pointer); 531 else if (v_type == B_INT32_TYPE) { 532 value32 = *((int32*)event->pointer); 533 value = (float)value32; 534 } 535 536 if (id == P_MUTE) { 537 fMute = value32; 538 fMuteLastChanged = now; 539 BroadcastNewParameterValue(now, id, event->pointer, size); 540 } else if (id == P_BYPASS) { 541 fByPass = value32; 542 fByPassLastChanged = now; 543 BroadcastNewParameterValue(now, id, event->pointer, size); 544 } else if (id == P_PREAMP) { 545 if (value != fEqualizer.PreAmp()) { 546 fEqualizer.SetPreAmp(value); 547 fPreAmpLastChanged = now; 548 BroadcastNewParameterValue(now, id, &value, size); 549 } 550 } else if (id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount()) { 551 int band = id - P_BANDS; 552 if (value != fEqualizer.Band(band)) { 553 fEqualizer.SetBand(band, value); 554 fBandsLastChanged[band] = now; 555 BroadcastNewParameterValue(now, id, &value, size); 556 } 557 } 558 } 559 560 561 status_t 562 EqualizerNode::ValidateFormat(const media_format &preferred_format, 563 media_format &proposed_format) 564 { 565 status_t ret = B_OK; 566 567 if (proposed_format.type != B_MEDIA_RAW_AUDIO) { 568 proposed_format = preferred_format; 569 return B_MEDIA_BAD_FORMAT; 570 } 571 572 const media_raw_audio_format &wild = media_raw_audio_format::wildcard; 573 media_raw_audio_format &f = proposed_format.u.raw_audio; 574 const media_raw_audio_format &pref = preferred_format.u.raw_audio; 575 576 if(pref.frame_rate != wild.frame_rate && f.frame_rate != pref.frame_rate) { 577 if(f.frame_rate != wild.frame_rate) 578 ret = B_MEDIA_BAD_FORMAT; 579 f.frame_rate = pref.frame_rate; 580 } 581 582 if(pref.channel_count != wild.channel_count && 583 f.channel_count != pref.channel_count) { 584 if(f.channel_count != wild.channel_count) 585 ret = B_MEDIA_BAD_FORMAT; 586 f.channel_count = pref.channel_count; 587 } 588 589 if(pref.format != wild.format && f.format != pref.format) { 590 if(f.format != wild.format) 591 ret = B_MEDIA_BAD_FORMAT; 592 f.format = pref.format; 593 } 594 595 if(pref.byte_order != wild.byte_order && 596 f.byte_order != pref.byte_order) { 597 if(f.byte_order != wild.byte_order) 598 ret = B_MEDIA_BAD_FORMAT; 599 f.byte_order = pref.byte_order; 600 } 601 602 if(pref.buffer_size != wild.buffer_size && 603 f.buffer_size != pref.buffer_size) { 604 if(f.buffer_size != wild.buffer_size) 605 ret = B_MEDIA_BAD_FORMAT; 606 f.buffer_size = pref.buffer_size; 607 } 608 609 return ret; 610 } 611 612 613 void 614 EqualizerNode::SetOutputFormat(media_format &format) 615 { 616 media_raw_audio_format &f = format.u.raw_audio; 617 const media_raw_audio_format &w = media_raw_audio_format::wildcard; 618 619 if (f.frame_rate == w.frame_rate) { 620 f.frame_rate = 44100.0; 621 } 622 if (f.channel_count == w.channel_count) { 623 if(fInputMedia.source != media_source::null) 624 f.channel_count = fInputMedia.format.u.raw_audio.channel_count; 625 else 626 f.channel_count = 2; 627 } 628 629 if (f.format == w.format) 630 f.format = media_raw_audio_format::B_AUDIO_FLOAT; 631 632 if (f.byte_order == w.format) { 633 f.byte_order = (B_HOST_IS_BENDIAN) ? 634 B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN; 635 } 636 637 if (f.buffer_size == w.buffer_size) 638 f.buffer_size = BUFF_SIZE; 639 } 640 641 642 void 643 EqualizerNode::InitParameterValues() 644 { 645 fMute = 0; 646 fByPass = 0; 647 fMuteLastChanged = 0LL; 648 fByPassLastChanged = 0LL; 649 fPreAmpLastChanged = 0LL; 650 651 for (int i = 0; i < EQ_BANDS; i++) 652 fBandsLastChanged[i] = 0LL; 653 654 fEqualizer.CleanUp(); 655 } 656 657 658 void 659 EqualizerNode::InitParameterWeb(void) 660 { 661 fWeb = new BParameterWeb(); 662 663 BParameterGroup* fParamGroup = fWeb->MakeGroup("EqualizerNode Parameters"); 664 BParameterGroup* fFControlGroup = fParamGroup->MakeGroup("FilterControl"); 665 666 fFControlGroup->MakeDiscreteParameter(P_MUTE,B_MEDIA_NO_TYPE,"Mute", 667 B_ENABLE); 668 fFControlGroup->MakeDiscreteParameter(P_BYPASS,B_MEDIA_NO_TYPE,"ByPass", 669 B_ENABLE); 670 671 BNullParameter* label; 672 BParameterGroup* group; 673 BContinuousParameter* value; 674 675 group = fParamGroup->MakeGroup("Pre Amp"); 676 label = group->MakeNullParameter(P_PREAMP_LABEL, B_MEDIA_NO_TYPE, "Pre Amp", 677 B_GENERIC); 678 value = group->MakeContinuousParameter(P_PREAMP, B_MEDIA_NO_TYPE, "", 679 B_GAIN, "dB", -8.0, 8.0, 0.1); 680 label->AddOutput(value); 681 value->AddInput(label); 682 683 for (int i = 0; i < fEqualizer.BandCount(); i++) { 684 char freq[32]; 685 sprintf(freq,"%gHz",fEqualizer.BandFrequency(i)); 686 group = fParamGroup->MakeGroup(freq); 687 label = group->MakeNullParameter(P_BAND_LABELS + i, B_MEDIA_NO_TYPE, 688 freq, B_GENERIC); 689 value = group->MakeContinuousParameter(P_BANDS + i, B_MEDIA_NO_TYPE, 690 "", B_GAIN, "dB", -16.0, 16.0, 0.1); 691 label->AddOutput(value); 692 value->AddInput(label); 693 } 694 695 SetParameterWeb(fWeb); 696 } 697 698 699 void 700 EqualizerNode::InitFilter(void) 701 { 702 fEqualizer.SetFormat(fFormat.u.raw_audio.channel_count, 703 fFormat.u.raw_audio.frame_rate); 704 } 705 706 707 bigtime_t 708 EqualizerNode::GetFilterLatency(void) 709 { 710 if (fOutputMedia.destination == media_destination::null) 711 return 0LL; 712 713 BBufferGroup* test_group = 714 new BBufferGroup(fOutputMedia.format.u.raw_audio.buffer_size, 1); 715 716 BBuffer* buffer = 717 test_group->RequestBuffer(fOutputMedia.format.u.raw_audio.buffer_size); 718 buffer->Header()->type = B_MEDIA_RAW_AUDIO; 719 buffer->Header()->size_used = fOutputMedia.format.u.raw_audio.buffer_size; 720 721 bigtime_t begin = system_time(); 722 FilterBuffer(buffer); 723 bigtime_t latency = system_time() - begin; 724 725 buffer->Recycle(); 726 delete test_group; 727 728 InitFilter(); 729 730 return latency; 731 } 732 733 734 void 735 EqualizerNode::FilterBuffer(BBuffer* buffer) 736 { 737 uint32 m_frameSize = (fFormat.u.raw_audio.format & 0x0f) 738 * fFormat.u.raw_audio.channel_count; 739 uint32 samples = buffer->Header()->size_used / m_frameSize; 740 uint32 channels = fFormat.u.raw_audio.channel_count; 741 if (fMute != 0) 742 memset(buffer->Data(), 0, buffer->Header()->size_used); 743 else if (fByPass == 0) 744 fEqualizer.ProcessBuffer((float*)buffer->Data(), samples * channels); 745 } 746