Qt 中的跨平台麦克风音频处理实用程序。






4.88/5 (23投票s)
麦克风音频的简单信号处理实现。
引言
本文介绍了如何从麦克风录制音频并使用DSP算法处理音频样本。 在本文中,我使用QAudioInput
和QAudioOutput
类来录制和回放输入音频,并使用低通滤波器算法来降低输入音频中的噪声。 在这里,我试图用Qt解释低级音频处理。 这里我没有解释任何复杂的DSP算法。 这只是一个更好的跨平台音频处理实用程序的起点。 您可以实现自己的算法或任何复杂的算法来扩展您的想法。 我使用Qt的音频输入和音频输出示例来开发这个实用程序。
背景
在最近的项目中,我遇到了同时录制和回放音频的一些问题。 我在网上搜索了相关内容,发现很多论坛讨论了同时捕获音频并播放到扬声器的问题。 没有人给出任何使用Qt进行此操作的正确答案。 经过一些研究工作,我终于成功地同时录制和回放音频。
使用代码
TARGET指定输出文件名 (TARGET = ApplicationName)
TEMPLATE指定其编译后的输出类型。 将其分配给一个应用程序 (TEMPLATE = app)
添加项目中使用的所有源文件和头文件。
将表单设计资源添加到 FORMS += mainwindow.ui。 这将为您的应用程序创建用户界面
在 Qt Creator 中启动一个新的 Qt Widget 项目。向导将创建启动桌面应用程序所需的所有文件。 为了
链接到多媒体模块,将 QT += multimedia 行添加到您的 AppNamae .pro 文件中
QT += core gui
multimedia
TARGET = MyAudio
TEMPLATE = app
SOURCES += main.cpp
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
在开始音频处理之前,初始化音频格式频率、通道、采样率等。使用 QAudioFormat
来初始化音频。
音频格式指定音频流中数据的排列方式,即如何解释流。 编码本身由用于流的 codec()
指定。
除了编码之外,QAudioFormat
还包含其他参数,这些参数进一步指定音频数据的排列方式。 这些是频率、通道数、采样大小、采样类型和字节顺序。 下表更详细地描述了这些内容
m_format.setFrequency(8000); //set frequency to 8000
m_format.setChannels(1); //set channels to mono
m_format.setSampleSize(16); //set sample sze to 16 bit
m_format.setSampleType(QAudioFormat::UnSignedInt ); //Sample type as usigned integer sample
m_format.setByteOrder(QAudioFormat::LittleEndian); //Byte order
m_format.setCodec("audio/pcm"); //set codec as simple audio/pcm
QAudioDeviceInfo infoIn(QAudioDeviceInfo::defaultInputDevice());
if (!infoIn.isFormatSupported(m_format))
{
//Default format not supported - trying to use nearest
m_format = infoIn.nearestFormat(m_format);
}
QAudioDeviceInfo infoOut(QAudioDeviceInfo::defaultOutputDevice());
if (!infoOut.isFormatSupported(m_format))
{
//Default format not supported - trying to use nearest
m_format = infoOut.nearestFormat(m_format);
}
使用 IO 设备和音频格式创建音频输入和输出对象。
QAudioInput
类提供了一个用于从音频输入设备接收音频数据的接口。
QAudioOutput
类提供了一个用于将音频数据发送到音频输出设备的接口。
m_audioInput = new QAudioInput(m_Inputdevice, m_format, this);
m_audioOutput = new QAudioOutput(m_Outputdevice, m_format, this);
启动音频输入和音频输出,并将 readyRead()
SIGNAL 连接到 readMore()
SLOT。
readyRead ()
信号在每次有新数据可从设备读取时发出。 它仅在有新数据可用时再次发出,例如当您的网络套接字上收到新的网络数据负载时,或者当新的数据块已附加到您的设备时。
//Audio output device
m_output= m_audioOutput->start();
//Audio input device
m_input = m_audioInput->start();
//connect readyRead signal to readMre slot.
//Call readmore when audio samples fill in inputbuffer
connect(m_input, SIGNAL(readyRead()), SLOT(readMore()));
从输入设备读取声音样本到缓冲区。
qint64 l = m_input->read(m_buffer.data(), len);
实现了低通滤波器算法来降低输入音频中的噪声,以产生平滑的声音。
int iIndex;
if(ui->chkRemoveNoise->checkState() == Qt::Checked)
{
//Remove noise using Low Pass filter algortm[Simple algorithm used to remove noise]
for ( iIndex=1; iIndex < len; iIndex++ )
{
outdata[ iIndex ] = 0.333 * resultingData[iIndex ] + ( 1.0 - 0.333 ) * outdata[ iIndex-1 ];
}
}
对音频样本应用音量以调整输出音量。 将一个整数乘以音频样本以调整其幅度。
for ( iIndex=0; iIndex < len; iIndex++ )
{
//Cange volume to each integer data in a sample
outdata[ iIndex ] = ApplyVolumeToSample( outdata[ iIndex ]);
}
int MainWindow::ApplyVolumeToSample(short iSample)
{
//Calculate volume, Volume limited to max 35535 and min -35535
return std::max(std::min(((iSample * m_iVolume) / 50) ,35535), -35535);
}
最后将修改后的音频样本回放到扬声器。 这将播放从麦克风到扬声器的修改后的音频。
//write modified sond sample to outputdevice for playback audio
m_output->write((char*)outdata, len);
您可以在 readMore()
函数中实现您自己的算法。 这里我实现了低通滤波器算法来降低输入音频中的噪声。 有很多复杂的音频滤波算法可用于产生完美的音频滤波,低通是该列表中最简单的算法。 显示了如何在低级音频处理中更改音量。