aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/alexainterface/QtMicrophoneWrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/alexainterface/QtMicrophoneWrapper.cpp')
-rw-r--r--plugins/alexainterface/QtMicrophoneWrapper.cpp220
1 files changed, 213 insertions, 7 deletions
diff --git a/plugins/alexainterface/QtMicrophoneWrapper.cpp b/plugins/alexainterface/QtMicrophoneWrapper.cpp
index c3fe0ef..86bfa6f 100644
--- a/plugins/alexainterface/QtMicrophoneWrapper.cpp
+++ b/plugins/alexainterface/QtMicrophoneWrapper.cpp
@@ -30,7 +30,7 @@
****************************************************************************/
#include "QtMicrophoneWrapper.h"
-
+#include <QtEndian>
#include <QDebug>
using alexaClientSDK::avsCommon::avs::AudioInputStream;
@@ -121,7 +121,7 @@ void QtMicrophoneWrapper::setAudioDevice(const QString &deviceName) {
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
- m_audioInfo = QAudioDeviceInfo::defaultInputDevice();
+ QAudioDeviceInfo audioInfo = QAudioDeviceInfo::defaultInputDevice();
QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
@@ -129,20 +129,23 @@ void QtMicrophoneWrapper::setAudioDevice(const QString &deviceName) {
for (QAudioDeviceInfo &device : devices) {
qDebug() << " device name: " << device.deviceName();
if (device.deviceName() == deviceName) {
- m_audioInfo = device;
+ audioInfo = device;
}
}
- qDebug() << "Selected capture device:" << m_audioInfo.deviceName();
+ qDebug() << "Selected capture device:" << audioInfo.deviceName();
qDebug() << "Requested format" << format;
- if (!m_audioInfo.isFormatSupported(format)) {
+ if (!audioInfo.isFormatSupported(format)) {
qWarning() << "QtMicrophoneWrapper: Default format not supported, trying to use the nearest.";
- format = m_audioInfo.nearestFormat(format);
+ format = audioInfo.nearestFormat(format);
qWarning() << "QtMicrophoneWrapper: Nearest format" << format;
}
- m_audioInput = new QAudioInput(m_audioInfo, format, this);
+ m_audioInput = new QAudioInput(audioInfo, format, this);
+
+ m_audioLevelInfo.init(m_audioInput->format());
+
QObject::connect(m_audioInput, &QAudioInput::notify, this, [this](){
QByteArray readBytes = m_audioInputIODevice->readAll();
@@ -153,6 +156,12 @@ void QtMicrophoneWrapper::setAudioDevice(const QString &deviceName) {
static_cast<size_t>(m_readAudioDataBytes)/m_writer->getWordSize() :
static_cast<size_t>(m_readAudioDataBytes);
m_writer->write(m_readAudioData.data(), nWords);
+
+ if (m_levelProcess) {
+ m_audioLevel = m_audioLevelInfo.processBuffer(m_readAudioData);
+ Q_EMIT audioLevelChanged();
+ }
+
m_readAudioData.clear();
m_readAudioDataBytes = 0;
});
@@ -161,3 +170,200 @@ void QtMicrophoneWrapper::setAudioDevice(const QString &deviceName) {
m_audioInput->setNotifyInterval(latency);
qDebug("QtMicrophoneWrapper: Latency is configured to: %d ms", m_audioInput->notifyInterval());
}
+
+AudioLevelInfo::AudioLevelInfo(const QAudioFormat &format)
+{
+ init(format);
+}
+
+bool AudioLevelInfo::init(const QAudioFormat &format)
+{
+ m_valid = true;
+ m_maxAmplitude = 0;
+
+ switch (format.sampleSize()) {
+ case 8:
+ switch (format.sampleType()) {
+ case QAudioFormat::UnSignedInt:
+ m_maxAmplitude = 255;
+ break;
+ case QAudioFormat::SignedInt:
+ m_maxAmplitude = 127;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 16:
+ switch (format.sampleType()) {
+ case QAudioFormat::UnSignedInt:
+ m_maxAmplitude = 65535;
+ break;
+ case QAudioFormat::SignedInt:
+ m_maxAmplitude = 32767;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 32:
+ switch (format.sampleType()) {
+ case QAudioFormat::UnSignedInt:
+ m_maxAmplitude = 0xffffffff;
+ break;
+ case QAudioFormat::SignedInt:
+ m_maxAmplitude = 0x7fffffff;
+ break;
+ case QAudioFormat::Float:
+ m_maxAmplitude = 0x7fffffff;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ m_valid = false;
+ return false;
+ }
+
+ if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::UnSignedInt) {
+ m_getAudioLevelValue = &AudioLevelInfo::processUnSignedInt8;
+ } else if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::SignedInt) {
+ m_getAudioLevelValue = &AudioLevelInfo::processSignedInt8;
+ } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::UnSignedInt) {
+ if (format.byteOrder() == QAudioFormat::LittleEndian) {
+ m_getAudioLevelValue = &AudioLevelInfo::processUnSignedInt16LE;
+ }
+ else {
+ m_getAudioLevelValue = &AudioLevelInfo::processUnSignedInt16BE;
+ }
+ } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::SignedInt) {
+ if (format.byteOrder() == QAudioFormat::LittleEndian) {
+ m_getAudioLevelValue = &AudioLevelInfo::processSignedInt16LE;
+ }
+ else{
+ m_getAudioLevelValue = &AudioLevelInfo::processSignedInt16BE;
+ }
+ } else if (format.sampleSize() == 32 && format.sampleType() == QAudioFormat::UnSignedInt) {
+ if (format.byteOrder() == QAudioFormat::LittleEndian) {
+ m_getAudioLevelValue = &AudioLevelInfo::processUnSignedInt32LE;
+ }
+ else {
+ m_getAudioLevelValue = &AudioLevelInfo::processUnSignedInt32BE;
+ }
+ } else if (format.sampleSize() == 32 && format.sampleType() == QAudioFormat::SignedInt) {
+ if (format.byteOrder() == QAudioFormat::LittleEndian) {
+ m_getAudioLevelValue = &AudioLevelInfo::processSignedInt32LE;
+ }
+ else {
+ m_getAudioLevelValue = &AudioLevelInfo::processSignedInt32BE;
+ }
+ } else if (format.sampleSize() == 32 && format.sampleType() == QAudioFormat::Float) {
+ m_getAudioLevelValue = &AudioLevelInfo::processFloat;
+ } else {
+ m_getAudioLevelValue = &AudioLevelInfo::processDefault;
+ m_valid = false;
+ }
+
+ if (format.sampleSize() % 8 != 0) {
+ m_valid = false;
+ }
+
+ m_channelBytes = format.sampleSize() / 8;
+ m_sampleBytes = m_channelBytes * format.channelCount();
+ m_channelCount = format.channelCount();
+
+ return m_valid;
+}
+
+qreal AudioLevelInfo::processBuffer(const QByteArray &ba) const
+{
+ if (ba.size() == 0) {
+ return 0.0;
+ }
+
+ if (m_valid) {
+ if (ba.size() % m_sampleBytes != 0)
+ return 0.0;
+
+ const int numSamples = ba.size() / m_sampleBytes;
+ const int step = numSamples / 50 + 1; //check 50 samples from buffer, skip all other info
+
+ quint32 maxValue = 0;
+ const char *ptr = ba.constData();
+
+ for (int i = 0; i < numSamples; i += step) {
+ for (int j = 0; j < m_channelCount; ++j) {
+ quint32 value = (*m_getAudioLevelValue)(ptr);
+ maxValue = qMax(value, maxValue);
+ ptr += m_channelBytes;
+ }
+ ptr += m_channelBytes * (m_channelCount) * (step - 1);
+ }
+
+ maxValue = qMin(maxValue, m_maxAmplitude);
+ return qreal(maxValue) / m_maxAmplitude;
+ }
+
+ return 0.0;
+}
+
+quint32 AudioLevelInfo::processUnSignedInt8(const char *ptr)
+{
+ return *reinterpret_cast<const quint8*>(ptr);
+}
+
+quint32 AudioLevelInfo::processSignedInt8(const char *ptr)
+{
+ return static_cast<quint32>(qAbs(*reinterpret_cast<const qint8*>(ptr)));
+}
+
+quint32 AudioLevelInfo::processUnSignedInt16LE(const char *ptr)
+{
+ return qFromLittleEndian<quint16>(ptr);
+}
+
+quint32 AudioLevelInfo::processUnSignedInt16BE(const char *ptr)
+{
+ return qFromBigEndian<quint16>(ptr);
+}
+
+quint32 AudioLevelInfo::processSignedInt16LE(const char *ptr)
+{
+ return static_cast<quint32>(qAbs(qFromLittleEndian<qint16>(ptr)));
+}
+
+quint32 AudioLevelInfo::processSignedInt16BE(const char *ptr)
+{
+ return static_cast<quint32>(qAbs(qFromBigEndian<qint16>(ptr)));
+}
+
+quint32 AudioLevelInfo::processUnSignedInt32LE(const char *ptr)
+{
+ return qFromLittleEndian<quint32>(ptr);
+}
+
+quint32 AudioLevelInfo::processUnSignedInt32BE(const char *ptr)
+{
+ return qFromBigEndian<quint32>(ptr);
+}
+
+quint32 AudioLevelInfo::processSignedInt32LE(const char *ptr)
+{
+ return static_cast<quint32>(qAbs(qFromLittleEndian<qint32>(ptr)));
+}
+
+quint32 AudioLevelInfo::processSignedInt32BE(const char *ptr)
+{
+ return static_cast<quint32>(qAbs(qFromBigEndian<qint32>(ptr)));
+}
+
+quint32 AudioLevelInfo::processFloat(const char *ptr)
+{
+ return static_cast<quint32>(qAbs(*reinterpret_cast<const float*>(ptr) * 0x7fffffff)); // assumes 0-1.0
+}
+quint32 AudioLevelInfo::processDefault(const char *ptr)
+{
+ Q_UNUSED(ptr)
+ return 0;
+}