本文介绍了如何从麦克风中录制音频,并利用DSP算法对音频样本进行处理。在本文中,我使用QAudioInput和QAudioOutput类来录制和回放输入音频,并使用低通滤波算法来降低输入音频中的噪声。在这里,我试图解释使用Qt的低电平音频处理,这里我不解释任何复杂的DSP算法。这只是一个更好的跨平台音频处理工具的起点。您可以实现自己的算法或任何复杂的算法来扩展您的思想。我用的是Qt的音频输入
背景
在我最近的项目中,我遇到了一些问题,记录音频和回放一次。我在网上搜索了一下,发现很多论坛都在讨论如何捕捉音频,并一次播放给说话者听。没有人给出使用Qt的正确答案,经过一些研究工作,最后我成功地一次记录和回放音频。
指定输出文件名(TARGET = ApplicationName)
TEMPLATE指定编译后的输出类型。将它分配给一个应用程序(TEMPLATE = app)
添加项目中使用的所有源文件和头文件。
添加表单设计资源到FORMS += mainwindow.ui。这将为您的应用程序创建用户界面
在Qt Creator中启动一个新的Qt Widget项目。该向导将创建启动桌面应用程序所需的所有文件。来
在你的AppNamae .pro文件中添加QT += multimedia行:
//.pro
QT += core gui
multimedia
TARGET = MyAudio
TEMPLATE = app
SOURCES += main.cpp
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
在开始音频处理之前,初始化音频格式频率,通道,采样率等。使用QAudioFormat初始化音频。
音频格式指定音频流中的数据如何排列,即如何解释流。编码本身由用于流的编解码器()指定。
除了编码之外,QAudioFormat还包含其他参数,这些参数进一步指定音频数据的排列方式。它们是频率、通道数、样本大小、样本类型和字节顺序。下表更详细地描述了这些
//C++
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类提供了一个向音频输出设备发送音频数据的接口。
//C++
m_audioInput = new QAudioInput(m_Inputdevice, m_format, this);
m_audioOutput = new QAudioOutput(m_Outputdevice, m_format, this);
启动音频输入和音频输出,并将readyRead() SIGNAL连接到readMore() SLOT。
每当可以从设备读取新数据时,就会发出一次readyRead()信号。只有当有新的数据可用时,它才会再次发出,例如当网络数据的新负载到达您的网络套接字时,或者当一个新的数据块被附加到您的设备时。
//c++
//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);
}
最后播放音频样本修改演讲者。这将从麦克风到扬声器播放修改后的音频。
m_output->write((char*)outdata, len);
您可以在readMore()函数中实现自己的算法。在这里,我实现了低通滤波算法,以减少输入音频中的噪声。有很多复杂的音频滤波算法可以产生一个完美的音频滤波,Low Pass是其中最简单的算法。演示如何在低电平音频处理中更改音量。