//
// AudioRenderer.cpp
// HighwayDash
//
// Created by John Ryland on 18/02/2016.
// Copyright © 2016 John Ryland. All rights reserved.
//
#include "AudioRenderer.h"
#include "Log.h"
#include <QAudioOutput>
#include <vector>
struct AudioRenderer::Pimpl
{
// private implementation details here
QIODevice *m_audioDevice;
QAudioOutput *m_audioUnit;
};
AudioRenderer::AudioRenderer()
: m_pimpl(std::unique_ptr<Pimpl>(new Pimpl()))
{
m_pimpl->m_audioUnit = nullptr;
m_pimpl->m_audioDevice = nullptr;
}
AudioRenderer::~AudioRenderer()
{
delete m_pimpl->m_audioUnit;
}
void AudioRenderer::initialize(SampleRate a_rate, BitsPerChannel a_bitsPerChannel, Channels a_channels)
{
QAudioFormat format;
// Set up the format, eg.
format.setSampleRate(a_rate);
format.setChannelCount(a_channels);
format.setSampleSize(a_bitsPerChannel);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format)) {
Log(LL_Warn, "AUDIO", "Raw audio format not supported by backend, cannot play audio.");
return;
}
delete m_pimpl->m_audioUnit;
m_pimpl->m_audioUnit = new QAudioOutput(format, this);
m_pimpl->m_audioUnit->setNotifyInterval(50);
m_pimpl->m_audioUnit->setBufferSize(100000);//in bytes
m_pimpl->m_audioUnit->setVolume(0.3);
connect(m_pimpl->m_audioUnit, SIGNAL(notify()), this, SLOT(writeMoreData()));
}
void AudioRenderer::start()
{
if (m_pimpl->m_audioUnit)
{
m_pimpl->m_audioDevice = m_pimpl->m_audioUnit->start();
writeMoreData();
}
}
void AudioRenderer::stop()
{
m_pimpl->m_audioUnit->stop();
}
void AudioRenderer::writeMoreData()
{
int nbBytes = m_pimpl->m_audioUnit->bytesFree();
if (nbBytes > 0 && m_pimpl->m_audioDevice)
{
std::vector<char> buf;
buf.resize(nbBytes);
renderSamples(buf.data(), buf.size()/2);
m_pimpl->m_audioDevice->write(buf.data(), buf.size());
}
}