Clear buffers on backend switch

sleep_for() replaced with sleep_until() in AudioProcessor::process()
Output audio formats in case of error
This commit is contained in:
Kirill Kirilenko 2020-11-12 15:46:05 +03:00
parent 49bf3d44dc
commit a59eb7b967
3 changed files with 34 additions and 23 deletions

View file

@ -78,6 +78,8 @@ void AudioProcessor::process()
{ {
while (doWork_) while (doWork_)
{ {
auto waitUntil = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(5);
const std::size_t bytesToRead = const std::size_t bytesToRead =
bufferSize_ * format_.sampleSize() / 8 * format_.channelCount(); bufferSize_ * format_.sampleSize() / 8 * format_.channelCount();
const std::size_t monitorToRead = const std::size_t monitorToRead =
@ -122,7 +124,7 @@ void AudioProcessor::process()
emit readyRead(); emit readyRead();
} }
std::this_thread::sleep_for(std::chrono::milliseconds(5)); std::this_thread::sleep_until(waitUntil);
} }
} }
@ -157,6 +159,10 @@ qint64 AudioProcessor::bytesAvailable() const
bool AudioProcessor::open(QIODevice::OpenMode mode) bool AudioProcessor::open(QIODevice::OpenMode mode)
{ {
std::unique_lock<std::mutex> lock1(inputMutex_);
std::unique_lock<std::mutex> lock2(outputMutex_);
std::unique_lock<std::mutex> lock3(monitorMutex_);
inputBuffer_.clear(); inputBuffer_.clear();
outputBuffer_.clear(); outputBuffer_.clear();
monitorBuffer_.clear(); monitorBuffer_.clear();
@ -195,6 +201,14 @@ Backend AudioProcessor::getCurrentBackend() const
void AudioProcessor::switchBackend(Backend backend) void AudioProcessor::switchBackend(Backend backend)
{ {
std::unique_lock<std::mutex> lock1(inputMutex_);
std::unique_lock<std::mutex> lock2(outputMutex_);
std::unique_lock<std::mutex> lock3(monitorMutex_);
inputBuffer_.clear();
outputBuffer_.clear();
monitorBuffer_.clear();
if (backend == Backend::Speex) if (backend == Backend::Speex)
dsp_.reset(new SpeexDSP(format_, monitorFormat_)); dsp_.reset(new SpeexDSP(format_, monitorFormat_));
else else

View file

@ -9,11 +9,11 @@ file(GLOB SOURCES *.cpp)
file(GLOB HEADERS *.h) file(GLOB HEADERS *.h)
file(GLOB_RECURSE RESOURCES *.qrc) file(GLOB_RECURSE RESOURCES *.qrc)
if (WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Release") #if (WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Release")
add_executable(${TARGET_NAME} WIN32 ${SOURCES} ${HEADERS} ${RESOURCES}) # add_executable(${TARGET_NAME} WIN32 ${SOURCES} ${HEADERS} ${RESOURCES})
else() #else()
add_executable(${TARGET_NAME} ${SOURCES} ${HEADERS} ${RESOURCES}) add_executable(${TARGET_NAME} ${SOURCES} ${HEADERS} ${RESOURCES})
endif() #endif()
target_link_libraries(${TARGET_NAME} target_link_libraries(${TARGET_NAME}
speexdsp speexdsp

View file

@ -85,6 +85,18 @@ MainWindow::~MainWindow()
stopRecording(); stopRecording();
} }
void fixFormatForDevice(QAudioFormat& format, const QAudioDeviceInfo& info)
{
if (!info.isFormatSupported(format))
{
QAudioFormat newFormat = info.nearestFormat(format);
qWarning(Gui).nospace() << "Preferred format " << format << " is not supported by device "
<< info.deviceName() << ".";
qWarning(Gui) << "Trying to use nearest format" << newFormat;
format = newFormat;
}
}
void MainWindow::initializeAudio(const QAudioDeviceInfo& inputDeviceInfo, void MainWindow::initializeAudio(const QAudioDeviceInfo& inputDeviceInfo,
const QAudioDeviceInfo& outputDeviceInfo, const QAudioDeviceInfo& outputDeviceInfo,
const QAudioDeviceInfo& monitorDeviceInfo) const QAudioDeviceInfo& monitorDeviceInfo)
@ -94,24 +106,9 @@ void MainWindow::initializeAudio(const QAudioDeviceInfo& inputDeviceInfo,
auto outputFormat = getOutputFormat(); auto outputFormat = getOutputFormat();
auto monitorFormat = getMonitorFormat(); auto monitorFormat = getMonitorFormat();
if (!inputDeviceInfo.isFormatSupported(captureFormat)) fixFormatForDevice(captureFormat, inputDeviceInfo);
{ fixFormatForDevice(outputFormat, outputDeviceInfo);
qWarning(Gui) fixFormatForDevice(monitorFormat, monitorDeviceInfo);
<< "Preferred format is not supported by input device - trying to use nearest";
captureFormat = inputDeviceInfo.nearestFormat(captureFormat);
}
if (!monitorDeviceInfo.isFormatSupported(monitorFormat))
{
qWarning(Gui)
<< "Preferred format is not supported by monitor device - trying to use nearest";
monitorFormat = inputDeviceInfo.nearestFormat(monitorFormat);
}
if (!outputDeviceInfo.isFormatSupported(outputFormat))
{
qWarning(Gui)
<< "Preferred format is not supported by output device - trying to use nearest";
outputFormat = inputDeviceInfo.nearestFormat(outputFormat);
}
audioInput_.reset(new QAudioInput(inputDeviceInfo, captureFormat)); audioInput_.reset(new QAudioInput(inputDeviceInfo, captureFormat));
audioOutput_.reset(new QAudioOutput(outputDeviceInfo, outputFormat)); audioOutput_.reset(new QAudioOutput(outputDeviceInfo, outputFormat));