filtros funcionando

This commit is contained in:
snt 2024-05-14 20:49:28 +02:00
parent f87c908d30
commit 3525133287
5 changed files with 195 additions and 57 deletions

View file

@ -10,6 +10,19 @@
#define ENTRY_POINT_COARSE 5
#define ENTRY_POINT_FINE 4
#define PITCH 7
#define LAYER_CHANNELS 9
#define VOL1 9
#define VOL2 10
#define LOW_FREQ 11
#define LOW_Q 12
#define MIDLOW_FREQ 13
#define MIDLOW_Q 14
#define MIDLOW_GAIN 15
#define MIDHIGH_FREQ 16
#define MIDHIGH_Q 17
#define MIDHIGH_GAIN 18
#define HIGH_FREQ 19
#define HIGH_Q 20
#define LAYER_CHANNELS 21
#endif // DMXPERSONALITY_H

View file

@ -26,10 +26,11 @@ libreMediaServerAudio::libreMediaServerAudio()
m_settings = Settings::getInstance();
m_settings->readFile();
m_ui = m_settings->getShowUi();
m_layersQty = m_settings->getLayersNumber();
m_dmxSettings = m_settings->getDmxSettings();
m_mediaLibrary = new MediaLibrary;
m_mediaLibrary->initMediaLibrary();
for (int i = 0; i < MAX_LAYERS; i++) {
for (uint i = 0; i < m_layersQty; i++) {
m_currentMedia[i] = "";
m_currentStatus[i] = Status::Iddle;
#ifdef NOGUI
@ -39,24 +40,24 @@ libreMediaServerAudio::libreMediaServerAudio()
m_updateUi[i][3] = -1;
#endif
}
m_ola = new olaThread(this, m_settings->getLayersNumber());
Q_CHECK_PTR(m_ola);
m_ola->blockSignals(true);
m_ola->registerUniverse();
if (!m_mae.startEngine()) {
if (!m_mae.startEngine(m_layersQty)) {
cout << "Can not start Audio Engine!" << endl;
this->~libreMediaServerAudio();
exit(-1);
}
uint *audioDevList = m_settings->getAudioDeviceId();
if (!m_mae.startDevice(audioDevList, m_settings->getAudioDeviceQty())) {
cout << "Can not start Audio Device!" << audioDevList << endl;
this->~libreMediaServerAudio();
exit(-1);
}
cout << "Core init Complete. Start reading DMX." << endl;
m_ola->blockSignals(false);
m_ola = new olaThread(this, m_layersQty);
Q_CHECK_PTR(m_ola);
m_ola->blockSignals(true);
m_ola->registerUniverse();
#ifdef NOGUI
m_ola->start(QThread::TimeCriticalPriority );
#endif
m_ola->blockSignals(false);
cout << "Core init Complete." << endl;
}
libreMediaServerAudio::~libreMediaServerAudio()
@ -74,7 +75,8 @@ void libreMediaServerAudio::loadMedia(int layer, int folder, int file)
if (strcmp(mediaFile.toLatin1().constData(), m_currentMedia[layer].toLatin1().constData()) == 0)
return;
if (QFile::exists(mediaFile)){
m_mae.loadMedia(layer, mediaFile.toLatin1().data(), m_dmxSettings.at(layer).audioDevice);
m_mae.loadMedia(layer, mediaFile.toLatin1().data(),\
m_dmxSettings.at(layer).audioDevice);
m_currentMedia[layer] = mediaFile;
#ifndef NOGUI
if (m_ui)
@ -138,6 +140,9 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
m_played.append(m_ola->getValue(layer, DMX_FILE));
}
#endif
} else if (channel >= LOW_FREQ) {
m_mae.filterParamChanged(layer, m_dmxSettings.at(layer).audioDevice, channel, value);
}
}
#ifndef NOGUI

View file

@ -57,6 +57,7 @@ private:
QList<dmxSetting> m_dmxSettings;
bool m_ui;
QList<int> m_played;
uint m_layersQty;
#ifndef NOGUI
QTimer *m_refreshUi;
libreMediaServerAudioUi *m_lmsUi;

View file

@ -1,35 +1,35 @@
#include "miniaudioengine.h"
#define LPF_BIAS 0.9f
#define LPF_CUTOFF_FACTOR 80
#define HPF_CUTOFF_FACTOR 1
#define LPF_ORDER 8
#include "dmxPersonality.h"
MiniAudioEngine::MiniAudioEngine()
{
for (int i =0; i < MAX_LAYERS; i++) {
m_mediaLoaded[i] = false;
m_currentLayerValues[i].status = Status::Iddle;
m_currentLayerValues[i].pan = 128;
m_currentLayerValues[i].pitch = 128;
m_currentLayerValues[i].vol = 0;
m_currentLayerValues[i].cursor = 0;
}
}
#define LPF_BIAS 0.9f
#define FILTER_ORDER 2
#define LPF_CUTOFF_FACTOR 2
#define HPF_CUTOFF_FACTOR 20
MiniAudioEngine::MiniAudioEngine() {}
void MiniAudioEngine::audioDataCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
{
(void)pInput;
(void)pDevice;
ma_result result;
result = ma_engine_read_pcm_frames((ma_engine*)pDevice->pUserData, pOutput, frameCount, NULL);
if (result != MA_SUCCESS) {
cout << "1";
cout << "Error " << result << ": error audio callback.";
}
}
void MiniAudioEngine::stopEngine()
{
for (uint i = 0; i < m_layersQty; i++) {
ma_sound_uninit(&m_currentSound[i]);
}
for (uint i = 0; i < m_devicesSelected; i++) {
for (uint j = 0; j < m_layersQty; j++) {
ma_hpf_node_uninit(&m_filterBank[i][j].hpf, NULL);
ma_lpf_node_uninit(&m_filterBank[i][j].lpf, NULL);
ma_peak_node_uninit(&m_filterBank[i][j].mLow, NULL);
ma_peak_node_uninit(&m_filterBank[i][j].mHigh, NULL);
}
ma_engine_uninit(&m_engine[i]);
ma_device_uninit(&m_device[i]);
}
@ -37,10 +37,19 @@ void MiniAudioEngine::stopEngine()
ma_resource_manager_uninit(&m_resourceManager);
}
bool MiniAudioEngine::startEngine()
bool MiniAudioEngine::startEngine(uint layers)
{
ma_result result;
m_layersQty = layers;
for (uint i =0; i < m_layersQty; i++) {
m_mediaLoaded[i] = false;
m_currentLayerValues[i].status = Status::Iddle;
m_currentLayerValues[i].pan = 128;
m_currentLayerValues[i].pitch = 128;
m_currentLayerValues[i].vol = 0;
m_currentLayerValues[i].cursor = 0;
}
result = this->startContext();
if (result != MA_SUCCESS) return false;
result = this->getAllAudioDevices();
@ -48,41 +57,74 @@ bool MiniAudioEngine::startEngine()
return true;
}
ma_result MiniAudioEngine::setNodeGraph(int id) {
// lpf -> hpf -> mLow -> mHigh -> engine
ma_result MiniAudioEngine::createFilterBank(int id, uint layer)
{
ma_result result;
ma_lpf_node_config lpfNodeConfig = ma_lpf_node_config_init(CHANNELS, SAMPLE_RATE, SAMPLE_RATE / LPF_CUTOFF_FACTOR, LPF_ORDER);
ma_node_graph *ng = ma_engine_get_node_graph(&m_engine[id]);
result = ma_lpf_node_init(ng, &lpfNodeConfig, NULL, &m_filterBank[id].lpfNode);
ma_node *endpoint = ma_engine_get_endpoint(&m_engine[id]);
filterBank *fb = &m_filterBank[id][layer];
ma_lpf_node_config lpfConfig = ma_lpf_node_config_init(CHANNELS, SAMPLE_RATE, SAMPLE_RATE / LPF_CUTOFF_FACTOR, FILTER_ORDER);
fb->lpfConfig = ma_lpf_config_init(FORMAT, CHANNELS, SAMPLE_RATE, SAMPLE_RATE / LPF_CUTOFF_FACTOR, FILTER_ORDER);
result = ma_lpf_node_init(ng, &lpfConfig, NULL, &fb->lpf);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to initialize low pass filter node." << endl;
return result;
}
ma_node *endpoint = ma_engine_get_endpoint(&m_engine[id]);
// ToDo: ampliar dimensión a m_filterBank con las capas
ma_hpf_node_config hpfNodeConfig = ma_hpf_node_config_init(CHANNELS, SAMPLE_RATE, SAMPLE_RATE / HPF_CUTOFF_FACTOR, LPF_ORDER);
result = ma_hpf_node_init(ng, &hpfNodeConfig, NULL, &m_filterBank[id].hpfNode);
ma_hpf_node_config hpfConfig = ma_hpf_node_config_init(CHANNELS, SAMPLE_RATE, HPF_CUTOFF_FACTOR, FILTER_ORDER);
fb->hpfConfig = ma_hpf_config_init(FORMAT, CHANNELS, SAMPLE_RATE, HPF_CUTOFF_FACTOR, FILTER_ORDER);
result = ma_hpf_node_init(ng, &hpfConfig, NULL, &fb->hpf);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to initialize high pass filter node." << endl;
return result;
}
result = ma_node_attach_output_bus(&m_filterBank[id].lpfNode, 0, &m_filterBank[id].hpfNode, 0);
ma_peak_node_config mLowConfig = ma_peak_node_config_init(CHANNELS, SAMPLE_RATE, 1.0, 5.0, 300); // double gainDB, double q, double frequency);
fb->mLowConfig = ma_peak2_config_init(FORMAT, CHANNELS, SAMPLE_RATE, 100.0, 50.0, 1000);
result = ma_peak_node_init(ng, &mLowConfig, NULL, &fb->mLow);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to initialize peak low filter node." << endl;
return result;
}
ma_peak_node_config mHighConfig = ma_peak_node_config_init(CHANNELS, SAMPLE_RATE, 0.0, 0.0, 1000); // double gainDB, double q, double frequency);
fb->mHighConfig = ma_peak2_config_init(FORMAT, CHANNELS, SAMPLE_RATE, 0.0, 0.0, 220);
result = ma_peak_node_init(ng, &mHighConfig, NULL, &fb->mHigh);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to initialize peak high filter node." << endl;
return result;
}
result = ma_node_attach_output_bus(&fb->lpf, 0, &fb->hpf, 0);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to attach low pass filter node." << endl;
return result;
}
// ToDo: add peak filters
result = ma_node_attach_output_bus(&m_filterBank[id].hpfNode, 0, endpoint, 0);
result = ma_node_attach_output_bus(&fb->hpf, 0, &fb->mLow, 0);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to attach low pass filter node." << endl;
cout << "ERROR " << result << ": Failed to attach Mid Low pass filter node." << endl;
return result;
}
/*
result = ma_node_set_state(&m_filterBank[id].lpfNode, ma_node_state::ma_node_state_started);
result = ma_node_attach_output_bus(&fb->mLow, 0, &fb->mHigh, 0);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to set state to filter node." << endl;
cout << "ERROR " << result << ": Failed to attach high peaks filter node." << endl;
return result;
}*/
}
result = ma_node_attach_output_bus(&fb->mHigh, 0, endpoint, 0);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to attach high peaks filter node." << endl;
return result;
}
return result;
}
ma_result MiniAudioEngine::setNodeGraph(int id) {
ma_result result = MA_SUCCESS;
uint i = 0;
while (result == MA_SUCCESS && i < m_layersQty) {
result = this->createFilterBank(id, i);
i++;
}
return (result);
}
@ -174,8 +216,11 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file, uint audioDevice)
ma_result result;
// ToDo: ver si s puede attach dos dispositivos a la vez. si no:
// enchufar a un splitter al sonido y attach cada uno de los lados.
// iniciar un sonido por cada capa
// - enchufar a un splitter al sonido y attach cada uno de los lados.
// - iniciar un sonido por cada capa, copiar la capa en otro dispositivo
// - splitter al final de filterBank, esas señales se mezclan en un nodo mudo
// y se escribe la mezcla en un buffer. Mezclar el buffer en disco con el
// del otro device en el audio callback .
if (m_mediaLoaded[layer] == true)
{
ma_sound_uninit(&m_currentSound[layer]);
@ -188,14 +233,11 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file, uint audioDevice)
cout << "Error " << result << ": Failed to load file " << file << endl;
return result;
}
result = ma_node_attach_output_bus(&m_currentSound[layer], 0, &m_filterBank[audioDevice].lpfNode, 0);
result = ma_node_attach_output_bus(&m_currentSound[layer], 0, &m_filterBank[audioDevice][layer].lpf, 0);
if (result != MA_SUCCESS) {
cout << "Error " << result << ": Failed to attach output bus " << audioDevice << endl;
//return result;
}
// ToDo: ampliar dimensión a m_filterBank con las capas
// attach las capas en los dispositivos
// master cada capa? al principio o final del filtro?
m_mediaLoaded[layer] = true;
this->refreshValues(layer);
m_currentLayerValues[layer].media = file;
@ -357,3 +399,71 @@ void MiniAudioEngine::refreshValues(int layer)
this->pitchChanged(layer, m_currentLayerValues[layer].pitch);
this->playbackChanged(layer, m_currentLayerValues[layer].status);
}
ma_result MiniAudioEngine::filterParamChanged(int layer, int audioDevice, int channel, int value)
{
ma_result result = MA_SUCCESS;
filterBank *fb = &m_filterBank[audioDevice][layer];
if (channel == LOW_FREQ) {
fb->hpfConfig.cutoffFrequency = (value * 2) + 20;
result = ma_hpf_node_reinit(&fb->hpfConfig, &fb->hpf);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to set frecuency Low filter node." << endl;
return result;
}
} else if (channel == HIGH_FREQ) {
fb->lpfConfig.cutoffFrequency = 22000 - (value * 80);
result = ma_lpf_node_reinit(&fb->lpfConfig, &fb->lpf);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to set frecuency High filter node." << endl;
return result;
}
} else if (channel == MIDLOW_FREQ) {
fb->mLowConfig.frequency = 60 + (value * 4);
result = ma_peak_node_reinit(&fb->mLowConfig, &fb->mLow);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to set frecuency Mid Low pass filter node." << endl;
return result;
}
cout << "frec " << fb->mLowConfig.frequency << endl;
} else if (channel == MIDLOW_Q) {
fb->mLowConfig.q = (double)( value / 32.0f) + 0.50;
result = ma_peak_node_reinit(&fb->mLowConfig, &fb->mLow);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to set Q Mid Low filter node." << endl;
return result;
}
cout << "Q " << fb->mLowConfig.q << endl;
} else if (channel == MIDLOW_GAIN) {
fb->mLowConfig.gainDB = (double)(value / 8.0f) - 16.0f;
result = ma_peak_node_reinit(&fb->mLowConfig, &fb->mLow);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to set gain Mid Low filter node." << endl;
return result;
}
} else if (channel == MIDHIGH_FREQ) {
fb->mHighConfig.frequency = 400 + (value * 32);
result = ma_peak_node_reinit(&fb->mHighConfig, &fb->mHigh);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to set frecuency Mid High filter node." << endl;
return result;
}
} else if (channel == MIDHIGH_Q) {
fb->mHighConfig.q = (double)( value / 32.0f) + 0.50;
result = ma_peak_node_reinit(&fb->mHighConfig, &fb->mHigh);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to set Q Mid High filter node." << endl;
return result;
}
} else if (channel == MIDHIGH_GAIN) {
fb->mHighConfig.gainDB = (double)(value / 8.0f) - 16.0f;
result = ma_peak_node_reinit(&fb->mHighConfig, &fb->mHigh);
if (result != MA_SUCCESS) {
cout << "ERROR " << result << ": Failed to set gain Mid High filter node." << endl;
return result;
}
}
return (result);
}

View file

@ -19,12 +19,18 @@ using namespace std;
typedef struct
{
ma_hpf_node hpfNode;
ma_lpf_node lpfNode;
ma_peak_node midLowNode;
ma_peak_node midHighNode;
ma_hpf_node hpf;
ma_hpf_config hpfConfig;
ma_lpf_node lpf;
ma_lpf_config lpfConfig;
ma_peak_node mLow;
ma_peak_config mLowConfig;
ma_peak_node mHigh;
ma_notch_node notch;
ma_peak_config mHighConfig;
} filterBank;
class MiniAudioEngine
{
friend class libreMediaServerAudio;
@ -32,7 +38,7 @@ class MiniAudioEngine
public:
MiniAudioEngine();
void stopEngine();
bool startEngine();
bool startEngine(uint layersQty);
bool startDevice(uint *id, uint nb);
static void audioDataCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount);
@ -50,6 +56,7 @@ protected:
inline float getVol(int layer) {
return ma_sound_get_volume(&m_currentSound[layer]); }
inline bool getAtEnd(int layer) { return m_currentSound[layer].atEnd; }
ma_result filterParamChanged(int layer, int audioDevice, int channel, int value);
private:
ma_resource_manager_config m_resourceManagerConfig;
@ -62,14 +69,16 @@ private:
ma_sound m_currentSound[MAX_LAYERS];
ma_bool8 m_mediaLoaded[MAX_LAYERS];
layerData m_currentLayerValues[MAX_LAYERS];
filterBank m_filterBank[MAX_LAYERS];
filterBank m_filterBank[MAX_AUDIODEVICES][MAX_LAYERS];
ma_engine m_engine[MAX_AUDIODEVICES];
uint m_layersQty;
ma_result getAllAudioDevices();
ma_result startContext();
void refreshValues(int layer);
ma_result seekToCursor(int layer, int cursor);
ma_result setNodeGraph(int id);
ma_result createFilterBank(int id, uint layer);
};
#endif // MINIAUDIOENGINE_H