2015-04-11 09:38:30 +02:00
|
|
|
|
/** @file
|
|
|
|
|
* @author Edouard DUPIN
|
|
|
|
|
* @copyright 2015, Edouard DUPIN, all right reserved
|
|
|
|
|
* @license APACHE v2.0 (see license file)
|
|
|
|
|
*/
|
2016-02-02 21:18:54 +01:00
|
|
|
|
#pragma once
|
2015-04-11 09:38:30 +02:00
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <stdint.h>
|
2015-09-14 21:11:04 +02:00
|
|
|
|
#include <mutex>
|
|
|
|
|
#include <chrono>
|
|
|
|
|
#include <functional>
|
|
|
|
|
#include <memory>
|
2015-04-11 09:38:30 +02:00
|
|
|
|
#include <audio/format.h>
|
|
|
|
|
#include <audio/channel.h>
|
|
|
|
|
#include <audio/drain/Process.h>
|
|
|
|
|
#include <audio/drain/EndPointCallback.h>
|
|
|
|
|
#include <audio/drain/EndPointWrite.h>
|
|
|
|
|
#include <ejson/ejson.h>
|
|
|
|
|
#include <etk/os/FSNode.h>
|
2015-04-13 21:49:48 +02:00
|
|
|
|
#include <audio/Time.h>
|
2015-04-11 09:38:30 +02:00
|
|
|
|
|
|
|
|
|
namespace audio {
|
|
|
|
|
namespace river {
|
|
|
|
|
namespace io {
|
|
|
|
|
class Node;
|
|
|
|
|
class NodeAirTAudio;
|
|
|
|
|
class NodeAEC;
|
|
|
|
|
class NodeMuxer;
|
|
|
|
|
}
|
|
|
|
|
enum modeInterface {
|
|
|
|
|
modeInterface_unknow,
|
|
|
|
|
modeInterface_input,
|
|
|
|
|
modeInterface_output,
|
|
|
|
|
modeInterface_feedback,
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* @brief Interface is the basic handle to manage the input output stream
|
|
|
|
|
* @note To create this class see @ref audio::river::Manager class
|
|
|
|
|
*/
|
2016-03-08 21:29:34 +01:00
|
|
|
|
class Interface : public std::enable_shared_from_this<Interface> {
|
2015-04-11 09:38:30 +02:00
|
|
|
|
friend class io::Node;
|
|
|
|
|
friend class io::NodeAirTAudio;
|
|
|
|
|
friend class io::NodeAEC;
|
|
|
|
|
friend class io::NodeMuxer;
|
|
|
|
|
friend class Manager;
|
|
|
|
|
protected:
|
|
|
|
|
uint32_t m_uid; //!< unique ID for interface
|
|
|
|
|
protected:
|
|
|
|
|
/**
|
|
|
|
|
* @brief Constructor (use factory)
|
|
|
|
|
*/
|
|
|
|
|
Interface();
|
|
|
|
|
/**
|
|
|
|
|
* @brief Initilize the Class (do all that is not manage by constructor) Call by factory.
|
|
|
|
|
* @param[in] _freq Frequency.
|
|
|
|
|
* @param[in] _map Channel map organization.
|
|
|
|
|
* @param[in] _format Sample format
|
|
|
|
|
* @param[in] _node Low level interface to connect the flow.
|
|
|
|
|
* @param[in] _config Special configuration of this interface.
|
|
|
|
|
* @return true Configuration done corectly.
|
|
|
|
|
* @return false the configuration has an error.
|
|
|
|
|
*/
|
|
|
|
|
bool init(float _freq,
|
|
|
|
|
const std::vector<audio::channel>& _map,
|
|
|
|
|
audio::format _format,
|
2016-03-08 21:29:34 +01:00
|
|
|
|
const std::shared_ptr<audio::river::io::Node>& _node,
|
|
|
|
|
const std::shared_ptr<const ejson::Object>& _config);
|
2015-04-11 09:38:30 +02:00
|
|
|
|
/**
|
|
|
|
|
* @brief Factory of this interface (called by class audio::river::Manager)
|
|
|
|
|
* @param[in] _freq Frequency.
|
|
|
|
|
* @param[in] _map Channel map organization.
|
|
|
|
|
* @param[in] _format Sample format
|
|
|
|
|
* @param[in] _node Low level interface to connect the flow.
|
|
|
|
|
* @param[in] _config Special configuration of this interface.
|
|
|
|
|
* @return nullptr The configuration does not work.
|
|
|
|
|
* @return pointer The interface has been corectly created.
|
|
|
|
|
*/
|
2016-03-08 21:29:34 +01:00
|
|
|
|
static std::shared_ptr<Interface> create(float _freq,
|
2015-04-11 09:38:30 +02:00
|
|
|
|
const std::vector<audio::channel>& _map,
|
|
|
|
|
audio::format _format,
|
2016-03-08 21:29:34 +01:00
|
|
|
|
const std::shared_ptr<audio::river::io::Node>& _node,
|
|
|
|
|
const std::shared_ptr<const ejson::Object>& _config);
|
2015-04-11 09:38:30 +02:00
|
|
|
|
public:
|
|
|
|
|
/**
|
|
|
|
|
* @brief Destructor
|
|
|
|
|
*/
|
|
|
|
|
virtual ~Interface();
|
|
|
|
|
protected:
|
2016-03-08 21:29:34 +01:00
|
|
|
|
mutable std::recursive_mutex m_mutex; //!< Local mutex to protect data
|
|
|
|
|
std::shared_ptr<const ejson::Object> m_config; //!< configuration set by the user.
|
2015-04-11 09:38:30 +02:00
|
|
|
|
protected:
|
|
|
|
|
enum modeInterface m_mode; //!< interface type (input/output/feedback)
|
|
|
|
|
public:
|
|
|
|
|
/**
|
|
|
|
|
* @brief Get mode type of the current interface.
|
|
|
|
|
* @return The mode requested.
|
|
|
|
|
*/
|
|
|
|
|
enum modeInterface getMode() {
|
|
|
|
|
return m_mode;
|
|
|
|
|
}
|
|
|
|
|
protected:
|
|
|
|
|
audio::drain::Process m_process; //!< Algorithme processing engine
|
|
|
|
|
public:
|
|
|
|
|
/**
|
|
|
|
|
* @brief Get the interface format configuration.
|
|
|
|
|
* @return The current format.
|
|
|
|
|
*/
|
|
|
|
|
const audio::drain::IOFormatInterface& getInterfaceFormat() {
|
|
|
|
|
if ( m_mode == modeInterface_input
|
|
|
|
|
|| m_mode == modeInterface_feedback) {
|
|
|
|
|
return m_process.getOutputConfig();
|
|
|
|
|
} else {
|
|
|
|
|
return m_process.getInputConfig();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
protected:
|
2016-03-08 21:29:34 +01:00
|
|
|
|
std::shared_ptr<audio::river::io::Node> m_node; //!< Hardware interface to/from stream audio flow.
|
2015-04-11 09:38:30 +02:00
|
|
|
|
protected:
|
|
|
|
|
std::string m_name; //!< Name of the interface.
|
|
|
|
|
public:
|
|
|
|
|
/**
|
|
|
|
|
* @brief Get interface name.
|
|
|
|
|
* @return The current name.
|
|
|
|
|
*/
|
|
|
|
|
virtual std::string getName() {
|
|
|
|
|
return m_name;
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set the interface name
|
|
|
|
|
* @param[in] _name new name of the interface
|
|
|
|
|
*/
|
|
|
|
|
virtual void setName(const std::string& _name) {
|
|
|
|
|
m_name = _name;
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* @brief set the read/write mode enable.
|
|
|
|
|
* @note If you not set a output/input callback you must call this function.
|
|
|
|
|
*/
|
|
|
|
|
virtual void setReadwrite();
|
|
|
|
|
/**
|
|
|
|
|
* @brief When we want to implement a Callback Mode:
|
|
|
|
|
*/
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set a callback on the write mode interface to know when data is needed in the buffer
|
|
|
|
|
* @param[in] _function Function to call
|
|
|
|
|
*/
|
|
|
|
|
virtual void setWriteCallback(audio::drain::playbackFunctionWrite _function);
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set Output callback mode with the specify callback.
|
|
|
|
|
* @param[in] _function Function to call
|
|
|
|
|
*/
|
|
|
|
|
virtual void setOutputCallback(audio::drain::playbackFunction _function);
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set Input callback mode with the specify callback.
|
|
|
|
|
* @param[in] _function Function to call
|
|
|
|
|
*/
|
|
|
|
|
virtual void setInputCallback(audio::drain::recordFunction _function);
|
|
|
|
|
/**
|
|
|
|
|
* @brief Add a volume group of the current channel.
|
|
|
|
|
* @note If you do not call this function with the group "FLOW" you chan not have a channel volume.
|
|
|
|
|
* @note the set volume stage can not be set after the start.
|
|
|
|
|
* @param[in] _name Name of the group classicle common group:
|
|
|
|
|
* - FLOW for channel volume.
|
|
|
|
|
* - MEDIA for multimedia volume control (audio player, player video, web streaming ...).
|
|
|
|
|
* - TTS for Test-to-speech volume control.
|
|
|
|
|
* - COMMUNICATION for user communication volume control.
|
|
|
|
|
* - NOTIFICATION for urgent notification volume control.
|
|
|
|
|
* - NOISE for small noise volume control.
|
|
|
|
|
*/
|
|
|
|
|
virtual void addVolumeGroup(const std::string& _name);
|
|
|
|
|
public:
|
|
|
|
|
/**
|
|
|
|
|
* @brief Start the Audio interface flow.
|
|
|
|
|
* @param[in] _time Time to start the flow (0) to start as fast as possible...
|
|
|
|
|
* @note _time to play buffer when output interface (if possible)
|
|
|
|
|
* @note _time to read buffer when inut interface (if possible)
|
|
|
|
|
*/
|
2015-04-13 21:49:48 +02:00
|
|
|
|
virtual void start(const audio::Time& _time = audio::Time());
|
2015-04-11 09:38:30 +02:00
|
|
|
|
/**
|
|
|
|
|
* @brief Stop the current flow.
|
|
|
|
|
* @param[in] _fast The stream stop as fast as possible (not write all the buffer in speaker) but apply cross fade out.
|
|
|
|
|
* @param[in] _abort The stream stop whith no garenty of good audio stop.
|
|
|
|
|
*/
|
|
|
|
|
virtual void stop(bool _fast=false, bool _abort=false);
|
|
|
|
|
/**
|
|
|
|
|
* @brief Abort flow (no audio garenty)
|
|
|
|
|
*/
|
|
|
|
|
virtual void abort();
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set a parameter in the stream flow
|
|
|
|
|
* @param[in] _filter name of the filter (if you added some personels)
|
|
|
|
|
* @param[in] _parameter Parameter name.
|
|
|
|
|
* @param[in] _value Value to set.
|
|
|
|
|
* @return true set done
|
|
|
|
|
* @return false An error occured
|
|
|
|
|
* @example : setParameter("volume", "FLOW", "-3dB");
|
|
|
|
|
* @example : setParameter("LowPassFilter", "cutFrequency", "1000Hz");
|
|
|
|
|
*/
|
|
|
|
|
virtual bool setParameter(const std::string& _filter, const std::string& _parameter, const std::string& _value);
|
|
|
|
|
/**
|
|
|
|
|
* @brief Get a parameter value
|
|
|
|
|
* @param[in] _filter name of the filter (if you added some personels)
|
|
|
|
|
* @param[in] _parameter Parameter name.
|
|
|
|
|
* @return The requested value.
|
|
|
|
|
* @example : getParameter("volume", "FLOW"); can return something like "-3dB"
|
|
|
|
|
* @example : getParameter("LowPassFilter", "cutFrequency"); can return something like "[-120..0]dB"
|
|
|
|
|
*/
|
|
|
|
|
virtual std::string getParameter(const std::string& _filter, const std::string& _parameter) const;
|
|
|
|
|
/**
|
|
|
|
|
* @brief Get a parameter value
|
|
|
|
|
* @param[in] _filter name of the filter (if you added some personels)
|
|
|
|
|
* @param[in] _parameter Parameter name.
|
|
|
|
|
* @return The requested value.
|
|
|
|
|
* @example : getParameter("volume", "FLOW"); can return something like "[-120..0]dB"
|
|
|
|
|
* @example : getParameter("LowPassFilter", "cutFreqiency"); can return something like "]100..10000]Hz"
|
|
|
|
|
*/
|
|
|
|
|
virtual std::string getParameterProperty(const std::string& _filter, const std::string& _parameter) const;
|
|
|
|
|
/**
|
|
|
|
|
* @brief write some audio sample in the speakers
|
|
|
|
|
* @param[in] _value Data To write on output
|
|
|
|
|
* @param[in] _nbChunk Number of audio chunk to write
|
|
|
|
|
*/
|
|
|
|
|
// TODO : TimeOut ???
|
|
|
|
|
virtual void write(const void* _value, size_t _nbChunk);
|
|
|
|
|
/**
|
|
|
|
|
* @brief read some audio sample from Microphone
|
|
|
|
|
* @param[in] _value Data To write on output
|
|
|
|
|
* @param[in] _nbChunk Number of audio chunk to write
|
|
|
|
|
*/
|
|
|
|
|
// TODO : TimeOut ???
|
|
|
|
|
virtual void read(void* _value, size_t _nbChunk);
|
|
|
|
|
/**
|
|
|
|
|
* @brief Get number of chunk in the local buffer
|
|
|
|
|
* @return Number of chunk
|
|
|
|
|
*/
|
|
|
|
|
virtual size_t size() const;
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set buffer size in chunk number
|
|
|
|
|
* @param[in] _nbChunk Number of chunk in the buffer
|
|
|
|
|
*/
|
|
|
|
|
virtual void setBufferSize(size_t _nbChunk);
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set buffer size size of the buffer with the stored time in <EFBFBD>s
|
|
|
|
|
* @param[in] _time Time in microsecond of the buffer
|
|
|
|
|
*/
|
2016-03-08 21:29:34 +01:00
|
|
|
|
virtual void setBufferSize(const std::chrono::microseconds& _time);
|
2015-04-11 09:38:30 +02:00
|
|
|
|
/**
|
|
|
|
|
* @brief get buffer size in chunk number
|
|
|
|
|
* @return Number of chunk that can be written in the buffer
|
|
|
|
|
*/
|
|
|
|
|
virtual size_t getBufferSize();
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set buffer size size of the buffer with the stored time in <EFBFBD>s
|
|
|
|
|
* @return Time in microsecond that can be written in the buffer
|
|
|
|
|
*/
|
2016-03-08 21:29:34 +01:00
|
|
|
|
virtual std::chrono::microseconds getBufferSizeMicrosecond();
|
2015-04-11 09:38:30 +02:00
|
|
|
|
/**
|
|
|
|
|
* @brief Get buffer size filled in chunk number
|
|
|
|
|
* @return Number of chunk in the buffer (that might be read/write)
|
|
|
|
|
*/
|
|
|
|
|
virtual size_t getBufferFillSize();
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set buffer size size of the buffer with the stored time in <EFBFBD>s
|
|
|
|
|
* @return Time in microsecond of the buffer (that might be read/write)
|
|
|
|
|
*/
|
2016-03-08 21:29:34 +01:00
|
|
|
|
virtual std::chrono::microseconds getBufferFillSizeMicrosecond();
|
2015-04-11 09:38:30 +02:00
|
|
|
|
/**
|
|
|
|
|
* @brief Remove internal Buffer
|
|
|
|
|
*/
|
|
|
|
|
virtual void clearInternalBuffer();
|
|
|
|
|
/**
|
|
|
|
|
* @brief Write : Get the time of the next sample time to write in the local buffer
|
|
|
|
|
* @brief Read : Get the time of the next sample time to read in the local buffer
|
|
|
|
|
*/
|
2015-04-13 21:49:48 +02:00
|
|
|
|
virtual audio::Time getCurrentTime() const;
|
2015-04-11 09:38:30 +02:00
|
|
|
|
private:
|
|
|
|
|
/**
|
|
|
|
|
* @brief Node Call interface : Input interface node has new data.
|
|
|
|
|
* @param[in] _time Time where the first sample has been capture.
|
|
|
|
|
* @param[in] _data Pointer on the new data.
|
|
|
|
|
* @param[in] _nbChunk Number of chunk in the buffer.
|
|
|
|
|
*/
|
2015-04-13 21:49:48 +02:00
|
|
|
|
virtual void systemNewInputData(audio::Time _time, const void* _data, size_t _nbChunk);
|
2015-04-11 09:38:30 +02:00
|
|
|
|
/**
|
|
|
|
|
* @brief Node Call interface: Output interface node need new data.
|
|
|
|
|
* @param[in] _time Time where the data might be played
|
|
|
|
|
* @param[in] _data Pointer on the data.
|
|
|
|
|
* @param[in] _nbChunk Number of chunk that might be write
|
|
|
|
|
* @param[in] _chunkSize Chunk size.
|
|
|
|
|
*/
|
2015-04-13 21:49:48 +02:00
|
|
|
|
virtual void systemNeedOutputData(audio::Time _time, void* _data, size_t _nbChunk, size_t _chunkSize);
|
2015-04-11 09:38:30 +02:00
|
|
|
|
/**
|
|
|
|
|
* @brief Node Call interface: A volume has change.
|
|
|
|
|
*/
|
|
|
|
|
virtual void systemVolumeChange();
|
|
|
|
|
public:
|
|
|
|
|
/**
|
|
|
|
|
* @brief Create the dot in the FileNode stream.
|
|
|
|
|
* @param[in,out] _node File node to write data.
|
|
|
|
|
* @param[in] _nameIO Name to link the interface node
|
|
|
|
|
* @param[in] _isLink True if the node is connected on the current interface.
|
|
|
|
|
*/
|
|
|
|
|
virtual void generateDot(etk::FSNode& _node, const std::string& _nameIO, bool _isLink=true);
|
|
|
|
|
/**
|
|
|
|
|
* @brief Get the current 'dot' name of the interface
|
|
|
|
|
* @return The anme requested.
|
|
|
|
|
*/
|
|
|
|
|
virtual std::string getDotNodeName() const;
|
|
|
|
|
protected:
|
|
|
|
|
/**
|
|
|
|
|
* @brief Interfanel generate of status
|
|
|
|
|
* @param[in] _origin status source
|
|
|
|
|
* @param[in] _status Event status
|
|
|
|
|
*/
|
|
|
|
|
void generateStatus(const std::string& _origin, const std::string& _status) {
|
|
|
|
|
m_process.generateStatus(_origin, _status);
|
|
|
|
|
}
|
|
|
|
|
public:
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set status callback
|
|
|
|
|
* @param[in] _newFunction Function to call
|
|
|
|
|
*/
|
|
|
|
|
void setStatusFunction(audio::drain::statusFunction _newFunction) {
|
|
|
|
|
m_process.setStatusFunction(_newFunction);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|