1.获取麦克风阵列:
QList<QAudioDeviceInfo> infos = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
for (int i = 0; i < infos.count(); i++)
{
qDebug() << infos.at(i).deviceName();
}
2.QAudioFormat
QAudioFormat formatAudio;
formatAudio.setSampleRate(8000);
formatAudio.setChannelCount(1);
formatAudio.setSampleSize(16);
formatAudio.setSampleType(QAudioFormat::SignedInt);
formatAudio.setByteOrder(QAudioFormat::LittleEndian);
formatAudio.setCodec("audio/pcm");
采样频率,声道数,采样位数
3.QList的push_back()
4.进行录音测试,获取过程中录入音量的最大值。
#pragma once
#include <QObject>
#include "GNIODevice.h"
#include <QStringList>
#include <QAudioRecorder>
#include <QAudioInput>
#include <QAudioFormat>
#include <QAudioBuffer>
#include <QAudioProbe>
#include <QFile>
#include <QMutex>
#include <qeventloop.h>
class MacController1 : public QObject
{
Q_OBJECT
public:
MacController1(QObject *parent);
~MacController1();
QStringList getMacList();
void StartTestingMac(int macIndex);
void StopTestingMac();
private:
QAudioFormat formatAudio;
GNIODevice* device;
int currentVolume;
int max_Volume;
QAudioInput * audioInput;
private:
void runTest(int index);
public slots:
void UpdateTestDisplay();
};
#include "MacController1.h"
#include <thread>
MacController1::MacController1(QObject *parent)
: QObject(parent)
{
formatAudio.setSampleRate(8000);
formatAudio.setChannelCount(1);
formatAudio.setSampleSize(16);
formatAudio.setSampleType(QAudioFormat::SignedInt);
formatAudio.setByteOrder(QAudioFormat::LittleEndian);
formatAudio.setCodec("audio/pcm");
currentVolume = 0;
max_Volume = 0;
}
MacController1::~MacController1()
{}
void MacController1::runTest(int index)
{
device->start();
audioInput->start(device);
}
void MacController1::StartTestingMac(int macIndex)
{
device = new GNIODevice(formatAudio, this);
connect(device, SIGNAL(update()), this, SLOT(UpdateTestDisplay()));
QAudioDeviceInfo testInfo;
QList<QAudioDeviceInfo> infos = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
testInfo = infos.at(macIndex);
audioInput = new QAudioInput(testInfo,formatAudio, this);
std::thread test(&MacController1::runTest, this,macIndex);
test.detach();
}
void MacController1::StopTestingMac()
{
device->stop();
audioInput->stop();
delete device;
delete audioInput;
device = nullptr;
audioInput = nullptr;
qDebug() << "max_Volume:" << max_Volume;
}
void MacController1::UpdateTestDisplay()
{
int volume = device->level() * 100;
if (volume < 0 || volume > 100)
{
volume = 0;
}
currentVolume = volume;
if (max_Volume < currentVolume) {
max_Volume = currentVolume;
}
}
QStringList MacController1::getMacList()
{
QList<QAudioDeviceInfo> infos = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
QStringList ansList;
for (int i = 0; i < infos.count(); i++)
{
ansList.push_back(QString::number(i + 1) + QString::fromLocal8Bit(": ") + infos[i].deviceName());
}
return ansList;
}
#pragma once
#include <QIODevice>
#include <QAudioFormat>
class GNIODevice :public QIODevice
{
Q_OBJECT
public:
GNIODevice(const QAudioFormat& format, QObject* parent);//音频格式
~GNIODevice();
void start();
void stop();
qreal level() const { return m_level; }
qint64 readData(char* data, qint64 maxlen) override;
qint64 writeData(const char* data, qint64 len) override;
private:
const QAudioFormat m_format;
quint32 m_maxAmplitude;//最大振幅
qreal m_level; // 0.0 <= m_level <= 1.0
signals:
void update();
};
#include "GNIODevice.h"
#include <QDebug>
#include <QtEndian>
const int BufferSize = 4096;//缓存大小
GNIODevice::GNIODevice(const QAudioFormat& format, QObject* parent) : QIODevice(parent)
, m_format(format)
, m_maxAmplitude(0)
, m_level(0.0)
{
//sampleSize,sampleType--->m_maxAmplitude
switch (m_format.sampleSize()) {
case 8:
switch (m_format.sampleType()) {
case QAudioFormat::UnSignedInt:
m_maxAmplitude = 255;
break;
case QAudioFormat::SignedInt:
m_maxAmplitude = 127;
break;
default:
break;
}
break;
case 16:
switch (m_format.sampleType()) {
case QAudioFormat::UnSignedInt:
m_maxAmplitude = 65535;
break;
case QAudioFormat::SignedInt:
m_maxAmplitude = 32767;
break;
default:
break;
}
break;
case 32:
switch (m_format.sampleType()) {
case QAudioFormat::UnSignedInt:
m_maxAmplitude = 0xffffffff;
break;
case QAudioFormat::SignedInt:
m_maxAmplitude = 0x7fffffff;
break;
case QAudioFormat::Float:
m_maxAmplitude = 0x7fffffff; // Kind of
default:
break;
}
break;
default:
break;
}
}
GNIODevice::~GNIODevice()
{
}
void GNIODevice::start()
{
open(QIODevice::WriteOnly);
}
void GNIODevice::stop()
{
close();
}
qint64 GNIODevice::writeData(const char* data, qint64 len)
{
if (m_maxAmplitude) {
Q_ASSERT(m_format.sampleSize() % 8 == 0);
const int channelBytes = m_format.sampleSize() / 8;
const int sampleBytes = m_format.channelCount() * channelBytes;
Q_ASSERT(len % sampleBytes == 0);
const int numSamples = len / sampleBytes;
quint32 maxValue = 0;
const unsigned char* ptr = reinterpret_cast<const unsigned char*>(data);
for (int i = 0; i < numSamples; ++i) {
for (int j = 0; j < m_format.channelCount(); ++j) {
quint32 value = 0;
if (m_format.sampleSize() == 8 && m_format.sampleType() == QAudioFormat::UnSignedInt) {
value = *reinterpret_cast<const quint8*>(ptr);
}
else if (m_format.sampleSize() == 8 && m_format.sampleType() == QAudioFormat::SignedInt) {
value = qAbs(*reinterpret_cast<const qint8*>(ptr));
}
else if (m_format.sampleSize() == 16 && m_format.sampleType() == QAudioFormat::UnSignedInt) {
if (m_format.byteOrder() == QAudioFormat::LittleEndian)
value = qFromLittleEndian<quint16>(ptr);
else
value = qFromBigEndian<quint16>(ptr);
}
else if (m_format.sampleSize() == 16 && m_format.sampleType() == QAudioFormat::SignedInt) {
if (m_format.byteOrder() == QAudioFormat::LittleEndian)
value = qAbs(qFromLittleEndian<qint16>(ptr));
else
value = qAbs(qFromBigEndian<qint16>(ptr));
}
else if (m_format.sampleSize() == 32 && m_format.sampleType() == QAudioFormat::UnSignedInt) {
if (m_format.byteOrder() == QAudioFormat::LittleEndian)
value = qFromLittleEndian<quint32>(ptr);
else
value = qFromBigEndian<quint32>(ptr);
}
else if (m_format.sampleSize() == 32 && m_format.sampleType() == QAudioFormat::SignedInt) {
if (m_format.byteOrder() == QAudioFormat::LittleEndian)
value = qAbs(qFromLittleEndian<qint32>(ptr));
else
value = qAbs(qFromBigEndian<qint32>(ptr));
}
else if (m_format.sampleSize() == 32 && m_format.sampleType() == QAudioFormat::Float) {
value = qAbs(*reinterpret_cast<const float*>(ptr) * 0x7fffffff); // assumes 0-1.0
}
maxValue = qMax(value, maxValue);
ptr += channelBytes;
}
}
maxValue = qMin(maxValue, m_maxAmplitude);
m_level = qreal(maxValue) / m_maxAmplitude;
}
emit update();
return len;
}
qint64 GNIODevice::readData(char* data, qint64 maxlen)
{
Q_UNUSED(data)
Q_UNUSED(maxlen)
return 0;
}
代码来源于CSDN的一个博主的下载资源。但我暂时找不到是谁了!!!
5.实现录音功能(存在bug)
#pragma once
#include <QObject>
#include "GNIODevice.h"
#include <QStringList>
#include <QAudioRecorder>
#include <QAudioInput>
#include <QAudioFormat>
#include <QAudioBuffer>
#include <QAudioProbe>
#include <QFile>
#include <QMutex>
#include <qeventloop.h>
class MacController2 : public QObject
{
Q_OBJECT
public:
MacController2(QObject *parent);
~MacController2();
QStringList getMacList();
void StartRecordingVoice(int macIndex);
void StopRecordingVoice();
private:
QAudioInput* audioInput;
GNIODevice* device;
QAudioFormat formatAudio;
QAudioProbe* probe;
QAudioRecorder* recorder;
QString fileName;
public slots:
void processBuffera(const QAudioBuffer& buffer);
};
#include "MacController2.h"
#include "qurl.h"
MacController2::MacController2(QObject *parent)
: QObject(parent)
{
probe = nullptr;
recorder = nullptr;
fileName = "E:/try/1.wav";
}
MacController2::~MacController2()
{}
QStringList MacController2::getMacList()
{
QList<QAudioDeviceInfo> infos = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
QStringList ansList;
for (int i = 0; i < infos.count(); i++)
{
ansList.push_back(QString::number(i + 1) + QString::fromLocal8Bit(": ") + infos[i].deviceName());
}
return ansList;
}
void MacController2::StartRecordingVoice(int macIndex)
{
qDebug() << fileName;
probe = new QAudioProbe(this);
connect(probe, &QAudioProbe::audioBufferProbed,
this, &MacController2::processBuffera); //关联函数
QAudioDeviceInfo info = QAudioDeviceInfo::availableDevices(QAudio::AudioInput).at(macIndex);
recorder = new QAudioRecorder(this);
QAudioEncoderSettings settings = recorder->audioSettings();
probe->setSource(recorder);
settings.setCodec("audio/PCM"); // 这些是QAudioRecorder是设置,见名思意
settings.setBitRate(96000);
//settings.setSampleRate(44100);
settings.setChannelCount(2);
settings.setQuality(QMultimedia::EncodingQuality::HighQuality);
settings.setEncodingMode(QMultimedia::ConstantQualityEncoding);
recorder->setAudioSettings(settings);
recorder->setAudioInput(info.deviceName());
recorder->setOutputLocation(QUrl::fromLocalFile(fileName));
recorder->setContainerFormat("audio/wav");
recorder->record();
}
void MacController2::processBuffera(const QAudioBuffer& buffer)
{
QByteArray arr;
qDebug() << "HAS VOICE in mac!";
//controlVoiceData(false, arr, buffer);
}
void MacController2::StopRecordingVoice()
{
recorder->stop();
recorder->deleteLater();
}
噪音其实有点大
QAudioProbe对象probe的槽函数仍在执行
从音频文件在线应用程序中删除背景噪音 - 免费在线音频文件背景噪音清洁器 (aspose.app)
降噪处理了一下
(我在想是不是CPU转动带来的噪声过大呢)