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