[DEV] try change the XRun detection in soft

This commit is contained in:
Edouard DUPIN 2015-03-06 22:50:03 +01:00
parent e4c46dbd64
commit 36e5f26cb4

View File

@ -663,6 +663,7 @@ bool airtaudio::api::Alsa::probeDeviceOpenName(const std::string& _deviceName,
snd_pcm_sw_params_t *swParams = nullptr; snd_pcm_sw_params_t *swParams = nullptr;
snd_pcm_sw_params_alloca(&swParams); snd_pcm_sw_params_alloca(&swParams);
snd_pcm_sw_params_current(phandle, swParams); snd_pcm_sw_params_current(phandle, swParams);
snd_pcm_sw_params_set_start_threshold(phandle, swParams, *_bufferSize); snd_pcm_sw_params_set_start_threshold(phandle, swParams, *_bufferSize);
snd_pcm_sw_params_set_stop_threshold(phandle, swParams, ULONG_MAX); snd_pcm_sw_params_set_stop_threshold(phandle, swParams, ULONG_MAX);
snd_pcm_sw_params_set_silence_threshold(phandle, swParams, 0); snd_pcm_sw_params_set_silence_threshold(phandle, swParams, 0);
@ -681,6 +682,15 @@ bool airtaudio::api::Alsa::probeDeviceOpenName(const std::string& _deviceName,
ATA_ERROR("error installing software configuration on device (" << _deviceName << "), " << snd_strerror(result) << "."); ATA_ERROR("error installing software configuration on device (" << _deviceName << "), " << snd_strerror(result) << ".");
return false; return false;
} }
{
snd_pcm_uframes_t _period_size = 0;
snd_pcm_uframes_t _buffer_size = 0;
snd_pcm_hw_params_get_period_size(hw_params, &_period_size, &dir);
snd_pcm_hw_params_get_buffer_size(hw_params, &_buffer_size);
ATA_ERROR("ploooooo _period_size=" << _period_size << " _buffer_size=" << _buffer_size);
}
// Set flags for buffer conversion // Set flags for buffer conversion
m_doConvertBuffer[modeToIdTable(_mode)] = false; m_doConvertBuffer[modeToIdTable(_mode)] = false;
if (m_userFormat != m_deviceFormat[modeToIdTable(_mode)]) { if (m_userFormat != m_deviceFormat[modeToIdTable(_mode)]) {
@ -1099,7 +1109,6 @@ void airtaudio::api::Alsa::callbackEventOneCycle() {
snd_pcm_t **handle; snd_pcm_t **handle;
snd_pcm_sframes_t frames; snd_pcm_sframes_t frames;
audio::format format; audio::format format;
handle = (snd_pcm_t **) m_private->handles;
if (m_state == airtaudio::state_stopped) { if (m_state == airtaudio::state_stopped) {
goto unlock; goto unlock;
@ -1120,23 +1129,23 @@ void airtaudio::api::Alsa::callbackEventOneCycle() {
} }
// Read samples from device in interleaved/non-interleaved format. // Read samples from device in interleaved/non-interleaved format.
if (m_deviceInterleaved[1]) { if (m_deviceInterleaved[1]) {
result = snd_pcm_readi(handle[1], buffer, m_bufferSize); result = snd_pcm_readi(m_private->handles[1], buffer, m_bufferSize);
} else { } else {
void *bufs[channels]; void *bufs[channels];
size_t offset = m_bufferSize * audio::getFormatBytes(format); size_t offset = m_bufferSize * audio::getFormatBytes(format);
for (int32_t i=0; i<channels; i++) for (int32_t i=0; i<channels; i++)
bufs[i] = (void *) (buffer + (i * offset)); bufs[i] = (void *) (buffer + (i * offset));
result = snd_pcm_readn(handle[1], bufs, m_bufferSize); result = snd_pcm_readn(m_private->handles[1], bufs, m_bufferSize);
} }
// get timestamp : (to init here ... // get timestamp : (to init here ...
streamTime = getStreamTime(); streamTime = getStreamTime();
if (result < (int) m_bufferSize) { if (result < (int) m_bufferSize) {
// Either an error or overrun occured. // Either an error or overrun occured.
if (result == -EPIPE) { if (result == -EPIPE) {
snd_pcm_state_t state = snd_pcm_state(handle[1]); snd_pcm_state_t state = snd_pcm_state(m_private->handles[1]);
if (state == SND_PCM_STATE_XRUN) { if (state == SND_PCM_STATE_XRUN) {
m_private->xrun[1] = true; m_private->xrun[1] = true;
result = snd_pcm_prepare(handle[1]); result = snd_pcm_prepare(m_private->handles[1]);
if (result < 0) { if (result < 0) {
ATA_ERROR("error preparing device after overrun, " << snd_strerror(result) << "."); ATA_ERROR("error preparing device after overrun, " << snd_strerror(result) << ".");
} }
@ -1159,7 +1168,7 @@ void airtaudio::api::Alsa::callbackEventOneCycle() {
convertBuffer(&m_userBuffer[1][0], m_deviceBuffer, m_convertInfo[1]); convertBuffer(&m_userBuffer[1][0], m_deviceBuffer, m_convertInfo[1]);
} }
// Check stream latency // Check stream latency
result = snd_pcm_delay(handle[1], &frames); result = snd_pcm_delay(m_private->handles[1], &frames);
if (result == 0 && frames > 0) { if (result == 0 && frames > 0) {
ATA_VERBOSE("Delay in the Input " << frames << " chunk"); ATA_VERBOSE("Delay in the Input " << frames << " chunk");
m_latency[1] = frames; m_latency[1] = frames;
@ -1168,12 +1177,21 @@ void airtaudio::api::Alsa::callbackEventOneCycle() {
noInput: noInput:
streamTime = getStreamTime(); streamTime = getStreamTime();
{
std11::chrono::system_clock::time_point startCall = std11::chrono::system_clock::now();
doStopStream = m_callback(&m_userBuffer[1][0], doStopStream = m_callback(&m_userBuffer[1][0],
streamTime,// - std11::chrono::nanoseconds(m_latency[1]*1000000000LL/int64_t(m_sampleRate)), streamTime,// - std11::chrono::nanoseconds(m_latency[1]*1000000000LL/int64_t(m_sampleRate)),
&m_userBuffer[0][0], &m_userBuffer[0][0],
streamTime,// + std11::chrono::nanoseconds(m_latency[0]*1000000000LL/int64_t(m_sampleRate)), streamTime,// + std11::chrono::nanoseconds(m_latency[0]*1000000000LL/int64_t(m_sampleRate)),
m_bufferSize, m_bufferSize,
status); status);
std11::chrono::system_clock::time_point stopCall = std11::chrono::system_clock::now();
std11::chrono::nanoseconds timeDelay(m_bufferSize*1000000000LL/int64_t(m_sampleRate));
std11::chrono::nanoseconds timeProcess = stopCall - startCall;
if (timeDelay <= timeProcess) {
ATA_ERROR("SOFT XRUN ... : (bufferTime) " << timeDelay.count() << " < " << timeProcess.count() << " (process time) ns");
}
}
if (doStopStream == 2) { if (doStopStream == 2) {
abortStream(); abortStream();
return; return;
@ -1199,22 +1217,22 @@ noInput:
} }
// Write samples to device in interleaved/non-interleaved format. // Write samples to device in interleaved/non-interleaved format.
if (m_deviceInterleaved[0]) { if (m_deviceInterleaved[0]) {
result = snd_pcm_writei(handle[0], buffer, m_bufferSize); result = snd_pcm_writei(m_private->handles[0], buffer, m_bufferSize);
} else { } else {
void *bufs[channels]; void *bufs[channels];
size_t offset = m_bufferSize * audio::getFormatBytes(format); size_t offset = m_bufferSize * audio::getFormatBytes(format);
for (int32_t i=0; i<channels; i++) { for (int32_t i=0; i<channels; i++) {
bufs[i] = (void *) (buffer + (i * offset)); bufs[i] = (void *) (buffer + (i * offset));
} }
result = snd_pcm_writen(handle[0], bufs, m_bufferSize); result = snd_pcm_writen(m_private->handles[0], bufs, m_bufferSize);
} }
if (result < (int) m_bufferSize) { if (result < (int) m_bufferSize) {
// Either an error or underrun occured. // Either an error or underrun occured.
if (result == -EPIPE) { if (result == -EPIPE) {
snd_pcm_state_t state = snd_pcm_state(handle[0]); snd_pcm_state_t state = snd_pcm_state(m_private->handles[0]);
if (state == SND_PCM_STATE_XRUN) { if (state == SND_PCM_STATE_XRUN) {
m_private->xrun[0] = true; m_private->xrun[0] = true;
result = snd_pcm_prepare(handle[0]); result = snd_pcm_prepare(m_private->handles[0]);
if (result < 0) { if (result < 0) {
ATA_ERROR("error preparing device after underrun, " << snd_strerror(result) << "."); ATA_ERROR("error preparing device after underrun, " << snd_strerror(result) << ".");
} }
@ -1228,7 +1246,7 @@ noInput:
goto unlock; goto unlock;
} }
// Check stream latency // Check stream latency
result = snd_pcm_delay(handle[0], &frames); result = snd_pcm_delay(m_private->handles[0], &frames);
if (result == 0 && frames > 0) { if (result == 0 && frames > 0) {
ATA_VERBOSE("Delay in the Output " << frames << " chunk"); ATA_VERBOSE("Delay in the Output " << frames << " chunk");
m_latency[0] = frames; m_latency[0] = frames;