diff options
Diffstat (limited to 'plugins/alexainterface/QtMicrophoneWrapper.cpp')
-rw-r--r-- | plugins/alexainterface/QtMicrophoneWrapper.cpp | 220 |
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; +} |