171c77851Sthreedeyes /* 256bc38ceSPhilippe Saint-Pierre * Copyright 2012, Gerasim Troeglazov (3dEyes**), 3dEyes@gmail.com. 356bc38ceSPhilippe 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 2056bc38ceSPhilippe Saint-Pierre EqualizerNode::~EqualizerNode() 2156bc38ceSPhilippe Saint-Pierre { 2271c77851Sthreedeyes Quit(); 2371c77851Sthreedeyes } 2471c77851Sthreedeyes 2556bc38ceSPhilippe Saint-Pierre 2656bc38ceSPhilippe Saint-Pierre EqualizerNode::EqualizerNode(BMediaAddOn* addon) 2756bc38ceSPhilippe 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 4056bc38ceSPhilippe Saint-Pierre 4171c77851Sthreedeyes //BMediaNode 4271c77851Sthreedeyes BMediaAddOn* 4371c77851Sthreedeyes EqualizerNode::AddOn(int32* id) const 4471c77851Sthreedeyes { 4571c77851Sthreedeyes if (fAddOn) 4671c77851Sthreedeyes *id = 0; 4771c77851Sthreedeyes return fAddOn; 4871c77851Sthreedeyes } 4971c77851Sthreedeyes 5056bc38ceSPhilippe 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; 6056bc38ceSPhilippe Saint-Pierre } 6171c77851Sthreedeyes BMediaNode::HandleBadMessage(message, data, size); 6271c77851Sthreedeyes return B_ERROR; 6371c77851Sthreedeyes } 6456bc38ceSPhilippe Saint-Pierre 6571c77851Sthreedeyes 6671c77851Sthreedeyes void 6771c77851Sthreedeyes EqualizerNode::NodeRegistered() 6871c77851Sthreedeyes { 6971c77851Sthreedeyes fPreferredFormat.type = B_MEDIA_RAW_AUDIO; 7071c77851Sthreedeyes fPreferredFormat.u.raw_audio.buffer_size = BUFF_SIZE; 7171c77851Sthreedeyes fPreferredFormat.u.raw_audio = media_raw_audio_format::wildcard; 7256bc38ceSPhilippe Saint-Pierre fPreferredFormat.u.raw_audio.channel_count = 7356bc38ceSPhilippe Saint-Pierre media_raw_audio_format::wildcard.channel_count; 7471c77851Sthreedeyes fPreferredFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT; 7571c77851Sthreedeyes 7671c77851Sthreedeyes fFormat.type = B_MEDIA_RAW_AUDIO; 7771c77851Sthreedeyes fFormat.u.raw_audio = media_raw_audio_format::wildcard; 7871c77851Sthreedeyes 7971c77851Sthreedeyes fInputMedia.destination.port = ControlPort(); 8071c77851Sthreedeyes fInputMedia.destination.id = ID_AUDIO_INPUT; 8171c77851Sthreedeyes fInputMedia.node = Node(); 8271c77851Sthreedeyes fInputMedia.source = media_source::null; 8371c77851Sthreedeyes fInputMedia.format = fFormat; 8471c77851Sthreedeyes strncpy(fInputMedia.name, "Audio Input", B_MEDIA_NAME_LENGTH); 8571c77851Sthreedeyes 8671c77851Sthreedeyes fOutputMedia.source.port = ControlPort(); 8771c77851Sthreedeyes fOutputMedia.source.id = ID_AUDIO_OUTPUT; 8871c77851Sthreedeyes fOutputMedia.node = Node(); 8971c77851Sthreedeyes fOutputMedia.destination = media_destination::null; 9071c77851Sthreedeyes fOutputMedia.format = fFormat; 9171c77851Sthreedeyes strncpy(fOutputMedia.name, "Audio Output", B_MEDIA_NAME_LENGTH); 9271c77851Sthreedeyes 9371c77851Sthreedeyes InitParameterValues(); 9471c77851Sthreedeyes InitParameterWeb(); 95*6d2f2ec1SDario Casalinuovo 96*6d2f2ec1SDario Casalinuovo SetPriority(B_REAL_TIME_PRIORITY); 97*6d2f2ec1SDario Casalinuovo Run(); 9871c77851Sthreedeyes } 9971c77851Sthreedeyes 10056bc38ceSPhilippe Saint-Pierre 10171c77851Sthreedeyes //BControllable 10271c77851Sthreedeyes status_t 10356bc38ceSPhilippe Saint-Pierre EqualizerNode::GetParameterValue(int32 id, bigtime_t* lastChangeTime, 10456bc38ceSPhilippe Saint-Pierre void* value, size_t* size) 10571c77851Sthreedeyes { 10656bc38ceSPhilippe 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); 12656bc38ceSPhilippe Saint-Pierre } else 12756bc38ceSPhilippe Saint-Pierre return B_ERROR; 12871c77851Sthreedeyes return B_OK; 12971c77851Sthreedeyes } 13071c77851Sthreedeyes 13171c77851Sthreedeyes 13271c77851Sthreedeyes void 13356bc38ceSPhilippe Saint-Pierre EqualizerNode::SetParameterValue(int32 id, bigtime_t time, const void* value, 13456bc38ceSPhilippe Saint-Pierre size_t size) 13571c77851Sthreedeyes { 13656bc38ceSPhilippe Saint-Pierre if (id == P_PREAMP || id == P_BYPASS || id == P_MUTE 13756bc38ceSPhilippe Saint-Pierre || (id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount())) { 13871c77851Sthreedeyes media_timed_event ev(time, BTimedEventQueue::B_PARAMETER, (void*)value, 139bdc10448Sthreedeyes BTimedEventQueue::B_NO_CLEANUP, size, id, (char*)"EQ"); 14056bc38ceSPhilippe Saint-Pierre //dirty hack for parameter processing (mediakit bug????) 141bdc10448Sthreedeyes ParameterEventProcessing(&ev); 14271c77851Sthreedeyes EventQueue()->AddEvent(ev); 14371c77851Sthreedeyes } 14471c77851Sthreedeyes } 14571c77851Sthreedeyes 14656bc38ceSPhilippe 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 15656bc38ceSPhilippe Saint-Pierre if (fOutputMedia.destination == media_destination::null 15756bc38ceSPhilippe Saint-Pierre || !fOutputMediaEnabled) { 15871c77851Sthreedeyes buffer->Recycle(); 15971c77851Sthreedeyes return; 16071c77851Sthreedeyes } 16171c77851Sthreedeyes 16271c77851Sthreedeyes FilterBuffer(buffer); 16371c77851Sthreedeyes 16456bc38ceSPhilippe Saint-Pierre status_t err = SendBuffer(buffer, fOutputMedia.source, 16556bc38ceSPhilippe Saint-Pierre fOutputMedia.destination); 16656bc38ceSPhilippe Saint-Pierre if (err < B_OK) 16771c77851Sthreedeyes buffer->Recycle(); 16871c77851Sthreedeyes } 16956bc38ceSPhilippe Saint-Pierre 17071c77851Sthreedeyes 17171c77851Sthreedeyes status_t 17271c77851Sthreedeyes EqualizerNode::AcceptFormat(const media_destination &dst, media_format* format) 17371c77851Sthreedeyes { 17456bc38ceSPhilippe Saint-Pierre if (dst != fInputMedia.destination) 17571c77851Sthreedeyes return B_MEDIA_BAD_DESTINATION; 17671c77851Sthreedeyes 17756bc38ceSPhilippe Saint-Pierre if (format->type != B_MEDIA_RAW_AUDIO) 17856bc38ceSPhilippe Saint-Pierre return B_MEDIA_BAD_FORMAT; 17956bc38ceSPhilippe Saint-Pierre 18056bc38ceSPhilippe Saint-Pierre ValidateFormat((fFormat.u.raw_audio.format 18156bc38ceSPhilippe Saint-Pierre != media_raw_audio_format::wildcard.format) ? 18271c77851Sthreedeyes fFormat : fPreferredFormat, *format); 18371c77851Sthreedeyes 18471c77851Sthreedeyes return B_OK; 18571c77851Sthreedeyes } 18671c77851Sthreedeyes 18756bc38ceSPhilippe Saint-Pierre 18871c77851Sthreedeyes status_t 18971c77851Sthreedeyes EqualizerNode::GetNextInput(int32* cookie, media_input* input) 19071c77851Sthreedeyes { 19156bc38ceSPhilippe Saint-Pierre if (*cookie) 19271c77851Sthreedeyes return B_BAD_INDEX; 19356bc38ceSPhilippe Saint-Pierre 19471c77851Sthreedeyes ++*cookie; 19571c77851Sthreedeyes *input = fInputMedia; 19671c77851Sthreedeyes return B_OK; 19771c77851Sthreedeyes } 19871c77851Sthreedeyes 19956bc38ceSPhilippe Saint-Pierre 20071c77851Sthreedeyes void 20171c77851Sthreedeyes EqualizerNode::DisposeInputCookie(int32 cookie) 20271c77851Sthreedeyes { 20371c77851Sthreedeyes } 20471c77851Sthreedeyes 20556bc38ceSPhilippe Saint-Pierre 20671c77851Sthreedeyes status_t 20756bc38ceSPhilippe Saint-Pierre EqualizerNode::FormatChanged(const media_source &src, 20856bc38ceSPhilippe Saint-Pierre const media_destination &dst, int32 changeTag, const media_format &format) 20971c77851Sthreedeyes { 21071c77851Sthreedeyes return B_MEDIA_BAD_FORMAT; 21171c77851Sthreedeyes } 21271c77851Sthreedeyes 21356bc38ceSPhilippe Saint-Pierre 21471c77851Sthreedeyes void 21556bc38ceSPhilippe Saint-Pierre EqualizerNode::ProducerDataStatus(const media_destination &dst, int32 status, 21656bc38ceSPhilippe Saint-Pierre bigtime_t when) 21771c77851Sthreedeyes { 21856bc38ceSPhilippe Saint-Pierre if (fOutputMedia.destination != media_destination::null) 21971c77851Sthreedeyes SendDataStatus(status, fOutputMedia.destination, when); 22071c77851Sthreedeyes } 22156bc38ceSPhilippe Saint-Pierre 22271c77851Sthreedeyes 22371c77851Sthreedeyes status_t 22471c77851Sthreedeyes EqualizerNode::GetLatencyFor(const media_destination &dst, bigtime_t* latency, 22571c77851Sthreedeyes media_node_id* outTimeSource) 22671c77851Sthreedeyes { 22771c77851Sthreedeyes 22856bc38ceSPhilippe 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 23656bc38ceSPhilippe 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 { 24256bc38ceSPhilippe Saint-Pierre if (destination != fInputMedia.destination) 24371c77851Sthreedeyes return B_MEDIA_BAD_DESTINATION; 24456bc38ceSPhilippe Saint-Pierre 24556bc38ceSPhilippe 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 25656bc38ceSPhilippe Saint-Pierre 25771c77851Sthreedeyes void 25856bc38ceSPhilippe Saint-Pierre EqualizerNode::Disconnected(const media_source &src, 25956bc38ceSPhilippe Saint-Pierre const media_destination &dst) 26071c77851Sthreedeyes { 26156bc38ceSPhilippe Saint-Pierre if (fInputMedia.source != src || dst != fInputMedia.destination) 26271c77851Sthreedeyes return; 26356bc38ceSPhilippe Saint-Pierre 26471c77851Sthreedeyes fInputMedia.source = media_source::null; 26571c77851Sthreedeyes 26656bc38ceSPhilippe Saint-Pierre if (fOutputMedia.destination == media_destination::null) 26771c77851Sthreedeyes fFormat.u.raw_audio = media_raw_audio_format::wildcard; 26856bc38ceSPhilippe Saint-Pierre 26971c77851Sthreedeyes fInputMedia.format = fFormat; 27071c77851Sthreedeyes } 27171c77851Sthreedeyes 27256bc38ceSPhilippe Saint-Pierre 27371c77851Sthreedeyes //BBufferProducer 27471c77851Sthreedeyes status_t 27556bc38ceSPhilippe Saint-Pierre EqualizerNode::FormatSuggestionRequested(media_type type, int32 quality, 27656bc38ceSPhilippe Saint-Pierre media_format* format) 27771c77851Sthreedeyes { 27856bc38ceSPhilippe Saint-Pierre if (type != B_MEDIA_RAW_AUDIO) 27971c77851Sthreedeyes return B_MEDIA_BAD_FORMAT; 28071c77851Sthreedeyes 28156bc38ceSPhilippe Saint-Pierre if (fFormat.u.raw_audio.format != media_raw_audio_format::wildcard.format) 28271c77851Sthreedeyes *format = fFormat; 28356bc38ceSPhilippe Saint-Pierre else 28471c77851Sthreedeyes *format = fPreferredFormat; 28571c77851Sthreedeyes return B_OK; 28671c77851Sthreedeyes } 28771c77851Sthreedeyes 28856bc38ceSPhilippe Saint-Pierre 28971c77851Sthreedeyes status_t 29071c77851Sthreedeyes EqualizerNode::FormatProposal(const media_source &src, media_format* format) 29171c77851Sthreedeyes { 29256bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source) 29371c77851Sthreedeyes return B_MEDIA_BAD_SOURCE; 29471c77851Sthreedeyes 29556bc38ceSPhilippe Saint-Pierre if (format->type != B_MEDIA_RAW_AUDIO) 29671c77851Sthreedeyes return B_MEDIA_BAD_FORMAT; 29771c77851Sthreedeyes 29856bc38ceSPhilippe Saint-Pierre ValidateFormat((fFormat.u.raw_audio.format 29956bc38ceSPhilippe Saint-Pierre != media_raw_audio_format::wildcard.format) ? 30071c77851Sthreedeyes fFormat:fPreferredFormat, *format); 30171c77851Sthreedeyes 30271c77851Sthreedeyes return B_OK; 30371c77851Sthreedeyes } 30471c77851Sthreedeyes 30556bc38ceSPhilippe Saint-Pierre 30671c77851Sthreedeyes status_t 30756bc38ceSPhilippe Saint-Pierre EqualizerNode::FormatChangeRequested(const media_source &src, 30856bc38ceSPhilippe Saint-Pierre const media_destination &dst, media_format* format, int32* _deprecated_) 30971c77851Sthreedeyes { 31071c77851Sthreedeyes return B_MEDIA_BAD_FORMAT; 31171c77851Sthreedeyes } 31271c77851Sthreedeyes 31356bc38ceSPhilippe Saint-Pierre 31471c77851Sthreedeyes void 31556bc38ceSPhilippe Saint-Pierre EqualizerNode::LateNoticeReceived(const media_source &src, bigtime_t late, 31656bc38ceSPhilippe Saint-Pierre bigtime_t when) 31771c77851Sthreedeyes { 31856bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source || fInputMedia.source == media_source::null) 31971c77851Sthreedeyes return; 32056bc38ceSPhilippe Saint-Pierre 32171c77851Sthreedeyes NotifyLateProducer(fInputMedia.source, late, when); 32271c77851Sthreedeyes } 32371c77851Sthreedeyes 32456bc38ceSPhilippe Saint-Pierre 32571c77851Sthreedeyes status_t 32671c77851Sthreedeyes EqualizerNode::GetNextOutput(int32* cookie, media_output* output) 32771c77851Sthreedeyes { 32856bc38ceSPhilippe Saint-Pierre if (*cookie) 32971c77851Sthreedeyes return B_BAD_INDEX; 33056bc38ceSPhilippe Saint-Pierre 33171c77851Sthreedeyes ++*cookie; 33271c77851Sthreedeyes *output = fOutputMedia; 33371c77851Sthreedeyes return B_OK; 33471c77851Sthreedeyes } 33571c77851Sthreedeyes 33656bc38ceSPhilippe Saint-Pierre 33771c77851Sthreedeyes status_t 33871c77851Sthreedeyes EqualizerNode::DisposeOutputCookie(int32 cookie) 33971c77851Sthreedeyes { 34071c77851Sthreedeyes return B_OK; 34171c77851Sthreedeyes } 34271c77851Sthreedeyes 34356bc38ceSPhilippe 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 35056bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source) 35171c77851Sthreedeyes return B_MEDIA_BAD_SOURCE; 35271c77851Sthreedeyes 35356bc38ceSPhilippe Saint-Pierre if (fInputMedia.source == media_source::null) 35456bc38ceSPhilippe Saint-Pierre return B_ERROR; 35556bc38ceSPhilippe Saint-Pierre 35656bc38ceSPhilippe Saint-Pierre ret = SetOutputBuffersFor(fInputMedia.source, fInputMedia.destination, 35756bc38ceSPhilippe Saint-Pierre group, 0, &changeTag); 35871c77851Sthreedeyes return ret; 35971c77851Sthreedeyes } 36071c77851Sthreedeyes 36156bc38ceSPhilippe Saint-Pierre 36271c77851Sthreedeyes status_t 36356bc38ceSPhilippe Saint-Pierre EqualizerNode::PrepareToConnect(const media_source &src, 36456bc38ceSPhilippe Saint-Pierre const media_destination &dst, media_format* format, media_source* outSource, 36556bc38ceSPhilippe Saint-Pierre char* outName) 36671c77851Sthreedeyes { 36756bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source) 36871c77851Sthreedeyes return B_MEDIA_BAD_SOURCE; 36971c77851Sthreedeyes 37056bc38ceSPhilippe Saint-Pierre if (format->type != B_MEDIA_RAW_AUDIO) 37171c77851Sthreedeyes return B_MEDIA_BAD_FORMAT; 37271c77851Sthreedeyes 37356bc38ceSPhilippe Saint-Pierre if (fOutputMedia.destination != media_destination::null) 37471c77851Sthreedeyes return B_MEDIA_ALREADY_CONNECTED; 37571c77851Sthreedeyes 37656bc38ceSPhilippe Saint-Pierre status_t err = ValidateFormat((fFormat.u.raw_audio.format 37756bc38ceSPhilippe Saint-Pierre != media_raw_audio_format::wildcard.format) ? fFormat 37856bc38ceSPhilippe Saint-Pierre : fPreferredFormat, *format); 37971c77851Sthreedeyes 38056bc38ceSPhilippe 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 39456bc38ceSPhilippe Saint-Pierre 39571c77851Sthreedeyes void 39656bc38ceSPhilippe Saint-Pierre EqualizerNode::Connect(status_t status, const media_source &src, 397bdc10448Sthreedeyes const media_destination &dst, const media_format &format, char* name) 39871c77851Sthreedeyes { 39971c77851Sthreedeyes if (status < B_OK) { 40071c77851Sthreedeyes fOutputMedia.destination = media_destination::null; 40171c77851Sthreedeyes return; 40271c77851Sthreedeyes } 40371c77851Sthreedeyes 404bdc10448Sthreedeyes strncpy(name, fOutputMedia.name, B_MEDIA_NAME_LENGTH); 40571c77851Sthreedeyes fOutputMedia.destination = dst; 40671c77851Sthreedeyes fFormat = format; 40771c77851Sthreedeyes 40871c77851Sthreedeyes media_node_id timeSource; 409bdc10448Sthreedeyes FindLatencyFor(fOutputMedia.destination, &fDownstreamLatency, &timeSource); 41071c77851Sthreedeyes 41171c77851Sthreedeyes InitFilter(); 41271c77851Sthreedeyes 41371c77851Sthreedeyes fProcessLatency = GetFilterLatency(); 41471c77851Sthreedeyes SetEventLatency(fDownstreamLatency + fProcessLatency); 41571c77851Sthreedeyes 41671c77851Sthreedeyes if (fInputMedia.source != media_source::null) { 41771c77851Sthreedeyes SendLatencyChange(fInputMedia.source, fInputMedia.destination, 41871c77851Sthreedeyes EventLatency() + SchedulingLatency()); 41971c77851Sthreedeyes } 42071c77851Sthreedeyes 42171c77851Sthreedeyes bigtime_t duration = 0; 42271c77851Sthreedeyes 42356bc38ceSPhilippe Saint-Pierre int sample_size = (fFormat.u.raw_audio.format & 0xf) 42456bc38ceSPhilippe Saint-Pierre * fFormat.u.raw_audio.channel_count; 42571c77851Sthreedeyes 42656bc38ceSPhilippe Saint-Pierre if (fFormat.u.raw_audio.buffer_size > 0 42756bc38ceSPhilippe Saint-Pierre && fFormat.u.raw_audio.frame_rate > 0 && sample_size > 0) { 42856bc38ceSPhilippe Saint-Pierre duration = (bigtime_t)(((fFormat.u.raw_audio.buffer_size / sample_size) 42956bc38ceSPhilippe Saint-Pierre / fFormat.u.raw_audio.frame_rate) * 1000000.0); 43071c77851Sthreedeyes } 43171c77851Sthreedeyes 43271c77851Sthreedeyes SetBufferDuration(duration); 43371c77851Sthreedeyes } 43471c77851Sthreedeyes 43556bc38ceSPhilippe Saint-Pierre 43671c77851Sthreedeyes void 43771c77851Sthreedeyes EqualizerNode::Disconnect(const media_source &src, const media_destination &dst) 43871c77851Sthreedeyes { 43956bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source) 44071c77851Sthreedeyes return; 44171c77851Sthreedeyes 44256bc38ceSPhilippe Saint-Pierre if (dst != fOutputMedia.destination) 44371c77851Sthreedeyes return; 44471c77851Sthreedeyes 44571c77851Sthreedeyes fOutputMedia.destination = media_destination::null; 44671c77851Sthreedeyes 44756bc38ceSPhilippe Saint-Pierre if (fInputMedia.source == media_source::null) 44871c77851Sthreedeyes fFormat.u.raw_audio = media_raw_audio_format::wildcard; 44971c77851Sthreedeyes 45071c77851Sthreedeyes fOutputMedia.format = fFormat; 45171c77851Sthreedeyes } 45271c77851Sthreedeyes 45356bc38ceSPhilippe Saint-Pierre 45471c77851Sthreedeyes void 45556bc38ceSPhilippe Saint-Pierre EqualizerNode::EnableOutput(const media_source &src, bool enabled, 45656bc38ceSPhilippe Saint-Pierre int32* _deprecated_) 45771c77851Sthreedeyes { 45856bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source) 45971c77851Sthreedeyes return; 46071c77851Sthreedeyes fOutputMediaEnabled = enabled; 46171c77851Sthreedeyes } 46271c77851Sthreedeyes 46356bc38ceSPhilippe Saint-Pierre 46471c77851Sthreedeyes status_t 46571c77851Sthreedeyes EqualizerNode::GetLatency(bigtime_t* latency) 46671c77851Sthreedeyes { 46771c77851Sthreedeyes *latency = EventLatency() + SchedulingLatency(); 46871c77851Sthreedeyes return B_OK; 46971c77851Sthreedeyes } 47071c77851Sthreedeyes 47156bc38ceSPhilippe Saint-Pierre 47271c77851Sthreedeyes void 47356bc38ceSPhilippe Saint-Pierre EqualizerNode::LatencyChanged(const media_source &src, 47456bc38ceSPhilippe Saint-Pierre const media_destination &dst, bigtime_t latency, uint32 flags) 47571c77851Sthreedeyes { 47656bc38ceSPhilippe Saint-Pierre if (src != fOutputMedia.source || dst != fOutputMedia.destination) 47771c77851Sthreedeyes return; 47871c77851Sthreedeyes 47971c77851Sthreedeyes fDownstreamLatency = latency; 48071c77851Sthreedeyes SetEventLatency(fDownstreamLatency + fProcessLatency); 48171c77851Sthreedeyes 48271c77851Sthreedeyes if (fInputMedia.source != media_source::null) { 48371c77851Sthreedeyes SendLatencyChange(fInputMedia.source, 48471c77851Sthreedeyes fInputMedia.destination,EventLatency() + SchedulingLatency()); 48571c77851Sthreedeyes } 48671c77851Sthreedeyes } 48771c77851Sthreedeyes 48856bc38ceSPhilippe Saint-Pierre 48971c77851Sthreedeyes //BMediaEventLooper 49071c77851Sthreedeyes bigtime_t 49171c77851Sthreedeyes EqualizerNode::OfflineTime() 49271c77851Sthreedeyes { 49371c77851Sthreedeyes return 0LL; 49471c77851Sthreedeyes } 49571c77851Sthreedeyes 49656bc38ceSPhilippe Saint-Pierre 49771c77851Sthreedeyes //EqualizerNode 49871c77851Sthreedeyes void 49956bc38ceSPhilippe Saint-Pierre EqualizerNode::HandleEvent(const media_timed_event* event, bigtime_t late, 50056bc38ceSPhilippe Saint-Pierre bool realTime) 50171c77851Sthreedeyes { 50256bc38ceSPhilippe Saint-Pierre if (event->type == BTimedEventQueue::B_PARAMETER) 50371c77851Sthreedeyes ParameterEventProcessing(event); 50471c77851Sthreedeyes } 50571c77851Sthreedeyes 50671c77851Sthreedeyes 50771c77851Sthreedeyes void 50871c77851Sthreedeyes EqualizerNode::ParameterEventProcessing(const media_timed_event* event) 50971c77851Sthreedeyes { 51071c77851Sthreedeyes float value = 0.0; 51171c77851Sthreedeyes int32 value32 = 0; 51271c77851Sthreedeyes 51371c77851Sthreedeyes int32 id = event->bigdata; 51471c77851Sthreedeyes size_t size = event->data; 51571c77851Sthreedeyes bigtime_t now = TimeSource()->Now(); 51671c77851Sthreedeyes 51771c77851Sthreedeyes type_code v_type = B_FLOAT_TYPE; 51871c77851Sthreedeyes 51971c77851Sthreedeyes BParameter* web_param; 52071c77851Sthreedeyes 52171c77851Sthreedeyes for (int i = 0; i < fWeb->CountParameters(); i++) { 52271c77851Sthreedeyes web_param = fWeb->ParameterAt(i); 52371c77851Sthreedeyes if (web_param->ID() == id) { 52471c77851Sthreedeyes v_type=web_param->ValueType(); 52571c77851Sthreedeyes break; 52671c77851Sthreedeyes } 52771c77851Sthreedeyes } 52871c77851Sthreedeyes 52971c77851Sthreedeyes if (v_type == B_FLOAT_TYPE) 53071c77851Sthreedeyes value = *((float*)event->pointer); 53156bc38ceSPhilippe Saint-Pierre else if (v_type == B_INT32_TYPE) { 53271c77851Sthreedeyes value32 = *((int32*)event->pointer); 53371c77851Sthreedeyes value = (float)value32; 53471c77851Sthreedeyes } 53571c77851Sthreedeyes 53671c77851Sthreedeyes if (id == P_MUTE) { 53771c77851Sthreedeyes fMute = value32; 53871c77851Sthreedeyes fMuteLastChanged = now; 53971c77851Sthreedeyes BroadcastNewParameterValue(now, id, event->pointer, size); 54071c77851Sthreedeyes } else if (id == P_BYPASS) { 54171c77851Sthreedeyes fByPass = value32; 54271c77851Sthreedeyes fByPassLastChanged = now; 54371c77851Sthreedeyes BroadcastNewParameterValue(now, id, event->pointer, size); 54471c77851Sthreedeyes } else if (id == P_PREAMP) { 54571c77851Sthreedeyes if (value != fEqualizer.PreAmp()) { 54671c77851Sthreedeyes fEqualizer.SetPreAmp(value); 54771c77851Sthreedeyes fPreAmpLastChanged = now; 54871c77851Sthreedeyes BroadcastNewParameterValue(now, id, &value, size); 54971c77851Sthreedeyes } 55071c77851Sthreedeyes } else if (id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount()) { 55171c77851Sthreedeyes int band = id - P_BANDS; 55271c77851Sthreedeyes if (value != fEqualizer.Band(band)) { 55371c77851Sthreedeyes fEqualizer.SetBand(band, value); 55471c77851Sthreedeyes fBandsLastChanged[band] = now; 55571c77851Sthreedeyes BroadcastNewParameterValue(now, id, &value, size); 55671c77851Sthreedeyes } 55771c77851Sthreedeyes } 55871c77851Sthreedeyes } 55971c77851Sthreedeyes 56056bc38ceSPhilippe Saint-Pierre 56171c77851Sthreedeyes status_t 562bdc10448Sthreedeyes EqualizerNode::ValidateFormat(const media_format &preferred_format, 563bdc10448Sthreedeyes media_format &proposed_format) 56471c77851Sthreedeyes { 56571c77851Sthreedeyes status_t ret = B_OK; 56671c77851Sthreedeyes 567bdc10448Sthreedeyes if (proposed_format.type != B_MEDIA_RAW_AUDIO) { 568bdc10448Sthreedeyes proposed_format = preferred_format; 56971c77851Sthreedeyes return B_MEDIA_BAD_FORMAT; 57071c77851Sthreedeyes } 57171c77851Sthreedeyes 57271c77851Sthreedeyes media_raw_audio_format &wild = media_raw_audio_format::wildcard; 573bdc10448Sthreedeyes media_raw_audio_format &f = proposed_format.u.raw_audio; 574bdc10448Sthreedeyes const media_raw_audio_format &pref = preferred_format.u.raw_audio; 57571c77851Sthreedeyes 57671c77851Sthreedeyes if(pref.frame_rate != wild.frame_rate && f.frame_rate != pref.frame_rate) { 577292cd8a9Sthreedeyes if(f.frame_rate != wild.frame_rate) 57871c77851Sthreedeyes ret = B_MEDIA_BAD_FORMAT; 57971c77851Sthreedeyes f.frame_rate = pref.frame_rate; 58071c77851Sthreedeyes } 58171c77851Sthreedeyes 582bdc10448Sthreedeyes if(pref.channel_count != wild.channel_count && 583bdc10448Sthreedeyes f.channel_count != pref.channel_count) { 584292cd8a9Sthreedeyes if(f.channel_count != wild.channel_count) 58571c77851Sthreedeyes ret = B_MEDIA_BAD_FORMAT; 58671c77851Sthreedeyes f.channel_count = pref.channel_count; 58771c77851Sthreedeyes } 58871c77851Sthreedeyes 58971c77851Sthreedeyes if(pref.format != wild.format && f.format != pref.format) { 590292cd8a9Sthreedeyes if(f.format != wild.format) 59171c77851Sthreedeyes ret = B_MEDIA_BAD_FORMAT; 59271c77851Sthreedeyes f.format = pref.format; 59371c77851Sthreedeyes } 59471c77851Sthreedeyes 595bdc10448Sthreedeyes if(pref.byte_order != wild.byte_order && 596bdc10448Sthreedeyes f.byte_order != pref.byte_order) { 597292cd8a9Sthreedeyes if(f.byte_order != wild.byte_order) 59871c77851Sthreedeyes ret = B_MEDIA_BAD_FORMAT; 599bdc10448Sthreedeyes f.byte_order = pref.byte_order; 600bdc10448Sthreedeyes } 601bdc10448Sthreedeyes 602bdc10448Sthreedeyes if(pref.buffer_size != wild.buffer_size && 603bdc10448Sthreedeyes f.buffer_size != pref.buffer_size) { 604292cd8a9Sthreedeyes if(f.buffer_size != wild.buffer_size) 605bdc10448Sthreedeyes ret = B_MEDIA_BAD_FORMAT; 60671c77851Sthreedeyes f.buffer_size = pref.buffer_size; 60771c77851Sthreedeyes } 60871c77851Sthreedeyes 60971c77851Sthreedeyes return ret; 61071c77851Sthreedeyes } 61171c77851Sthreedeyes 61256bc38ceSPhilippe Saint-Pierre 61371c77851Sthreedeyes void 61471c77851Sthreedeyes EqualizerNode::SetOutputFormat(media_format &format) 61571c77851Sthreedeyes { 61671c77851Sthreedeyes media_raw_audio_format &f = format.u.raw_audio; 61771c77851Sthreedeyes media_raw_audio_format &w = media_raw_audio_format::wildcard; 61871c77851Sthreedeyes 619bdc10448Sthreedeyes if (f.frame_rate == w.frame_rate) { 62071c77851Sthreedeyes f.frame_rate = 44100.0; 621bdc10448Sthreedeyes } 62271c77851Sthreedeyes if (f.channel_count == w.channel_count) { 623292cd8a9Sthreedeyes if(fInputMedia.source != media_source::null) 62471c77851Sthreedeyes f.channel_count = fInputMedia.format.u.raw_audio.channel_count; 625292cd8a9Sthreedeyes else 62671c77851Sthreedeyes f.channel_count = 2; 62771c77851Sthreedeyes } 628292cd8a9Sthreedeyes 629292cd8a9Sthreedeyes if (f.format == w.format) 63071c77851Sthreedeyes f.format = media_raw_audio_format::B_AUDIO_FLOAT; 631292cd8a9Sthreedeyes 632bdc10448Sthreedeyes if (f.byte_order == w.format) { 633bdc10448Sthreedeyes f.byte_order = (B_HOST_IS_BENDIAN) ? 634bdc10448Sthreedeyes B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN; 635bdc10448Sthreedeyes } 636292cd8a9Sthreedeyes 637292cd8a9Sthreedeyes if (f.buffer_size == w.buffer_size) 63871c77851Sthreedeyes f.buffer_size = BUFF_SIZE; 63971c77851Sthreedeyes } 64056bc38ceSPhilippe 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 65156bc38ceSPhilippe Saint-Pierre for (int i = 0; i < EQ_BANDS; i++) 65271c77851Sthreedeyes fBandsLastChanged[i] = 0LL; 65371c77851Sthreedeyes 65471c77851Sthreedeyes fEqualizer.CleanUp(); 65571c77851Sthreedeyes } 65671c77851Sthreedeyes 65756bc38ceSPhilippe 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 66656bc38ceSPhilippe Saint-Pierre fFControlGroup->MakeDiscreteParameter(P_MUTE,B_MEDIA_NO_TYPE,"Mute", 66756bc38ceSPhilippe Saint-Pierre B_ENABLE); 66856bc38ceSPhilippe Saint-Pierre fFControlGroup->MakeDiscreteParameter(P_BYPASS,B_MEDIA_NO_TYPE,"ByPass", 66956bc38ceSPhilippe Saint-Pierre B_ENABLE); 67071c77851Sthreedeyes 67171c77851Sthreedeyes BNullParameter* label; 67271c77851Sthreedeyes BParameterGroup* group; 67371c77851Sthreedeyes BContinuousParameter* value; 67471c77851Sthreedeyes 67571c77851Sthreedeyes group = fParamGroup->MakeGroup("Pre Amp"); 67656bc38ceSPhilippe Saint-Pierre label = group->MakeNullParameter(P_PREAMP_LABEL, B_MEDIA_NO_TYPE, "Pre Amp", 67756bc38ceSPhilippe Saint-Pierre B_GENERIC); 67856bc38ceSPhilippe Saint-Pierre value = group->MakeContinuousParameter(P_PREAMP, B_MEDIA_NO_TYPE, "", 67956bc38ceSPhilippe 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 69856bc38ceSPhilippe Saint-Pierre 69971c77851Sthreedeyes void 70071c77851Sthreedeyes EqualizerNode::InitFilter(void) 70171c77851Sthreedeyes { 70256bc38ceSPhilippe Saint-Pierre fEqualizer.SetFormat(fFormat.u.raw_audio.channel_count, 70356bc38ceSPhilippe Saint-Pierre fFormat.u.raw_audio.frame_rate); 70471c77851Sthreedeyes } 70571c77851Sthreedeyes 70656bc38ceSPhilippe Saint-Pierre 70771c77851Sthreedeyes bigtime_t 70871c77851Sthreedeyes EqualizerNode::GetFilterLatency(void) 70971c77851Sthreedeyes { 71056bc38ceSPhilippe Saint-Pierre if (fOutputMedia.destination == media_destination::null) 71171c77851Sthreedeyes return 0LL; 71271c77851Sthreedeyes 71356bc38ceSPhilippe Saint-Pierre BBufferGroup* test_group = 71456bc38ceSPhilippe Saint-Pierre new BBufferGroup(fOutputMedia.format.u.raw_audio.buffer_size, 1); 71571c77851Sthreedeyes 71656bc38ceSPhilippe Saint-Pierre BBuffer* buffer = 71756bc38ceSPhilippe 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 73356bc38ceSPhilippe Saint-Pierre 73471c77851Sthreedeyes void 73571c77851Sthreedeyes EqualizerNode::FilterBuffer(BBuffer* buffer) 73671c77851Sthreedeyes { 73756bc38ceSPhilippe Saint-Pierre uint32 m_frameSize = (fFormat.u.raw_audio.format & 0x0f) 73856bc38ceSPhilippe 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; 74156bc38ceSPhilippe Saint-Pierre if (fMute != 0) 74271c77851Sthreedeyes memset(buffer->Data(), 0, buffer->Header()->size_used); 74356bc38ceSPhilippe Saint-Pierre else if (fByPass == 0) 74471c77851Sthreedeyes fEqualizer.ProcessBuffer((float*)buffer->Data(), samples * channels); 74571c77851Sthreedeyes } 746