Skip to content
Snippets Groups Projects
Commit 44cd6110 authored by Guillaume Roguez's avatar Guillaume Roguez
Browse files

portaudio: factorize device open code

This factorization decreases code lines and increases
maintainance factor.

Change-Id: If79a20594ccbfbab0ced400d5fff606afa6474dd
parent 0a5e63b6
Branches
Tags
No related merge requests found
...@@ -267,42 +267,45 @@ PortAudioLayer::PortAudioLayerImpl::paOutputCallback(PortAudioLayer& parent, ...@@ -267,42 +267,45 @@ PortAudioLayer::PortAudioLayerImpl::paOutputCallback(PortAudioLayer& parent,
(void) timeInfo; (void) timeInfo;
(void) statusFlags; (void) statusFlags;
AudioFormat mainBufferAudioFormat = Manager::instance().getRingBufferPool().getInternalAudioFormat(); auto& manager = Manager::instance();
bool resample = parent.audioFormat_.sample_rate != mainBufferAudioFormat.sample_rate; auto& buffer_pool = manager.getRingBufferPool();
auto urgentFramesToGet = parent.urgentRingBuffer_.availableForGet(RingBufferPool::DEFAULT_ID);
auto mainbuffer_format = buffer_pool.getInternalAudioFormat();
auto layer_format = parent.audioFormat_;
auto resample = layer_format.sample_rate != mainbuffer_format.sample_rate;
auto urgentFramesToGet = parent.urgentRingBuffer_.availableForGet(RingBufferPool::DEFAULT_ID);
if (urgentFramesToGet > 0) { if (urgentFramesToGet > 0) {
RING_WARN("Getting urgent frames."); RING_WARN("Getting urgent frames");
size_t totSample = std::min(framesPerBuffer, (unsigned long)urgentFramesToGet); auto totSample = std::min(framesPerBuffer, (unsigned long)urgentFramesToGet);
playbackBuff_.setFormat(parent.audioFormat_); playbackBuff_.setFormat(layer_format);
playbackBuff_.resize(totSample); playbackBuff_.resize(totSample);
parent.urgentRingBuffer_.get(playbackBuff_, RingBufferPool::DEFAULT_ID); parent.urgentRingBuffer_.get(playbackBuff_, RingBufferPool::DEFAULT_ID);
playbackBuff_.applyGain(parent.isPlaybackMuted_ ? 0.0 : parent.playbackGain_); playbackBuff_.applyGain(parent.isPlaybackMuted_ ? 0.0 : parent.playbackGain_);
playbackBuff_.interleave(outputBuffer); playbackBuff_.interleave(outputBuffer);
Manager::instance().getRingBufferPool().discard(totSample, RingBufferPool::DEFAULT_ID); manager.getRingBufferPool().discard(totSample, RingBufferPool::DEFAULT_ID);
} }
unsigned normalFramesToGet = auto normalFramesToGet = buffer_pool.availableForGet(RingBufferPool::DEFAULT_ID);
Manager::instance().getRingBufferPool().availableForGet(RingBufferPool::DEFAULT_ID);
if (normalFramesToGet > 0) { if (normalFramesToGet > 0) {
double resampleFactor = 1.0; double resampleFactor;
unsigned readableSamples = framesPerBuffer; decltype(normalFramesToGet) readableSamples;
if (resample) { if (resample) {
resampleFactor = static_cast<double>(parent.audioFormat_.sample_rate) resampleFactor = static_cast<double>(layer_format.sample_rate) / mainbuffer_format.sample_rate;
/ mainBufferAudioFormat.sample_rate;
readableSamples = std::ceil(framesPerBuffer / resampleFactor); readableSamples = std::ceil(framesPerBuffer / resampleFactor);
} else {
resampleFactor = 1.0;
readableSamples = framesPerBuffer;
} }
readableSamples = std::min(readableSamples, normalFramesToGet); readableSamples = std::min(readableSamples, normalFramesToGet);
playbackBuff_.setFormat(parent.audioFormat_); playbackBuff_.setFormat(parent.audioFormat_);
playbackBuff_.resize(readableSamples); playbackBuff_.resize(readableSamples);
Manager::instance().getRingBufferPool().getData(playbackBuff_, RingBufferPool::DEFAULT_ID); buffer_pool.getData(playbackBuff_, RingBufferPool::DEFAULT_ID);
playbackBuff_.applyGain(parent.isPlaybackMuted_ ? 0.0 : parent.playbackGain_); playbackBuff_.applyGain(parent.isPlaybackMuted_ ? 0.0 : parent.playbackGain_);
if (resample) { if (resample) {
...@@ -313,10 +316,9 @@ PortAudioLayer::PortAudioLayerImpl::paOutputCallback(PortAudioLayer& parent, ...@@ -313,10 +316,9 @@ PortAudioLayer::PortAudioLayerImpl::paOutputCallback(PortAudioLayer& parent,
} else { } else {
playbackBuff_.interleave(outputBuffer); playbackBuff_.interleave(outputBuffer);
} }
} } else {
if (normalFramesToGet <= 0) { auto tone = manager.getTelephoneTone();
auto tone = Manager::instance().getTelephoneTone(); auto file_tone = manager.getTelephoneFile();
auto file_tone = Manager::instance().getTelephoneFile();
playbackBuff_.setFormat(parent.audioFormat_); playbackBuff_.setFormat(parent.audioFormat_);
playbackBuff_.resize(framesPerBuffer); playbackBuff_.resize(framesPerBuffer);
...@@ -326,11 +328,11 @@ PortAudioLayer::PortAudioLayerImpl::paOutputCallback(PortAudioLayer& parent, ...@@ -326,11 +328,11 @@ PortAudioLayer::PortAudioLayerImpl::paOutputCallback(PortAudioLayer& parent,
} else if (file_tone) { } else if (file_tone) {
file_tone->getNext(playbackBuff_, parent.playbackGain_); file_tone->getNext(playbackBuff_, parent.playbackGain_);
} else { } else {
//RING_WARN("No tone or file_tone!");
playbackBuff_.reset(); playbackBuff_.reset();
} }
playbackBuff_.interleave(outputBuffer); playbackBuff_.interleave(outputBuffer);
} }
return paContinue; return paContinue;
} }
...@@ -361,10 +363,8 @@ PortAudioLayer::PortAudioLayerImpl::paInputCallback(PortAudioLayer& parent, ...@@ -361,10 +363,8 @@ PortAudioLayer::PortAudioLayerImpl::paInputCallback(PortAudioLayer& parent,
inBuff.applyGain(parent.isCaptureMuted_ ? 0.0 : parent.captureGain_); inBuff.applyGain(parent.isCaptureMuted_ ? 0.0 : parent.captureGain_);
if (resample) { if (resample) {
auto outSamples = auto sample_factor = static_cast<double>(parent.audioInputFormat_.sample_rate) / mainBufferFormat.sample_rate;
framesPerBuffer auto outSamples = framesPerBuffer / sample_factor;
/ (static_cast<double>(parent.audioInputFormat_.sample_rate)
/ mainBufferFormat.sample_rate);
AudioBuffer out(outSamples, mainBufferFormat); AudioBuffer out(outSamples, mainBufferFormat);
parent.inputResampler_->resample(inBuff, out); parent.inputResampler_->resample(inBuff, out);
parent.dcblocker_.process(out); parent.dcblocker_.process(out);
...@@ -416,37 +416,52 @@ void ...@@ -416,37 +416,52 @@ void
PortAudioLayer::PortAudioLayerImpl::terminate() const PortAudioLayer::PortAudioLayerImpl::terminate() const
{ {
RING_DBG("PortAudioLayer terminate."); RING_DBG("PortAudioLayer terminate.");
const auto err = Pa_Terminate(); auto err = Pa_Terminate();
if (err != paNoError) if (err != paNoError)
RING_ERR("PortAudioLayer error : %s", Pa_GetErrorText(err)); RING_ERR("PortAudioLayer error : %s", Pa_GetErrorText(err));
} }
void static void
PortAudioLayer::PortAudioLayerImpl::initStream(PortAudioLayer& parent) openStreamDevice(PaStream** stream,
PaDeviceIndex device, Direction direction,
PaStreamCallback* callback, void* user_data)
{ {
parent.dcblocker_.reset(); auto is_out = direction == Direction::Output;
auto device_info = Pa_GetDeviceInfo(device);
RING_DBG("Open PortAudio Output Stream");
PaStreamParameters outputParameters;
outputParameters.device = indexOut_;
if (outputParameters.device == paNoDevice) { PaStreamParameters params;
RING_ERR("Error: No valid output device. There will be no sound."); params.device = device;
} else { params.channelCount = is_out ? device_info->maxOutputChannels : device_info->maxInputChannels;
const auto outputDeviceInfo = Pa_GetDeviceInfo(outputParameters.device); params.sampleFormat = paInt16;
outputParameters.channelCount = parent.audioFormat_.nb_channels = outputDeviceInfo->maxOutputChannels; params.suggestedLatency = is_out ? device_info->defaultLowOutputLatency: device_info->defaultLowInputLatency;
outputParameters.sampleFormat = paInt16; params.hostApiSpecificStreamInfo = nullptr;
outputParameters.suggestedLatency = outputDeviceInfo->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = nullptr;
auto err = Pa_OpenStream( auto err = Pa_OpenStream(
&streams_[Direction::Output], stream,
nullptr, is_out ? nullptr : &params,
&outputParameters, is_out ? &params : nullptr,
outputDeviceInfo->defaultSampleRate, device_info->defaultSampleRate,
paFramesPerBufferUnspecified, paFramesPerBufferUnspecified,
paNoFlag, paNoFlag,
[](const void* inputBuffer, void* outputBuffer, callback,
user_data);
if (err != paNoError)
RING_ERR("PortAudioLayer error : %s", Pa_GetErrorText(err));
}
void
PortAudioLayer::PortAudioLayerImpl::initStream(PortAudioLayer& parent)
{
parent.dcblocker_.reset();
RING_DBG("Open PortAudio Output Stream");
if (indexOut_ != paNoDevice) {
openStreamDevice(&streams_[Direction::Output],
indexOut_,
Direction::Output,
[](const void* inputBuffer,
void* outputBuffer,
unsigned long framesPerBuffer, unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo, const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags, PaStreamCallbackFlags statusFlags,
...@@ -460,31 +475,17 @@ PortAudioLayer::PortAudioLayerImpl::initStream(PortAudioLayer& parent) ...@@ -460,31 +475,17 @@ PortAudioLayer::PortAudioLayerImpl::initStream(PortAudioLayer& parent)
statusFlags); statusFlags);
}, },
&parent); &parent);
if(err != paNoError) } else {
RING_ERR("PortAudioLayer error : %s", Pa_GetErrorText(err)); RING_ERR("Error: No valid output device. There will be no sound.");
} }
RING_DBG("Open PortAudio Input Stream"); RING_DBG("Open PortAudio Input Stream");
PaStreamParameters inputParameters; if (indexIn_ != paNoDevice) {
inputParameters.device = indexIn_; openStreamDevice(&streams_[Direction::Input],
indexIn_,
if (inputParameters.device == paNoDevice) { Direction::Input,
RING_ERR("Error: No valid input device. There will be no mic."); [](const void* inputBuffer,
} else { void* outputBuffer,
const auto inputDeviceInfo = Pa_GetDeviceInfo(inputParameters.device);
inputParameters.channelCount = parent.audioInputFormat_.nb_channels = inputDeviceInfo->maxInputChannels;
inputParameters.sampleFormat = paInt16;
inputParameters.suggestedLatency = inputDeviceInfo->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = nullptr;
auto err = Pa_OpenStream(
&streams_[Direction::Input],
&inputParameters,
nullptr,
inputDeviceInfo->defaultSampleRate,
paFramesPerBufferUnspecified,
paNoFlag,
[](const void* inputBuffer, void* outputBuffer,
unsigned long framesPerBuffer, unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo, const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags, PaStreamCallbackFlags statusFlags,
...@@ -498,8 +499,8 @@ PortAudioLayer::PortAudioLayerImpl::initStream(PortAudioLayer& parent) ...@@ -498,8 +499,8 @@ PortAudioLayer::PortAudioLayerImpl::initStream(PortAudioLayer& parent)
statusFlags); statusFlags);
}, },
&parent); &parent);
if (err != paNoError) } else {
RING_ERR("PortAudioLayer error : %s", Pa_GetErrorText(err)); RING_ERR("Error: No valid input device. There will be no mic.");
} }
RING_DBG("Start PortAudio Streams"); RING_DBG("Start PortAudio Streams");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment