171c77851Sthreedeyes /* 2*56bc38ceSPhilippe Saint-Pierre * Copyright 2012, Gerasim Troeglazov (3dEyes**), 3dEyes@gmail.com. 3*56bc38ceSPhilippe Saint-Pierre * All rights reserved. 471c77851Sthreedeyes * Distributed under the terms of the MIT License. 571c77851Sthreedeyes */ 671c77851Sthreedeyes 771c77851Sthreedeyes #include <ByteOrder.h> 871c77851Sthreedeyes #include <Buffer.h> 971c77851Sthreedeyes #include <BufferGroup.h> 1071c77851Sthreedeyes #include <TimeSource.h> 1171c77851Sthreedeyes #include <ParameterWeb.h> 1271c77851Sthreedeyes #include <String.h> 1371c77851Sthreedeyes 1471c77851Sthreedeyes #include <stdio.h> 1571c77851Sthreedeyes #include <string.h> 1671c77851Sthreedeyes 1771c77851Sthreedeyes #include "EqualizerNode.h" 1871c77851Sthreedeyes 1971c77851Sthreedeyes //EqualizerNode 20*56bc38ceSPhilippe Saint-Pierre EqualizerNode::~EqualizerNode() 21*56bc38ceSPhilippe Saint-Pierre { 2271c77851Sthreedeyes Quit(); 2371c77851Sthreedeyes } 2471c77851Sthreedeyes 25*56bc38ceSPhilippe Saint-Pierre 26*56bc38ceSPhilippe Saint-Pierre EqualizerNode::EqualizerNode(BMediaAddOn* addon) 27*56bc38ceSPhilippe Saint-Pierre : 2871c77851Sthreedeyes BMediaNode("10 Band Equalizer"), 2971c77851Sthreedeyes BBufferConsumer(B_MEDIA_RAW_AUDIO), 3071c77851Sthreedeyes BBufferProducer(B_MEDIA_RAW_AUDIO), 3171c77851Sthreedeyes BControllable(), 3271c77851Sthreedeyes BMediaEventLooper(), 3371c77851Sthreedeyes fAddOn(addon), 3471c77851Sthreedeyes fProcessLatency(0), 3571c77851Sthreedeyes fDownstreamLatency(0), 3671c77851Sthreedeyes fOutputMediaEnabled(true) 3771c77851Sthreedeyes { 3871c77851Sthreedeyes } 3971c77851Sthreedeyes 40*56bc38ceSPhilippe Saint-Pierre 4171c77851Sthreedeyes //BMediaNode 4271c77851Sthreedeyes BMediaAddOn* 4371c77851Sthreedeyes EqualizerNode::AddOn(int32* id) const 4471c77851Sthreedeyes { 4571c77851Sthreedeyes if (fAddOn) 4671c77851Sthreedeyes *id = 0; 4771c77851Sthreedeyes return fAddOn; 4871c77851Sthreedeyes } 4971c77851Sthreedeyes 50*56bc38ceSPhilippe Saint-Pierre 5171c77851Sthreedeyes status_t 5271c77851Sthreedeyes EqualizerNode::HandleMessage(int32 message, const void *data, size_t size) 5371c77851Sthreedeyes { 5471c77851Sthreedeyes if ((BControllable::HandleMessage(message, data, size) != B_OK) && 5571c77851Sthreedeyes (BBufferConsumer::HandleMessage(message, data, size) != B_OK) && 5671c77851Sthreedeyes (BBufferProducer::HandleMessage(message, data, size) != B_OK) && 5771c77851Sthreedeyes (BControllable::HandleMessage(message, data, size) != B_OK)) { 5871c77851Sthreedeyes BMediaNode::HandleMessage(message, data, size); 5971c77851Sthreedeyes return B_OK; 60*56bc38ceSPhilippe Saint-Pierre } 6171c77851Sthreedeyes BMediaNode::HandleBadMessage(message, data, size); 6271c77851Sthreedeyes return B_ERROR; 6371c77851Sthreedeyes } 64*56bc38ceSPhilippe Saint-Pierre 6571c77851Sthreedeyes 6671c77851Sthreedeyes void 6771c77851Sthreedeyes EqualizerNode::NodeRegistered() 6871c77851Sthreedeyes { 6971c77851Sthreedeyes SetPriority(B_REAL_TIME_PRIORITY); 7071c77851Sthreedeyes Run(); 7171c77851Sthreedeyes 7271c77851Sthreedeyes fPreferredFormat.type = B_MEDIA_RAW_AUDIO; 7371c77851Sthreedeyes fPreferredFormat.u.raw_audio.buffer_size = BUFF_SIZE; 7471c77851Sthreedeyes fPreferredFormat.u.raw_audio = media_raw_audio_format::wildcard; 75*56bc38ceSPhilippe Saint-Pierre fPreferredFormat.u.raw_audio.channel_count = 76*56bc38ceSPhilippe Saint-Pierre media_raw_audio_format::wildcard.channel_count; 7771c77851Sthreedeyes fPreferredFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; 7871c77851Sthreedeyes 7971c77851Sthreedeyes fFormat.type = B_MEDIA_RAW_AUDIO; 8071c77851Sthreedeyes fFormat.u.raw_audio = media_raw_audio_format::wildcard; 8171c77851Sthreedeyes 8271c77851Sthreedeyes fInputMedia.destination.port = ControlPort(); 8371c77851Sthreedeyes fInputMedia.destination.id = ID_AUDIO_INPUT; 8471c77851Sthreedeyes fInputMedia.node = Node(); 8571c77851Sthreedeyes fInputMedia.source = media_source::null; 8671c77851Sthreedeyes fInputMedia.format = fFormat; 8771c77851Sthreedeyes strncpy(fInputMedia.name, "Audio Input", B_MEDIA_NAME_LENGTH); 8871c77851Sthreedeyes 8971c77851Sthreedeyes fOutputMedia.source.port = ControlPort(); 9071c77851Sthreedeyes fOutputMedia.source.id = ID_AUDIO_OUTPUT; 9171c77851Sthreedeyes fOutputMedia.node = Node(); 9271c77851Sthreedeyes fOutputMedia.destination = media_destination::null; 9371c77851Sthreedeyes fOutputMedia.format = fFormat; 9471c77851Sthreedeyes strncpy(fOutputMedia.name, "Audio Output", B_MEDIA_NAME_LENGTH); 9571c77851Sthreedeyes 9671c77851Sthreedeyes InitParameterValues(); 9771c77851Sthreedeyes InitParameterWeb(); 9871c77851Sthreedeyes } 9971c77851Sthreedeyes 100*56bc38ceSPhilippe Saint-Pierre 10171c77851Sthreedeyes //BControllable 10271c77851Sthreedeyes status_t 103*56bc38ceSPhilippe Saint-Pierre EqualizerNode::GetParameterValue(int32 id, bigtime_t* lastChangeTime, 104*56bc38ceSPhilippe Saint-Pierre void* value, size_t* size) 10571c77851Sthreedeyes { 106*56bc38ceSPhilippe Saint-Pierre if (*size < sizeof(float)) 10771c77851Sthreedeyes return B_NO_MEMORY; 10871c77851Sthreedeyes 10971c77851Sthreedeyes if (id == P_MUTE) { 11071c77851Sthreedeyes *(int32*)value = fMute; 11171c77851Sthreedeyes *lastChangeTime = fMuteLastChanged; 11271c77851Sthreedeyes *size = sizeof(int32); 11371c77851Sthreedeyes } else if (id == P_BYPASS) { 11471c77851Sthreedeyes *(int32*)value = fByPass; 11571c77851Sthreedeyes *lastChangeTime = fByPassLastChanged; 11671c77851Sthreedeyes *size = sizeof(int32); 11771c77851Sthreedeyes } else if (id == P_PREAMP) { 11871c77851Sthreedeyes *(float*)value = (float)fEqualizer.PreAmp(); 11971c77851Sthreedeyes *lastChangeTime = fPreAmpLastChanged; 12071c77851Sthreedeyes *size = sizeof(float); 12171c77851Sthreedeyes } else if (id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount()) { 12271c77851Sthreedeyes int band = id - P_BANDS; 12371c77851Sthreedeyes *(float*)value = (float)fEqualizer.Band(band); 12471c77851Sthreedeyes *lastChangeTime = fBandsLastChanged[band]; 12571c77851Sthreedeyes *size = sizeof(float); 126*56bc38ceSPhilippe Saint-Pierre } else 127*56bc38ceSPhilippe Saint-Pierre return B_ERROR; 12871c77851Sthreedeyes return B_OK; 12971c77851Sthreedeyes } 13071c77851Sthreedeyes 13171c77851Sthreedeyes 13271c77851Sthreedeyes void 133*56bc38ceSPhilippe Saint-Pierre EqualizerNode::SetParameterValue(int32 id, bigtime_t time, const void* value, 134*56bc38ceSPhilippe Saint-Pierre size_t size) 13571c77851Sthreedeyes { 136*56bc38ceSPhilippe Saint-Pierre if (id == P_PREAMP || id == P_BYPASS || id == P_MUTE 137*56bc38ceSPhilippe Saint-Pierre || (id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount())) { 13871c77851Sthreedeyes media_timed_event ev(time, BTimedEventQueue::B_PARAMETER, (void*)value, 13971c77851Sthreedeyes BTimedEventQueue::B_NO_CLEANUP, size, id, "EQ"); 140*56bc38ceSPhilippe Saint-Pierre ParameterEventProcessing(&ev); 141*56bc38ceSPhilippe Saint-Pierre //dirty hack for parameter processing (mediakit bug????) 14271c77851Sthreedeyes EventQueue()->AddEvent(ev); 14371c77851Sthreedeyes } 14471c77851Sthreedeyes } 14571c77851Sthreedeyes 146*56bc38ceSPhilippe Saint-Pierre 14771c77851Sthreedeyes //BBufferConsumer 14871c77851Sthreedeyes void 14971c77851Sthreedeyes EqualizerNode::BufferReceived(BBuffer* buffer) 15071c77851Sthreedeyes { 15171c77851Sthreedeyes if (buffer->Header()->destination != fInputMedia.destination.id) { 15271c77851Sthreedeyes buffer->Recycle(); 15371c77851Sthreedeyes return; 15471c77851Sthreedeyes } 15571c77851Sthreedeyes 156*56bc38ceSPhilippe Saint-Pierre if (fOutputMedia.destination == media_destination::null 157*56bc38ceSPhilippe Saint-Pierre || !fOutputMediaEnabled) { 15871c77851Sthreedeyes buffer->Recycle(); 15971c77851Sthreedeyes return; 16071c77851Sthreedeyes } 16171c77851Sthreedeyes 16271c77851Sthreedeyes FilterBuffer(buffer); 16371c77851Sthreedeyes 164*56bc38ceSPhilippe Saint-Pierre status_t err = SendBuffer(buffer, fOutputMedia.source, 165*56bc38ceSPhilippe Saint-Pierre fOutputMedia.destination); 166*56bc38ceSPhilippe Saint-Pierre if (err < B_OK) 16771c77851Sthreedeyes buffer->Recycle(); 16871c77851Sthreedeyes } 169*56bc38ceSPhilippe Saint-Pierre 17071c77851Sthreedeyes 17171c77851Sthreedeyes status_t 17271c77851Sthreedeyes EqualizerNode::AcceptFormat(const media_destination &dst, media_format* format) 17371c77851Sthreedeyes { 174*56bc38ceSPhilippe Saint-Pierre if (dst != fInputMedia.destination) 17571c77851Sthreedeyes return B_MEDIA_BAD_DESTINATION; 17671c77851Sthreedeyes 177*56bc38ceSPhilippe Saint-Pierre if (format->type != B_MEDIA_RAW_AUDIO) 178*56bc38ceSPhilippe Saint-Pierre return B_MEDIA_BAD_FORMAT; 179*56bc38ceSPhilippe Saint-Pierre 180*56bc38ceSPhilippe Saint-Pierre ValidateFormat((fFormat.u.raw_audio.format 181*56bc38ceSPhilippe Saint-Pierre != media_raw_audio_format::wildcard.format) ? 18271c77851Sthreedeyes fFormat : fPreferredFormat, *format); 18371c77851Sthreedeyes 18471c77851Sthreedeyes return B_OK; 18571c77851Sthreedeyes } 18671c77851Sthreedeyes 187*56bc38ceSPhilippe Saint-Pierre 18871c77851Sthreedeyes status_t 18971c77851Sthreedeyes EqualizerNode::GetNextInput(int32* cookie, media_input* input) 19071c77851Sthreedeyes { 191*56bc38ceSPhilippe Saint-Pierre if (*cookie) 19271c77851Sthreedeyes return B_BAD_INDEX; 193*56bc38ceSPhilippe Saint-Pierre 19471c77851Sthreedeyes ++*cookie; 19571c77851Sthreedeyes *input = fInputMedia; 19671c77851Sthreedeyes return B_OK; 19771c77851Sthreedeyes } 19871c77851Sthreedeyes 199*56bc38ceSPhilippe Saint-Pierre 20071c77851Sthreedeyes void 20171c77851Sthreedeyes EqualizerNode::DisposeInputCookie(int32 cookie) 20271c77851Sthreedeyes { 20371c77851Sthreedeyes } 20471c77851Sthreedeyes 205*56bc38ceSPhilippe Saint-Pierre 20671c77851Sthreedeyes status_t 207*56bc38ceSPhilippe Saint-Pierre EqualizerNode::FormatChanged(const media_source &src, 208*56bc38ceSPhilippe Saint-Pierre const media_destination &dst, int32 changeTag, const media_format &format) 20971c77851Sthreedeyes { 21071c77851Sthreedeyes return B_MEDIA_BAD_FORMAT; 21171c77851Sthreedeyes } 21271c77851Sthreedeyes 213*56bc38ceSPhilippe Saint-Pierre 21471c77851Sthreedeyes void 215*56bc38ceSPhilippe Saint-Pierre EqualizerNode::ProducerDataStatus(const media_destination &dst, int32 status, 216*56bc38ceSPhilippe Saint-Pierre bigtime_t when) 21771c77851Sthreedeyes { 218*56bc38ceSPhilippe Saint-Pierre if (fOutputMedia.destination != media_destination::null) 21971c77851Sthreedeyes SendDataStatus(status, fOutputMedia.destination, when); 22071c77851Sthreedeyes } 221*56bc38ceSPhilippe Saint-Pierre 22271c77851Sthreedeyes 22371c77851Sthreedeyes status_t 22471c77851Sthreedeyes EqualizerNode::GetLatencyFor(const media_destination &dst, bigtime_t* latency, 22571c77851Sthreedeyes media_node_id* outTimeSource) 22671c77851Sthreedeyes { 22771c77851Sthreedeyes 228*56bc38ceSPhilippe Saint-Pierre if (dst != fInputMedia.destination) 22971c77851Sthreedeyes return B_MEDIA_BAD_DESTINATION; 23071c77851Sthreedeyes 23171c77851Sthreedeyes *latency = fDownstreamLatency + fProcessLatency; 23271c77851Sthreedeyes *outTimeSource = TimeSource()->ID(); 23371c77851Sthreedeyes return B_OK; 23471c77851Sthreedeyes } 23571c77851Sthreedeyes 236*56bc38ceSPhilippe Saint-Pierre 23771c77851Sthreedeyes status_t 23871c77851Sthreedeyes EqualizerNode::Connected(const media_source& source, 23971c77851Sthreedeyes const media_destination& destination, const media_format& format, 24071c77851Sthreedeyes media_input* poInput) 24171c77851Sthreedeyes { 242*56bc38ceSPhilippe Saint-Pierre if (destination != fInputMedia.destination) 24371c77851Sthreedeyes return B_MEDIA_BAD_DESTINATION; 244*56bc38ceSPhilippe Saint-Pierre 245*56bc38ceSPhilippe Saint-Pierre if (fInputMedia.source != media_source::null) 24671c77851Sthreedeyes return B_MEDIA_ALREADY_CONNECTED; 24771c77851Sthreedeyes 24871c77851Sthreedeyes fInputMedia.source = source; 24971c77851Sthreedeyes fInputMedia.format = format; 25071c77851Sthreedeyes *poInput = fInputMedia; 25171c77851Sthreedeyes fFormat = format; 25271c77851Sthreedeyes 25371c77851Sthreedeyes return B_OK; 25471c77851Sthreedeyes } 25571c77851Sthreedeyes 256*56bc38ceSPhilippe Saint-Pierre 25771c77851Sthreedeyes void 258*56bc38ceSPhilippe Saint-Pierre EqualizerNode::Disconnected(const media_source &src, 259*56bc38ceSPhilippe Saint-Pierre const media_destination &dst) 26071c77851Sthreedeyes { 261*56bc38ceSPhilippe Saint-Pierre if (fInputMedia.source != src || dst != fInputMedia.destination) 26271c77851Sthreedeyes return; 263*56bc38ceSPhilippe Saint-Pierre 26471c77851Sthreedeyes fInputMedia.source = media_source::null; 26571c77851Sthreedeyes 266*56bc38ceSPhilippe Saint-Pierre if (fOutputMedia.destination == media_destination::null) 26771c77851Sthreedeyes fFormat.u.raw_audio = media_raw_audio_format::wildcard; 268*56bc38ceSPhilippe Saint-Pierre 26971c77851Sthreedeyes fInputMedia.format = fFormat; 27071c77851Sthreedeyes } 27171c77851Sthreedeyes 272*56bc38ceSPhilippe Saint-Pierre 27371c77851Sthreedeyes //BBufferProducer 27471c77851Sthreedeyes status_t 275*56bc38ceSPhilippe Saint-Pierre EqualizerNode::FormatSuggestionRequested(media_type type, int32 quality, 276*56bc38ceSPhilippe Saint-Pierre media_format* format) 27771c77851Sthreedeyes { 278*56bc38ceSPhilippe Saint-Pierre if (type != B_MEDIA_RAW_AUDIO) 27971c77851Sthreedeyes return B_MEDIA_BAD_FORMAT; 28071c77851Sthreedeyes 281*56bc38ceSPhilippe Saint-Pierre if (fFormat.u.raw_audio.format != media_raw_audio_format::wildcard.format) 28271c77851Sthreedeyes *format = fFormat; 283*56bc38ceSPhilippe Saint-Pierre else 28471c77851Sthreedeyes *format = fPreferredFormat; 28571c77851Sthreedeyes return B_OK; 28671c77851Sthreedeyes } 28771c77851Sthreedeyes 288*56bc38ceSPhilippe Saint-Pierre 28971c77851Sthreedeyes status_t 29071c77851Sthreedeyes EqualizerNode::FormatProposal(const media_source &src, media_format* format) 29171c77851Sthreedeyes { 292*56bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source) 29371c77851Sthreedeyes return B_MEDIA_BAD_SOURCE; 29471c77851Sthreedeyes 295*56bc38ceSPhilippe Saint-Pierre if (format->type != B_MEDIA_RAW_AUDIO) 29671c77851Sthreedeyes return B_MEDIA_BAD_FORMAT; 29771c77851Sthreedeyes 298*56bc38ceSPhilippe Saint-Pierre ValidateFormat((fFormat.u.raw_audio.format 299*56bc38ceSPhilippe Saint-Pierre != media_raw_audio_format::wildcard.format) ? 30071c77851Sthreedeyes fFormat:fPreferredFormat, *format); 30171c77851Sthreedeyes 30271c77851Sthreedeyes return B_OK; 30371c77851Sthreedeyes } 30471c77851Sthreedeyes 305*56bc38ceSPhilippe Saint-Pierre 30671c77851Sthreedeyes status_t 307*56bc38ceSPhilippe Saint-Pierre EqualizerNode::FormatChangeRequested(const media_source &src, 308*56bc38ceSPhilippe Saint-Pierre const media_destination &dst, media_format* format, int32* _deprecated_) 30971c77851Sthreedeyes { 31071c77851Sthreedeyes return B_MEDIA_BAD_FORMAT; 31171c77851Sthreedeyes } 31271c77851Sthreedeyes 313*56bc38ceSPhilippe Saint-Pierre 31471c77851Sthreedeyes void 315*56bc38ceSPhilippe Saint-Pierre EqualizerNode::LateNoticeReceived(const media_source &src, bigtime_t late, 316*56bc38ceSPhilippe Saint-Pierre bigtime_t when) 31771c77851Sthreedeyes { 318*56bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source || fInputMedia.source == media_source::null) 31971c77851Sthreedeyes return; 320*56bc38ceSPhilippe Saint-Pierre 32171c77851Sthreedeyes NotifyLateProducer(fInputMedia.source, late, when); 32271c77851Sthreedeyes } 32371c77851Sthreedeyes 324*56bc38ceSPhilippe Saint-Pierre 32571c77851Sthreedeyes status_t 32671c77851Sthreedeyes EqualizerNode::GetNextOutput(int32* cookie, media_output* output) 32771c77851Sthreedeyes { 328*56bc38ceSPhilippe Saint-Pierre if (*cookie) 32971c77851Sthreedeyes return B_BAD_INDEX; 330*56bc38ceSPhilippe Saint-Pierre 33171c77851Sthreedeyes ++*cookie; 33271c77851Sthreedeyes *output = fOutputMedia; 33371c77851Sthreedeyes return B_OK; 33471c77851Sthreedeyes } 33571c77851Sthreedeyes 336*56bc38ceSPhilippe Saint-Pierre 33771c77851Sthreedeyes status_t 33871c77851Sthreedeyes EqualizerNode::DisposeOutputCookie(int32 cookie) 33971c77851Sthreedeyes { 34071c77851Sthreedeyes return B_OK; 34171c77851Sthreedeyes } 34271c77851Sthreedeyes 343*56bc38ceSPhilippe Saint-Pierre 34471c77851Sthreedeyes status_t 34571c77851Sthreedeyes EqualizerNode::SetBufferGroup(const media_source &src, BBufferGroup* group) 34671c77851Sthreedeyes { 34771c77851Sthreedeyes int32 changeTag; 34871c77851Sthreedeyes status_t ret = B_OK; 34971c77851Sthreedeyes 350*56bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source) 35171c77851Sthreedeyes return B_MEDIA_BAD_SOURCE; 35271c77851Sthreedeyes 353*56bc38ceSPhilippe Saint-Pierre if (fInputMedia.source == media_source::null) 354*56bc38ceSPhilippe Saint-Pierre return B_ERROR; 355*56bc38ceSPhilippe Saint-Pierre 356*56bc38ceSPhilippe Saint-Pierre ret = SetOutputBuffersFor(fInputMedia.source, fInputMedia.destination, 357*56bc38ceSPhilippe Saint-Pierre group, 0, &changeTag); 35871c77851Sthreedeyes return ret; 35971c77851Sthreedeyes } 36071c77851Sthreedeyes 361*56bc38ceSPhilippe Saint-Pierre 36271c77851Sthreedeyes status_t 363*56bc38ceSPhilippe Saint-Pierre EqualizerNode::PrepareToConnect(const media_source &src, 364*56bc38ceSPhilippe Saint-Pierre const media_destination &dst, media_format* format, media_source* outSource, 365*56bc38ceSPhilippe Saint-Pierre char* outName) 36671c77851Sthreedeyes { 367*56bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source) 36871c77851Sthreedeyes return B_MEDIA_BAD_SOURCE; 36971c77851Sthreedeyes 370*56bc38ceSPhilippe Saint-Pierre if (format->type != B_MEDIA_RAW_AUDIO) 37171c77851Sthreedeyes return B_MEDIA_BAD_FORMAT; 37271c77851Sthreedeyes 373*56bc38ceSPhilippe Saint-Pierre if (fOutputMedia.destination != media_destination::null) 37471c77851Sthreedeyes return B_MEDIA_ALREADY_CONNECTED; 37571c77851Sthreedeyes 376*56bc38ceSPhilippe Saint-Pierre status_t err = ValidateFormat((fFormat.u.raw_audio.format 377*56bc38ceSPhilippe Saint-Pierre != media_raw_audio_format::wildcard.format) ? fFormat 378*56bc38ceSPhilippe Saint-Pierre : fPreferredFormat, *format); 37971c77851Sthreedeyes 380*56bc38ceSPhilippe Saint-Pierre if (err < B_OK) 38171c77851Sthreedeyes return err; 38271c77851Sthreedeyes 38371c77851Sthreedeyes SetOutputFormat(*format); 38471c77851Sthreedeyes 38571c77851Sthreedeyes fOutputMedia.destination = dst; 38671c77851Sthreedeyes fOutputMedia.format = *format; 38771c77851Sthreedeyes 38871c77851Sthreedeyes *outSource = fOutputMedia.source; 38971c77851Sthreedeyes strncpy(outName, fOutputMedia.name, B_MEDIA_NAME_LENGTH); 39071c77851Sthreedeyes 39171c77851Sthreedeyes return B_OK; 39271c77851Sthreedeyes } 39371c77851Sthreedeyes 394*56bc38ceSPhilippe Saint-Pierre 39571c77851Sthreedeyes void 396*56bc38ceSPhilippe Saint-Pierre EqualizerNode::Connect(status_t status, const media_source &src, 397*56bc38ceSPhilippe Saint-Pierre const media_destination &dst, const media_format &format, char* outName) 39871c77851Sthreedeyes { 39971c77851Sthreedeyes status_t err; 40071c77851Sthreedeyes if (status < B_OK) { 40171c77851Sthreedeyes fOutputMedia.destination = media_destination::null; 40271c77851Sthreedeyes return; 40371c77851Sthreedeyes } 40471c77851Sthreedeyes 40571c77851Sthreedeyes strncpy(outName, fOutputMedia.name, B_MEDIA_NAME_LENGTH); 40671c77851Sthreedeyes fOutputMedia.destination = dst; 40771c77851Sthreedeyes fFormat = format; 40871c77851Sthreedeyes 40971c77851Sthreedeyes media_node_id timeSource; 410*56bc38ceSPhilippe Saint-Pierre err = FindLatencyFor(fOutputMedia.destination, &fDownstreamLatency, 411*56bc38ceSPhilippe Saint-Pierre &timeSource); 41271c77851Sthreedeyes 41371c77851Sthreedeyes InitFilter(); 41471c77851Sthreedeyes 41571c77851Sthreedeyes fProcessLatency = GetFilterLatency(); 41671c77851Sthreedeyes SetEventLatency(fDownstreamLatency + fProcessLatency); 41771c77851Sthreedeyes 41871c77851Sthreedeyes if (fInputMedia.source != media_source::null) { 41971c77851Sthreedeyes SendLatencyChange(fInputMedia.source, fInputMedia.destination, 42071c77851Sthreedeyes EventLatency() + SchedulingLatency()); 42171c77851Sthreedeyes } 42271c77851Sthreedeyes 42371c77851Sthreedeyes bigtime_t duration = 0; 42471c77851Sthreedeyes 425*56bc38ceSPhilippe Saint-Pierre int sample_size = (fFormat.u.raw_audio.format & 0xf) 426*56bc38ceSPhilippe Saint-Pierre * fFormat.u.raw_audio.channel_count; 42771c77851Sthreedeyes 428*56bc38ceSPhilippe Saint-Pierre if (fFormat.u.raw_audio.buffer_size > 0 429*56bc38ceSPhilippe Saint-Pierre && fFormat.u.raw_audio.frame_rate > 0 && sample_size > 0) { 430*56bc38ceSPhilippe Saint-Pierre duration = (bigtime_t)(((fFormat.u.raw_audio.buffer_size / sample_size) 431*56bc38ceSPhilippe Saint-Pierre / fFormat.u.raw_audio.frame_rate) * 1000000.0); 43271c77851Sthreedeyes } 43371c77851Sthreedeyes 43471c77851Sthreedeyes SetBufferDuration(duration); 43571c77851Sthreedeyes } 43671c77851Sthreedeyes 437*56bc38ceSPhilippe Saint-Pierre 43871c77851Sthreedeyes void 43971c77851Sthreedeyes EqualizerNode::Disconnect(const media_source &src, const media_destination &dst) 44071c77851Sthreedeyes { 441*56bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source) 44271c77851Sthreedeyes return; 44371c77851Sthreedeyes 444*56bc38ceSPhilippe Saint-Pierre if (dst != fOutputMedia.destination) 44571c77851Sthreedeyes return; 44671c77851Sthreedeyes 44771c77851Sthreedeyes fOutputMedia.destination = media_destination::null; 44871c77851Sthreedeyes 449*56bc38ceSPhilippe Saint-Pierre if (fInputMedia.source == media_source::null) 45071c77851Sthreedeyes fFormat.u.raw_audio = media_raw_audio_format::wildcard; 45171c77851Sthreedeyes 45271c77851Sthreedeyes fOutputMedia.format = fFormat; 45371c77851Sthreedeyes } 45471c77851Sthreedeyes 455*56bc38ceSPhilippe Saint-Pierre 45671c77851Sthreedeyes void 457*56bc38ceSPhilippe Saint-Pierre EqualizerNode::EnableOutput(const media_source &src, bool enabled, 458*56bc38ceSPhilippe Saint-Pierre int32* _deprecated_) 45971c77851Sthreedeyes { 460*56bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source) 46171c77851Sthreedeyes return; 46271c77851Sthreedeyes fOutputMediaEnabled = enabled; 46371c77851Sthreedeyes } 46471c77851Sthreedeyes 465*56bc38ceSPhilippe Saint-Pierre 46671c77851Sthreedeyes status_t 46771c77851Sthreedeyes EqualizerNode::GetLatency(bigtime_t* latency) 46871c77851Sthreedeyes { 46971c77851Sthreedeyes *latency = EventLatency() + SchedulingLatency(); 47071c77851Sthreedeyes return B_OK; 47171c77851Sthreedeyes } 47271c77851Sthreedeyes 473*56bc38ceSPhilippe Saint-Pierre 47471c77851Sthreedeyes void 475*56bc38ceSPhilippe Saint-Pierre EqualizerNode::LatencyChanged(const media_source &src, 476*56bc38ceSPhilippe Saint-Pierre const media_destination &dst, bigtime_t latency, uint32 flags) 47771c77851Sthreedeyes { 478*56bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source || dst != fOutputMedia.destination) 47971c77851Sthreedeyes return; 48071c77851Sthreedeyes 48171c77851Sthreedeyes fDownstreamLatency = latency; 48271c77851Sthreedeyes SetEventLatency(fDownstreamLatency + fProcessLatency); 48371c77851Sthreedeyes 48471c77851Sthreedeyes if (fInputMedia.source != media_source::null) { 48571c77851Sthreedeyes SendLatencyChange(fInputMedia.source, 48671c77851Sthreedeyes fInputMedia.destination,EventLatency() + SchedulingLatency()); 48771c77851Sthreedeyes } 48871c77851Sthreedeyes } 48971c77851Sthreedeyes 490*56bc38ceSPhilippe Saint-Pierre 49171c77851Sthreedeyes //BMediaEventLooper 49271c77851Sthreedeyes bigtime_t 49371c77851Sthreedeyes EqualizerNode::OfflineTime() 49471c77851Sthreedeyes { 49571c77851Sthreedeyes return 0LL; 49671c77851Sthreedeyes } 49771c77851Sthreedeyes 498*56bc38ceSPhilippe Saint-Pierre 49971c77851Sthreedeyes //EqualizerNode 50071c77851Sthreedeyes void 501*56bc38ceSPhilippe Saint-Pierre EqualizerNode::HandleEvent(const media_timed_event* event, bigtime_t late, 502*56bc38ceSPhilippe Saint-Pierre bool realTime) 50371c77851Sthreedeyes { 504*56bc38ceSPhilippe Saint-Pierre if (event->type == BTimedEventQueue::B_PARAMETER) 50571c77851Sthreedeyes ParameterEventProcessing(event); 50671c77851Sthreedeyes } 50771c77851Sthreedeyes 50871c77851Sthreedeyes 50971c77851Sthreedeyes void 51071c77851Sthreedeyes EqualizerNode::ParameterEventProcessing(const media_timed_event* event) 51171c77851Sthreedeyes { 51271c77851Sthreedeyes float value = 0.0; 51371c77851Sthreedeyes int32 value32 = 0; 51471c77851Sthreedeyes 51571c77851Sthreedeyes int32 id = event->bigdata; 51671c77851Sthreedeyes size_t size = event->data; 51771c77851Sthreedeyes bigtime_t now = TimeSource()->Now(); 51871c77851Sthreedeyes 51971c77851Sthreedeyes type_code v_type = B_FLOAT_TYPE; 52071c77851Sthreedeyes 52171c77851Sthreedeyes BParameter* web_param; 52271c77851Sthreedeyes 52371c77851Sthreedeyes for (int i = 0; i < fWeb->CountParameters(); i++) { 52471c77851Sthreedeyes web_param = fWeb->ParameterAt(i); 52571c77851Sthreedeyes if (web_param->ID() == id) { 52671c77851Sthreedeyes v_type=web_param->ValueType(); 52771c77851Sthreedeyes break; 52871c77851Sthreedeyes } 52971c77851Sthreedeyes } 53071c77851Sthreedeyes 53171c77851Sthreedeyes if (v_type == B_FLOAT_TYPE) 53271c77851Sthreedeyes value = *((float*)event->pointer); 533*56bc38ceSPhilippe Saint-Pierre else if (v_type == B_INT32_TYPE) { 53471c77851Sthreedeyes value32 = *((int32*)event->pointer); 53571c77851Sthreedeyes value = (float)value32; 53671c77851Sthreedeyes } 53771c77851Sthreedeyes 53871c77851Sthreedeyes if (id == P_MUTE) { 53971c77851Sthreedeyes fMute = value32; 54071c77851Sthreedeyes fMuteLastChanged = now; 54171c77851Sthreedeyes BroadcastNewParameterValue(now, id, event->pointer, size); 54271c77851Sthreedeyes } else if (id == P_BYPASS) { 54371c77851Sthreedeyes fByPass = value32; 54471c77851Sthreedeyes fByPassLastChanged = now; 54571c77851Sthreedeyes BroadcastNewParameterValue(now, id, event->pointer, size); 54671c77851Sthreedeyes } else if (id == P_PREAMP) { 54771c77851Sthreedeyes if (value != fEqualizer.PreAmp()) { 54871c77851Sthreedeyes fEqualizer.SetPreAmp(value); 54971c77851Sthreedeyes fPreAmpLastChanged = now; 55071c77851Sthreedeyes BroadcastNewParameterValue(now, id, &value, size); 55171c77851Sthreedeyes } 55271c77851Sthreedeyes } else if (id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount()) { 55371c77851Sthreedeyes int band = id - P_BANDS; 55471c77851Sthreedeyes if (value != fEqualizer.Band(band)) { 55571c77851Sthreedeyes fEqualizer.SetBand(band, value); 55671c77851Sthreedeyes fBandsLastChanged[band] = now; 55771c77851Sthreedeyes BroadcastNewParameterValue(now, id, &value, size); 55871c77851Sthreedeyes } 55971c77851Sthreedeyes } 56071c77851Sthreedeyes } 56171c77851Sthreedeyes 562*56bc38ceSPhilippe Saint-Pierre 56371c77851Sthreedeyes status_t 56471c77851Sthreedeyes EqualizerNode::ValidateFormat(const media_format &preferredFormat, 56571c77851Sthreedeyes media_format &format) 56671c77851Sthreedeyes { 56771c77851Sthreedeyes status_t ret = B_OK; 56871c77851Sthreedeyes 56971c77851Sthreedeyes if (format.type != B_MEDIA_RAW_AUDIO) { 57071c77851Sthreedeyes format = preferredFormat; 57171c77851Sthreedeyes return B_MEDIA_BAD_FORMAT; 57271c77851Sthreedeyes } 57371c77851Sthreedeyes 57471c77851Sthreedeyes media_raw_audio_format &wild = media_raw_audio_format::wildcard; 57571c77851Sthreedeyes media_raw_audio_format &f = format.u.raw_audio; 57671c77851Sthreedeyes const media_raw_audio_format &pref = format.u.raw_audio; 57771c77851Sthreedeyes 57871c77851Sthreedeyes if (pref.frame_rate != wild.frame_rate && f.frame_rate != pref.frame_rate) { 579*56bc38ceSPhilippe Saint-Pierre if (f.frame_rate != wild.frame_rate) 58071c77851Sthreedeyes ret = B_MEDIA_BAD_FORMAT; 58171c77851Sthreedeyes f.frame_rate = pref.frame_rate; 58271c77851Sthreedeyes } 58371c77851Sthreedeyes 584*56bc38ceSPhilippe Saint-Pierre if (pref.channel_count != wild.channel_count 585*56bc38ceSPhilippe Saint-Pierre && f.channel_count != pref.channel_count) { 586*56bc38ceSPhilippe Saint-Pierre if (f.channel_count != wild.channel_count) 58771c77851Sthreedeyes ret = B_MEDIA_BAD_FORMAT; 58871c77851Sthreedeyes f.channel_count = pref.channel_count; 58971c77851Sthreedeyes } 59071c77851Sthreedeyes 59171c77851Sthreedeyes if (pref.byte_order != wild.byte_order && f.byte_order != pref.byte_order) { 592*56bc38ceSPhilippe Saint-Pierre if (f.byte_order != wild.byte_order) 59371c77851Sthreedeyes ret = B_MEDIA_BAD_FORMAT; 59471c77851Sthreedeyes f.byte_order = pref.byte_order; 59571c77851Sthreedeyes } 59671c77851Sthreedeyes 59771c77851Sthreedeyes if (pref.format != wild.format && f.format != pref.format) { 598*56bc38ceSPhilippe Saint-Pierre if (f.format != wild.format) 59971c77851Sthreedeyes ret = B_MEDIA_BAD_FORMAT; 60071c77851Sthreedeyes f.format = pref.format; 60171c77851Sthreedeyes } 60271c77851Sthreedeyes 603*56bc38ceSPhilippe Saint-Pierre if (pref.buffer_size != wild.buffer_size 604*56bc38ceSPhilippe Saint-Pierre && f.buffer_size != pref.buffer_size) { 605*56bc38ceSPhilippe Saint-Pierre if (f.buffer_size != wild.buffer_size) 60671c77851Sthreedeyes ret = B_MEDIA_BAD_FORMAT; 60771c77851Sthreedeyes f.buffer_size = pref.buffer_size; 60871c77851Sthreedeyes } 60971c77851Sthreedeyes 61071c77851Sthreedeyes return ret; 61171c77851Sthreedeyes } 61271c77851Sthreedeyes 613*56bc38ceSPhilippe Saint-Pierre 61471c77851Sthreedeyes void 61571c77851Sthreedeyes EqualizerNode::SetOutputFormat(media_format &format) 61671c77851Sthreedeyes { 61771c77851Sthreedeyes media_raw_audio_format &f = format.u.raw_audio; 61871c77851Sthreedeyes media_raw_audio_format &w = media_raw_audio_format::wildcard; 61971c77851Sthreedeyes 620*56bc38ceSPhilippe Saint-Pierre if (f.frame_rate == w.frame_rate) 62171c77851Sthreedeyes f.frame_rate = 44100.0; 62271c77851Sthreedeyes 62371c77851Sthreedeyes if (f.channel_count == w.channel_count) { 624*56bc38ceSPhilippe Saint-Pierre if (fInputMedia.source != media_source::null) 62571c77851Sthreedeyes f.channel_count = fInputMedia.format.u.raw_audio.channel_count; 626*56bc38ceSPhilippe Saint-Pierre else 62771c77851Sthreedeyes f.channel_count = 2; 62871c77851Sthreedeyes } 62971c77851Sthreedeyes 630*56bc38ceSPhilippe Saint-Pierre if (f.format == w.format) 63171c77851Sthreedeyes f.format = media_raw_audio_format::B_AUDIO_FLOAT; 63271c77851Sthreedeyes 633*56bc38ceSPhilippe Saint-Pierre if (f.byte_order == w.format) 634*56bc38ceSPhilippe Saint-Pierre f.byte_order = (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN 635*56bc38ceSPhilippe Saint-Pierre : B_MEDIA_LITTLE_ENDIAN; 63671c77851Sthreedeyes 637*56bc38ceSPhilippe Saint-Pierre if (f.buffer_size == w.buffer_size) 63871c77851Sthreedeyes f.buffer_size = BUFF_SIZE; 63971c77851Sthreedeyes } 640*56bc38ceSPhilippe Saint-Pierre 64171c77851Sthreedeyes 64271c77851Sthreedeyes void 64371c77851Sthreedeyes EqualizerNode::InitParameterValues() 64471c77851Sthreedeyes { 64571c77851Sthreedeyes fMute = 0; 64671c77851Sthreedeyes fByPass = 0; 64771c77851Sthreedeyes fMuteLastChanged = 0LL; 64871c77851Sthreedeyes fByPassLastChanged = 0LL; 64971c77851Sthreedeyes fPreAmpLastChanged = 0LL; 65071c77851Sthreedeyes 651*56bc38ceSPhilippe Saint-Pierre for (int i = 0; i < EQ_BANDS; i++) 65271c77851Sthreedeyes fBandsLastChanged[i] = 0LL; 65371c77851Sthreedeyes 65471c77851Sthreedeyes fEqualizer.CleanUp(); 65571c77851Sthreedeyes } 65671c77851Sthreedeyes 657*56bc38ceSPhilippe Saint-Pierre 65871c77851Sthreedeyes void 65971c77851Sthreedeyes EqualizerNode::InitParameterWeb(void) 66071c77851Sthreedeyes { 66171c77851Sthreedeyes fWeb = new BParameterWeb(); 66271c77851Sthreedeyes 66371c77851Sthreedeyes BParameterGroup* fParamGroup = fWeb->MakeGroup("EqualizerNode Parameters"); 66471c77851Sthreedeyes BParameterGroup* fFControlGroup = fParamGroup->MakeGroup("FilterControl"); 66571c77851Sthreedeyes 666*56bc38ceSPhilippe Saint-Pierre fFControlGroup->MakeDiscreteParameter(P_MUTE,B_MEDIA_NO_TYPE,"Mute", 667*56bc38ceSPhilippe Saint-Pierre B_ENABLE); 668*56bc38ceSPhilippe Saint-Pierre fFControlGroup->MakeDiscreteParameter(P_BYPASS,B_MEDIA_NO_TYPE,"ByPass", 669*56bc38ceSPhilippe Saint-Pierre B_ENABLE); 67071c77851Sthreedeyes 67171c77851Sthreedeyes BNullParameter* label; 67271c77851Sthreedeyes BParameterGroup* group; 67371c77851Sthreedeyes BContinuousParameter* value; 67471c77851Sthreedeyes 67571c77851Sthreedeyes group = fParamGroup->MakeGroup("Pre Amp"); 676*56bc38ceSPhilippe Saint-Pierre label = group->MakeNullParameter(P_PREAMP_LABEL, B_MEDIA_NO_TYPE, "Pre Amp", 677*56bc38ceSPhilippe Saint-Pierre B_GENERIC); 678*56bc38ceSPhilippe Saint-Pierre value = group->MakeContinuousParameter(P_PREAMP, B_MEDIA_NO_TYPE, "", 679*56bc38ceSPhilippe Saint-Pierre B_GAIN, "dB", -8.0, 8.0, 0.1); 68071c77851Sthreedeyes label->AddOutput(value); 68171c77851Sthreedeyes value->AddInput(label); 68271c77851Sthreedeyes 68371c77851Sthreedeyes for (int i = 0; i < fEqualizer.BandCount(); i++) { 68471c77851Sthreedeyes char freq[32]; 68571c77851Sthreedeyes sprintf(freq,"%gHz",fEqualizer.BandFrequency(i)); 68671c77851Sthreedeyes group = fParamGroup->MakeGroup(freq); 68771c77851Sthreedeyes label = group->MakeNullParameter(P_BAND_LABELS + i, B_MEDIA_NO_TYPE, 68871c77851Sthreedeyes freq, B_GENERIC); 68971c77851Sthreedeyes value = group->MakeContinuousParameter(P_BANDS + i, B_MEDIA_NO_TYPE, 69071c77851Sthreedeyes "", B_GAIN, "dB", -16.0, 16.0, 0.1); 69171c77851Sthreedeyes label->AddOutput(value); 69271c77851Sthreedeyes value->AddInput(label); 69371c77851Sthreedeyes } 69471c77851Sthreedeyes 69571c77851Sthreedeyes SetParameterWeb(fWeb); 69671c77851Sthreedeyes } 69771c77851Sthreedeyes 698*56bc38ceSPhilippe Saint-Pierre 69971c77851Sthreedeyes void 70071c77851Sthreedeyes EqualizerNode::InitFilter(void) 70171c77851Sthreedeyes { 702*56bc38ceSPhilippe Saint-Pierre fEqualizer.SetFormat(fFormat.u.raw_audio.channel_count, 703*56bc38ceSPhilippe Saint-Pierre fFormat.u.raw_audio.frame_rate); 70471c77851Sthreedeyes } 70571c77851Sthreedeyes 706*56bc38ceSPhilippe Saint-Pierre 70771c77851Sthreedeyes bigtime_t 70871c77851Sthreedeyes EqualizerNode::GetFilterLatency(void) 70971c77851Sthreedeyes { 710*56bc38ceSPhilippe Saint-Pierre if (fOutputMedia.destination == media_destination::null) 71171c77851Sthreedeyes return 0LL; 71271c77851Sthreedeyes 713*56bc38ceSPhilippe Saint-Pierre BBufferGroup* test_group = 714*56bc38ceSPhilippe Saint-Pierre new BBufferGroup(fOutputMedia.format.u.raw_audio.buffer_size, 1); 71571c77851Sthreedeyes 716*56bc38ceSPhilippe Saint-Pierre BBuffer* buffer = 717*56bc38ceSPhilippe Saint-Pierre test_group->RequestBuffer(fOutputMedia.format.u.raw_audio.buffer_size); 71871c77851Sthreedeyes buffer->Header()->type = B_MEDIA_RAW_AUDIO; 71971c77851Sthreedeyes buffer->Header()->size_used = fOutputMedia.format.u.raw_audio.buffer_size; 72071c77851Sthreedeyes 72171c77851Sthreedeyes bigtime_t begin = system_time(); 72271c77851Sthreedeyes FilterBuffer(buffer); 72371c77851Sthreedeyes bigtime_t latency = system_time() - begin; 72471c77851Sthreedeyes 72571c77851Sthreedeyes buffer->Recycle(); 72671c77851Sthreedeyes delete test_group; 72771c77851Sthreedeyes 72871c77851Sthreedeyes InitFilter(); 72971c77851Sthreedeyes 73071c77851Sthreedeyes return latency; 73171c77851Sthreedeyes } 73271c77851Sthreedeyes 733*56bc38ceSPhilippe Saint-Pierre 73471c77851Sthreedeyes void 73571c77851Sthreedeyes EqualizerNode::FilterBuffer(BBuffer* buffer) 73671c77851Sthreedeyes { 737*56bc38ceSPhilippe Saint-Pierre uint32 m_frameSize = (fFormat.u.raw_audio.format & 0x0f) 738*56bc38ceSPhilippe Saint-Pierre * fFormat.u.raw_audio.channel_count; 73971c77851Sthreedeyes uint32 samples = buffer->Header()->size_used / m_frameSize; 74071c77851Sthreedeyes uint32 channels = fFormat.u.raw_audio.channel_count; 741*56bc38ceSPhilippe Saint-Pierre if (fMute != 0) 74271c77851Sthreedeyes memset(buffer->Data(), 0, buffer->Header()->size_used); 743*56bc38ceSPhilippe Saint-Pierre else if (fByPass == 0) 74471c77851Sthreedeyes fEqualizer.ProcessBuffer((float*)buffer->Data(), samples * channels); 74571c77851Sthreedeyes } 746