/** @file * @author Edouard DUPIN * @copyright 2011, Edouard DUPIN, all right reserved * @license APACHE v2.0 (see license file) */ #include #include #include // see http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt // see http://www.earlevel.com/main/2013/10/13/biquad-calculator-v2/ drain::Equalizer::Equalizer() { } void drain::Equalizer::init() { drain::Algo::init(); drain::Algo::m_type = "Equalizer"; m_supportedFormat.push_back(audio::format_int16); configureBiQuad(); } std11::shared_ptr drain::Equalizer::create() { std11::shared_ptr tmp(new drain::Equalizer()); tmp->init(); return tmp; } drain::Equalizer::~Equalizer() { } void drain::Equalizer::configurationChange() { drain::Algo::configurationChange(); if (m_biquads.size() != getOutputFormat().getMap().size()) { configureBiQuad(); } } bool drain::Equalizer::process(std11::chrono::system_clock::time_point& _time, void* _input, size_t _inputNbChunk, void*& _output, size_t& _outputNbChunk) { _outputNbChunk = _inputNbChunk; _output = _input; if (_input == nullptr) { return false; } if (getOutputFormat().getFormat() == audio::format_float) { for (size_t jjj=0; jjj(_input); // move to sample offset: data += jjj; for (size_t iii=0; iii(_input); // move to sample offset: data += jjj; for (size_t iii=0; iii& _object, float _frequency) { drain::BiQuadFloat out; // 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); out.setBiquadCoef(a0, a1, a2, b0, b1); } else { enum drain::filterType type; 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); out.setBiquad(type, frequency, quality, gain, _frequency); } return out; } void drain::Equalizer::configureBiQuad() { m_biquads.clear(); m_biquads.resize(getOutputFormat().getMap().size()); if (m_config == nullptr) { return; } // check for a global config: const std11::shared_ptr global = m_config->getArray("global"); if (global != nullptr) { // only global configuration get all elements: for (size_t kkk=0; kkksize(); ++kkk) { const std11::shared_ptr tmpObject = global->getObject(kkk); if (tmpObject == nullptr) { DRAIN_ERROR("Parse the configuration error : not a correct parameter:" << kkk); continue; } // declare biquad: drain::BiQuadFloat biquad = getBiquad(tmpObject, getOutputFormat().getFrequency()); // add this bequad for every Channel: for (size_t iii=0; iii 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; kkksize(); ++kkk) { const std11::shared_ptr tmpObject = channelConfig->getObject(kkk); if (tmpObject == nullptr) { DRAIN_ERROR("Parse the configuration error : not a correct parameter:" << kkk); continue; } // declare biquad: drain::BiQuadFloat biquad = getBiquad(tmpObject, getOutputFormat().getFrequency()); // add this bequad for specific channel: m_biquads[iii].push_back(biquad); } } return; } std::vector > drain::Equalizer::calculateTheory() { std::vector > out; for (size_t iii=0; iii > tmp = m_biquads[0][iii].calculateTheory(getOutputFormat().getFrequency()); for (size_t jjj=0; jjj< out.size(); ++jjj) { out[jjj].second += tmp[jjj].second; } } } return out; }