diff --git a/include/f1x/openauto/autoapp/Projection/RtAudioOutput.hpp b/include/f1x/openauto/autoapp/Projection/RtAudioOutput.hpp
new file mode 100644
index 0000000..1e111b8
--- /dev/null
+++ b/include/f1x/openauto/autoapp/Projection/RtAudioOutput.hpp
@@ -0,0 +1,63 @@
+/*
+* This file is part of openauto project.
+* Copyright (C) 2018 f1x.studio (Michal Szwaj)
+*
+* openauto is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 3 of the License, or
+* (at your option) any later version.
+
+* openauto is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with openauto. If not, see .
+*/
+
+#pragma once
+
+#include
+#include
+#include
+
+namespace f1x
+{
+namespace openauto
+{
+namespace autoapp
+{
+namespace projection
+{
+
+class RtAudioOutput: public IAudioOutput
+{
+public:
+ RtAudioOutput(uint32_t channelCount, uint32_t sampleSize, uint32_t sampleRate);
+ bool open() override;
+ void write(const aasdk::common::DataConstBuffer& buffer) override;
+ void start() override;
+ void stop() override;
+ void suspend() override;
+ uint32_t getSampleSize() const override;
+ uint32_t getChannelCount() const override;
+ uint32_t getSampleRate() const override;
+
+private:
+ static int audioBufferReadHandler(void* outputBuffer, void* inputBuffer, unsigned int nBufferFrames,
+ double streamTime, RtAudioStreamStatus status, void* userData);
+
+ uint32_t channelCount_;
+ uint32_t sampleSize_;
+ uint32_t sampleRate_;
+ SequentialBuffer audioBuffer_;
+ bool playbackStarted_;
+ RtAudio dac_;
+ std::mutex mutex_;
+};
+
+}
+}
+}
+}
diff --git a/src/autoapp/Projection/AudioService.cpp b/src/autoapp/Projection/AudioService.cpp
index 3e68c11..d5d2da5 100644
--- a/src/autoapp/Projection/AudioService.cpp
+++ b/src/autoapp/Projection/AudioService.cpp
@@ -93,6 +93,12 @@ void AudioService::onChannelOpenRequest(const aasdk::proto::messages::ChannelOpe
OPENAUTO_LOG(info) << "[AudioService] open request"
<< ", channel: " << aasdk::messenger::channelIdToString(channel_->getId())
<< ", priority: " << request.priority();
+
+ OPENAUTO_LOG(debug) << "[AudioService] channel: " << aasdk::messenger::channelIdToString(channel_->getId())
+ << " audio output sample rate: " << audioOutput_->getSampleRate()
+ << ", sample size: " << audioOutput_->getSampleSize()
+ << ", channel count: " << audioOutput_->getChannelCount();
+
const aasdk::proto::enums::Status::Enum status = audioOutput_->open() ? aasdk::proto::enums::Status::OK : aasdk::proto::enums::Status::FAIL;
OPENAUTO_LOG(info) << "[AudioService] open status: " << status
<< ", channel: " << aasdk::messenger::channelIdToString(channel_->getId());
diff --git a/src/autoapp/Projection/RtAudioOutput.cpp b/src/autoapp/Projection/RtAudioOutput.cpp
new file mode 100644
index 0000000..68a1756
--- /dev/null
+++ b/src/autoapp/Projection/RtAudioOutput.cpp
@@ -0,0 +1,148 @@
+/*
+* This file is part of openauto project.
+* Copyright (C) 2018 f1x.studio (Michal Szwaj)
+*
+* openauto is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 3 of the License, or
+* (at your option) any later version.
+
+* openauto is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with openauto. If not, see .
+*/
+
+#include
+#include
+
+namespace f1x
+{
+namespace openauto
+{
+namespace autoapp
+{
+namespace projection
+{
+
+RtAudioOutput::RtAudioOutput(uint32_t channelCount, uint32_t sampleSize, uint32_t sampleRate)
+ : channelCount_(channelCount)
+ , sampleSize_(sampleSize)
+ , sampleRate_(sampleRate)
+ , playbackStarted_(false)
+{
+}
+
+bool RtAudioOutput::open()
+{
+ std::lock_guard lock(mutex_);
+
+ if(dac_.getDeviceCount() > 0)
+ {
+ RtAudio::StreamParameters parameters;
+ parameters.deviceId = dac_.getDefaultOutputDevice();
+ parameters.nChannels = channelCount_;
+ parameters.firstChannel = 0;
+
+ try
+ {
+ uint32_t bufferFrames = 256;
+ dac_.openStream(¶meters, nullptr, RTAUDIO_SINT16, sampleRate_, &bufferFrames, &RtAudioOutput::audioBufferReadHandler, static_cast(this));
+
+ return audioBuffer_.open(QIODevice::ReadWrite);
+ }
+ catch(const RtAudioError& e)
+ {
+ OPENAUTO_LOG(error) << "[RtAudioOutput] Failed to open audio output, what: " << e.what();
+ }
+ }
+ else
+ {
+ OPENAUTO_LOG(error) << "[RtAudioOutput] No output devices found.";
+ }
+
+ return false;
+}
+
+void RtAudioOutput::write(const aasdk::common::DataConstBuffer& buffer)
+{
+ audioBuffer_.write(reinterpret_cast(buffer.cdata), buffer.size);
+}
+
+void RtAudioOutput::start()
+{
+ std::lock_guard lock(mutex_);
+
+ if(dac_.isStreamOpen() && !dac_.isStreamRunning())
+ {
+ try
+ {
+ dac_.startStream();
+ }
+ catch(const RtAudioError& e)
+ {
+ OPENAUTO_LOG(error) << "[RtAudioOutput] Failed to start audio output, what: " << e.what();
+ }
+ }
+}
+
+void RtAudioOutput::stop()
+{
+ std::lock_guard lock(mutex_);
+
+ this->suspend();
+
+ if(dac_.isStreamOpen())
+ {
+ dac_.closeStream();
+ }
+}
+
+void RtAudioOutput::suspend()
+{
+ std::lock_guard lock(mutex_);
+
+ if(!dac_.isStreamOpen() && !dac_.isStreamRunning())
+ {
+ try
+ {
+ dac_.stopStream();
+ }
+ catch(const RtAudioError& e)
+ {
+ OPENAUTO_LOG(error) << "[RtAudioOutput] Failed to suspend audio output, what: " << e.what();
+ }
+ }
+}
+
+uint32_t RtAudioOutput::getSampleSize() const
+{
+ return sampleSize_;
+}
+
+uint32_t RtAudioOutput::getChannelCount() const
+{
+ return channelCount_;
+}
+
+uint32_t RtAudioOutput::getSampleRate() const
+{
+ return sampleRate_;
+}
+
+int RtAudioOutput::audioBufferReadHandler(void* outputBuffer, void* inputBuffer, unsigned int nBufferFrames,
+ double streamTime, RtAudioStreamStatus status, void* userData)
+{
+ RtAudioOutput* self = static_cast(userData);
+ const auto bufferSize = nBufferFrames * (self->sampleSize_ / 8) * self->channelCount_;
+ self->audioBuffer_.read(reinterpret_cast(outputBuffer), bufferSize);
+ return 0;
+}
+
+}
+}
+}
+}
diff --git a/src/autoapp/Projection/ServiceFactory.cpp b/src/autoapp/Projection/ServiceFactory.cpp
index 9205b25..2e54710 100644
--- a/src/autoapp/Projection/ServiceFactory.cpp
+++ b/src/autoapp/Projection/ServiceFactory.cpp
@@ -32,6 +32,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -64,17 +65,20 @@ ServiceList ServiceFactory::create(aasdk::messenger::IMessenger::Pointer messeng
if(configuration_->musicAudioChannelEnabled())
{
- IAudioOutput::Pointer mediaAudioOutput(new QtAudioOutput(2, 16, 48000), std::bind(&QObject::deleteLater, std::placeholders::_1));
+ //IAudioOutput::Pointer mediaAudioOutput(new QtAudioOutput(2, 16, 48000), std::bind(&QObject::deleteLater, std::placeholders::_1));
+ auto mediaAudioOutput(std::make_shared(2, 16, 48000));
serviceList.emplace_back(std::make_shared(ioService_, messenger, std::move(mediaAudioOutput)));
}
if(configuration_->speechAudioChannelEnabled())
{
IAudioOutput::Pointer speechAudioOutput(new QtAudioOutput(1, 16, 16000), std::bind(&QObject::deleteLater, std::placeholders::_1));
+ //auto speechAudioOutput(std::make_shared(1, 16, 1600));
serviceList.emplace_back(std::make_shared(ioService_, messenger, std::move(speechAudioOutput)));
}
IAudioOutput::Pointer systemAudioOutput(new QtAudioOutput(1, 16, 16000), std::bind(&QObject::deleteLater, std::placeholders::_1));
+ //auto systemAudioOutput(std::make_shared(1, 16, 1600));
serviceList.emplace_back(std::make_shared(ioService_, messenger, std::move(systemAudioOutput)));
serviceList.emplace_back(std::make_shared(ioService_, messenger));