From d274d793baef388bcfc94590fe7905f763d67eb2 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Sun, 9 Mar 2014 15:08:31 +0100 Subject: [PATCH] [DEV] basic decode stream --- eaudiofx/base/GeneratorFile.cpp | 69 ++++++++++++++++ eaudiofx/base/GeneratorFile.h | 9 ++- eaudiofx/base/GeneratorRtAudio.cpp | 1 + eaudiofx/base/GeneratorRtAudio.h | 2 + eaudiofx/base/GeneratorSignal.cpp | 39 ++++++++- eaudiofx/base/GeneratorSignal.h | 2 + eaudiofx/base/ReceiverRtAudio.cpp | 32 +++++--- eaudiofx/base/ReceiverRtAudio.h | 6 +- eaudiofx/core/Block.cpp | 58 +++++++++++++- eaudiofx/core/Block.h | 25 ++++-- eaudiofx/core/BlockDecoder.cpp | 122 ++++++++++++++++++++++++++++- eaudiofx/core/BlockDecoder.h | 8 ++ eaudiofx/core/BlockGenerator.cpp | 5 +- eaudiofx/core/BlockGenerator.h | 19 +++++ eaudiofx/core/BlockMeta.cpp | 73 ++++++++++++++++- eaudiofx/core/BlockMeta.h | 10 +++ eaudiofx/core/BlockReceiver.cpp | 3 +- eaudiofx/core/BlockReceiver.h | 18 +++++ eaudiofx/core/Buffer.cpp | 14 +++- eaudiofx/core/Buffer.h | 19 +++++ eaudiofx/core/BufferAudio.cpp | 8 ++ eaudiofx/core/BufferAudioRaw.cpp | 18 +++++ eaudiofx/core/BufferAudioRaw.h | 2 + eaudiofx/core/BufferStream.cpp | 38 ++++++++- eaudiofx/core/BufferStream.h | 24 +++++- eaudiofx/core/Processing.cpp | 18 ++++- eaudiofx/core/Processing.h | 6 ++ eaudiofx/core/audio.h | 1 + test/Windows.cpp | 97 +++++++++++++++++------ 29 files changed, 687 insertions(+), 59 deletions(-) diff --git a/eaudiofx/base/GeneratorFile.cpp b/eaudiofx/base/GeneratorFile.cpp index 9cad170..2d65910 100644 --- a/eaudiofx/base/GeneratorFile.cpp +++ b/eaudiofx/base/GeneratorFile.cpp @@ -6,6 +6,75 @@ * @license BSD v3 (see license file) */ +#include +#include +#include #include + +eaudiofx::GeneratorFile::GeneratorFile(void) : + m_file(NULL) { + // set output : + m_io.insert( + std::pair( + "out", + eaudiofx::Block::IOProperty( + eaudiofx::Block::ioOutput, + "{ type:'bitstream', format:'file' }", + new eaudiofx::BufferStream(*this) + ) ) ); + +} + +int32_t eaudiofx::GeneratorFile::pull(double _currentTime, int32_t _request, float _timeout) { + auto it = m_io.find("out"); + if (it == m_io.end()) { + EAUDIOFX_WARNING("request to pull data with no output !!!"); + return eaudiofx::ERR_FAIL; + } + eaudiofx::BufferStream* buffer = dynamic_cast(it->second.m_buffer); + //EAUDIOFX_ERROR("Generate data, request : " << _request << " at time : " << _currentTime); + if (buffer == NULL) { + // !! impossible case => a buffer can not be removed ... + EAUDIOFX_ERROR("Buffer has been removed... OR change type ..."); + return eaudiofx::ERR_FAIL; + } + //request outpuffer needed size : + buffer->setProperty(_request); + uint8_t* data = buffer->getData(); + if (m_file == NULL) { + return eaudiofx::ERR_FAIL; + } + int64_t nbRead = m_file->fileRead(data, sizeof(uint8_t), _request); + buffer->setAvaillableSize(nbRead); + return eaudiofx::ERR_NONE; +} + + +int32_t eaudiofx::GeneratorFile::init(void) { + m_file = new etk::FSNode("./menu.wav"); + if (m_file == NULL) { + EAUDIOFX_ERROR("Can not allocate the input file ..."); + return eaudiofx::ERR_FAIL; + } + if (m_file->fileOpenRead() == false) { + EAUDIOFX_ERROR("Can not open the input file ..."); + return eaudiofx::ERR_FAIL; + } + +} + + +int32_t eaudiofx::GeneratorFile::unInit(void) { + if (m_file == NULL) { + return eaudiofx::ERR_NONE; + } + if (m_file->fileClose() == false) { + EAUDIOFX_ERROR("Can not close the input file ..."); + return eaudiofx::ERR_FAIL; + } + +} + + diff --git a/eaudiofx/base/GeneratorFile.h b/eaudiofx/base/GeneratorFile.h index 1525c3c..8bf3552 100644 --- a/eaudiofx/base/GeneratorFile.h +++ b/eaudiofx/base/GeneratorFile.h @@ -10,12 +10,19 @@ #define __EAUDIOFX_GENERATOR_FILE_H__ #include +#include namespace eaudiofx { class GeneratorFile : public eaudiofx::BlockGenerator { public: - GeneratorFile(void) {}; + GeneratorFile(void); virtual ~GeneratorFile(void) {}; + protected: + etk::FSNode* m_file; + public: // herieted function : + virtual int32_t pull(double _currentTime, int32_t _request, float _timeout); + virtual int32_t init(void); + virtual int32_t unInit(void); }; }; diff --git a/eaudiofx/base/GeneratorRtAudio.cpp b/eaudiofx/base/GeneratorRtAudio.cpp index 255d880..e235f9e 100644 --- a/eaudiofx/base/GeneratorRtAudio.cpp +++ b/eaudiofx/base/GeneratorRtAudio.cpp @@ -11,6 +11,7 @@ #include eaudiofx::GeneratorRtAudio::GeneratorRtAudio(void) { + setLive(true); // set output : m_io.insert( std::pair( diff --git a/eaudiofx/base/GeneratorRtAudio.h b/eaudiofx/base/GeneratorRtAudio.h index 4e1ad45..c8ecf27 100644 --- a/eaudiofx/base/GeneratorRtAudio.h +++ b/eaudiofx/base/GeneratorRtAudio.h @@ -16,6 +16,8 @@ namespace eaudiofx { public: GeneratorRtAudio(void); virtual ~GeneratorRtAudio(void) {}; + public: + int32_t pull(double _currentTime, int32_t _request, float _timeout); }; }; diff --git a/eaudiofx/base/GeneratorSignal.cpp b/eaudiofx/base/GeneratorSignal.cpp index 83a35bf..df9d5f2 100644 --- a/eaudiofx/base/GeneratorSignal.cpp +++ b/eaudiofx/base/GeneratorSignal.cpp @@ -6,9 +6,10 @@ * @license BSD v3 (see license file) */ +#include #include #include - +#include eaudiofx::GeneratorSignal::GeneratorSignal(void) : @@ -19,9 +20,43 @@ eaudiofx::GeneratorSignal::GeneratorSignal(void) : "out", eaudiofx::Block::IOProperty( eaudiofx::Block::ioOutput, - "", + "{ type:'audio', compression:'raw', frequency:48000, channel:2, format:'float' }", new eaudiofx::BufferAudioRaw(*this, 48000, 2) ) ) ); } +int32_t eaudiofx::GeneratorSignal::pull(double _currentTime, int32_t _request, float _timeout) { + auto it = m_io.find("out"); + if (it == m_io.end()) { + EAUDIOFX_WARNING("request to pull data with no output !!!"); + return eaudiofx::ERR_FAIL; + } + eaudiofx::BufferAudioRaw* buffer = dynamic_cast(it->second.m_buffer); + //EAUDIOFX_ERROR("Generate data, request : " << _request << " at time : " << _currentTime); + if (buffer == NULL) { + // !! impossible case => a buffer can not be removed ... + EAUDIOFX_ERROR("Buffer has been removed... OR change type ..."); + return eaudiofx::ERR_FAIL; + } + //request outpuffer needed size : + buffer->setProperty(48000, 2, _request); + float* data = buffer->getData(); + + for (int32_t iii=0; iii<_request; ++iii) { + for (int32_t jjj=0; jjj<2; ++jjj) { + *data++ = cos(m_phase)*0.5f; + } + m_phase += 0.1; + if (m_phase > 4.0*M_PI) { + m_phase -= 4.0*M_PI; + } + } + /* + FILE* plopppp = fopen("plop.raw", "a"); + fwrite(buffer->getData(), sizeof(float), _request*2, plopppp); + fflush(plopppp); + fclose(plopppp); + */ + return eaudiofx::ERR_NONE; +} \ No newline at end of file diff --git a/eaudiofx/base/GeneratorSignal.h b/eaudiofx/base/GeneratorSignal.h index 39db29f..96f8ce5 100644 --- a/eaudiofx/base/GeneratorSignal.h +++ b/eaudiofx/base/GeneratorSignal.h @@ -18,6 +18,8 @@ namespace eaudiofx { public: GeneratorSignal(void); virtual ~GeneratorSignal(void) {}; + public: + int32_t pull(double _currentTime, int32_t _request, float _timeout); }; }; diff --git a/eaudiofx/base/ReceiverRtAudio.cpp b/eaudiofx/base/ReceiverRtAudio.cpp index 80656a2..2dba898 100644 --- a/eaudiofx/base/ReceiverRtAudio.cpp +++ b/eaudiofx/base/ReceiverRtAudio.cpp @@ -38,39 +38,53 @@ int32_t eaudiofx::ReceiverRtAudio::needData(float* _outputBuffer, size_t _nBufferFrames, double _streamTime, RtAudioStreamStatus _status) { - // TODO: reset output: // Request block input: - int32_t nbSampleOne = _nBufferFrames/2; - int32_t ret = eaudiofx::Block::pull(_streamTime, nbSampleOne, (float)nbSampleOne/48000.0f); + int32_t ret = eaudiofx::Block::pull(_streamTime, _nBufferFrames, (float)_nBufferFrames/48000.0f); if (ret != eaudiofx::ERR_NONE) { + EAUDIOFX_ERROR("wan not get data ..."); return -1; } auto it = m_io.find("in"); if (it == m_io.end()) { + EAUDIOFX_WARNING("Request an un-existing IO"); + return 0; + } + eaudiofx::BufferAudioRaw* buffer = dynamic_cast(it->second.m_buffer); + if (buffer == NULL) { EAUDIOFX_WARNING("no IO plugged"); return 0; } - // TODO : Do the copy of data ... + float* data = buffer->getData(); + for (int32_t iii=0; iii<_nBufferFrames*2; ++iii) { + _outputBuffer[iii] = data[iii]*0.05f; + } + /* + FILE* plopppp = fopen("plopout.raw", "a"); + fwrite(_outputBuffer, sizeof(float), _nBufferFrames, plopppp); + fflush(plopppp); + fclose(plopppp); + */ return 0; } eaudiofx::ReceiverRtAudio::ReceiverRtAudio(void) { + setLive(true); // set output : m_io.insert( std::pair( "in", eaudiofx::Block::IOProperty( eaudiofx::Block::ioInput, - "", - new eaudiofx::BufferAudioRaw(*this, 48000, 2) + "{ type:'audio', compression:'raw', frequency:48000, channel:2, format:'float' }", + NULL ) ) ); }; -int32_t eaudiofx::ReceiverRtAudio::Init(void) { +int32_t eaudiofx::ReceiverRtAudio::init(void) { EAUDIOFX_DEBUG("Create RTAudio generator ..."); if ( m_dac.getDeviceCount() < 1 ) { EAUDIOFX_ERROR("No audio devices found!"); @@ -84,7 +98,7 @@ int32_t eaudiofx::ReceiverRtAudio::Init(void) { unsigned int bufferFrames = 256; try { EAUDIOFX_DEBUG("OPEN Stream ..."); - m_dac.openStream( &m_parameters, NULL, RTAUDIO_FLOAT32, 48000, &bufferFrames, &rtAudioCallBack, (void *)this ); + m_dac.openStream(&m_parameters, NULL, RTAUDIO_FLOAT32, 48000, &bufferFrames, &rtAudioCallBack, (void *)this); m_dac.startStream(); }catch ( RtError& e ) { e.printMessage(); @@ -93,7 +107,7 @@ int32_t eaudiofx::ReceiverRtAudio::Init(void) { return eaudiofx::ERR_NONE; }; -int32_t eaudiofx::ReceiverRtAudio::UnInit(void) { +int32_t eaudiofx::ReceiverRtAudio::unInit(void) { try { EAUDIOFX_DEBUG("STOP Stream ..."); // Stop the stream diff --git a/eaudiofx/base/ReceiverRtAudio.h b/eaudiofx/base/ReceiverRtAudio.h index 28a948c..5cea9f6 100644 --- a/eaudiofx/base/ReceiverRtAudio.h +++ b/eaudiofx/base/ReceiverRtAudio.h @@ -30,9 +30,9 @@ namespace eaudiofx { ReceiverRtAudio(void); virtual ~ReceiverRtAudio(void) {}; public: // herieted function : - virtual int32_t Init(void); - virtual int32_t UnInit(void); - private: + virtual int32_t init(void); + virtual int32_t unInit(void); + protected: RtAudio m_dac; RtAudio::StreamParameters m_parameters; }; diff --git a/eaudiofx/core/Block.cpp b/eaudiofx/core/Block.cpp index c0bc324..061b478 100644 --- a/eaudiofx/core/Block.cpp +++ b/eaudiofx/core/Block.cpp @@ -39,6 +39,24 @@ eaudiofx::Block::~Block(void) { } } +int32_t eaudiofx::Block::pull(double _currentTime, int32_t _request, float _timeout) { + int32_t ret = eaudiofx::ERR_NONE; + for (auto &it : m_io) { + if (it.second.m_buffer == NULL) { + continue; + } + if ( it.second.m_type != eaudiofx::Block::ioInput + && it.second.m_type != eaudiofx::Block::ioParameter) { + continue; + } + if (it.second.m_buffer->pull(_currentTime, _request, _timeout) != eaudiofx::ERR_NONE) { + ret = eaudiofx::ERR_FAIL; + } + } + return ret; +}; + + void eaudiofx::Block::subRemoveBuffer(const eaudiofx::Buffer* _buffer) { if (_buffer == NULL) { return; @@ -51,6 +69,33 @@ void eaudiofx::Block::subRemoveBuffer(const eaudiofx::Buffer* _buffer) { } void eaudiofx::Block::onRemoveBuffer(const eaudiofx::Buffer* _buffer) { + unLinkBuffer(_buffer); +} + +int32_t eaudiofx::Block::linkBuffer(eaudiofx::Buffer* _buffer, const std::string& _name) { + if ( _buffer == NULL + || _name.size() == 0) { + return eaudiofx::ERR_INPUT_NULL; + } + for (auto &it : m_io) { + if (it.first == _name) { + if (it.second.m_type == ioOutput) { + EAUDIOFX_ERROR("[" << getUID() << "Can not overwrite output buffer..."); + return eaudiofx::ERR_FORBIDEN; + } + it.second.m_buffer = _buffer; + // TODO : Negiciate ??? + return eaudiofx::ERR_NONE; + } + } + return eaudiofx::ERR_NO_IO; +} + + +int32_t eaudiofx::Block::unLinkBuffer(const eaudiofx::Buffer* _buffer) { + if (_buffer == NULL) { + return eaudiofx::ERR_INPUT_NULL; + } // For every buffer, remove internal reference... for (auto &it : m_io) { if (it.second.m_buffer == _buffer) { @@ -59,14 +104,20 @@ void eaudiofx::Block::onRemoveBuffer(const eaudiofx::Buffer* _buffer) { } } -int32_t eaudiofx::Block::linkBuffer(eaudiofx::Buffer* _buffer, const std::string& _name) { +int32_t eaudiofx::Block::unLinkBuffer(const std::string& _name) { + if (_name.size() == 0) { + return eaudiofx::ERR_INPUT_NULL; + } for (auto &it : m_io) { if (it.first == _name) { if (it.second.m_type == ioOutput) { EAUDIOFX_ERROR("[" << getUID() << "Can not overwrite output buffer..."); return eaudiofx::ERR_FORBIDEN; } - it.second.m_buffer = _buffer; + it.second.m_buffer = NULL; + if (it.second.m_type == ioParameter) { + // TODO : Re-create the basic input buffer ... (Or duplicate the last one??? + } return eaudiofx::ERR_NONE; } } @@ -74,6 +125,9 @@ int32_t eaudiofx::Block::linkBuffer(eaudiofx::Buffer* _buffer, const std::string } int32_t eaudiofx::Block::getBuffer(eaudiofx::Buffer*& _buffer, const std::string& _name) { + if (_name.size() == 0) { + return eaudiofx::ERR_INPUT_NULL; + } for (auto &it : m_io) { if (it.first == _name) { if (it.second.m_type == ioInput) { diff --git a/eaudiofx/core/Block.h b/eaudiofx/core/Block.h index 2762be5..12d4e6a 100644 --- a/eaudiofx/core/Block.h +++ b/eaudiofx/core/Block.h @@ -109,14 +109,14 @@ namespace eaudiofx { * @brief Init the block with the properties * @return A generic error. */ - virtual int32_t Init(void) { + virtual int32_t init(void) { return eaudiofx::ERR_NONE; }; /** * @brief UnInit the block with the properties * @return A generic error. */ - virtual int32_t UnInit(void) { + virtual int32_t unInit(void) { return eaudiofx::ERR_NONE; }; /** @@ -126,9 +126,7 @@ namespace eaudiofx { * @param[in] _timeout system time to be obsolet (for realTime streaming) (-1 for no realTime streaming) * @return generic error */ - virtual int32_t pull(double _currentTime, int32_t _request, float _timeout) { - return eaudiofx::ERR_NONE; - }; + virtual int32_t pull(double _currentTime, int32_t _request, float _timeout); /** * @brief Get The total stream size (in byte for streaming byte element, in second for time streaming) * @param[out] _value Get total streaming time (-1 for unknown) @@ -205,6 +203,7 @@ namespace eaudiofx { } }; std::map m_io; //!< All IO in the Block + public: /** * @brief Link the provided buffer to the IO name. * @param[in] _buffer Pointer on the buffer to link. @@ -212,6 +211,15 @@ namespace eaudiofx { * @return A generic error. */ virtual int32_t linkBuffer(eaudiofx::Buffer* _buffer, const std::string& _name); + /** + * @brief Un link a speific buffer to the IO name. + * @param[in] _buffer Pointer on the buffer to unlink. + * @param[in] _name Name of the IO to unlink; + * @return A generic error. + */ + virtual int32_t unLinkBuffer(const eaudiofx::Buffer* _buffer); + //! @previous + virtual int32_t unLinkBuffer(const std::string& _name); /** * @brief Request a buffer pointer on the IO named. * @param[out] _buffer Pointer on the buffer to link. @@ -219,6 +227,13 @@ namespace eaudiofx { * @return A generic error. */ virtual int32_t getBuffer(eaudiofx::Buffer*& _buffer, const std::string& _name); + /** + * @brief Update the IO property + * @return A generic error. + */ + virtual int32_t UpdateIOProperty(void) { + return eaudiofx::ERR_NONE; + }; }; }; diff --git a/eaudiofx/core/BlockDecoder.cpp b/eaudiofx/core/BlockDecoder.cpp index 5ed73fc..515a436 100644 --- a/eaudiofx/core/BlockDecoder.cpp +++ b/eaudiofx/core/BlockDecoder.cpp @@ -6,10 +6,130 @@ * @license BSD v3 (see license file) */ +#include +#include +#include +#include #include -eaudiofx::BlockDecoder::BlockDecoder(void) { +eaudiofx::BlockDecoder::BlockDecoder(void) : + m_nbSampleIn(0) { setType(eaudiofx::blockTypeDecoder); + // set input : + m_io.insert( + std::pair( + "in", + eaudiofx::Block::IOProperty( + eaudiofx::Block::ioInput, + "{ type:'bitstream', format:'file', extention:['wav','ogg'] }" + ) ) ); + // set output : + m_io.insert( + std::pair( + "out", + eaudiofx::Block::IOProperty( + eaudiofx::Block::ioOutput, + "{ type:'audio', compression:'raw', frequency:48000, channel:2, format:'float' }", + new eaudiofx::BufferAudioRaw(*this, 48000, 2, 4096) + ) ) ); } + +int32_t eaudiofx::BlockDecoder::pull(double _currentTime, int32_t _request, float _timeout) { + + auto itOut = m_io.find("out"); + if (itOut == m_io.end()) { + EAUDIOFX_WARNING("request to pull data with no output !!!"); + return eaudiofx::ERR_FAIL; + } + auto itIn = m_io.find("in"); + if (itIn == m_io.end()) { + EAUDIOFX_WARNING("request to pull data with no Input !!!"); + return eaudiofx::ERR_FAIL; + } + eaudiofx::BufferAudioRaw* bufferOut = dynamic_cast(itOut->second.m_buffer); + if (bufferOut == NULL) { + // !! impossible case => a buffer can not be removed ... + EAUDIOFX_ERROR("Buffer has been removed... OR change type ..."); + return eaudiofx::ERR_FAIL; + } + //request outpuffer needed size : + bufferOut->setProperty(48000, 2, _request); + float* dataOut = bufferOut->getData(); + int32_t offset = 0; + EAUDIOFX_DEBUG("Request data : " << (_request*2) ); + while (1) { + int32_t nbSampleToCopy = etk_min(m_nbSampleIn, _request*2 - offset); + if (m_nbSampleIn > 0) { + // no pull needed ==> just copy data to output ... + for (int32_t iii=0; iii < nbSampleToCopy; ++iii) { + dataOut[offset + iii] = m_tmpBuffer[iii]; + } + offset += nbSampleToCopy; + m_nbSampleIn -= nbSampleToCopy; + if (m_nbSampleIn > 0) { + // some data in the buffer ==> move it ... + for (int32_t iii=0; iii < MAX_DATA_IN_BUFFER-nbSampleToCopy; ++iii) { + m_tmpBuffer[iii] = m_tmpBuffer[nbSampleToCopy+iii]; + } + } + if (offset == _request*2) { + FILE* plopppp = fopen("plopDEC.raw", "a"); + fwrite(dataOut, sizeof(float), _request*2, plopppp); + fflush(plopppp); + fclose(plopppp); + // putput have enought data + return eaudiofx::ERR_NONE; + } + } + + // Request block input: + int32_t ret = eaudiofx::Block::pull(_currentTime, 256, _timeout); + + if (ret != eaudiofx::ERR_NONE) { + EAUDIOFX_ERROR("can not get data ..."); + return -1; + } + eaudiofx::BufferStream* bufferIn = dynamic_cast(itIn->second.m_buffer); + if (bufferIn == NULL) { + // !! impossible case => a buffer can not be removed ... + EAUDIOFX_ERROR("Buffer has been removed... OR change type ..."); + return eaudiofx::ERR_FAIL; + } + if (bufferIn->setAvaillableSize() == 0) { + for (size_t iii=0; iii<64; ++iii) { + m_tmpBuffer[m_nbSampleIn] = 0.0f; + m_nbSampleIn++; + m_tmpBuffer[m_nbSampleIn] = 0.0f; + m_nbSampleIn++; + } + } + if (true == true) { + // wav input : + // TODO : Do it better ... + size_t provideData = bufferIn->setAvaillableSize(); + int16_t* inputData = (int16_t*)bufferIn->getData(); + for (size_t iii=0; iii - - -eaudiofx::BlockGenerator::BlockGenerator(void) { +eaudiofx::BlockGenerator::BlockGenerator(void) : + m_isLive(false) { setType(eaudiofx::blockTypeGenerator); } diff --git a/eaudiofx/core/BlockGenerator.h b/eaudiofx/core/BlockGenerator.h index ffac393..fd3e38a 100644 --- a/eaudiofx/core/BlockGenerator.h +++ b/eaudiofx/core/BlockGenerator.h @@ -16,6 +16,25 @@ namespace eaudiofx { public: BlockGenerator(void); virtual ~BlockGenerator(void) {}; + private: + bool m_isLive; //!< a generator mark as a live element is manage by an external event system like IO interuption + public: + /** + * @brief Get if the genertor is a live stream + * @return true This is a live stream + * @return false This is not a live stream + */ + bool getLive(void) { + return m_isLive; + } + /** + * @brief Set the new status of live stream. + * @param[in] _isLive status requested. + */ + void setLive(bool _isLive=true) { + m_isLive = _isLive; + } + }; }; diff --git a/eaudiofx/core/BlockMeta.cpp b/eaudiofx/core/BlockMeta.cpp index 324cc2b..b9e8a5b 100644 --- a/eaudiofx/core/BlockMeta.cpp +++ b/eaudiofx/core/BlockMeta.cpp @@ -28,6 +28,21 @@ eaudiofx::BlockMeta::~BlockMeta(void) { m_list.clear(); } +eaudiofx::Block* eaudiofx::BlockMeta::getBlock(const std::string& _name) { + if (_name.size() == 0) { + return NULL; + } + for (auto &it : m_list) { + if (it == NULL) { + continue; + } + if (it->getName() == _name) { + return it; + } + } + return NULL; +} + int32_t eaudiofx::BlockMeta::addBlock(eaudiofx::Block* _block) { if (_block == NULL) { EAUDIOFX_ERROR("[" << getUID() << "] Add NULL block"); @@ -68,8 +83,28 @@ int32_t eaudiofx::BlockMeta::linkBlock(const std::string& _generatorBlockName, const std::string& _generatorIoName, const std::string& _receiverBlockName, const std::string& _receiverIoName) { - - return eaudiofx::ERR_NOT_IMPLEMENTED; + eaudiofx::Block* itGenerator = getBlock(_generatorBlockName); + eaudiofx::Block* itReceiver = getBlock(_receiverBlockName); + if ( itGenerator == NULL + || itReceiver == NULL) { + EAUDIOFX_ERROR("Can not link : '" << _generatorBlockName << "' and '" << _receiverBlockName << "' one element does not exist ..."); + return eaudiofx::ERR_FAIL; + } + eaudiofx::Buffer* outputBuffer = NULL; + if (itGenerator->getBuffer(outputBuffer, _generatorIoName) != eaudiofx::ERR_NONE) { + EAUDIOFX_ERROR("Can not get buffer : '" << _generatorBlockName << "':'" << _generatorIoName << "'"); + return eaudiofx::ERR_FAIL; + } + if (outputBuffer == NULL) { + EAUDIOFX_ERROR("Get NULL buffer : '" << _generatorBlockName << "':'" << _generatorIoName << "'"); + return eaudiofx::ERR_FAIL; + } + if (itReceiver->linkBuffer(outputBuffer, _receiverIoName) != eaudiofx::ERR_NONE) { + EAUDIOFX_ERROR("Can not Link buffer : '" << _receiverBlockName << "':'" << _receiverIoName << "'"); + return eaudiofx::ERR_FAIL; + } + EAUDIOFX_INFO("Link : " << _generatorBlockName << ":" << _generatorIoName << " and " << _receiverBlockName << ":" << _receiverIoName); + return eaudiofx::ERR_NONE; } int32_t eaudiofx::BlockMeta::openFile(const std::string& _fileName) { @@ -82,3 +117,37 @@ int32_t eaudiofx::BlockMeta::openStream(const std::string& _stream) { return eaudiofx::ERR_NOT_IMPLEMENTED; } + +int32_t eaudiofx::BlockMeta::init(void) { + EAUDIOFX_INFO("[" << getUID() << "]Init Meta block : '" << getName() << "'"); + int32_t ret = eaudiofx::ERR_NONE; + for (auto &it : m_list) { + if (it == NULL) { + continue; + } + if (it->init() != eaudiofx::ERR_NONE) { + ret = eaudiofx::ERR_FAIL; + } + } + if (ret != eaudiofx::ERR_NONE) { + EAUDIOFX_WARNING("Pb when init the Meta-block '" << getName() << "' "); + } + return ret; +}; + +int32_t eaudiofx::BlockMeta::unInit(void) { + int32_t ret = eaudiofx::ERR_NONE; + for (auto &it : m_list) { + if (it == NULL) { + continue; + } + if (it->unInit() != eaudiofx::ERR_NONE) { + ret = eaudiofx::ERR_FAIL; + } + } + if (ret != eaudiofx::ERR_NONE) { + EAUDIOFX_WARNING("Pb when un-init the Meta-block '" << getName() << "' "); + } + return ret; +}; + diff --git a/eaudiofx/core/BlockMeta.h b/eaudiofx/core/BlockMeta.h index edf48b2..056e456 100644 --- a/eaudiofx/core/BlockMeta.h +++ b/eaudiofx/core/BlockMeta.h @@ -19,6 +19,13 @@ namespace eaudiofx { virtual ~BlockMeta(void); private: std::vector m_list; //!< list of all block to process. + protected: + /** + * @brief Get a pointer on a specific block. + * @param[in] _name Name of the block. + * @return generic error + */ + eaudiofx::Block* getBlock(const std::string& _name); public: /** * @brief Add a block in the Meta-block @@ -72,6 +79,9 @@ namespace eaudiofx { * @return generic error */ int32_t openStream(const std::string& _stream); + public: // herited function + virtual int32_t init(void); + virtual int32_t unInit(void); }; }; diff --git a/eaudiofx/core/BlockReceiver.cpp b/eaudiofx/core/BlockReceiver.cpp index 7984419..0170bd6 100644 --- a/eaudiofx/core/BlockReceiver.cpp +++ b/eaudiofx/core/BlockReceiver.cpp @@ -8,7 +8,8 @@ #include -eaudiofx::BlockReceiver::BlockReceiver(void) { +eaudiofx::BlockReceiver::BlockReceiver(void) : + m_isLive(false) { setType(eaudiofx::blockTypeReceiver); } diff --git a/eaudiofx/core/BlockReceiver.h b/eaudiofx/core/BlockReceiver.h index b1b9307..45359a4 100644 --- a/eaudiofx/core/BlockReceiver.h +++ b/eaudiofx/core/BlockReceiver.h @@ -16,6 +16,24 @@ namespace eaudiofx { public: BlockReceiver(void); virtual ~BlockReceiver(void) {}; + private: + bool m_isLive; //!< a generator mark as a live element is manage by an external event system like IO interuption + public: + /** + * @brief Get if the genertor is a live stream + * @return true This is a live stream + * @return false This is not a live stream + */ + bool getLive(void) { + return m_isLive; + } + /** + * @brief Set the new status of live stream. + * @param[in] _isLive status requested. + */ + void setLive(bool _isLive=true) { + m_isLive = _isLive; + } }; }; diff --git a/eaudiofx/core/Buffer.cpp b/eaudiofx/core/Buffer.cpp index c5b6cbc..8806c51 100644 --- a/eaudiofx/core/Buffer.cpp +++ b/eaudiofx/core/Buffer.cpp @@ -13,6 +13,16 @@ eaudiofx::Buffer::Buffer(eaudiofx::Block& _parent) : m_parent(_parent), m_timestamp(0), - m_time(0) { + m_time(0), + m_negociated(false) { -} \ No newline at end of file +} + + +int32_t eaudiofx::Buffer::pull(double _currentTime, int32_t _request, float _timeout) { + if (_currentTime > m_timestamp) { + return m_parent.pull(_currentTime, _request, _timeout); + } + return eaudiofx::ERR_NONE; +} + diff --git a/eaudiofx/core/Buffer.h b/eaudiofx/core/Buffer.h index bcd3eaa..31635ad 100644 --- a/eaudiofx/core/Buffer.h +++ b/eaudiofx/core/Buffer.h @@ -23,6 +23,25 @@ namespace eaudiofx { protected: double m_timestamp; //!< current buffer time; double m_time; //!< current buffer data time size; + public: + int32_t pull(double _currentTime, int32_t _request, float _timeout); + protected: + bool m_negociated; //!< negiciation status. + public: + /** + * @brief Get if the IO buffer status is negociated. + * @return true if buffer is negosiated. + * @return false Not negociated. + */ + bool isNegociated(void) { + return m_negociated; + } + /** + * @brief uset the negociation status of the buffer. + */ + void requestNewNegociation(void) { + m_negociated = false; + } }; }; diff --git a/eaudiofx/core/BufferAudio.cpp b/eaudiofx/core/BufferAudio.cpp index 4a926f8..3bce357 100644 --- a/eaudiofx/core/BufferAudio.cpp +++ b/eaudiofx/core/BufferAudio.cpp @@ -31,17 +31,25 @@ eaudiofx::BufferAudio::~BufferAudio(void) { if (m_data != NULL) { delete[] m_data; m_data = NULL; + m_allocated = 0; } } void eaudiofx::BufferAudio::resize(size_t _newSize) { + if (m_allocated >= _newSize) { + // nothing to do, enought data ... + return; + } if (m_data != NULL) { delete[] m_data; m_data = NULL; + m_allocated = 0; } EAUDIOFX_ERROR("Request allocate of " << _newSize << " samples"); m_data = new float[_newSize]; if (m_data == NULL) { EAUDIOFX_ERROR("Can not allocate Buffer Audio"); + } else { + m_allocated = _newSize; } } \ No newline at end of file diff --git a/eaudiofx/core/BufferAudioRaw.cpp b/eaudiofx/core/BufferAudioRaw.cpp index ad02a22..d2d4d2b 100644 --- a/eaudiofx/core/BufferAudioRaw.cpp +++ b/eaudiofx/core/BufferAudioRaw.cpp @@ -25,3 +25,21 @@ eaudiofx::BufferAudioRaw::BufferAudioRaw(eaudiofx::Block& _parent, int32_t _freq EAUDIOFX_INFO("Resize the buffer : " << m_frequency << "Hz, " << m_nbChannel << " channel(s), " << m_allocatedSample << " sample(s)"); resize(m_nbChannel*m_allocatedSample); } + + +void eaudiofx::BufferAudioRaw::setProperty(int32_t _frequency, int32_t _nbChannel, int32_t _nbSample) { + bool increaseSize = false; + if (_nbSample > m_allocatedSample) { + m_allocatedSample = _nbSample; + increaseSize = true; + } + if (_nbChannel > m_nbChannel) { + increaseSize = true; + } + m_nbChannel = _nbChannel; + m_frequency = _frequency; + if (increaseSize == true) { + EAUDIOFX_INFO("Resize the buffer : " << m_frequency << "Hz, " << m_nbChannel << " channel(s), " << m_allocatedSample << " sample(s)"); + resize(m_nbChannel*m_allocatedSample); + } +} \ No newline at end of file diff --git a/eaudiofx/core/BufferAudioRaw.h b/eaudiofx/core/BufferAudioRaw.h index 26963df..62e4375 100644 --- a/eaudiofx/core/BufferAudioRaw.h +++ b/eaudiofx/core/BufferAudioRaw.h @@ -23,6 +23,8 @@ namespace eaudiofx { size_t m_size; //!< number of sample for each channels provided in this buffer ... (write by the upstream (can be 0)) protected: size_t m_sizeRequested; //!< in pull mode, number of sample for each channels requested by the next Filter + public: + void setProperty(int32_t _frequency, int32_t _nbChannel, int32_t _nbSample); }; }; diff --git a/eaudiofx/core/BufferStream.cpp b/eaudiofx/core/BufferStream.cpp index 631b518..8152f88 100644 --- a/eaudiofx/core/BufferStream.cpp +++ b/eaudiofx/core/BufferStream.cpp @@ -6,12 +6,46 @@ * @license BSD v3 (see license file) */ +#include #include eaudiofx::BufferStream::BufferStream(eaudiofx::Block& _parent) : - eaudiofx::Buffer(_parent) { + eaudiofx::Buffer(_parent), + m_data(NULL), + m_allocated(0), + m_size(0) { } eaudiofx::BufferStream::~BufferStream(void) { - + if (m_data != NULL) { + delete[] m_data; + m_data = NULL; + m_allocated = 0; + } +} + +void eaudiofx::BufferStream::resize(size_t _newSize) { + if (m_allocated >= _newSize) { + // nothing to do, enought data ... + return; + } + if (m_data != NULL) { + delete[] m_data; + m_data = NULL; + m_allocated = 0; + } + EAUDIOFX_ERROR("Request allocate of " << _newSize << " samples"); + m_data = new uint8_t[_newSize]; + if (m_data == NULL) { + EAUDIOFX_ERROR("Can not allocate Buffer Audio"); + } else { + m_allocated = _newSize; + } +} + +void eaudiofx::BufferStream::setProperty(int32_t _dataSize) { + if (_dataSize<=0) { + return; + } + resize(_dataSize); } \ No newline at end of file diff --git a/eaudiofx/core/BufferStream.h b/eaudiofx/core/BufferStream.h index 7e2f9ca..309192e 100644 --- a/eaudiofx/core/BufferStream.h +++ b/eaudiofx/core/BufferStream.h @@ -17,12 +17,32 @@ namespace eaudiofx { BufferStream(eaudiofx::Block& _parent); virtual ~BufferStream(void); protected: - void* m_data; //!< buffer data + uint8_t* m_data; //!< buffer data size_t m_allocated; //!< number of byte allocated protected: size_t m_size; //!< number of byte provided in this buffer ... (write by the upstream (can be 0)) + public: + void setAvaillableSize(size_t _availlableSize) { + m_size = _availlableSize; + } + size_t setAvaillableSize(void) { + return m_size; + } + public: + void setProperty(int32_t _dataSize); protected: - size_t m_sizeRequested; //!< in pull mode, number of byte requested by the next Filter + /** + * @brief Reallocate the Buffer data. + */ + virtual void resize(size_t _newSize); + public: + /** + * @brief Get the buffer casted in float* + * @return Pointer on the buffer with correct cast. + */ + uint8_t* getData(void) { + return m_data; + } }; }; diff --git a/eaudiofx/core/Processing.cpp b/eaudiofx/core/Processing.cpp index 07bb3ed..03f3166 100644 --- a/eaudiofx/core/Processing.cpp +++ b/eaudiofx/core/Processing.cpp @@ -6,10 +6,26 @@ * @license BSD v3 (see license file) */ +#include #include int32_t eaudiofx::Processing::process(void) { - + EAUDIOFX_INFO("Start process : '" << getName() << "'"); + return eaudiofx::ERR_NONE; +} + +int32_t eaudiofx::Processing::start(void) { + EAUDIOFX_INFO("Start Processing : '" << getName() << "'"); + return init(); +} + +int32_t eaudiofx::Processing::stop(void) { + EAUDIOFX_INFO("Stop Processing : '" << getName() << "'"); + return unInit(); +} + +int32_t eaudiofx::Processing::waitEndOfProcess(void) { + EAUDIOFX_INFO("wait end of Processing : '" << getName() << "'"); return eaudiofx::ERR_NONE; } \ No newline at end of file diff --git a/eaudiofx/core/Processing.h b/eaudiofx/core/Processing.h index 09bec46..899f1a8 100644 --- a/eaudiofx/core/Processing.h +++ b/eaudiofx/core/Processing.h @@ -22,6 +22,12 @@ namespace eaudiofx { virtual ~Processing(void) {}; public: int32_t process(void); + int32_t start(void); + int32_t stop(void); + int32_t waitEndOfProcess(void); + bool isLiveStream(void) { + return false; + } }; }; diff --git a/eaudiofx/core/audio.h b/eaudiofx/core/audio.h index d6fbf5d..d11926b 100644 --- a/eaudiofx/core/audio.h +++ b/eaudiofx/core/audio.h @@ -77,6 +77,7 @@ namespace eaudiofx { enum { ERR_NONE = 0, ERR_NOT_IMPLEMENTED, + ERR_FAIL, ERR_ALREADY_EXIST, ERR_INPUT_NULL, ERR_FORBIDEN, diff --git a/test/Windows.cpp b/test/Windows.cpp index 45da6e2..822327e 100644 --- a/test/Windows.cpp +++ b/test/Windows.cpp @@ -12,6 +12,9 @@ #include #include #include + +#include +#include #include #include @@ -60,36 +63,84 @@ void appl::Windows::onObjectRemove(ewol::Object * _removeObject) { } } +eaudiofx::Processing* process = NULL; void appl::Windows::onReceiveMessage(const ewol::object::Message& _msg) { if (_msg.getMessage() == g_eventPlay1) { - APPL_ERROR("Play Requested ..."); - eaudiofx::Processing* process = new eaudiofx::Processing(); - if (process == NULL) { - APPL_ERROR("can not create processing ..."); + #if 0 + APPL_INFO("Play Requested ..."); + process = new eaudiofx::Processing(); + if (process == NULL) { + APPL_ERROR("can not create processing ..."); + return; + } + APPL_INFO("Create Generator ..."); + eaudiofx::GeneratorSignal* generator = new eaudiofx::GeneratorSignal(); + if (generator == NULL) { + APPL_ERROR("can not create Generator ..."); + return; + } + generator->setName("myGenerator"); + process->addBlock(generator); + APPL_INFO("Create Receiver ..."); + eaudiofx::ReceiverRtAudio* receiver = new eaudiofx::ReceiverRtAudio(); + if (receiver == NULL) { + APPL_ERROR("can not create Receiver ..."); + return; + } + receiver->setName("myReceiver"); + process->addBlock(receiver); + + process->linkBlock("myGenerator", "out","myReceiver", "in"); + + process->start(); return; - } - APPL_ERROR("Create Generator ..."); - eaudiofx::GeneratorSignal* generator = new eaudiofx::GeneratorSignal(); - if (generator == NULL) { - APPL_ERROR("can not create Generator ..."); + #else + + APPL_INFO("Play Requested ..."); + process = new eaudiofx::Processing(); + if (process == NULL) { + APPL_ERROR("can not create processing ..."); + return; + } + APPL_INFO("Create Generator ..."); + eaudiofx::GeneratorFile* generator = new eaudiofx::GeneratorFile(); + if (generator == NULL) { + APPL_ERROR("can not create Generator ..."); + return; + } + generator->setName("myGenerator"); + process->addBlock(generator); + + APPL_INFO("Create DECODER ..."); + eaudiofx::BlockDecoder* decoder = new eaudiofx::BlockDecoder(); + if (decoder == NULL) { + APPL_ERROR("can not create Generator ..."); + return; + } + decoder->setName("myDecoder"); + process->addBlock(decoder); + + APPL_INFO("Create Receiver ..."); + eaudiofx::ReceiverRtAudio* receiver = new eaudiofx::ReceiverRtAudio(); + if (receiver == NULL) { + APPL_ERROR("can not create Receiver ..."); + return; + } + receiver->setName("myReceiver"); + process->addBlock(receiver); + + process->linkBlock("myGenerator", "out","myDecoder", "in"); + process->linkBlock("myDecoder", "out","myReceiver", "in"); + + process->start(); return; - } - generator->setName("myGenerator"); - process->addBlock(generator); - APPL_ERROR("Create Receiver ..."); - eaudiofx::ReceiverRtAudio* receiver = new eaudiofx::ReceiverRtAudio(); - if (receiver == NULL) { - APPL_ERROR("can not create Receiver ..."); - return; - } - receiver->setName("myReceiver"); - process->addBlock(receiver); - process->process(); - return; + #endif } if (_msg.getMessage() == g_eventPlay2) { - + if (process != NULL) { + process->stop(); + } return; } }