Added Equalizer media add-on.
This commit is contained in:
@@ -17,4 +17,5 @@ SubInclude HAIKU_TOP src add-ons media media-add-ons usb_webcam ;
|
|||||||
SubInclude HAIKU_TOP src add-ons media media-add-ons video_producer_demo ;
|
SubInclude HAIKU_TOP src add-ons media media-add-ons video_producer_demo ;
|
||||||
SubInclude HAIKU_TOP src add-ons media media-add-ons videowindow ;
|
SubInclude HAIKU_TOP src add-ons media media-add-ons videowindow ;
|
||||||
SubInclude HAIKU_TOP src add-ons media media-add-ons video_mixer ;
|
SubInclude HAIKU_TOP src add-ons media media-add-ons video_mixer ;
|
||||||
|
SubInclude HAIKU_TOP src add-ons media media-add-ons equalizer ;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Gerasim Troeglazov (3dEyes**), [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Equalizer.h"
|
||||||
|
|
||||||
|
Equalizer::Equalizer()
|
||||||
|
{
|
||||||
|
fActivated = false;
|
||||||
|
CleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
Equalizer::~Equalizer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Equalizer::SetFormat(int channels, float framerate)
|
||||||
|
{
|
||||||
|
fChannels = channels;
|
||||||
|
fRate = framerate;
|
||||||
|
|
||||||
|
memset(fWDataVector[0][0], 0, sizeof(fWDataVector));
|
||||||
|
|
||||||
|
fActiveBands = BandCount();
|
||||||
|
while(fFrequency[fActiveBands-1] * 2.0 > fRate) {
|
||||||
|
fActiveBands--;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < fActiveBands; i++) {
|
||||||
|
BandPassFilterCalcs(fAWeights[i], fBWeights[i],
|
||||||
|
fFrequency[i] / (float)fRate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Equalizer::SetPreAmp(double value)
|
||||||
|
{
|
||||||
|
fPreAmp = value;
|
||||||
|
RecalcGains();
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
Equalizer::PreAmp(void)
|
||||||
|
{
|
||||||
|
return fPreAmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Equalizer::SetBand(int band, double value)
|
||||||
|
{
|
||||||
|
if(band < 0 || band >= BandCount()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fBands[band] = value;
|
||||||
|
RecalcGains();
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
Equalizer::Band(int band)
|
||||||
|
{
|
||||||
|
if(band < 0 || band >= BandCount()) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
return fBands[band];
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Equalizer::BandCount(void)
|
||||||
|
{
|
||||||
|
return EQ_BANDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
Equalizer::BandFrequency(int band)
|
||||||
|
{
|
||||||
|
if(band < 0 || band >= BandCount()) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
return fFrequency[band];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Equalizer::ProcessBuffer(float *buffer, int samples)
|
||||||
|
{
|
||||||
|
if(!fActivated || samples <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < fChannels; i++) {
|
||||||
|
float *g = fGainVector[i];
|
||||||
|
float *end = buffer + samples;
|
||||||
|
for(float *fptr = buffer + i; fptr < end; fptr += fChannels) {
|
||||||
|
float yt = *fptr;
|
||||||
|
for (int k = 0; k < fActiveBands; k ++) {
|
||||||
|
float *Wq = fWDataVector[i][k];
|
||||||
|
float w = yt * fBWeights[k][0] +
|
||||||
|
Wq[0] * fAWeights[k][0] +
|
||||||
|
Wq[1] * fAWeights[k][1];
|
||||||
|
yt += (w + Wq[1] * fBWeights[k][1]) * g[k];
|
||||||
|
Wq[1] = Wq[0];
|
||||||
|
Wq[0] = w;
|
||||||
|
}
|
||||||
|
*fptr = yt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Equalizer::CleanUp()
|
||||||
|
{
|
||||||
|
float freq[EQ_BANDS] = {31.25, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000};
|
||||||
|
|
||||||
|
for(int i = 0; i < BandCount(); i++) {
|
||||||
|
fFrequency[i] = freq[i];
|
||||||
|
fBands[i] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fPreAmp = 0.0;
|
||||||
|
RecalcGains();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Equalizer::RecalcGains(void)
|
||||||
|
{
|
||||||
|
float adjust[EQ_BANDS];
|
||||||
|
for(int i = 0; i < BandCount(); i++) {
|
||||||
|
adjust[i] = fPreAmp + fBands[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int c = 0; c < MAX_CHANNELS; c++) {
|
||||||
|
for(int i = 0; i<BandCount(); i++) {
|
||||||
|
fGainVector[c][i] = pow(10, adjust[i] / 20) - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fActivated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Equalizer::BandPassFilterCalcs(float *a, float *b, float f)
|
||||||
|
{
|
||||||
|
float q = 1.2247449;
|
||||||
|
float theta = 2.0 * M_PI * f;
|
||||||
|
float c_value = (1 - tanf(theta * q / 2.0)) / (1 + tanf(theta * q / 2.0));
|
||||||
|
|
||||||
|
a[0] = (1 + c_value) * cosf(theta);
|
||||||
|
a[1] = -c_value;
|
||||||
|
b[0] = (1 - c_value) / 2.0;
|
||||||
|
b[1] = -1.005;
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Gerasim Troeglazov (3dEyes**), [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __EQUALIZER_H__
|
||||||
|
#define __EQUALIZER_H__
|
||||||
|
|
||||||
|
#define MAX_CHANNELS 8
|
||||||
|
#define EQ_BANDS 10
|
||||||
|
|
||||||
|
class Equalizer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Equalizer();
|
||||||
|
~Equalizer();
|
||||||
|
void SetFormat(int channels, float framerate);
|
||||||
|
void SetPreAmp(double);
|
||||||
|
double PreAmp(void);
|
||||||
|
void SetBand(int band, double value);
|
||||||
|
double Band(int band);
|
||||||
|
int BandCount(void);
|
||||||
|
float BandFrequency(int band);
|
||||||
|
void ProcessBuffer(float *buffer, int samples);
|
||||||
|
void CleanUp();
|
||||||
|
private:
|
||||||
|
void RecalcGains(void);
|
||||||
|
void BandPassFilterCalcs(float *a, float *b, float f);
|
||||||
|
|
||||||
|
bool fActivated;
|
||||||
|
int fChannels;
|
||||||
|
float fRate;
|
||||||
|
int fActiveBands;
|
||||||
|
|
||||||
|
float fAWeights[EQ_BANDS][2];
|
||||||
|
float fBWeights[EQ_BANDS][2];
|
||||||
|
float fWDataVector[MAX_CHANNELS][EQ_BANDS][2];
|
||||||
|
float fGainVector[MAX_CHANNELS][EQ_BANDS];
|
||||||
|
float fFrequency[EQ_BANDS];
|
||||||
|
|
||||||
|
double fBands[EQ_BANDS];
|
||||||
|
double fPreAmp;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__EQUALIZER_H__
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Equalizer.rdef
|
||||||
|
*/
|
||||||
|
|
||||||
|
resource app_signature "application/x-vnd.equalizer.media_addon";
|
||||||
|
|
||||||
|
resource app_version {
|
||||||
|
major = 0,
|
||||||
|
middle = 0,
|
||||||
|
minor = 2,
|
||||||
|
variety = 0,
|
||||||
|
internal = 0,
|
||||||
|
short_info = "0.0.2",
|
||||||
|
long_info = "Haiku 10 Band Equalizer media add-on."
|
||||||
|
};
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Gerasim Troeglazov (3dEyes**), [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Entry.h>
|
||||||
|
|
||||||
|
#include "EqualizerNode.h"
|
||||||
|
#include "EqualizerAddOn.h"
|
||||||
|
|
||||||
|
extern "C" _EXPORT BMediaAddOn* make_media_addon(image_id image)
|
||||||
|
{
|
||||||
|
return new EqualizerAddOn(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
EqualizerAddOn::~EqualizerAddOn()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EqualizerAddOn::EqualizerAddOn(image_id image) : BMediaAddOn(image)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerAddOn::InitCheck(const char **text)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
EqualizerAddOn::CountFlavors()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EqualizerAddOn::GetFlavorAt(int32 idx, const flavor_info **info)
|
||||||
|
{
|
||||||
|
if(idx < 0 || idx >= CountFlavors())
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
flavor_info *f_info = new flavor_info;
|
||||||
|
f_info->internal_id = idx;
|
||||||
|
f_info->kinds = B_BUFFER_CONSUMER | B_BUFFER_PRODUCER | B_CONTROLLABLE;
|
||||||
|
f_info->possible_count = 0;
|
||||||
|
f_info->flavor_flags = 0;
|
||||||
|
f_info->info = (char *)"10 Band Equalizer.\nby 3dEyes**";
|
||||||
|
f_info->name = (char *)"Equalizer (10 Band)";
|
||||||
|
|
||||||
|
media_format *format = new media_format;
|
||||||
|
format->type = B_MEDIA_RAW_AUDIO;
|
||||||
|
format->u.raw_audio = media_raw_audio_format::wildcard;
|
||||||
|
format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||||
|
|
||||||
|
f_info->in_format_count = 1;
|
||||||
|
f_info->in_formats = format;
|
||||||
|
|
||||||
|
format = new media_format;
|
||||||
|
format->type = B_MEDIA_RAW_AUDIO;
|
||||||
|
format->u.raw_audio = media_raw_audio_format::wildcard;
|
||||||
|
format->u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||||
|
|
||||||
|
f_info->out_format_count = 1;
|
||||||
|
f_info->out_formats = format;
|
||||||
|
|
||||||
|
*info = f_info;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
BMediaNode*
|
||||||
|
EqualizerAddOn::InstantiateNodeFor(const flavor_info *info, BMessage *config,
|
||||||
|
status_t *err)
|
||||||
|
{
|
||||||
|
EqualizerNode *node = new EqualizerNode(this);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerAddOn::GetConfigurationFor(BMediaNode *node, BMessage *message)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
EqualizerAddOn::WantsAutoStart()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerAddOn::AutoStart(int count, BMediaNode **node, int32 *id, bool *more)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Gerasim Troeglazov (3dEyes**), [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __EQUALIZER_ADDON_H__
|
||||||
|
#define __EQUALIZER_ADDON_H__
|
||||||
|
|
||||||
|
#include <MediaAddOn.h>
|
||||||
|
|
||||||
|
class EqualizerAddOn : public BMediaAddOn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~EqualizerAddOn();
|
||||||
|
explicit EqualizerAddOn(image_id image);
|
||||||
|
virtual status_t InitCheck(const char **text);
|
||||||
|
virtual int32 CountFlavors();
|
||||||
|
virtual status_t GetFlavorAt(int32 idx, const flavor_info **info);
|
||||||
|
virtual BMediaNode* InstantiateNodeFor(const flavor_info *info, BMessage *config,
|
||||||
|
status_t *err);
|
||||||
|
virtual status_t GetConfigurationFor(BMediaNode *node, BMessage *message);
|
||||||
|
virtual bool WantsAutoStart();
|
||||||
|
virtual status_t AutoStart(int count, BMediaNode **node, int32 *id, bool *more);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__EQUALIZER_ADDON_H__
|
||||||
@@ -0,0 +1,721 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Gerasim Troeglazov (3dEyes**), [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ByteOrder.h>
|
||||||
|
#include <Buffer.h>
|
||||||
|
#include <BufferGroup.h>
|
||||||
|
#include <TimeSource.h>
|
||||||
|
#include <ParameterWeb.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "EqualizerNode.h"
|
||||||
|
|
||||||
|
//EqualizerNode
|
||||||
|
EqualizerNode::~EqualizerNode() {
|
||||||
|
Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
EqualizerNode::EqualizerNode(BMediaAddOn* addon) :
|
||||||
|
BMediaNode("10 Band Equalizer"),
|
||||||
|
BBufferConsumer(B_MEDIA_RAW_AUDIO),
|
||||||
|
BBufferProducer(B_MEDIA_RAW_AUDIO),
|
||||||
|
BControllable(),
|
||||||
|
BMediaEventLooper(),
|
||||||
|
fAddOn(addon),
|
||||||
|
fProcessLatency(0),
|
||||||
|
fDownstreamLatency(0),
|
||||||
|
fOutputMediaEnabled(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//BMediaNode
|
||||||
|
BMediaAddOn*
|
||||||
|
EqualizerNode::AddOn(int32 *id) const
|
||||||
|
{
|
||||||
|
if(fAddOn)
|
||||||
|
*id = 0;
|
||||||
|
return fAddOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::HandleMessage(int32 message, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
if((BControllable::HandleMessage(message, data, size)!=B_OK) &&
|
||||||
|
(BBufferConsumer::HandleMessage(message, data, size) != B_OK) &&
|
||||||
|
(BBufferProducer::HandleMessage(message, data, size) != B_OK) &&
|
||||||
|
(BControllable::HandleMessage(message, data, size) != B_OK) ) {
|
||||||
|
BMediaNode::HandleMessage(message, data, size);
|
||||||
|
return B_OK;
|
||||||
|
} else {
|
||||||
|
BMediaNode::HandleBadMessage(message, data, size);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::NodeRegistered()
|
||||||
|
{
|
||||||
|
SetPriority(B_REAL_TIME_PRIORITY);
|
||||||
|
Run();
|
||||||
|
|
||||||
|
fPreferredFormat.type = B_MEDIA_RAW_AUDIO;
|
||||||
|
fPreferredFormat.u.raw_audio.buffer_size = BUFF_SIZE;
|
||||||
|
fPreferredFormat.u.raw_audio = media_raw_audio_format::wildcard;
|
||||||
|
fPreferredFormat.u.raw_audio.channel_count = media_raw_audio_format::wildcard.channel_count;
|
||||||
|
fPreferredFormat.u.raw_audio.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||||
|
|
||||||
|
fFormat.type = B_MEDIA_RAW_AUDIO;
|
||||||
|
fFormat.u.raw_audio = media_raw_audio_format::wildcard;
|
||||||
|
|
||||||
|
fInputMedia.destination.port = ControlPort();
|
||||||
|
fInputMedia.destination.id = ID_AUDIO_INPUT;
|
||||||
|
fInputMedia.node = Node();
|
||||||
|
fInputMedia.source = media_source::null;
|
||||||
|
fInputMedia.format = fFormat;
|
||||||
|
strncpy(fInputMedia.name, "Audio Input", B_MEDIA_NAME_LENGTH);
|
||||||
|
|
||||||
|
fOutputMedia.source.port = ControlPort();
|
||||||
|
fOutputMedia.source.id = ID_AUDIO_OUTPUT;
|
||||||
|
fOutputMedia.node = Node();
|
||||||
|
fOutputMedia.destination = media_destination::null;
|
||||||
|
fOutputMedia.format = fFormat;
|
||||||
|
strncpy(fOutputMedia.name, "Audio Output", B_MEDIA_NAME_LENGTH);
|
||||||
|
|
||||||
|
InitParameterValues();
|
||||||
|
InitParameterWeb();
|
||||||
|
}
|
||||||
|
|
||||||
|
//BControllable
|
||||||
|
status_t
|
||||||
|
EqualizerNode::GetParameterValue(int32 id, bigtime_t *lastChangeTime, void *value, size_t *size)
|
||||||
|
{
|
||||||
|
if(*size < sizeof(float)) {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(id == P_MUTE) {
|
||||||
|
*(int32*)value = fMute;
|
||||||
|
*lastChangeTime = fMuteLastChanged;
|
||||||
|
*size = sizeof(int32);
|
||||||
|
return B_OK;
|
||||||
|
} else if(id == P_BYPASS) {
|
||||||
|
*(int32*)value = fByPass;
|
||||||
|
*lastChangeTime = fByPassLastChanged;
|
||||||
|
*size = sizeof(int32);
|
||||||
|
return B_OK;
|
||||||
|
} else if(id == P_PREAMP) {
|
||||||
|
*(float*)value = (float)fEqualizer.PreAmp();
|
||||||
|
*lastChangeTime = fPreAmpLastChanged;
|
||||||
|
*size = sizeof(float);
|
||||||
|
return B_OK;
|
||||||
|
} else if(id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount()) {
|
||||||
|
int band = id - P_BANDS;
|
||||||
|
*(float*)value = (float)fEqualizer.Band(band);
|
||||||
|
*lastChangeTime = fBandsLastChanged[band];
|
||||||
|
*size = sizeof(float);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::SetParameterValue(int32 id, bigtime_t time, const void *value, size_t size)
|
||||||
|
{
|
||||||
|
if(id == P_PREAMP || id == P_BYPASS || id == P_MUTE ||
|
||||||
|
(id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount())) {
|
||||||
|
media_timed_event ev(time, BTimedEventQueue::B_PARAMETER, (void*)value,
|
||||||
|
BTimedEventQueue::B_NO_CLEANUP, size, id, "EQ");
|
||||||
|
ParameterEventProcessing(&ev); //dirty hack for parameter processing (mediakit bug????)
|
||||||
|
EventQueue()->AddEvent(ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//BBufferConsumer
|
||||||
|
void
|
||||||
|
EqualizerNode::BufferReceived(BBuffer *buffer)
|
||||||
|
{
|
||||||
|
if(buffer->Header()->destination != fInputMedia.destination.id) {
|
||||||
|
buffer->Recycle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fOutputMedia.destination == media_destination::null || !fOutputMediaEnabled) {
|
||||||
|
buffer->Recycle();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterBuffer(buffer);
|
||||||
|
|
||||||
|
status_t err = SendBuffer(buffer, fOutputMedia.source, fOutputMedia.destination);
|
||||||
|
if (err < B_OK) {
|
||||||
|
buffer->Recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::AcceptFormat(const media_destination &dst, media_format *format)
|
||||||
|
{
|
||||||
|
if(dst != fInputMedia.destination) {
|
||||||
|
return B_MEDIA_BAD_DESTINATION;
|
||||||
|
}
|
||||||
|
if(format->type != B_MEDIA_RAW_AUDIO) {
|
||||||
|
return B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValidateFormat((fFormat.u.raw_audio.format != media_raw_audio_format::wildcard.format) ?
|
||||||
|
fFormat : fPreferredFormat, *format);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::GetNextInput(int32* cookie, media_input* input)
|
||||||
|
{
|
||||||
|
if(*cookie) {
|
||||||
|
return B_BAD_INDEX;
|
||||||
|
}
|
||||||
|
++*cookie;
|
||||||
|
*input = fInputMedia;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::DisposeInputCookie(int32 cookie)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::FormatChanged(const media_source &src, const media_destination &dst,
|
||||||
|
int32 changeTag, const media_format &format)
|
||||||
|
{
|
||||||
|
return B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::ProducerDataStatus(const media_destination &dst, int32 status, bigtime_t when)
|
||||||
|
{
|
||||||
|
if(fOutputMedia.destination != media_destination::null) {
|
||||||
|
SendDataStatus(status, fOutputMedia.destination, when);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::GetLatencyFor( const media_destination &dst, bigtime_t *latency,
|
||||||
|
media_node_id* outTimeSource)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(dst != fInputMedia.destination) {
|
||||||
|
return B_MEDIA_BAD_DESTINATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
*latency = fDownstreamLatency + fProcessLatency;
|
||||||
|
*outTimeSource = TimeSource()->ID();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::Connected(const media_source& source,
|
||||||
|
const media_destination& destination, const media_format& format,
|
||||||
|
media_input* poInput)
|
||||||
|
{
|
||||||
|
if(destination != fInputMedia.destination) {
|
||||||
|
return B_MEDIA_BAD_DESTINATION;
|
||||||
|
}
|
||||||
|
if(fInputMedia.source != media_source::null) {
|
||||||
|
return B_MEDIA_ALREADY_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
fInputMedia.source = source;
|
||||||
|
fInputMedia.format = format;
|
||||||
|
*poInput = fInputMedia;
|
||||||
|
fFormat = format;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::Disconnected(const media_source &src, const media_destination &dst)
|
||||||
|
{
|
||||||
|
if(fInputMedia.source != src || dst != fInputMedia.destination) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fInputMedia.source = media_source::null;
|
||||||
|
|
||||||
|
if(fOutputMedia.destination == media_destination::null) {
|
||||||
|
fFormat.u.raw_audio = media_raw_audio_format::wildcard;
|
||||||
|
}
|
||||||
|
fInputMedia.format = fFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
//BBufferProducer
|
||||||
|
status_t
|
||||||
|
EqualizerNode::FormatSuggestionRequested(media_type type, int32 quality, media_format *format)
|
||||||
|
{
|
||||||
|
if(type != B_MEDIA_RAW_AUDIO) {
|
||||||
|
return B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fFormat.u.raw_audio.format != media_raw_audio_format::wildcard.format) {
|
||||||
|
*format = fFormat;
|
||||||
|
} else {
|
||||||
|
*format = fPreferredFormat;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::FormatProposal(const media_source &src, media_format* format)
|
||||||
|
{
|
||||||
|
if(src != fOutputMedia.source) {
|
||||||
|
return B_MEDIA_BAD_SOURCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(format->type != B_MEDIA_RAW_AUDIO) {
|
||||||
|
return B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValidateFormat((fFormat.u.raw_audio.format != media_raw_audio_format::wildcard.format) ?
|
||||||
|
fFormat:fPreferredFormat,*format);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::FormatChangeRequested(const media_source &src, const media_destination &dst,
|
||||||
|
media_format* format, int32* _deprecated_)
|
||||||
|
{
|
||||||
|
return B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::LateNoticeReceived(const media_source &src, bigtime_t late, bigtime_t when)
|
||||||
|
{
|
||||||
|
if(src != fOutputMedia.source || fInputMedia.source == media_source::null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NotifyLateProducer(fInputMedia.source, late, when);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::GetNextOutput(int32 *cookie, media_output* output)
|
||||||
|
{
|
||||||
|
if(*cookie) {
|
||||||
|
return B_BAD_INDEX;
|
||||||
|
}
|
||||||
|
++*cookie;
|
||||||
|
*output = fOutputMedia;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::DisposeOutputCookie(int32 cookie)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::SetBufferGroup(const media_source &src, BBufferGroup *group)
|
||||||
|
{
|
||||||
|
int32 changeTag;
|
||||||
|
status_t ret = B_OK;
|
||||||
|
|
||||||
|
if(src != fOutputMedia.source) {
|
||||||
|
return B_MEDIA_BAD_SOURCE;
|
||||||
|
}
|
||||||
|
if(fInputMedia.source == media_source::null) {
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = SetOutputBuffersFor(fInputMedia.source, fInputMedia.destination, group, 0, &changeTag);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::PrepareToConnect( const media_source &src, const media_destination &dst,
|
||||||
|
media_format* format, media_source* outSource, char* outName)
|
||||||
|
{
|
||||||
|
if(src != fOutputMedia.source) {
|
||||||
|
return B_MEDIA_BAD_SOURCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(format->type != B_MEDIA_RAW_AUDIO) {
|
||||||
|
return B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fOutputMedia.destination != media_destination::null) {
|
||||||
|
return B_MEDIA_ALREADY_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t err = ValidateFormat((fFormat.u.raw_audio.format != media_raw_audio_format::wildcard.format) ?
|
||||||
|
fFormat : fPreferredFormat, *format);
|
||||||
|
|
||||||
|
if(err < B_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetOutputFormat(*format);
|
||||||
|
|
||||||
|
fOutputMedia.destination = dst;
|
||||||
|
fOutputMedia.format = *format;
|
||||||
|
|
||||||
|
*outSource = fOutputMedia.source;
|
||||||
|
strncpy(outName, fOutputMedia.name, B_MEDIA_NAME_LENGTH);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::Connect(status_t status, const media_source &src, const media_destination &dst,
|
||||||
|
const media_format &format, char *outName)
|
||||||
|
{
|
||||||
|
status_t err;
|
||||||
|
if(status < B_OK) {
|
||||||
|
fOutputMedia.destination = media_destination::null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(outName, fOutputMedia.name, B_MEDIA_NAME_LENGTH);
|
||||||
|
fOutputMedia.destination = dst;
|
||||||
|
fFormat = format;
|
||||||
|
|
||||||
|
media_node_id timeSource;
|
||||||
|
err = FindLatencyFor(fOutputMedia.destination, &fDownstreamLatency, &timeSource);
|
||||||
|
|
||||||
|
InitFilter();
|
||||||
|
|
||||||
|
fProcessLatency = GetFilterLatency();
|
||||||
|
SetEventLatency(fDownstreamLatency + fProcessLatency);
|
||||||
|
|
||||||
|
if(fInputMedia.source != media_source::null) {
|
||||||
|
SendLatencyChange(fInputMedia.source, fInputMedia.destination,
|
||||||
|
EventLatency() + SchedulingLatency());
|
||||||
|
}
|
||||||
|
|
||||||
|
bigtime_t duration = 0;
|
||||||
|
|
||||||
|
int sample_size = (fFormat.u.raw_audio.format & 0xf) *
|
||||||
|
fFormat.u.raw_audio.channel_count;
|
||||||
|
|
||||||
|
if (fFormat.u.raw_audio.buffer_size > 0 &&
|
||||||
|
fFormat.u.raw_audio.frame_rate > 0 &&
|
||||||
|
sample_size > 0) {
|
||||||
|
duration = (bigtime_t)(((fFormat.u.raw_audio.buffer_size / sample_size) /
|
||||||
|
fFormat.u.raw_audio.frame_rate) * 1000000.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetBufferDuration(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::Disconnect(const media_source &src, const media_destination &dst)
|
||||||
|
{
|
||||||
|
if(src != fOutputMedia.source) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dst != fOutputMedia.destination) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fOutputMedia.destination = media_destination::null;
|
||||||
|
|
||||||
|
if(fInputMedia.source == media_source::null) {
|
||||||
|
fFormat.u.raw_audio = media_raw_audio_format::wildcard;
|
||||||
|
}
|
||||||
|
|
||||||
|
fOutputMedia.format = fFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::EnableOutput(const media_source &src, bool enabled, int32* _deprecated_)
|
||||||
|
{
|
||||||
|
if(src != fOutputMedia.source) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fOutputMediaEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::GetLatency(bigtime_t *latency)
|
||||||
|
{
|
||||||
|
*latency = EventLatency() + SchedulingLatency();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::LatencyChanged(const media_source &src, const media_destination &dst,
|
||||||
|
bigtime_t latency, uint32 flags)
|
||||||
|
{
|
||||||
|
if(src != fOutputMedia.source || dst != fOutputMedia.destination) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fDownstreamLatency = latency;
|
||||||
|
SetEventLatency(fDownstreamLatency + fProcessLatency);
|
||||||
|
|
||||||
|
if(fInputMedia.source != media_source::null) {
|
||||||
|
SendLatencyChange(fInputMedia.source,
|
||||||
|
fInputMedia.destination,EventLatency() + SchedulingLatency());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//BMediaEventLooper
|
||||||
|
bigtime_t
|
||||||
|
EqualizerNode::OfflineTime()
|
||||||
|
{
|
||||||
|
return 0LL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//EqualizerNode
|
||||||
|
void
|
||||||
|
EqualizerNode::HandleEvent(const media_timed_event *event, bigtime_t late, bool realTime)
|
||||||
|
{
|
||||||
|
if(event->type == BTimedEventQueue::B_PARAMETER) {
|
||||||
|
ParameterEventProcessing(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::ParameterEventProcessing(const media_timed_event* event)
|
||||||
|
{
|
||||||
|
float value = 0.0;
|
||||||
|
int32 value32 = 0;
|
||||||
|
|
||||||
|
int32 id = event->bigdata;
|
||||||
|
size_t size = event->data;
|
||||||
|
bigtime_t now = TimeSource()->Now();
|
||||||
|
|
||||||
|
type_code v_type = B_FLOAT_TYPE;
|
||||||
|
|
||||||
|
BParameter *web_param;
|
||||||
|
|
||||||
|
for(int i=0; i<fWeb->CountParameters(); i++) {
|
||||||
|
web_param = fWeb->ParameterAt(i);
|
||||||
|
if(web_param->ID() == id) {
|
||||||
|
v_type=web_param->ValueType();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(v_type == B_FLOAT_TYPE)
|
||||||
|
value = *((float*)event->pointer);
|
||||||
|
if(v_type == B_INT32_TYPE) {
|
||||||
|
value32 = *((int32*)event->pointer);
|
||||||
|
value = (float)value32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(id == P_MUTE) {
|
||||||
|
fMute = value32;
|
||||||
|
fMuteLastChanged = now;
|
||||||
|
BroadcastNewParameterValue(now, id, event->pointer, size);
|
||||||
|
} else if(id == P_BYPASS) {
|
||||||
|
fByPass = value32;
|
||||||
|
fByPassLastChanged = now;
|
||||||
|
BroadcastNewParameterValue(now, id, event->pointer, size);
|
||||||
|
} else if(id == P_PREAMP) {
|
||||||
|
if(value != fEqualizer.PreAmp()) {
|
||||||
|
fEqualizer.SetPreAmp(value);
|
||||||
|
fPreAmpLastChanged = now;
|
||||||
|
BroadcastNewParameterValue(now, id, &value, size);
|
||||||
|
}
|
||||||
|
} else if(id >= P_BANDS && id < P_BANDS + fEqualizer.BandCount()) {
|
||||||
|
int band = id - P_BANDS;
|
||||||
|
if(value != fEqualizer.Band(band)) {
|
||||||
|
fEqualizer.SetBand(band, value);
|
||||||
|
fBandsLastChanged[band] = now;
|
||||||
|
BroadcastNewParameterValue(now, id, &value, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
EqualizerNode::ValidateFormat(const media_format &preferredFormat,
|
||||||
|
media_format &format)
|
||||||
|
{
|
||||||
|
status_t ret = B_OK;
|
||||||
|
|
||||||
|
if(format.type != B_MEDIA_RAW_AUDIO) {
|
||||||
|
format = preferredFormat;
|
||||||
|
return B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
media_raw_audio_format &wild = media_raw_audio_format::wildcard;
|
||||||
|
media_raw_audio_format &f = format.u.raw_audio;
|
||||||
|
const media_raw_audio_format &pref = format.u.raw_audio;
|
||||||
|
|
||||||
|
if(pref.frame_rate != wild.frame_rate && f.frame_rate != pref.frame_rate) {
|
||||||
|
if(f.frame_rate != wild.frame_rate) {
|
||||||
|
ret = B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
f.frame_rate = pref.frame_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pref.channel_count != wild.channel_count && f.channel_count != pref.channel_count) {
|
||||||
|
if(f.channel_count != wild.channel_count) {
|
||||||
|
ret = B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
f.channel_count = pref.channel_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pref.byte_order != wild.byte_order && f.byte_order != pref.byte_order) {
|
||||||
|
if(f.byte_order != wild.byte_order) {
|
||||||
|
ret = B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
f.byte_order = pref.byte_order;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pref.format != wild.format && f.format != pref.format) {
|
||||||
|
if(f.format != wild.format) {
|
||||||
|
ret = B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
f.format = pref.format;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pref.buffer_size != wild.buffer_size && f.buffer_size != pref.buffer_size) {
|
||||||
|
if(f.buffer_size != wild.buffer_size) {
|
||||||
|
ret = B_MEDIA_BAD_FORMAT;
|
||||||
|
}
|
||||||
|
f.buffer_size = pref.buffer_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::SetOutputFormat(media_format &format)
|
||||||
|
{
|
||||||
|
media_raw_audio_format &f = format.u.raw_audio;
|
||||||
|
media_raw_audio_format &w = media_raw_audio_format::wildcard;
|
||||||
|
|
||||||
|
if(f.frame_rate == w.frame_rate) {
|
||||||
|
f.frame_rate = 44100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(f.channel_count == w.channel_count) {
|
||||||
|
if(fInputMedia.source != media_source::null) {
|
||||||
|
f.channel_count = fInputMedia.format.u.raw_audio.channel_count;
|
||||||
|
} else {
|
||||||
|
f.channel_count = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(f.format == w.format) {
|
||||||
|
f.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(f.byte_order == w.format) {
|
||||||
|
f.byte_order = (B_HOST_IS_BENDIAN) ? B_MEDIA_BIG_ENDIAN : B_MEDIA_LITTLE_ENDIAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(f.buffer_size == w.buffer_size) {
|
||||||
|
f.buffer_size = BUFF_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::InitParameterValues()
|
||||||
|
{
|
||||||
|
fMute = 0;
|
||||||
|
fByPass = 0;
|
||||||
|
fMuteLastChanged = 0LL;
|
||||||
|
fByPassLastChanged = 0LL;
|
||||||
|
fPreAmpLastChanged = 0LL;
|
||||||
|
|
||||||
|
for(int i=0;i<EQ_BANDS;i++) {
|
||||||
|
fBandsLastChanged[i] = 0LL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fEqualizer.CleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::InitParameterWeb(void)
|
||||||
|
{
|
||||||
|
fWeb = new BParameterWeb();
|
||||||
|
|
||||||
|
BParameterGroup *fParamGroup = fWeb->MakeGroup("EqualizerNode Parameters");
|
||||||
|
BParameterGroup *fFControlGroup = fParamGroup->MakeGroup("FilterControl");
|
||||||
|
|
||||||
|
fFControlGroup->MakeDiscreteParameter(P_MUTE,B_MEDIA_NO_TYPE,"Mute", B_ENABLE);
|
||||||
|
fFControlGroup->MakeDiscreteParameter(P_BYPASS,B_MEDIA_NO_TYPE,"ByPass", B_ENABLE);
|
||||||
|
|
||||||
|
BNullParameter *label;
|
||||||
|
BParameterGroup *group;
|
||||||
|
BContinuousParameter *value;
|
||||||
|
|
||||||
|
group = fParamGroup->MakeGroup("Pre Amp");
|
||||||
|
label = group->MakeNullParameter(P_PREAMP_LABEL, B_MEDIA_NO_TYPE,
|
||||||
|
"Pre Amp", B_GENERIC);
|
||||||
|
value = group->MakeContinuousParameter(P_PREAMP, B_MEDIA_NO_TYPE,
|
||||||
|
"", B_GAIN, "dB", -8.0, 8.0, 0.1);
|
||||||
|
label->AddOutput(value);
|
||||||
|
value->AddInput(label);
|
||||||
|
|
||||||
|
for(int i=0; i<fEqualizer.BandCount(); i++) {
|
||||||
|
char freq[32];
|
||||||
|
sprintf(freq,"%gHz",fEqualizer.BandFrequency(i));
|
||||||
|
group = fParamGroup->MakeGroup(freq);
|
||||||
|
label = group->MakeNullParameter(P_BAND_LABELS + i, B_MEDIA_NO_TYPE,
|
||||||
|
freq, B_GENERIC);
|
||||||
|
value = group->MakeContinuousParameter(P_BANDS + i, B_MEDIA_NO_TYPE,
|
||||||
|
"", B_GAIN, "dB", -16.0, 16.0, 0.1);
|
||||||
|
label->AddOutput(value);
|
||||||
|
value->AddInput(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetParameterWeb(fWeb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::InitFilter(void)
|
||||||
|
{
|
||||||
|
fEqualizer.SetFormat(fFormat.u.raw_audio.channel_count, fFormat.u.raw_audio.frame_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
bigtime_t
|
||||||
|
EqualizerNode::GetFilterLatency(void)
|
||||||
|
{
|
||||||
|
if(fOutputMedia.destination == media_destination::null) {
|
||||||
|
return 0LL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BBufferGroup *test_group = new BBufferGroup(fOutputMedia.format.u.raw_audio.buffer_size, 1);
|
||||||
|
|
||||||
|
BBuffer *buffer = test_group->RequestBuffer(fOutputMedia.format.u.raw_audio.buffer_size);
|
||||||
|
buffer->Header()->type = B_MEDIA_RAW_AUDIO;
|
||||||
|
buffer->Header()->size_used = fOutputMedia.format.u.raw_audio.buffer_size;
|
||||||
|
|
||||||
|
bigtime_t begin = system_time();
|
||||||
|
FilterBuffer(buffer);
|
||||||
|
bigtime_t latency = system_time() - begin;
|
||||||
|
|
||||||
|
buffer->Recycle();
|
||||||
|
delete test_group;
|
||||||
|
|
||||||
|
InitFilter();
|
||||||
|
|
||||||
|
return latency;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EqualizerNode::FilterBuffer(BBuffer* buffer)
|
||||||
|
{
|
||||||
|
uint32 m_frameSize = (fFormat.u.raw_audio.format & 0x0f) * fFormat.u.raw_audio.channel_count;
|
||||||
|
uint32 samples = buffer->Header()->size_used / m_frameSize;
|
||||||
|
uint32 channels = fFormat.u.raw_audio.channel_count;
|
||||||
|
if(fMute !=0 ) {
|
||||||
|
memset(buffer->Data(), 0, buffer->Header()->size_used);
|
||||||
|
} else {
|
||||||
|
if(fByPass == 0) {
|
||||||
|
fEqualizer.ProcessBuffer((float*)buffer->Data(), samples*channels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Gerasim Troeglazov (3dEyes**), [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __EQUALIZER_NODE_H__
|
||||||
|
#define __EQUALIZER_NODE_H__
|
||||||
|
|
||||||
|
#include <Controllable.h>
|
||||||
|
#include <BufferProducer.h>
|
||||||
|
#include <BufferConsumer.h>
|
||||||
|
#include <MediaEventLooper.h>
|
||||||
|
|
||||||
|
#include "Equalizer.h"
|
||||||
|
|
||||||
|
class BMediaAddOn;
|
||||||
|
class BBufferGroup;
|
||||||
|
|
||||||
|
#define BUFF_SIZE 0x2000
|
||||||
|
|
||||||
|
#define ID_AUDIO_INPUT 1
|
||||||
|
#define ID_AUDIO_OUTPUT 2
|
||||||
|
|
||||||
|
#define P_PREAMP_LABEL 100
|
||||||
|
#define P_PREAMP 101
|
||||||
|
#define P_MUTE 102
|
||||||
|
#define P_BYPASS 103
|
||||||
|
#define P_BAND_LABELS 200
|
||||||
|
#define P_BANDS 300
|
||||||
|
|
||||||
|
class EqualizerNode : public BBufferConsumer,
|
||||||
|
public BBufferProducer,
|
||||||
|
public BControllable,
|
||||||
|
public BMediaEventLooper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~EqualizerNode();
|
||||||
|
EqualizerNode(BMediaAddOn *pAddOn=NULL);
|
||||||
|
//BMediaNode
|
||||||
|
public:
|
||||||
|
virtual BMediaAddOn *AddOn(int32 *id) const;
|
||||||
|
virtual status_t HandleMessage(int32 code, const void *data, size_t size);
|
||||||
|
protected:
|
||||||
|
virtual void NodeRegistered();
|
||||||
|
//BControllable
|
||||||
|
public:
|
||||||
|
virtual status_t GetParameterValue(int32 id, bigtime_t *lastChangeTime,
|
||||||
|
void *value, size_t *size);
|
||||||
|
virtual void SetParameterValue(int32 id, bigtime_t changeTime,
|
||||||
|
const void *value, size_t size);
|
||||||
|
//BBufferConsumer
|
||||||
|
public:
|
||||||
|
virtual void BufferReceived(BBuffer *buffer);
|
||||||
|
virtual status_t AcceptFormat(const media_destination &dst,
|
||||||
|
media_format *format);
|
||||||
|
virtual status_t GetNextInput(int32 *cookie, media_input *input);
|
||||||
|
virtual void DisposeInputCookie(int32 cookie);
|
||||||
|
virtual status_t FormatChanged(const media_source &src,
|
||||||
|
const media_destination &dst,
|
||||||
|
int32 change_tag, const media_format &format);
|
||||||
|
virtual void ProducerDataStatus(const media_destination &dst,
|
||||||
|
int32 status,
|
||||||
|
bigtime_t when);
|
||||||
|
virtual status_t GetLatencyFor(const media_destination &dst,
|
||||||
|
bigtime_t *latency,
|
||||||
|
media_node_id *time_src);
|
||||||
|
virtual status_t Connected(const media_source &src,
|
||||||
|
const media_destination &dst,
|
||||||
|
const media_format &format,
|
||||||
|
media_input *input);
|
||||||
|
virtual void Disconnected(const media_source &src,
|
||||||
|
const media_destination &dst);
|
||||||
|
//BBufferProducer
|
||||||
|
public:
|
||||||
|
virtual status_t FormatSuggestionRequested(media_type type,
|
||||||
|
int32 quality, media_format *format);
|
||||||
|
virtual status_t FormatProposal(const media_source &src,
|
||||||
|
media_format *format);
|
||||||
|
virtual status_t FormatChangeRequested(const media_source &src,
|
||||||
|
const media_destination &dst,
|
||||||
|
media_format *format,
|
||||||
|
int32* _deprecated_);
|
||||||
|
virtual void LateNoticeReceived(const media_source &src,
|
||||||
|
bigtime_t late, bigtime_t when);
|
||||||
|
virtual status_t GetNextOutput(int32 *cookie, media_output *output);
|
||||||
|
virtual status_t DisposeOutputCookie(int32 cookie);
|
||||||
|
virtual status_t SetBufferGroup(const media_source &src,
|
||||||
|
BBufferGroup *group);
|
||||||
|
virtual status_t PrepareToConnect(const media_source &src,
|
||||||
|
const media_destination &dst,
|
||||||
|
media_format *format, media_source *source,
|
||||||
|
char *name);
|
||||||
|
virtual void Connect(status_t status,
|
||||||
|
const media_source &src,
|
||||||
|
const media_destination &dst,
|
||||||
|
const media_format &format,
|
||||||
|
char* name);
|
||||||
|
virtual void Disconnect(const media_source &src,
|
||||||
|
const media_destination &dst);
|
||||||
|
virtual void EnableOutput(const media_source &src,
|
||||||
|
bool enabled, int32* _deprecated_);
|
||||||
|
virtual status_t GetLatency(bigtime_t *outLatency);
|
||||||
|
virtual void LatencyChanged( const media_source &src,
|
||||||
|
const media_destination &dst,
|
||||||
|
bigtime_t latency, uint32 flags);
|
||||||
|
//BMediaEventLooper
|
||||||
|
protected:
|
||||||
|
virtual bigtime_t OfflineTime();
|
||||||
|
//EqualizerNode
|
||||||
|
protected:
|
||||||
|
virtual void HandleEvent(const media_timed_event *event,
|
||||||
|
bigtime_t late,
|
||||||
|
bool realTimeEvent=false);
|
||||||
|
void ParameterEventProcessing(const media_timed_event *event);
|
||||||
|
status_t ValidateFormat(const media_format &preferredFormat,
|
||||||
|
media_format &format);
|
||||||
|
void SetOutputFormat(media_format &format);
|
||||||
|
virtual void InitParameterValues(void);
|
||||||
|
virtual void InitParameterWeb(void);
|
||||||
|
virtual void InitFilter(void);
|
||||||
|
virtual bigtime_t GetFilterLatency(void);
|
||||||
|
virtual void FilterBuffer(BBuffer* pBuffer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BMediaAddOn *fAddOn;
|
||||||
|
BParameterWeb *fWeb;
|
||||||
|
|
||||||
|
Equalizer fEqualizer;
|
||||||
|
|
||||||
|
media_format fPreferredFormat;
|
||||||
|
media_format fFormat;
|
||||||
|
media_input fInputMedia;
|
||||||
|
media_output fOutputMedia;
|
||||||
|
|
||||||
|
int32 fMute;
|
||||||
|
int32 fByPass;
|
||||||
|
|
||||||
|
bigtime_t fMuteLastChanged;
|
||||||
|
bigtime_t fByPassLastChanged;
|
||||||
|
bigtime_t fPreAmpLastChanged;
|
||||||
|
bigtime_t fBandsLastChanged[EQ_BANDS];
|
||||||
|
|
||||||
|
bigtime_t fProcessLatency;
|
||||||
|
bigtime_t fDownstreamLatency;
|
||||||
|
bool fOutputMediaEnabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__EQUALIZER_NODE_H__
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
SubDir HAIKU_TOP src add-ons media media-add-ons equalizer ;
|
||||||
|
|
||||||
|
AddResources equalizer.media_addon : Equalizer.rdef ;
|
||||||
|
|
||||||
|
Addon equalizer.media_addon :
|
||||||
|
Equalizer.cpp
|
||||||
|
EqualizerAddOn.cpp
|
||||||
|
EqualizerNode.cpp
|
||||||
|
: be media
|
||||||
|
;
|
||||||
Reference in New Issue
Block a user