324 lines
11 KiB
C++
324 lines
11 KiB
C++
/** @file
|
|
* @author Edouard DUPIN
|
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
|
* @license MPL v2.0 (see license file)
|
|
*/
|
|
|
|
#include <etk/types.hpp>
|
|
#include <ewol/ewol.hpp>
|
|
#include <appl/debug.hpp>
|
|
#include <appl/Windows.hpp>
|
|
#include <ewol/widget/Label.hpp>
|
|
#include <ewol/widget/Entry.hpp>
|
|
#include <ewol/widget/Button.hpp>
|
|
#include <ewol/widget/Slider.hpp>
|
|
#include <audio/drain/Equalizer.hpp>
|
|
|
|
define APPL_SAVE_FILE_MACRO(type,fileName,dataPointer,nbElement) \
|
|
do { \
|
|
static FILE *pointerOnFile = null; \
|
|
static bool errorOpen = false; \
|
|
if (pointerOnFile == null) { \
|
|
APPL_WARNING("open file '" << fileName << "' type=" << #type); \
|
|
pointerOnFile = fopen(fileName,"w"); \
|
|
if ( errorOpen == false \
|
|
&& pointerOnFile == null) { \
|
|
APPL_ERROR("ERROR OPEN file ... '" << fileName << "' type=" << #type); \
|
|
errorOpen=true; \
|
|
} \
|
|
} \
|
|
if (pointerOnFile != null) { \
|
|
fwrite((dataPointer), sizeof(type), (nbElement), pointerOnFile); \
|
|
/* fflush(pointerOnFile);*/ \
|
|
} \
|
|
}while(0)
|
|
|
|
appl::Windows::Windows() :
|
|
m_sampleRate(48000),
|
|
m_type(audio::algo::drain::biQuadType_lowPass),
|
|
m_cutFrequency(8000.0),
|
|
m_gain(0.0),
|
|
m_quality(0.707) {
|
|
addObjectType("appl::Windows");
|
|
m_listSampleRate.pushBack(192000);
|
|
m_listSampleRate.pushBack(176400);
|
|
m_listSampleRate.pushBack(96000);
|
|
m_listSampleRate.pushBack(88200);
|
|
m_listSampleRate.pushBack(48000);
|
|
m_listSampleRate.pushBack(44100);
|
|
m_listSampleRate.pushBack(32000);
|
|
m_listSampleRate.pushBack(22050);
|
|
m_listSampleRate.pushBack(16000);
|
|
m_listSampleRate.pushBack(11025);
|
|
m_listSampleRate.pushBack(8000);
|
|
m_listSampleRate.pushBack(4000);
|
|
m_listType.pushBack(audio::algo::drain::biQuadType_none);
|
|
m_listType.pushBack(audio::algo::drain::biQuadType_lowPass);
|
|
m_listType.pushBack(audio::algo::drain::biQuadType_highPass);
|
|
m_listType.pushBack(audio::algo::drain::biQuadType_bandPass);
|
|
m_listType.pushBack(audio::algo::drain::biQuadType_notch);
|
|
m_listType.pushBack(audio::algo::drain::biQuadType_peak);
|
|
m_listType.pushBack(audio::algo::drain::biQuadType_lowShelf);
|
|
m_listType.pushBack(audio::algo::drain::biQuadType_highShelf);
|
|
}
|
|
|
|
void appl::Windows::init() {
|
|
ewol::widget::Windows::init();
|
|
setTitle("Drain Equalizer Profiler");
|
|
|
|
m_gui = ewol::widget::Composer::create(ewol::widget::Composer::file, "DATA:///gui.xml");
|
|
if (m_gui != null) {
|
|
setSubWidget(m_gui);
|
|
}
|
|
subBind(ewol::widget::Button, "sample-rate-low", signalPressed, sharedFromThis(), &appl::Windows::onCallbackSampleRateLow);
|
|
subBind(ewol::widget::Button, "sample-rate-up", signalPressed, sharedFromThis(), &appl::Windows::onCallbackSampleRateUp);
|
|
subBind(ewol::widget::Button, "type-low", signalPressed, sharedFromThis(), &appl::Windows::onCallbackTypeLow);
|
|
subBind(ewol::widget::Button, "type-up", signalPressed, sharedFromThis(), &appl::Windows::onCallbackTypeUp);
|
|
|
|
subBind(ewol::widget::Entry, "gain", signalModify, sharedFromThis(), &appl::Windows::onCallbackGain);
|
|
subBind(ewol::widget::Slider, "gain-slider", signalChange, sharedFromThis(), &appl::Windows::onCallbackGainSlider);
|
|
|
|
subBind(ewol::widget::Entry, "frequency", signalModify, sharedFromThis(), &appl::Windows::onCallbackFrequency);
|
|
subBind(ewol::widget::Slider, "frequency-slider", signalChange, sharedFromThis(), &appl::Windows::onCallbackFrequencySlider);
|
|
|
|
subBind(ewol::widget::Entry, "quality", signalModify, sharedFromThis(), &appl::Windows::onCallbackQuality);
|
|
subBind(ewol::widget::Slider, "quality-slider", signalChange, sharedFromThis(), &appl::Windows::onCallbackQualitySlider);
|
|
|
|
subBind(ewol::widget::Button, "display16", signalPressed, sharedFromThis(), &appl::Windows::onCallbackStart16);
|
|
subBind(ewol::widget::Button, "displayFloat", signalPressed, sharedFromThis(), &appl::Windows::onCallbackStartFloat);
|
|
m_displayer = ememory::dynamicPointerCast<appl::widget::DisplayFrequency>(getSubObjectNamed("displayer"));
|
|
onCallbackStart();
|
|
}
|
|
|
|
|
|
void appl::Windows::onCallbackSampleRateUp() {
|
|
for (int32_t iii=0; iii<m_listSampleRate.size(); ++iii) {
|
|
if (m_sampleRate == m_listSampleRate[iii]) {
|
|
iii++;
|
|
if (iii<m_listSampleRate.size()) {
|
|
m_sampleRate = m_listSampleRate[iii];
|
|
} else {
|
|
m_sampleRate = m_listSampleRate[0];
|
|
}
|
|
ewol::parameterSetOnObjectNamed("sample-rate", "value", etk::toString(m_sampleRate));
|
|
ewol::parameterSetOnObjectNamed("frequency-slider", "max", etk::toString(m_sampleRate/2));
|
|
onCallbackStart();
|
|
return;
|
|
}
|
|
}
|
|
m_sampleRate = m_listSampleRate[0];
|
|
ewol::parameterSetOnObjectNamed("sample-rate", "value", etk::toString(m_sampleRate));
|
|
ewol::parameterSetOnObjectNamed("frequency-slider", "max", etk::toString(m_sampleRate/2));
|
|
onCallbackStart();
|
|
}
|
|
|
|
void appl::Windows::onCallbackSampleRateLow() {
|
|
for (int32_t iii=0; iii<m_listSampleRate.size(); ++iii) {
|
|
if (m_sampleRate == m_listSampleRate[iii]) {
|
|
iii--;
|
|
if (iii>=0) {
|
|
m_sampleRate = m_listSampleRate[iii];
|
|
} else {
|
|
m_sampleRate = m_listSampleRate[m_listSampleRate.size()-1];
|
|
}
|
|
ewol::parameterSetOnObjectNamed("sample-rate", "value", etk::toString(m_sampleRate));
|
|
ewol::parameterSetOnObjectNamed("frequency-slider", "max", etk::toString(m_sampleRate/2));
|
|
onCallbackStart();
|
|
return;
|
|
}
|
|
}
|
|
m_sampleRate = m_listSampleRate[0];
|
|
ewol::parameterSetOnObjectNamed("sample-rate", "value", etk::toString(m_sampleRate));
|
|
ewol::parameterSetOnObjectNamed("frequency-slider", "max", etk::toString(m_sampleRate/2));
|
|
onCallbackStart();
|
|
}
|
|
|
|
void appl::Windows::onCallbackTypeUp() {
|
|
for (int32_t iii=0; iii<m_listType.size(); ++iii) {
|
|
if (m_type == m_listType[iii]) {
|
|
iii++;
|
|
if (iii<m_listType.size()) {
|
|
m_type = m_listType[iii];
|
|
} else {
|
|
m_type = m_listType[0];
|
|
}
|
|
ewol::parameterSetOnObjectNamed("type", "value", etk::toString(m_type));
|
|
onCallbackStart();
|
|
return;
|
|
}
|
|
}
|
|
m_type = m_listType[0];
|
|
ewol::parameterSetOnObjectNamed("type", "value", etk::toString(m_type));
|
|
onCallbackStart();
|
|
}
|
|
|
|
void appl::Windows::onCallbackTypeLow() {
|
|
for (int32_t iii=0; iii<m_listType.size(); ++iii) {
|
|
if (m_type == m_listType[iii]) {
|
|
iii--;
|
|
if (iii>=0) {
|
|
m_type = m_listType[iii];
|
|
} else {
|
|
m_type = m_listType[m_listType.size()-1];
|
|
}
|
|
ewol::parameterSetOnObjectNamed("type", "value", etk::toString(m_type));
|
|
onCallbackStart();
|
|
return;
|
|
}
|
|
}
|
|
m_type = m_listType[0];
|
|
ewol::parameterSetOnObjectNamed("type", "value", etk::toString(m_type));
|
|
onCallbackStart();
|
|
}
|
|
|
|
|
|
void appl::Windows::onCallbackGain(const etk::String& _value) {
|
|
m_gain = etk::string_to_float(_value);
|
|
ewol::parameterSetOnObjectNamed("gain-slider", "value", etk::toString(_value));
|
|
APPL_INFO("Gain " << m_gain);
|
|
onCallbackStart();
|
|
}
|
|
|
|
void appl::Windows::onCallbackGainSlider(const float& _value) {
|
|
m_gain = _value;
|
|
ewol::parameterSetOnObjectNamed("gain", "value", etk::toString(_value));
|
|
APPL_INFO("Gain " << m_gain);
|
|
onCallbackStart();
|
|
}
|
|
|
|
|
|
|
|
void appl::Windows::onCallbackQuality(const etk::String& _value) {
|
|
m_quality = etk::string_to_float(_value);
|
|
ewol::parameterSetOnObjectNamed("quality-slider", "value", etk::toString(_value));
|
|
APPL_INFO("quality " << m_quality);
|
|
onCallbackStart();
|
|
}
|
|
|
|
void appl::Windows::onCallbackQualitySlider(const float& _value) {
|
|
m_quality = _value;
|
|
ewol::parameterSetOnObjectNamed("quality", "value", etk::toString(_value));
|
|
APPL_INFO("quality " << m_quality);
|
|
onCallbackStart();
|
|
}
|
|
|
|
|
|
void appl::Windows::onCallbackFrequency(const etk::String& _value) {
|
|
m_cutFrequency = etk::string_to_float(_value);
|
|
ewol::parameterSetOnObjectNamed("frequency-slider", "value", etk::toString(_value));
|
|
APPL_INFO("cut frequency " << m_cutFrequency);
|
|
onCallbackStart();
|
|
}
|
|
|
|
void appl::Windows::onCallbackFrequencySlider(const float& _value) {
|
|
m_cutFrequency = _value;
|
|
ewol::parameterSetOnObjectNamed("frequency", "value", etk::toString(_value));
|
|
APPL_INFO("cut frequency " << m_cutFrequency);
|
|
onCallbackStart();
|
|
}
|
|
|
|
#include <appl/debug.hpp>
|
|
#include <audio/algo/drain/BiQuad.hpp>
|
|
#include <audio/float_t.hpp>
|
|
#include <audio/int16_16_t.hpp>
|
|
|
|
void appl::Windows::onCallbackStart() {
|
|
APPL_INFO("start ");
|
|
int32_t iii = 10;
|
|
etk::Vector<audio::channel> map;
|
|
map.pushBack(audio::channel_frontCenter);
|
|
// audio::drain::IOFormatInterface format(map, audio::format_int16, m_sampleRate);
|
|
// audio::drain::IOFormatInterface format(map, audio::format_float, m_sampleRate);
|
|
// create biquad
|
|
audio::algo::drain::BiQuad<audio::float_t> bq;
|
|
// configure parameter
|
|
bq.setBiquad(m_type, m_cutFrequency, m_quality, m_gain, m_sampleRate);
|
|
etk::Vector<etk::Pair<float,float> > theory = bq.calculateTheory(m_sampleRate);
|
|
m_displayer->clear();
|
|
m_displayer->setValue(theory);
|
|
}
|
|
|
|
|
|
void appl::Windows::onCallbackStart16() {
|
|
APPL_INFO("start ");
|
|
// create biquad
|
|
audio::algo::drain::BiQuad<audio::int16_16_t> bq;
|
|
// configure parameter
|
|
bq.setBiquad(m_type, m_cutFrequency, m_quality, m_gain, m_sampleRate);
|
|
etk::Vector<etk::Pair<float,float> > pratic;
|
|
size_t len = 512;
|
|
for (size_t iii=1; iii < len; iii++) {
|
|
float freq = iii / (len - 1.0) * m_sampleRate / 2.0;
|
|
// To reset filter
|
|
bq.reset();
|
|
double m_phase = 0;
|
|
double baseCycle = 2.0*M_PI/double(m_sampleRate) * double(freq);
|
|
float gain = 0;
|
|
etk::Vector<audio::int16_16_t> data;
|
|
// create sinus
|
|
data.resize(16000, 0);
|
|
for (int32_t iii=0; iii<data.size(); iii++) {
|
|
data[iii] = cos(m_phase) * 32000;
|
|
m_phase += baseCycle;
|
|
if (m_phase >= 2*M_PI) {
|
|
m_phase -= 2*M_PI;
|
|
}
|
|
}
|
|
// process
|
|
int16_t* output = null;
|
|
void* outputVoid = null;
|
|
size_t outputNbChunk = 0;
|
|
APPL_SAVE_FILE_MACRO(int16_t,"aaa_test_INPUT_16.raw",&data[0],data.size());
|
|
bq.process(&data[0], &data[0], data.size(), 1, 1);
|
|
APPL_SAVE_FILE_MACRO(int16_t,"aaa_test_OUTPUT_16.raw",&data[0],data.size());
|
|
audio::int16_16_t value = 0;
|
|
for (size_t iii=800; iii<data.size()-200; ++iii) {
|
|
value = etk::max(value, data[iii]);
|
|
}
|
|
gain = 20.0 * etk::log10(value.getDouble()/32000.0);
|
|
APPL_VERBOSE("LEVEL " << iii << " out = " << value << " % : " << gain);
|
|
pratic.pushBack(etk::makePair<float, float>(float(freq),float(gain)));
|
|
}
|
|
m_displayer->setValue(pratic);
|
|
}
|
|
|
|
void appl::Windows::onCallbackStartFloat() {
|
|
APPL_INFO("start ");
|
|
// create biquad
|
|
audio::algo::drain::BiQuad<audio::float_t> bq;
|
|
// configure parameter
|
|
bq.setBiquad(m_type, m_cutFrequency, m_quality, m_gain, m_sampleRate);
|
|
etk::Vector<etk::Pair<float,float> > pratic;
|
|
size_t len = 512;
|
|
for (size_t iii=1; iii < len; iii++) {
|
|
float freq = iii / (len - 1.0) * m_sampleRate / 2.0;
|
|
// To reset filter
|
|
bq.reset();
|
|
double m_phase = 0;
|
|
double baseCycle = 2.0*M_PI/double(m_sampleRate) * double(freq);
|
|
float gain = 0;
|
|
etk::Vector<audio::float_t> data;
|
|
// create sinus
|
|
data.resize(16000, 0);
|
|
for (int32_t iii=0; iii<data.size(); iii++) {
|
|
data[iii] = cos(m_phase);
|
|
m_phase += baseCycle;
|
|
if (m_phase >= 2*M_PI) {
|
|
m_phase -= 2*M_PI;
|
|
}
|
|
}
|
|
APPL_SAVE_FILE_MACRO(float,"aaa_test_INPUT_F.raw",&data[0],data.size());
|
|
bq.process(&data[0], &data[0], data.size(), 1, 1);
|
|
APPL_SAVE_FILE_MACRO(float,"aaa_test_OUTPUT_F.raw",&data[0],data.size());
|
|
audio::float_t value = 0.0f;
|
|
for (size_t iii=800; iii<data.size()-200; ++iii) {
|
|
value = etk::max(value, data[iii]);
|
|
}
|
|
gain = 20.0 * etk::log10(value.getDouble()/1.0);
|
|
APPL_VERBOSE("LEVEL " << iii << " out = " << value << " % : " << gain);
|
|
pratic.pushBack(etk::makePair<float, float>(float(freq),float(gain)));
|
|
}
|
|
m_displayer->setValue(pratic);
|
|
}
|
|
|