Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / QT

Cross Platform Microphone Audio Processing Utility In Qt

4.88/5 (24 votes)
25 Jul 2012CPOL3 min read 90.3K   3.7K  
Simple signal processing implementation to microphone audio

Image 1

Introduction

This article explains how to record audio from microphone and process the audio sample using DSP algorithms. In this article, I am using the QAudioInput and QAudioOutput classes to record and play back to the input audio, and used Low pass filter algorithm to reduce noise in input audio. Here, I have tried to explain the low level audio processing using Qt. Here I am not explaining anycomplex DSP algorithms. It’s just a starting point to a better cross platform audio processing utility. You can implement your own algorithms or any complex algorithms to extend your ideas. I used Qt's audio input and audio output examples to develop this utility.

Background

In my recent project, I met with some issues to record audio and playback at a time. I searched about it in the web and saw a lot of forums discussing about to capture audio and play back to the speaker at a time. No one given any proper answer to do this using Qt. After some research work finally I succeeded to record and playback audio at a time.

Using the code

TARGET specify the output file name (TARGET = ApplicationName)

TEMPLATE specify its compiled output type. Assign it to an application (TEMPLATE = app)

Add all the source and header files are using in your project.

Add Form design resources to FORMS += mainwindow.ui. This will create user interface to your application

In Qt Creator start a new Qt Widget project. The wizard will create all the necessary files to start a desktop application. To

link against the multimedia module, add QT += multimedia line to your AppNamae .pro file:

QT       += core gui
             multimedia
 
TARGET = MyAudio
TEMPLATE = app
 
SOURCES += main.cpp
        mainwindow.cpp
 
HEADERS  += mainwindow.h
FORMS    += mainwindow.ui

Before starting the audio processing initialize Audio Format Frequency, Channel, Sample Rate etc. Use QAudioFormat to initialize audio.

An audio format specifies how data in an audio stream is arranged, i.e, how the stream is to be interpreted. The encoding itself is specified by the codec() used for the stream.

In addition to the encoding, QAudioFormat contains other parameters that further specify how the audio data is arranged. These are the frequency, the number of channels, the sample size, the sample type, and the byte order. The following table describes these in more detail

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

Create audio input and output objects with IO device and audio formats.

The QAudioInput class provides an interface for receiving audio data from an audio input device.

The QAudioOutput class provides an interface for sending audio data to an audio output device.

C++
m_audioInput = new QAudioInput(m_Inputdevice, m_format, this);
m_audioOutput = new QAudioOutput(m_Outputdevice, m_format, this);

Start audio input and audio output and connect readyRead() SIGNAL to readMore() SLOT.

The readyRead () signal is emitted once every time new data is available for reading from the device. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device.

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

Read sound samples from input device to buffer.

C++
qint64 l = m_input->read(m_buffer.data(), len);

Implemented Low Pass filter algorithm to reduce noise in the input audio to produce smooth sound.

C++
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 ];
    }
}

Apply volume to audio sample for adjusting the output volume. Multiply an integer number to audio sample to adjust its amplitude.

C++
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);
}

Finally play back the modified audio samples to speaker. This will play modified audio from microphone to speaker.

C++
//write modified sond sample to outputdevice for playback audio
m_output->write((char*)outdata, len);

You can implement your own algorithms in readMore() function. Here I implemented Low Pass filter algorithms to reduce noise in input audio. There are lots of complex audio filtering algorithms are available to produce a perfect audio filtering Low Pass is the simplest algorithm in that list. Shows how to change the volume in low level audio processing.

Reference

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)