1.获取麦克风阵列:

    QList<QAudioDeviceInfo> infos = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
    for (int i = 0; i < infos.count(); i++)
    {
        qDebug() << infos.at(i).deviceName();
    }

Qt---录音-LMLPHP

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");

音频文件计算大小_比特率和时间求音频大小-CSDN博客

采样频率,声道数,采样位数

什么是大小端?如何确定大小端?-CSDN博客

pcm编码_百度百科 (baidu.com)

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;
}

Qt---录音-LMLPHP

Qt---录音-LMLPHP

代码来源于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();
}

Qt---录音-LMLPHP

噪音其实有点大

QAudioProbe对象probe的槽函数仍在执行

从音频文件在线应用程序中删除背景噪音 - 免费在线音频文件背景噪音清洁器 (aspose.app)

降噪处理了一下

(我在想是不是CPU转动带来的噪声过大呢)

05-28 05:25