[DEV] change time properties

This commit is contained in:
Edouard DUPIN 2015-02-10 22:38:30 +01:00
parent 5c9361c199
commit 1a24bb9254
14 changed files with 56 additions and 49 deletions

View File

@ -43,7 +43,6 @@ const std::vector<uint32_t>& airtaudio::genericSampleRate() {
airtaudio::Api::Api() : airtaudio::Api::Api() :
m_apiHandle(nullptr),
m_deviceBuffer(nullptr) { m_deviceBuffer(nullptr) {
m_device[0] = 11111; m_device[0] = 11111;
m_device[1] = 11111; m_device[1] = 11111;
@ -55,6 +54,12 @@ airtaudio::Api::~Api() {
} }
enum airtaudio::error airtaudio::Api::startStream() {
m_startTime = std::chrono::system_clock::now();
m_duration = std::chrono::duration<int64_t, std::micro>(0);
return airtaudio::error_none;
}
enum airtaudio::error airtaudio::Api::openStream(airtaudio::StreamParameters *oParams, enum airtaudio::error airtaudio::Api::openStream(airtaudio::StreamParameters *oParams,
airtaudio::StreamParameters *iParams, airtaudio::StreamParameters *iParams,
enum audio::format format, enum audio::format format,
@ -168,13 +173,7 @@ bool airtaudio::Api::probeDeviceOpen(uint32_t /*device*/,
} }
void airtaudio::Api::tickStreamTime() { void airtaudio::Api::tickStreamTime() {
// Subclasses that do not provide their own implementation of m_duration += std::chrono::duration<int64_t, std::micro>((m_bufferSize * 1000000) / m_sampleRate);
// getStreamTime should call this function once per buffer I/O to
// provide basic stream time support.
m_streamTime += (m_bufferSize * 1.0 / m_sampleRate);
#if defined(HAVE_GETTIMEOFDAY)
gettimeofday(&m_lastTickTimestamp, nullptr);
#endif
} }
long airtaudio::Api::getStreamLatency() { long airtaudio::Api::getStreamLatency() {
@ -193,26 +192,11 @@ long airtaudio::Api::getStreamLatency() {
return totalLatency; return totalLatency;
} }
double airtaudio::Api::getStreamTime() { std::chrono::system_clock::time_point airtaudio::Api::getStreamTime() {
if (verifyStream() != airtaudio::error_none) { if (verifyStream() != airtaudio::error_none) {
return 0.0f; return std::chrono::system_clock::time_point();
} }
#if defined(HAVE_GETTIMEOFDAY) return m_startTime + m_duration;
// Return a very accurate estimate of the stream time by
// adding in the elapsed time since the last tick.
struct timeval then;
struct timeval now;
if (m_state != airtaudio::state_running || m_streamTime == 0.0) {
return m_streamTime;
}
gettimeofday(&now, nullptr);
then = m_lastTickTimestamp;
return m_streamTime
+ ((now.tv_sec + 0.000001 * now.tv_usec)
- (then.tv_sec + 0.000001 * then.tv_usec));
#else
return m_streamTime;
#endif
} }
uint32_t airtaudio::Api::getStreamSampleRate() { uint32_t airtaudio::Api::getStreamSampleRate() {
@ -237,8 +221,8 @@ void airtaudio::Api::clearStreamInfo() {
m_bufferSize = 0; m_bufferSize = 0;
m_nBuffers = 0; m_nBuffers = 0;
m_userFormat = audio::format_unknow; m_userFormat = audio::format_unknow;
m_streamTime = 0.0; m_startTime = std::chrono::system_clock::time_point();
m_apiHandle = nullptr; m_duration = std::chrono::duration<int64_t, std::micro>(0);
m_deviceBuffer = nullptr; m_deviceBuffer = nullptr;
m_callbackInfo.callback = 0; m_callbackInfo.callback = 0;
m_callbackInfo.isRunning = false; m_callbackInfo.isRunning = false;

View File

@ -9,6 +9,7 @@
#define __AIRTAUDIO_API_H__ #define __AIRTAUDIO_API_H__
#include <sstream> #include <sstream>
#include <chrono>
#include <airtaudio/debug.h> #include <airtaudio/debug.h>
#include <airtaudio/type.h> #include <airtaudio/type.h>
#include <airtaudio/state.h> #include <airtaudio/state.h>
@ -46,12 +47,12 @@ namespace airtaudio {
airtaudio::AirTAudioCallback _callback, airtaudio::AirTAudioCallback _callback,
airtaudio::StreamOptions* _options); airtaudio::StreamOptions* _options);
virtual enum airtaudio::error closeStream(); virtual enum airtaudio::error closeStream();
virtual enum airtaudio::error startStream() = 0; virtual enum airtaudio::error startStream();
virtual enum airtaudio::error stopStream() = 0; virtual enum airtaudio::error stopStream() = 0;
virtual enum airtaudio::error abortStream() = 0; virtual enum airtaudio::error abortStream() = 0;
long getStreamLatency(); long getStreamLatency();
uint32_t getStreamSampleRate(); uint32_t getStreamSampleRate();
virtual double getStreamTime(); virtual std::chrono::time_point<std::chrono::system_clock> getStreamTime();
bool isStreamOpen() const { bool isStreamOpen() const {
return m_state != airtaudio::state_closed; return m_state != airtaudio::state_closed;
} }
@ -81,8 +82,10 @@ namespace airtaudio {
// TODO : Remove this ... // TODO : Remove this ...
airtaudio::CallbackInfo m_callbackInfo; airtaudio::CallbackInfo m_callbackInfo;
airtaudio::ConvertInfo m_convertInfo[2]; airtaudio::ConvertInfo m_convertInfo[2];
// TODO : use : std::chrono::system_clock::time_point ...
double m_streamTime; // Number of elapsed seconds since the stream started. //std::chrono::system_clock::time_point
std::chrono::time_point<std::chrono::system_clock> m_startTime; //!< start time of the stream (restart at every stop, pause ...)
std::chrono::duration<int64_t, std::micro> m_duration; //!< duration from wich the stream is started
/** /**
* @brief api-specific method that attempts to open a device * @brief api-specific method that attempts to open a device

View File

@ -266,9 +266,9 @@ namespace airtaudio {
* @brief If a stream is not open, an RtError (type = INVALID_USE) will be thrown. * @brief If a stream is not open, an RtError (type = INVALID_USE) will be thrown.
* @return the number of elapsed seconds since the stream was started. * @return the number of elapsed seconds since the stream was started.
*/ */
double getStreamTime() { std::chrono::time_point<std::chrono::system_clock> getStreamTime() {
if (m_rtapi == nullptr) { if (m_rtapi == nullptr) {
return 0.0; return std::chrono::time_point<std::chrono::system_clock>();
} }
return m_rtapi->getStreamTime(); return m_rtapi->getStreamTime();
} }

View File

@ -771,6 +771,8 @@ enum airtaudio::error airtaudio::api::Alsa::closeStream() {
} }
enum airtaudio::error airtaudio::api::Alsa::startStream() { enum airtaudio::error airtaudio::api::Alsa::startStream() {
// TODO : Check return ...
airtaudio::Api::startStream();
// This method calls snd_pcm_prepare if the device isn't already in that state. // This method calls snd_pcm_prepare if the device isn't already in that state.
if (verifyStream() != airtaudio::error_none) { if (verifyStream() != airtaudio::error_none) {
return airtaudio::error_fail; return airtaudio::error_fail;
@ -934,7 +936,7 @@ void airtaudio::api::Alsa::callbackEventOneCycle() {
return; // TODO : notify appl: airtaudio::error_warning; return; // TODO : notify appl: airtaudio::error_warning;
} }
int32_t doStopStream = 0; int32_t doStopStream = 0;
double streamTime = getStreamTime(); std::chrono::system_clock::time_point streamTime = getStreamTime();
enum airtaudio::status status = airtaudio::status_ok; enum airtaudio::status status = airtaudio::status_ok;
if (m_mode != airtaudio::mode_input && m_private->xrun[0] == true) { if (m_mode != airtaudio::mode_input && m_private->xrun[0] == true) {
status = airtaudio::status_underflow; status = airtaudio::status_underflow;

View File

@ -85,6 +85,8 @@ enum airtaudio::error airtaudio::api::Android::closeStream() {
enum airtaudio::error airtaudio::api::Android::startStream() { enum airtaudio::error airtaudio::api::Android::startStream() {
ATA_INFO("Start Stream"); ATA_INFO("Start Stream");
// TODO : Check return ...
airtaudio::Api::startStream();
// Can not close the stream now... // Can not close the stream now...
return airtaudio::error_none; return airtaudio::error_none;
} }
@ -108,7 +110,7 @@ enum airtaudio::error airtaudio::api::Android::abortStream() {
void airtaudio::api::Android::callBackEvent(void* _data, void airtaudio::api::Android::callBackEvent(void* _data,
int32_t _frameRate) { int32_t _frameRate) {
int32_t doStopStream = 0; int32_t doStopStream = 0;
double streamTime = getStreamTime(); std::chrono::system_clock::time_point streamTime = getStreamTime();
enum airtaudio::status status = airtaudio::status_ok; enum airtaudio::status status = airtaudio::status_ok;
if (m_doConvertBuffer[airtaudio::mode_output] == true) { if (m_doConvertBuffer[airtaudio::mode_output] == true) {
doStopStream = m_callbackInfo.callback(m_userBuffer[airtaudio::mode_output], doStopStream = m_callbackInfo.callback(m_userBuffer[airtaudio::mode_output],

View File

@ -582,6 +582,8 @@ enum airtaudio::error airtaudio::api::Asio::closeStream() {
bool stopThreadCalled = false; bool stopThreadCalled = false;
enum airtaudio::error airtaudio::api::Asio::startStream() { enum airtaudio::error airtaudio::api::Asio::startStream() {
// TODO : Check return ...
airtaudio::Api::startStream();
if (verifyStream() != airtaudio::error_none) { if (verifyStream() != airtaudio::error_none) {
return airtaudio::error_fail; return airtaudio::error_fail;
} }
@ -692,7 +694,7 @@ bool airtaudio::api::Asio::callbackEvent(long bufferIndex) {
// Invoke user callback to get fresh output data UNLESS we are // Invoke user callback to get fresh output data UNLESS we are
// draining stream. // draining stream.
if (m_private->drainCounter == 0) { if (m_private->drainCounter == 0) {
double streamTime = getStreamTime(); std::chrono::system_clock::time_point streamTime = getStreamTime();
rtaudio::streamStatus status = 0; rtaudio::streamStatus status = 0;
if (m_mode != airtaudio::mode_input && asioXRun == true) { if (m_mode != airtaudio::mode_input && asioXRun == true) {
status |= RTAUDIO_airtaudio::status_underflow; status |= RTAUDIO_airtaudio::status_underflow;

View File

@ -934,6 +934,8 @@ enum airtaudio::error airtaudio::api::Core::closeStream() {
} }
enum airtaudio::error airtaudio::api::Core::startStream() { enum airtaudio::error airtaudio::api::Core::startStream() {
// TODO : Check return ...
airtaudio::Api::startStream();
if (verifyStream() != airtaudio::error_none) { if (verifyStream() != airtaudio::error_none) {
return airtaudio::error_fail; return airtaudio::error_fail;
} }
@ -1058,7 +1060,7 @@ bool airtaudio::api::Core::callbackEvent(AudioDeviceID _deviceId,
// draining stream or duplex mode AND the input/output devices are // draining stream or duplex mode AND the input/output devices are
// different AND this function is called for the input device. // different AND this function is called for the input device.
if (m_private->drainCounter == 0 && (m_mode != airtaudio::mode_duplex || _deviceId == outputDevice)) { if (m_private->drainCounter == 0 && (m_mode != airtaudio::mode_duplex || _deviceId == outputDevice)) {
double streamTime = getStreamTime(); std::chrono::system_clock::time_point streamTime = getStreamTime();
enum airtaudio::status status = airtaudio::status_ok; enum airtaudio::status status = airtaudio::status_ok;
if ( m_mode != airtaudio::mode_input if ( m_mode != airtaudio::mode_input
&& m_private->xrun[0] == true) { && m_private->xrun[0] == true) {

View File

@ -91,6 +91,8 @@ enum airtaudio::error airtaudio::api::CoreIos::closeStream(void) {
enum airtaudio::error airtaudio::api::CoreIos::startStream(void) { enum airtaudio::error airtaudio::api::CoreIos::startStream(void) {
ATA_INFO("Start Stream"); ATA_INFO("Start Stream");
// TODO : Check return ...
airtaudio::Api::startStream();
OSStatus status = AudioOutputUnitStart(m_private->audioUnit); OSStatus status = AudioOutputUnitStart(m_private->audioUnit);
// Can not close the stream now... // Can not close the stream now...
return airtaudio::error_none; return airtaudio::error_none;
@ -127,7 +129,7 @@ void airtaudio::api::CoreIos::callBackEvent(void* _data,
return; return;
#endif #endif
int32_t doStopStream = 0; int32_t doStopStream = 0;
double streamTime = getStreamTime(); std::chrono::system_clock::time_point streamTime = getStreamTime();
enum airtaudio::status status = airtaudio::status_ok; enum airtaudio::status status = airtaudio::status_ok;
if (m_doConvertBuffer[airtaudio::mode_output] == true) { if (m_doConvertBuffer[airtaudio::mode_output] == true) {
doStopStream = m_callbackInfo.callback(m_userBuffer[airtaudio::mode_output], doStopStream = m_callbackInfo.callback(m_userBuffer[airtaudio::mode_output],

View File

@ -878,6 +878,8 @@ enum airtaudio::error airtaudio::api::Ds::closeStream() {
} }
enum airtaudio::error airtaudio::api::Ds::startStream() { enum airtaudio::error airtaudio::api::Ds::startStream() {
// TODO : Check return ...
airtaudio::Api::startStream();
if (verifyStream() != airtaudio::error_none) { if (verifyStream() != airtaudio::error_none) {
return airtaudio::error_fail; return airtaudio::error_fail;
} }
@ -1040,7 +1042,7 @@ void airtaudio::api::Ds::callbackEvent() {
// Invoke user callback to get fresh output data UNLESS we are // Invoke user callback to get fresh output data UNLESS we are
// draining stream. // draining stream.
if (m_private->drainCounter == 0) { if (m_private->drainCounter == 0) {
double streamTime = getStreamTime(); std::chrono::system_clock::time_point streamTime = getStreamTime();
rtaudio::streamStatus status = 0; rtaudio::streamStatus status = 0;
if ( m_mode != airtaudio::mode_input if ( m_mode != airtaudio::mode_input
&& m_private->xrun[0] == true) { && m_private->xrun[0] == true) {

View File

@ -35,6 +35,8 @@ enum airtaudio::error airtaudio::api::Dummy::closeStream() {
} }
enum airtaudio::error airtaudio::api::Dummy::startStream() { enum airtaudio::error airtaudio::api::Dummy::startStream() {
// TODO : Check return ...
airtaudio::Api::startStream();
return airtaudio::error_none; return airtaudio::error_none;
} }

View File

@ -512,6 +512,8 @@ enum airtaudio::error airtaudio::api::Jack::closeStream() {
} }
enum airtaudio::error airtaudio::api::Jack::startStream() { enum airtaudio::error airtaudio::api::Jack::startStream() {
// TODO : Check return ...
airtaudio::Api::startStream();
if (verifyStream() != airtaudio::error_none) { if (verifyStream() != airtaudio::error_none) {
return airtaudio::error_fail; return airtaudio::error_fail;
} }
@ -649,7 +651,7 @@ bool airtaudio::api::Jack::callbackEvent(uint64_t _nframes) {
} }
// Invoke user callback first, to get fresh output data. // Invoke user callback first, to get fresh output data.
if (m_private->drainCounter == 0) { if (m_private->drainCounter == 0) {
double streamTime = getStreamTime(); std::chrono::time_point<std::chrono::system_clock> streamTime = getStreamTime();
enum airtaudio::status status = airtaudio::status_ok; enum airtaudio::status status = airtaudio::status_ok;
if (m_mode != airtaudio::mode_input && m_private->xrun[0] == true) { if (m_mode != airtaudio::mode_input && m_private->xrun[0] == true) {
status = airtaudio::status_underflow; status = airtaudio::status_underflow;

View File

@ -578,6 +578,8 @@ enum airtaudio::error airtaudio::api::Oss::closeStream() {
} }
enum airtaudio::error airtaudio::api::Oss::startStream() { enum airtaudio::error airtaudio::api::Oss::startStream() {
// TODO : Check return ...
airtaudio::Api::startStream();
if (verifyStream() != airtaudio::error_none) { if (verifyStream() != airtaudio::error_none) {
return airtaudio::error_fail; return airtaudio::error_fail;
} }
@ -709,7 +711,7 @@ void airtaudio::api::Oss::callbackEvent() {
} }
// Invoke user callback to get fresh output data. // Invoke user callback to get fresh output data.
int32_t doStopStream = 0; int32_t doStopStream = 0;
double streamTime = getStreamTime(); std::chrono::system_clock::time_point streamTime = getStreamTime();
rtaudio::streamStatus status = 0; rtaudio::streamStatus status = 0;
if ( m_mode != airtaudio::mode_input if ( m_mode != airtaudio::mode_input
&& m_private->xrun[0] == true) { && m_private->xrun[0] == true) {

View File

@ -150,7 +150,7 @@ void airtaudio::api::Pulse::callbackEventOneCycle() {
ATA_ERROR("the stream is closed ... this shouldn't happen!"); ATA_ERROR("the stream is closed ... this shouldn't happen!");
return; return;
} }
double streamTime = getStreamTime(); std::chrono::system_clock::time_point streamTime = getStreamTime();
enum airtaudio::status status = airtaudio::status_ok; enum airtaudio::status status = airtaudio::status_ok;
int32_t doStopStream = m_callbackInfo.callback(&m_userBuffer[airtaudio::modeToIdTable(airtaudio::mode_output)][0], int32_t doStopStream = m_callbackInfo.callback(&m_userBuffer[airtaudio::modeToIdTable(airtaudio::mode_output)][0],
&m_userBuffer[airtaudio::modeToIdTable(airtaudio::mode_input)][0], &m_userBuffer[airtaudio::modeToIdTable(airtaudio::mode_input)][0],
@ -211,6 +211,8 @@ unlock:
} }
enum airtaudio::error airtaudio::api::Pulse::startStream() { enum airtaudio::error airtaudio::api::Pulse::startStream() {
// TODO : Check return ...
airtaudio::Api::startStream();
if (m_state == airtaudio::state_closed) { if (m_state == airtaudio::state_closed) {
ATA_ERROR("the stream is not open!"); ATA_ERROR("the stream is not open!");
return airtaudio::error_invalidUse; return airtaudio::error_invalidUse;

View File

@ -32,9 +32,9 @@ namespace airtaudio {
//! Defined error types. //! Defined error types.
/** /**
* @brief RtAudio callback function prototype. * @brief airtaudio callback function prototype.
* *
* All RtAudio clients must create a function of type RtAudioCallback * All airtaudio clients must create a function of type AirTAudioCallback
* to read and/or write data from/to the audio stream. When the * to read and/or write data from/to the audio stream. When the
* underlying audio system is ready for new input or output data, this * underlying audio system is ready for new input or output data, this
* function will be invoked. * function will be invoked.
@ -51,11 +51,11 @@ namespace airtaudio {
* stream was opened. For output-only streams, this argument * stream was opened. For output-only streams, this argument
* will be nullptr. * will be nullptr.
* *
* @param _nFrames The number of sample frames of input or output * @param _nbChunk The number of chunk of input or output
* data in the buffers. The actual buffer size in bytes is * data in the buffers. The actual buffer size in bytes is
* dependent on the data type and number of channels in use. * dependent on the data type and number of channels in use.
* *
* @param _streamTime The number of seconds that have elapsed since the * @param _time The number of seconds that have elapsed since the
* stream was started. * stream was started.
* *
* @param _status If non-zero, this argument indicates a data overflow * @param _status If non-zero, this argument indicates a data overflow
@ -70,8 +70,8 @@ namespace airtaudio {
*/ */
typedef std::function<int32_t (void* _outputBuffer, typedef std::function<int32_t (void* _outputBuffer,
void* _inputBuffer, void* _inputBuffer,
uint32_t _nFrames, uint32_t _nbChunk,
double _streamTime, const std::chrono::system_clock::time_point& _time,
airtaudio::status _status)> AirTAudioCallback; airtaudio::status _status)> AirTAudioCallback;
} }