2015-03-24 21:25:13 +01:00
|
|
|
/** @file
|
|
|
|
* @author Edouard DUPIN
|
|
|
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
|
|
* @license APACHE v2.0 (see license file)
|
|
|
|
*/
|
|
|
|
|
2015-04-10 23:00:13 +02:00
|
|
|
#include <audio/drain/Equalizer.h>
|
|
|
|
#include <audio/drain/Algo.h>
|
|
|
|
#include <audio/drain/debug.h>
|
2015-03-24 21:25:13 +01:00
|
|
|
|
|
|
|
// see http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
|
2015-03-27 21:40:54 +01:00
|
|
|
// see http://www.earlevel.com/main/2013/10/13/biquad-calculator-v2/
|
2015-03-24 21:25:13 +01:00
|
|
|
|
2015-04-10 23:00:13 +02:00
|
|
|
audio::drain::Equalizer::Equalizer() {
|
2015-03-24 21:25:13 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-04-10 23:00:13 +02:00
|
|
|
void audio::drain::Equalizer::init() {
|
|
|
|
audio::drain::Algo::init();
|
|
|
|
audio::drain::Algo::m_type = "Equalizer";
|
2015-03-24 21:25:13 +01:00
|
|
|
m_supportedFormat.push_back(audio::format_int16);
|
2015-05-04 22:25:32 +02:00
|
|
|
m_supportedFormat.push_back(audio::format_int16);
|
2015-03-24 21:25:13 +01:00
|
|
|
configureBiQuad();
|
|
|
|
}
|
|
|
|
|
2015-04-10 23:00:13 +02:00
|
|
|
std11::shared_ptr<audio::drain::Equalizer> audio::drain::Equalizer::create() {
|
|
|
|
std11::shared_ptr<audio::drain::Equalizer> tmp(new audio::drain::Equalizer());
|
2015-03-24 21:25:13 +01:00
|
|
|
tmp->init();
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
2015-04-10 23:00:13 +02:00
|
|
|
audio::drain::Equalizer::~Equalizer() {
|
2015-03-24 21:25:13 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-04-10 23:00:13 +02:00
|
|
|
void audio::drain::Equalizer::configurationChange() {
|
|
|
|
audio::drain::Algo::configurationChange();
|
2015-05-04 22:25:32 +02:00
|
|
|
configureBiQuad();
|
2015-03-24 21:25:13 +01:00
|
|
|
}
|
|
|
|
|
2015-04-13 21:49:48 +02:00
|
|
|
bool audio::drain::Equalizer::process(audio::Time& _time,
|
2015-04-10 23:00:13 +02:00
|
|
|
void* _input,
|
|
|
|
size_t _inputNbChunk,
|
|
|
|
void*& _output,
|
|
|
|
size_t& _outputNbChunk) {
|
2015-03-24 21:25:13 +01:00
|
|
|
_outputNbChunk = _inputNbChunk;
|
|
|
|
_output = _input;
|
|
|
|
if (_input == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
2015-05-04 22:25:32 +02:00
|
|
|
m_algo.process(_output, _input, _inputNbChunk);
|
2015-03-24 21:25:13 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-04-10 23:00:13 +02:00
|
|
|
bool audio::drain::Equalizer::setParameter(const std::string& _parameter, const std::string& _value) {
|
2015-03-27 21:40:54 +01:00
|
|
|
//DRAIN_WARNING("set : " << _parameter << " " << _value);
|
2015-03-30 21:00:12 +02:00
|
|
|
if (_parameter == "config") {
|
|
|
|
m_config = ejson::Object::create(_value);
|
2015-03-24 21:25:13 +01:00
|
|
|
configureBiQuad();
|
2015-03-27 21:40:54 +01:00
|
|
|
} else if (_parameter == "reset") {
|
2015-05-04 22:25:32 +02:00
|
|
|
// TODO : m_algo.reset();
|
2015-03-27 21:40:54 +01:00
|
|
|
return true;
|
2015-03-24 21:25:13 +01:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-04-10 23:00:13 +02:00
|
|
|
std::string audio::drain::Equalizer::getParameter(const std::string& _parameter) const {
|
2015-03-24 21:25:13 +01:00
|
|
|
return "error";
|
|
|
|
}
|
|
|
|
|
2015-04-10 23:00:13 +02:00
|
|
|
std::string audio::drain::Equalizer::getParameterProperty(const std::string& _parameter) const {
|
2015-03-24 21:25:13 +01:00
|
|
|
return "error";
|
|
|
|
}
|
|
|
|
|
2015-05-04 22:25:32 +02:00
|
|
|
void audio::drain::Equalizer::addBiquad(int32_t _idBiquad, const std11::shared_ptr<const ejson::Object>& _object) {
|
2015-03-30 21:00:12 +02:00
|
|
|
// get type:
|
|
|
|
std::string typeString = _object->getStringValue("type", "none");
|
|
|
|
if (typeString == "direct-value") {
|
|
|
|
double a0 = _object->getNumberValue("a0", 0.0);
|
|
|
|
double a1 = _object->getNumberValue("a1", 0.0);
|
|
|
|
double a2 = _object->getNumberValue("a2", 0.0);
|
|
|
|
double b0 = _object->getNumberValue("b0", 0.0);
|
|
|
|
double b1 = _object->getNumberValue("b1", 0.0);
|
2015-05-04 22:25:32 +02:00
|
|
|
if (_idBiquad < 0) {
|
|
|
|
m_algo.addBiquad(a0, a1, a2, b0, b1);
|
|
|
|
} else {
|
|
|
|
m_algo.addBiquad(_idBiquad, a0, a1, a2, b0, b1);
|
|
|
|
}
|
2015-03-30 21:00:12 +02:00
|
|
|
} else {
|
2015-05-04 22:25:32 +02:00
|
|
|
enum audio::algo::drain::biQuadType type;
|
2015-03-30 21:00:12 +02:00
|
|
|
if (etk::from_string(type, typeString) == false) {
|
|
|
|
DRAIN_ERROR("Can not parse equalizer type:'" << typeString << "'");
|
|
|
|
}
|
|
|
|
double gain = _object->getNumberValue("gain", 0.0);
|
|
|
|
double frequency = _object->getNumberValue("cut-frequency", 0.0);
|
|
|
|
double quality = _object->getNumberValue("quality", 0.0);
|
2015-05-04 22:25:32 +02:00
|
|
|
if (_idBiquad < 0) {
|
|
|
|
m_algo.addBiquad(type, frequency, quality, gain);
|
|
|
|
} else {
|
|
|
|
m_algo.addBiquad(_idBiquad, type, frequency, quality, gain);
|
|
|
|
}
|
2015-03-30 21:00:12 +02:00
|
|
|
}
|
2015-03-27 21:40:54 +01:00
|
|
|
}
|
|
|
|
|
2015-04-10 23:00:13 +02:00
|
|
|
void audio::drain::Equalizer::configureBiQuad() {
|
2015-05-04 22:25:32 +02:00
|
|
|
m_algo.init(getOutputFormat().getFrequency(),
|
|
|
|
getOutputFormat().getMap().size(),
|
|
|
|
getOutputFormat().getFormat());
|
2015-03-30 21:00:12 +02:00
|
|
|
if (m_config == nullptr) {
|
2015-03-27 21:40:54 +01:00
|
|
|
return;
|
|
|
|
}
|
2015-03-30 21:00:12 +02:00
|
|
|
// check for a global config:
|
|
|
|
const std11::shared_ptr<const ejson::Array> global = m_config->getArray("global");
|
|
|
|
if (global != nullptr) {
|
|
|
|
// only global configuration get all elements:
|
|
|
|
for (size_t kkk=0; kkk<global->size(); ++kkk) {
|
|
|
|
const std11::shared_ptr<const ejson::Object> tmpObject = global->getObject(kkk);
|
|
|
|
if (tmpObject == nullptr) {
|
|
|
|
DRAIN_ERROR("Parse the configuration error : not a correct parameter:" << kkk);
|
|
|
|
continue;
|
2015-03-27 21:40:54 +01:00
|
|
|
}
|
2015-05-04 22:25:32 +02:00
|
|
|
// Add biquad...
|
|
|
|
addBiquad(-1, tmpObject);
|
2015-03-30 21:00:12 +02:00
|
|
|
}
|
|
|
|
return;
|
2015-03-28 19:43:20 +01:00
|
|
|
}
|
2015-03-30 21:00:12 +02:00
|
|
|
for (size_t iii=0; iii<getOutputFormat().getMap().size(); ++iii) {
|
|
|
|
std::string channelName = etk::to_string(getOutputFormat().getMap()[iii]);
|
|
|
|
const std11::shared_ptr<const ejson::Array> channelConfig = m_config->getArray(channelName);
|
|
|
|
if (channelConfig == nullptr) {
|
|
|
|
// no config ... not a problem ...
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// only global configuration get all elements:
|
|
|
|
for (size_t kkk=0; kkk<channelConfig->size(); ++kkk) {
|
|
|
|
const std11::shared_ptr<const ejson::Object> tmpObject = channelConfig->getObject(kkk);
|
|
|
|
if (tmpObject == nullptr) {
|
|
|
|
DRAIN_ERROR("Parse the configuration error : not a correct parameter:" << kkk);
|
|
|
|
continue;
|
2015-03-28 19:43:20 +01:00
|
|
|
}
|
2015-05-04 22:25:32 +02:00
|
|
|
// add biquad:
|
|
|
|
addBiquad(kkk, tmpObject);
|
2015-03-28 19:43:20 +01:00
|
|
|
}
|
|
|
|
}
|
2015-03-30 21:00:12 +02:00
|
|
|
return;
|
2015-03-28 19:43:20 +01:00
|
|
|
}
|
2015-04-01 23:18:46 +02:00
|
|
|
|
2015-04-10 23:00:13 +02:00
|
|
|
std::vector<std::pair<float,float> > audio::drain::Equalizer::calculateTheory() {
|
2015-05-04 22:25:32 +02:00
|
|
|
return m_algo.calculateTheory();
|
2015-04-01 23:18:46 +02:00
|
|
|
}
|