[DEV] create a basic recorder

This commit is contained in:
Edouard DUPIN 2019-01-07 22:54:49 +01:00
parent 2bacaaeba8
commit 366a8d56c6
9 changed files with 795 additions and 0 deletions

Binary file not shown.

116
recoWord/appl/Windows.cpp Normal file
View File

@ -0,0 +1,116 @@
/** @file
* @author Edouard DUPIN
* @copyright 2019, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <ewol/ewol.hpp>
#include <appl/debug.hpp>
#include <appl/Windows.hpp>
#include <ewol/widget/Label.hpp>
#include <ewol/widget/Button.hpp>
#include <appl/widget/DataViewer.hpp>
#include <etk/tool.hpp>
appl::Windows::Windows() :
propertyCount(this, "count",
5,
"Number of time we restart a record"),
m_composer(null) {
addObjectType("appl::Windows");
propertyTitle.setDirectCheck("River IO viewer");
}
void appl::Windows::init() {
ewol::widget::Windows::init();
APPL_ERROR("Load Application");
etk::String composition = etk::String("");
composition += "<sizer mode='vert'>\n";
composition += " <sizer mode='hori' lock='true' min-size='10,10%'>\n";
composition += " <button name='bt-record' expand='false,true' fill='true'>\n";
composition += " <label>\n";
composition += " Start/Stop record\n";
composition += " </label>\n";
composition += " </button>\n";
composition += " <button name='bt-reset' expand='false,true' fill='true'>\n";
composition += " <label>\n";
composition += " Reset Currrent Record\n";
composition += " </label>\n";
composition += " </button>\n";
composition += " <label name='text-to-say' expand='true' fill='true'>\n";
composition += " Text to say ...\n";
composition += " </label>\n";
composition += " </sizer>\n";
composition += " <DataViewer name='displayer' expand='true' fill='true'/>\n";
composition += "</sizer>\n";
m_composer = ewol::widget::Composer::create();
if (m_composer == null) {
APPL_CRITICAL(" An error occured ... in the windows creatrion ...");
return;
}
APPL_ERROR("Composer LOAD [BEGIN]");
m_composer->loadFromString(composition);
setSubWidget(m_composer);
APPL_ERROR("Composer LOAD [ END ]");
subBind(ewol::widget::Button, "bt-record", signalPressed, sharedFromThis(), &appl::Windows::onCallbackRecord);
subBind(ewol::widget::Button, "bt-reset", signalPressed, sharedFromThis(), &appl::Windows::onCallbackGenerate);
subBind(appl::widget::DataViewer, "displayer", signalFinished, sharedFromThis(), &appl::Windows::onCallbackFinished);
next();
}
void appl::Windows::onCallbackFinished() {
APPL_INFO("Recording is finished");
ememory::SharedPtr<appl::widget::DataViewer> tmpDisp = ememory::dynamicPointerCast<appl::widget::DataViewer>(getSubObjectNamed("displayer"));
if (tmpDisp != null) {
tmpDisp->store("Edouard DUPIN", m_list[m_listPos], "FR_fr");
m_count++;
if (m_count >= propertyCount.get()) {
m_count = 0;
next();
} else {
updateCurentLabel();
tmpDisp->recordToggle();
}
}
}
void appl::Windows::onCallbackRecord() {
APPL_INFO("Start/stop Record of data");
ememory::SharedPtr<appl::widget::DataViewer> tmpDisp = ememory::dynamicPointerCast<appl::widget::DataViewer>(getSubObjectNamed("displayer"));
if (tmpDisp != null) {
tmpDisp->recordToggle();
}
}
void appl::Windows::onCallbackGenerate() {
ememory::SharedPtr<appl::widget::DataViewer> tmpDisp = ememory::dynamicPointerCast<appl::widget::DataViewer>(getSubObjectNamed("displayer"));
if (tmpDisp != null) {
tmpDisp->stop();
tmpDisp->reset();
tmpDisp->start();
}
}
void appl::Windows::next() {
m_listPos++;
if (m_listPos >= m_list.size()) {
m_listPos = 0;
return;
}
configureNewText(m_list[m_listPos]);
}
void appl::Windows::updateCurentLabel() {
auto elem = ememory::dynamicPointerCast<ewol::widget::Label>(getSubObjectNamed("text-to-say"));
if (elem == null) {
return;
}
elem->propertyValue.set("[" + etk::toString(m_count+1) + "/" + etk::toString(propertyCount.get()) + "] "+ m_textToSay);
}
void appl::Windows::configureNewText(const etk::String& _text) {
m_textToSay = _text;
updateCurentLabel();
onCallbackGenerate();
}

41
recoWord/appl/Windows.hpp Normal file
View File

@ -0,0 +1,41 @@
/** @file
* @author Edouard DUPIN
* @copyright 2019, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <ewol/widget/Windows.hpp>
#include <ewol/widget/Composer.hpp>
namespace appl {
class Windows : public ewol::widget::Windows {
public:
eproperty::Value<int32_t> propertyCount;
private:
ememory::SharedPtr<ewol::widget::Composer> m_composer;
protected:
Windows();
void init() override;
public:
DECLARE_FACTORY(Windows);
public: // callback functions
void onCallbackRecord();
void onCallbackGenerate();
void onCallbackFinished();
etk::String m_textToSay;
etk::Vector<etk::String> m_list = {
"",
//"bonjour", "ordinateur", "démarre", "arrête", "joue",
//"suivant", "suivante", "précédent", "précédente", "heure", "jour", "moi", "année",
"maître", "esclave",
"quelle", "quel", "comment", "pourquoi",
"zoo", "wagon", "téléphone", "télévision", "appel", "film", "musique", "vidéo", "annimation", "enfant", "adulte"};
int32_t m_listPos = 0;
int32_t m_count = 0;
void configureNewText(const etk::String& _text);
void next();
void updateCurentLabel();
};
}

13
recoWord/appl/debug.cpp Normal file
View File

@ -0,0 +1,13 @@
/** @file
* @author Edouard DUPIN
* @copyright 2019, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.hpp>
int32_t appl::getLogId() {
static int32_t g_val = elog::registerInstance("RecoWord");
return g_val;
}

39
recoWord/appl/debug.hpp Normal file
View File

@ -0,0 +1,39 @@
/** @file
* @author Edouard DUPIN
* @copyright 2019, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <elog/log.hpp>
namespace appl {
int32_t getLogId();
}
#define APPL_BASE(info,data) ELOG_BASE(appl::getLogId(),info,data)
#define APPL_PRINT(data) APPL_BASE(-1, data)
#define APPL_CRITICAL(data) APPL_BASE(1, data)
#define APPL_ERROR(data) APPL_BASE(2, data)
#define APPL_WARNING(data) APPL_BASE(3, data)
#ifdef DEBUG
#define APPL_INFO(data) APPL_BASE(4, data)
#define APPL_DEBUG(data) APPL_BASE(5, data)
#define APPL_VERBOSE(data) APPL_BASE(6, data)
#define APPL_TODO(data) APPL_BASE(4, "TODO : " << data)
#else
#define APPL_INFO(data) do { } while(false)
#define APPL_DEBUG(data) do { } while(false)
#define APPL_VERBOSE(data) do { } while(false)
#define APPL_TODO(data) do { } while(false)
#endif
#define APPL_ASSERT(cond,data) \
do { \
if (!(cond)) { \
APPL_CRITICAL(data); \
assert(!#cond); \
} \
} while (0)

140
recoWord/appl/main.cpp Normal file
View File

@ -0,0 +1,140 @@
/** @file
* @author Edouard DUPIN
* @copyright 2019, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <ewol/ewol.hpp>
#include <gale/context/commandLine.hpp>
#include <appl/debug.hpp>
#include <appl/Windows.hpp>
#include <ewol/object/Object.hpp>
#include <ewol/widget/Manager.hpp>
#include <ewol/context/Context.hpp>
#include <appl/widget/DataViewer.hpp>
#include <etk/theme/theme.hpp>
static const etk::String configurationRiver =
"{\n"
" microphone:{\n"
" io:'input',\n"
" map-on:{\n"
" interface:'auto',\n"
" name:'default',\n"
" },\n"
" frequency:48000,\n"
" channel-map:['front-left', 'front-right'],\n"
" type:'auto',\n"
" nb-chunk:1024\n"
" }\n"
"}\n";
class MainApplication : public ewol::context::Application {
public:
virtual void onCreate(ewol::Context& _context) override {
APPL_INFO(" == > CREATE ... (START) [" << gale::getBoardType() << "] (" << gale::getCompilationMode() << ") (BEGIN)");
for( int32_t iii=0 ; iii<_context.getCmd().size(); iii++) {
etk::String tmpppp = _context.getCmd().get(iii);
if ( tmpppp == "-h"
|| tmpppp == "--help") {
//APPL_PRINT(" --ctags=xxx c-flags-file-name" );
exit(0);
}
}
etk::theme::setName("COLOR", "color/white/");
_context.setSize(vec2(800, 600));
_context.setTitle("edn");
// select internal data for font ...
_context.getFontDefault().setUseExternal(true);
#ifdef __TARGET_OS__Android
_context.getFontDefault().set("FreeSerif", 19);
#else
_context.getFontDefault().set("FreeSerif;DejaVuSansMono",14);
#endif
// set the application icon ...
//_context.setIcon("DATA:///icon.png");
APPL_INFO("==> CREATE ... (END)");
}
void onStart(ewol::Context& _context) override {
APPL_INFO("==> START ... (BEGIN)");
// init internal global value
audio::river::initString(configurationRiver);
_context.setSize(vec2(800, 600));
// select internal data for font ...
_context.getFontDefault().setUseExternal(true);
_context.getFontDefault().setSize(19);
appl::widget::DataViewer::createManagerWidget(_context.getWidgetManager());
ememory::SharedPtr<ewol::widget::Windows> basicWindows = appl::Windows::create();
if (basicWindows == null) {
APPL_ERROR("Can not allocate the basic windows");
_context.exit(-1);
return;
}
// create the specific windows
_context.setWindows(basicWindows);
// add files
APPL_INFO("show list of files : ");
/*
for( int32_t iii=0 ; iii<_context.getCmd().size(); iii++) {
etk::String tmpppp = _context.getCmd().get(iii);
if (tmpppp.startWith("--ctags=") == true) {
etk::String name = tmpppp.extract(8);
APPL_INFO("Load ctag file : \"" << name << "\"" );
appl::setCtagsFileName(name);
} else if ( tmpppp == "-h"
|| tmpppp == "--help") {
// nothing to do ...
} else {
etk::Path file(tmpppp);
if (etk::path::isFile(file) == true) {
APPL_INFO("need load file : \"" << file << "\"" );
m_bufferManager->open(file);
} else if (etk::path::isDirectory(file) == true) {
etk::Vector<etk::Path> listOfFiles = etk::path::list(file, etk::path::LIST_FILE);
for (auto &it: listOfFiles) {
if (etk::path::isFile(it) == true) {
APPL_INFO("need load file : \"" << it << "\"" );
m_bufferManager->open(it);
}
}
}
}
}
*/
APPL_INFO("==> START ... (END)");
return;
}
void onStop(ewol::Context& _context) override {
APPL_INFO("==> STOP ... (START)");
APPL_INFO("==> STOP ... (END)");
}
void onKillDemand(ewol::Context& _context) override {
APPL_INFO("==> User demand kill ... (START)");
_context.exit(0);
APPL_INFO("==> User demand kill ... (END)");
}
};
/**
* @brief Main of the program (This can be set in every case, but it is not used in Andoid...).
* @param std IO
* @return std IO
*/
int main(int _argc, const char *_argv[]) {
// second possibility
return ewol::run(ETK_NEW(MainApplication), _argc, _argv);
}

View File

@ -0,0 +1,332 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <appl/debug.hpp>
#include <appl/widget/DataViewer.hpp>
#include <etk/tool.hpp>
#include <ewol/object/Manager.hpp>
static const int32_t nbSecondOffset = 3;
static const float nbSecondSilence = 1.1;
static const int32_t nbSecond = 10;
static const float nbSecondPreviousPost = 1;
static const float startThresholdLevel = 0.2;
static const float stopThresholdLevel = 0.1;
appl::widget::DataViewer::DataViewer() :
m_minVal(-1.0f),
m_maxVal(1.0f),
m_sampleRate(48000) {
addObjectType("appl::widget::DataViewer");
}
void appl::widget::DataViewer::init() {
ewol::Widget::init();
m_manager = audio::river::Manager::create("appl::widget::DataViewer");
m_data.resize(m_sampleRate*nbSecond*3, 0.0);
m_data.clear();
reset();
}
appl::widget::DataViewer::~DataViewer() {
}
void appl::widget::DataViewer::onDataReceived(const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
ethread::RecursiveLock lock(m_mutex);
if (_format != audio::format_float) {
APPL_ERROR("call wrong type ... (need int16_t)");
}
// get the curent power of the signal.
const float* data = static_cast<const float*>(_data);
for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) {
m_data.pushBack(data[iii]);
if (m_startAnalyse == false) {
m_detectStartPosition = m_data.size();
m_detectStopPosition = m_data.size() + 1;
if (data[iii] > startThresholdLevel) {
m_startAnalyse = true;
m_time = echrono::Clock::now();
m_silenceCount = 0;
}
} else {
if (data[iii] > stopThresholdLevel) {
m_silenceCount = 0;
m_detectStopPosition = m_data.size();
m_detectMax = etk::max(m_detectMax, etk::abs(data[iii]));
} else {
m_silenceCount++;
}
}
}
}
void appl::widget::DataViewer::start() {
ethread::RecursiveLock lock(m_mutex);
if (m_interface == null) {
reset();
//Get the generic input:
etk::Vector<audio::channel> channel;
channel.pushBack(audio::channel_frontLeft);
m_interface = m_manager->createInput(m_sampleRate,
channel,
audio::format_float,
"microphone");
if(m_interface == null) {
APPL_ERROR("null interface");
return;
}
// set callback mode ...
m_interface->setInputCallback([&](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataReceived(_data, _time, _nbChunk, _format, _frequency, _map);
});
// start the stream
m_interface->start();
m_PCH = getObjectManager().periodicCall.connect(this, &appl::widget::DataViewer::periodicCall);
}
}
void appl::widget::DataViewer::stop() {
ethread::RecursiveLock lock(m_mutex);
if (m_interface != null) {
m_interface->stop();
m_interface.reset();
m_PCH.disconnect();
}
}
void appl::widget::DataViewer::recordToggle() {
ethread::RecursiveLock lock(m_mutex);
if (m_interface == null) {
start();
} else {
stop();
}
}
void appl::widget::DataViewer::onDraw() {
m_draw.draw();
}
void appl::widget::DataViewer::onRegenerateDisplay() {
//!< Check if we really need to redraw the display, if not needed, we redraw the previous data ...
if (needRedraw() == false) {
return;
}
// remove previous data
m_draw.clear();
// set background
m_draw.setColor(etk::color::black);
m_draw.setPos(vec2(0,0));
m_draw.rectangleWidth(m_size);
ethread::RecursiveLock lock(m_mutex);
if (m_data.size() == 0) {
return;
}
// create n section for display:
int32_t nbSlot = m_size.x();
int32_t sizeSlot = m_size.x()/nbSlot;
etk::Vector<float> list;
//APPL_INFO("nbSlot : " << nbSlot << " sizeSlot=" << sizeSlot << " m_size=" << m_size);
list.resize(nbSlot,0.0f);
int32_t step = m_sampleRate*nbSecond/nbSlot;
for (size_t kkk=0; kkk<m_sampleRate*nbSecond; ++kkk) {
int32_t id = kkk/step;
if (id < list.size()) {
if (kkk < m_data.size()-m_startDisplayOffset) {
list[id] = etk::max(list[id], m_data[m_startDisplayOffset+kkk]);
}
}
}
// set all the line:
m_draw.setColor(etk::color::white);
m_draw.setThickness(1);
float origin = m_size.y()*0.5f;
float ratioY = m_size.y() / (m_maxVal - m_minVal);
float baseX = 0;
for (size_t iii=1; iii<list.size(); ++iii) {
m_draw.setPos(vec2(iii*sizeSlot, origin - ratioY*list[iii]));
m_draw.rectangle(vec2((iii+1)*sizeSlot, origin + ratioY*list[iii]));
if ((iii+1)*sizeSlot > m_size.x()) {
APPL_ERROR("wrong display position");
}
}
// detect sound
if (m_detectStopPosition > m_detectStartPosition) {
m_draw.setColor(etk::color::orange);
m_draw.setThickness(1);
float posStart = double(m_detectStartPosition-m_startDisplayOffset)/double(step)*sizeSlot;
float posStop = double(m_detectStopPosition-m_startDisplayOffset)/double(step)*sizeSlot;
m_draw.setPos(vec2(posStart, origin - ratioY*m_detectMax));
//m_draw.rectangle(vec2(posStop, origin + ratioY*m_detectMax));
//APPL_ERROR("draw position: " << posStart << " " << posStop);
m_draw.lineTo(vec2(posStart, origin + ratioY*m_detectMax));
m_draw.lineTo(vec2(posStop, origin + ratioY*m_detectMax));
m_draw.lineTo(vec2(posStop, origin - ratioY*m_detectMax));
m_draw.lineTo(vec2(posStart, origin - ratioY*m_detectMax));
}
// sound recorded
if (m_detectStopPosition > m_detectStartPosition) {
m_draw.setColor(etk::color::blue);
m_draw.setThickness(1);
float posStart = double(m_detectStartPosition-m_startDisplayOffset-nbSecondPreviousPost*m_sampleRate)/double(step)*sizeSlot;
float posStop = double(m_detectStopPosition-m_startDisplayOffset+nbSecondPreviousPost*m_sampleRate)/double(step)*sizeSlot;
m_draw.setPos(vec2(posStart, origin - ratioY*0.5));
m_draw.lineTo(vec2(posStart, origin + ratioY*0.5));
m_draw.lineTo(vec2(posStop, origin + ratioY*0.5));
m_draw.lineTo(vec2(posStop, origin - ratioY*0.5));
m_draw.lineTo(vec2(posStart, origin - ratioY*0.5));
}
// End of silence detection
if (m_detectStopPosition > m_detectStartPosition) {
m_draw.setColor(etk::color::red);
m_draw.setThickness(1);
float pos = double(m_detectStopPosition-m_startDisplayOffset+nbSecondSilence*m_sampleRate)/double(step)*sizeSlot;
m_draw.setPos(vec2(pos, origin - ratioY*0.5));
m_draw.lineTo(vec2(pos, origin + ratioY*0.5));
}
if (m_detectStopPosition <= m_detectStartPosition) {
m_draw.setColor(etk::color::red);
m_draw.setThickness(1);
// start threshold
m_draw.setPos(vec2(0, origin - ratioY*startThresholdLevel));
m_draw.lineTo(vec2(m_size.x(), origin - ratioY*startThresholdLevel));
m_draw.setPos(vec2(0, origin + ratioY*startThresholdLevel));
m_draw.lineTo(vec2(m_size.x(), origin + ratioY*startThresholdLevel));
} else {
m_draw.setColor(etk::color::red);
m_draw.setThickness(1);
float posStop = double(m_detectStopPosition-m_startDisplayOffset)/double(step)*sizeSlot;
// start threshold
m_draw.setPos(vec2(0, origin - ratioY*startThresholdLevel));
m_draw.lineTo(vec2(posStop, origin - ratioY*startThresholdLevel));
m_draw.setPos(vec2(0, origin + ratioY*startThresholdLevel));
m_draw.lineTo(vec2(posStop, origin + ratioY*startThresholdLevel));
// stop threshold
m_draw.setPos(vec2(posStop, origin - ratioY*stopThresholdLevel));
m_draw.lineTo(vec2(m_size.x(), origin - ratioY*stopThresholdLevel));
m_draw.setPos(vec2(posStop, origin + ratioY*stopThresholdLevel));
m_draw.lineTo(vec2(m_size.x(), origin + ratioY*stopThresholdLevel));
}
}
void appl::widget::DataViewer::periodicCall(const ewol::event::Time& _event) {
ethread::RecursiveLock lock(m_mutex);
int32_t nbSampleDelta = _event.getDeltaCall() * float(m_sampleRate);
if (m_startAnalyse == false) {
if (m_data.size() > m_sampleRate*nbSecondOffset) {
m_startDisplayOffset = m_data.size() - m_sampleRate*nbSecondOffset;
}
} else {
if (m_silenceCount > m_sampleRate*nbSecondSilence) {
stop();
signalFinished.emit();
}
}
markToRedraw();
}
void appl::widget::DataViewer::reset() {
ethread::RecursiveLock lock(m_mutex);
m_data.clear();
m_startDisplayOffset = 0;
m_startAnalyse = false;
m_silenceCount = 0;
m_detectStartPosition = 0;
m_detectStopPosition = 0;
m_detectMax = 0;
m_data.resize(m_sampleRate*nbSecondOffset, 0.0);
}
bool appl::widget::DataViewer::onEventInput(const ewol::event::Input& _event) {
APPL_INFO("event XXX " << _event);
vec2 relativePos = relativePosition(_event.getPos());
if ( _event.getType() == gale::key::type::mouse
&& _event.getId() == 4
&& _event.getStatus() == gale::key::status::down) {
m_startDisplayOffset += m_sampleRate * 0.25;
if(m_startDisplayOffset >= m_data.size()-m_sampleRate*nbSecondOffset) {
m_startDisplayOffset = m_data.size()- m_sampleRate*nbSecondOffset;
}
markToRedraw();
return true;
} else if ( _event.getType() == gale::key::type::mouse
&& _event.getId() == 5
&& _event.getStatus() == gale::key::status::down) {
m_startDisplayOffset -= m_sampleRate * 0.25;
if(m_startDisplayOffset<0) {
m_startDisplayOffset = 0;
}
markToRedraw();
return true;
}
return false;
}
void appl::widget::DataViewer::store(const etk::String& _userName, const etk::String& _value, const etk::String& _language) {
if (m_data.size() == 0) {
return;
}
etk::String baseName = _language + "_" + _userName + "_" + etk::toString(m_time.get());
// create the buffer
ejson::Document doc;
doc.add("user", ejson::String(_userName));
doc.add("value", ejson::String(_value));
doc.add("language", ejson::String(_language));
doc.add("time", ejson::Number(m_time.get()));
doc.add("audio_format", ejson::String("float"));
doc.add("audio_channel", ejson::Number(1));
doc.add("audio_sample_rate", ejson::Number(48000));
doc.add("audio_filename", ejson::String(baseName + ".raw"));
etk::String fileNameMetaData = "USER_DATA:///corpus/" + baseName + ".json";
doc.storeSafe(etk::Uri(fileNameMetaData));
APPL_WARNING("store: " << fileNameMetaData);
etk::String fileNameAudioFile = "USER_DATA:///corpus/" + baseName + ".raw";
int64_t posStart = int64_t(m_detectStartPosition)-nbSecondPreviousPost*m_sampleRate;
posStart = etk::avg(int64_t(0), posStart, int64_t(m_data.size()));
int64_t posStop = int64_t(m_detectStopPosition)+nbSecondPreviousPost*m_sampleRate;
posStop = etk::avg(int64_t(0), posStop, int64_t(m_data.size()));
{
ememory::SharedPtr<etk::io::Interface> fileIO = etk::uri::get(fileNameAudioFile);
if (fileIO->open(etk::io::OpenMode::Write) == false) {
return;
}
fileIO->write(&m_data[posStart], 1*audio::getFormatBytes(audio::format_float), (posStop-posStart));
fileIO->close();
}
APPL_WARNING("store: " << fileNameAudioFile);
}

View File

@ -0,0 +1,73 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <ewol/widget/Widget.hpp>
#include <ewol/compositing/Drawing.hpp>
#include <audio/river/river.hpp>
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
#include <ethread/MutexRecursive.hpp>
namespace appl {
namespace widget {
class DataViewer : public ewol::Widget {
public:
esignal::Signal<> signalFinished;
private:
mutable ethread::MutexRecursive m_mutex;
private:
ewol::compositing::Drawing m_draw; //!< drawing instance
protected:
//! @brief constructor
DataViewer();
void init() override;
public:
DECLARE_WIDGET_FACTORY(DataViewer, "DataViewer");
//! @brief destructor
virtual ~DataViewer();
bool onEventInput(const ewol::event::Input& _event) override;
void start();
void stop();
void recordToggle();
void reset();
private:
etk::Vector<float> m_data;
int32_t m_startDisplayOffset = 0;
bool m_startAnalyse = false;
int32_t m_silenceCount = 0;
float m_detectMax = 0;
int32_t m_detectStartPosition = 0;
int32_t m_detectStopPosition = 0;
echrono::Clock m_time;
private:
float m_minVal; //!< display minimum value
float m_maxVal; //!< display maximum value
public:
void onDraw() override;
void onRegenerateDisplay() override;
void store(const etk::String& _userName, const etk::String& _value, const etk::String& _language);
protected:
esignal::Connection m_PCH; //!< Periodic Call Handle to remove it when needed
/**
* @brief Periodic call to update grapgic display
* @param[in] _event Time generic event
*/
virtual void periodicCall(const ewol::event::Time& _event);
private:
ememory::SharedPtr<audio::river::Manager> m_manager;
ememory::SharedPtr<audio::river::Interface> m_interface;
void onDataReceived(const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map);
int32_t m_sampleRate;
};
}
}

View File

@ -0,0 +1,41 @@
#!/usr/bin/python
import lutin.debug as debug
import lutin.tools as tools
import os
def get_type():
return "BINARY"
def get_desc():
return "Simpleaudio IO viewer and test ..."
def get_licence():
return "MPL-2"
def get_compagny_type():
return "com"
def get_compagny_name():
return "atria-soft"
def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def configure(target, my_module):
my_module.add_extra_flags()
my_module.add_src_file([
'appl/debug.cpp',
'appl/main.cpp',
'appl/Windows.cpp',
'appl/widget/DataViewer.cpp',
])
my_module.add_depend(['ewol', 'audio-river'])
my_module.add_path(".")
# set the package properties :
my_module.set_pkg("SECTION", ["Development"])
my_module.set_pkg("PRIORITY", "optional")
my_module.add_pkg("RIGHT", "RECORD_AUDIO")
return True