mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-02 15:15:50 +08:00
127 lines
4.6 KiB
C++
127 lines
4.6 KiB
C++
/* Copyright (C) 2019
|
|
* swift project Community / Contributors
|
|
*
|
|
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
|
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
|
|
* or distributed except according to the terms contained in the LICENSE file.
|
|
*/
|
|
|
|
//! \file
|
|
|
|
#include "output.h"
|
|
#include "blackmisc/logmessage.h"
|
|
#include "blacksound/audioutilities.h"
|
|
|
|
#include <QDebug>
|
|
#include <QStringBuilder>
|
|
#include <cmath>
|
|
|
|
using namespace BlackMisc;
|
|
using namespace BlackMisc::Audio;
|
|
using namespace BlackSound;
|
|
using namespace BlackSound::SampleProvider;
|
|
|
|
namespace BlackCore
|
|
{
|
|
namespace Afv
|
|
{
|
|
namespace Audio
|
|
{
|
|
CAudioOutputBuffer::CAudioOutputBuffer(ISampleProvider *sampleProvider, QObject *parent) :
|
|
QIODevice(parent),
|
|
m_sampleProvider(sampleProvider)
|
|
{
|
|
this->setObjectName("CAudioOutputBuffer");
|
|
}
|
|
|
|
qint64 CAudioOutputBuffer::readData(char *data, qint64 maxlen)
|
|
{
|
|
int sampleBytes = m_outputFormat.sampleSize() / 8;
|
|
int channelCount = m_outputFormat.channelCount();
|
|
qint64 count = maxlen / (sampleBytes * channelCount);
|
|
QVector<float> buffer;
|
|
m_sampleProvider->readSamples(buffer, count);
|
|
|
|
for (float sample : buffer)
|
|
{
|
|
const float absSample = qAbs(sample);
|
|
if (absSample > m_maxSampleOutput) { m_maxSampleOutput = absSample; }
|
|
}
|
|
|
|
m_sampleCount += buffer.size();
|
|
if (m_sampleCount >= SampleCountPerEvent)
|
|
{
|
|
OutputVolumeStreamArgs outputVolumeStreamArgs;
|
|
outputVolumeStreamArgs.PeakRaw = m_maxSampleOutput / 1.0;
|
|
outputVolumeStreamArgs.PeakDb = static_cast<float>(20 * std::log10(outputVolumeStreamArgs.PeakRaw));
|
|
const double db = qBound(m_minDb, outputVolumeStreamArgs.PeakDb, m_maxDb);
|
|
double ratio = (db - m_minDb) / (m_maxDb - m_minDb);
|
|
if (ratio < 0.30) { ratio = 0.0; }
|
|
if (ratio > 1.0) { ratio = 1.0; }
|
|
outputVolumeStreamArgs.PeakVU = ratio;
|
|
emit outputVolumeStream(outputVolumeStreamArgs);
|
|
m_sampleCount = 0;
|
|
m_maxSampleOutput = 0;
|
|
}
|
|
|
|
if (channelCount == 2)
|
|
{
|
|
buffer = convertFromMonoToStereo(buffer);
|
|
}
|
|
|
|
memcpy(data, buffer.constData(), maxlen);
|
|
|
|
return maxlen;
|
|
}
|
|
|
|
qint64 CAudioOutputBuffer::writeData(const char *data, qint64 len)
|
|
{
|
|
Q_UNUSED(data)
|
|
Q_UNUSED(len)
|
|
return -1;
|
|
}
|
|
|
|
Output::Output(QObject *parent) : QObject(parent)
|
|
{
|
|
this->setObjectName("COutput");
|
|
}
|
|
|
|
void Output::start(const CAudioDeviceInfo &outputDevice, ISampleProvider *sampleProvider)
|
|
{
|
|
if (m_started) { return; }
|
|
|
|
m_audioOutputBuffer = new CAudioOutputBuffer(sampleProvider, this);
|
|
connect(m_audioOutputBuffer, &CAudioOutputBuffer::outputVolumeStream, this, &Output::outputVolumeStream);
|
|
|
|
m_device = outputDevice;
|
|
|
|
QAudioFormat outputFormat;
|
|
outputFormat.setSampleRate(48000);
|
|
outputFormat.setChannelCount(1);
|
|
outputFormat.setSampleSize(32);
|
|
outputFormat.setSampleType(QAudioFormat::Float);
|
|
outputFormat.setByteOrder(QAudioFormat::LittleEndian);
|
|
outputFormat.setCodec("audio/pcm");
|
|
|
|
QAudioDeviceInfo selectedDevice = getLowestLatencyDevice(outputDevice, outputFormat);
|
|
m_audioOutputCom.reset(new QAudioOutput(selectedDevice, outputFormat));
|
|
m_audioOutputBuffer->open(QIODevice::ReadWrite | QIODevice::Unbuffered);
|
|
m_audioOutputBuffer->setAudioFormat(outputFormat);
|
|
m_audioOutputCom->start(m_audioOutputBuffer);
|
|
|
|
m_started = true;
|
|
}
|
|
|
|
void Output::stop()
|
|
{
|
|
if (!m_started) { return; }
|
|
m_started = false;
|
|
m_audioOutputCom->stop();
|
|
m_audioOutputCom.reset();
|
|
m_audioOutputBuffer->deleteLater();
|
|
m_audioOutputBuffer = nullptr;
|
|
}
|
|
} // ns
|
|
} // ns
|
|
} // ns
|