Qt录音机

标签: qt 录音 QAudioInput
4019人阅读 评论(3) 收藏 举报
分类:

最近做项目, 需要一个麦克风音量监听的功能:

找了好多这方面的资料, 不知道为什么 总之很少, 

在此总结一下, 发贴一枚..

\

不啰嗦了, 直接上代码了: 

#ifndef AUDIORECORDER_H
#define AUDIORECORDER_H

#include <QFile>
#include <QWidget>
#include <QPushButton>
#include <QAudioInput>
#include <QAudioOutput>
#include <QAudioDeviceInfo>

#include "ui_AudioRecorder.h"

class AudioRecorder : public QWidget
{
	Q_OBJECT

public:
	AudioRecorder(QWidget *parent = 0);
	~AudioRecorder();

private:
	int AddWavHeader(char *);
	int ApplyVolumeToSample(short iSample);
	void InitMonitor();
	void CreateAudioInput();
	void CreateAudioOutput();

private slots:
	void OnRecordStart();
	void OnRecordStop();
	void OnRecordPlay();
	void OnRecordSave();

	void OnStateChange(QAudio::State s);
	void OnReadMore();
	void OnSliderValueChanged(int);
	void OnTimeOut();

private:
	Ui::Recorder ui;
	int miVolume;
	int miMaxValue;

private:
	QAudioFormat mFormatFile;
	QFile *mpOutputFile;

	QAudioInput *mpAudioInputFile;		// 负责读写文件
	QAudioOutput *mpAudioOutputFile;

	QAudioFormat mFormatSound;
	QAudioInput *mpAudioInputSound;		// 负责监听声音
	QAudioOutput *mpAudioOutputSound;

	QIODevice *mpInputDevSound;
	QIODevice *mpOutputDevSound;
};

#endif // AUDIORECORDER_H

#include "AudioRecorder.h"
#include <QLayout>
#include <QDebug>
#include <QTimer>
#include <QFileDialog>
#include <QMessageBox>

#define BufferSize 14096

struct HEADER
{
	char RIFFNAME[4];
	unsigned long nRIFFLength;
	char WAVNAME[4];
	char FMTNAME[4];
	unsigned long nFMTLength;
	unsigned short nAudioFormat;
	unsigned short nChannleNumber;
	unsigned long nSampleRate;
	unsigned long nBytesPerSecond;
	unsigned short nBytesPerSample;
	unsigned short    nBitsPerSample;
	char    DATANAME[4];
	unsigned long   nDataLength;
};

AudioRecorder::AudioRecorder(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);
	
	miMaxValue = 0;
	miVolume = ui.horizontalSlider->value();
	mpOutputFile = NULL;
	mpAudioInputFile = NULL;
	mpAudioOutputFile = NULL;

	mpAudioInputSound = NULL;
	mpAudioOutputSound = NULL;

	mpInputDevSound = NULL;
	mpInputDevSound = NULL;

	ui.btn_stop->setDisabled(true);
	ui.btn_play->setDisabled(true);
	ui.btn_save->setDisabled(true);

	mpOutputFile = new QFile();
	mpOutputFile->setFileName(tr("record.raw"));

	//mFormatFile.setFrequency(8000);
	//mFormatFile.setChannels(1);
	mFormatFile.setSampleSize(16);
	mFormatFile.setSampleType(QAudioFormat::SignedInt);
	mFormatFile.setByteOrder(QAudioFormat::LittleEndian);
	mFormatFile.setCodec("audio/pcm");

	QAudioDeviceInfo info(QAudioDeviceInfo::defaultInputDevice());
	if (!info.isFormatSupported(mFormatFile)) {
		qWarning("input default mFormatFile not supported try to use nearest");
		mFormatFile = info.nearestFormat(mFormatFile);
	}

	QAudioDeviceInfo info1(QAudioDeviceInfo::defaultOutputDevice());
	if (!info1.isFormatSupported(mFormatFile)) {
		qWarning() << "output default mFormatFile not supported - trying to use nearest";
		//           mFormatFile = info.nearestFormat(mFormatSound);
		qWarning() << "output no support input mFormatFile.";
		return;
	}

	if(mFormatFile.sampleSize() != 16) {
		qWarning("audio device doesn't support 16 bit support %d bit samples, example cannot run", 
<span style="white-space:pre">		</span>mFormatFile.sampleSize());

		mpAudioInputFile = 0;
		return;
	}

	mpAudioInputFile = NULL;
	mpAudioOutputFile = NULL;

	connect(ui.btn_start, SIGNAL(clicked()), this,SLOT(OnRecordStart()));
	connect(ui.btn_stop, SIGNAL(clicked()), this,SLOT(OnRecordStop()));
	connect(ui.btn_play, SIGNAL(clicked()), this,SLOT(OnRecordPlay()));
	connect(ui.btn_save, SIGNAL(clicked()), this,SLOT(OnRecordSave()));

	InitMonitor();
}

AudioRecorder::~AudioRecorder()
{

}

void AudioRecorder::OnRecordStart()
{
	mpOutputFile->open(QIODevice::WriteOnly | QIODevice::Truncate);

	mpAudioInputFile = new QAudioInput(mFormatFile, this);
	mpAudioInputFile->start(mpOutputFile);

	ui.btn_start->setDisabled(true);
	ui.btn_stop->setDisabled(false);
	ui.btn_play->setDisabled(true);
	ui.btn_save->setDisabled(true);
}

void AudioRecorder::OnRecordPlay()
{
	mpOutputFile->open(QIODevice::ReadOnly | QIODevice::Truncate);

	mpAudioOutputFile = new QAudioOutput(mFormatFile, this);
	connect(mpAudioOutputFile, SIGNAL(stateChanged(QAudio::State)), 
		this,SLOT(OnStateChange(QAudio::State)));
	mpAudioOutputFile->start(mpOutputFile);

	ui.btn_start->setDisabled(true);
	ui.btn_stop->setDisabled(false);
	ui.btn_play->setDisabled(true);
	ui.btn_save->setDisabled(true);
}

void AudioRecorder::OnRecordStop()
{
	if(mpAudioInputFile != NULL){
		mpAudioInputFile->stop();
		delete mpAudioInputFile;
		mpAudioInputFile = NULL;
	}

	if(mpAudioOutputFile != NULL){
		mpAudioOutputFile->stop();
		delete mpAudioOutputFile;
		mpAudioOutputFile = NULL;
	}

	mpOutputFile->close();

	ui.btn_start->setDisabled(false);
	ui.btn_stop->setDisabled(true);
	ui.btn_play->setDisabled(false);
	ui.btn_save->setDisabled(false);
}

void AudioRecorder::OnRecordSave()
{
	QString filename = QFileDialog::getSaveFileName(
		this,
		tr("choose a filename to save under"),
		QDir::currentPath(),
		"Wav(*.wav)");
	if(filename.length() == 0) {
		QMessageBox::information(NULL, tr("filename"), tr("You didn't select any files."));
	} else {
		if(AddWavHeader((filename+tr(".wav")).toLatin1().data())>0)
			QMessageBox::information(NULL, tr("Save"), tr("Success Save :") + filename);
	}
}

void AudioRecorder::OnStateChange(QAudio::State state)
{
	if(state == QAudio::IdleState)
		OnRecordStop();
}

int AudioRecorder::AddWavHeader(char *filename)
{
	// 开始准备WAV的文件头
	HEADER DestionFileHeader;
	DestionFileHeader.RIFFNAME[0] = 'R';
	DestionFileHeader.RIFFNAME[1] = 'I';
	DestionFileHeader.RIFFNAME[2] = 'F';
	DestionFileHeader.RIFFNAME[3] = 'F';

	DestionFileHeader.WAVNAME[0] = 'W';
	DestionFileHeader.WAVNAME[1] = 'A';
	DestionFileHeader.WAVNAME[2] = 'V';
	DestionFileHeader.WAVNAME[3] = 'E';

	DestionFileHeader.FMTNAME[0] = 'f';
	DestionFileHeader.FMTNAME[1] = 'm';
	DestionFileHeader.FMTNAME[2] = 't';
	DestionFileHeader.FMTNAME[3] = 0x20;
	DestionFileHeader.nFMTLength = 16;  //  表示 FMT 的长度
	DestionFileHeader.nAudioFormat = 1; //这个表示a law PCM

	DestionFileHeader.DATANAME[0] = 'd';
	DestionFileHeader.DATANAME[1] = 'a';
	DestionFileHeader.DATANAME[2] = 't';
	DestionFileHeader.DATANAME[3] = 'a';
	DestionFileHeader.nBitsPerSample = 16;
	DestionFileHeader.nBytesPerSample = 2;    //
	DestionFileHeader.nSampleRate = 8000;    //
	DestionFileHeader.nBytesPerSecond = 16000;
	DestionFileHeader.nChannleNumber = 1;

	int nFileLen = 0;
	int nSize = sizeof(DestionFileHeader);

	FILE *fp_s = NULL;
	FILE *fp_d = NULL;

	fp_s = fopen("record.raw", "rb");
	if (fp_s == NULL)
		return -1;

	fp_d = fopen(filename, "wb+");
	if (fp_d == NULL)
		return -2;


	int nWrite = fwrite(&DestionFileHeader, 1, nSize, fp_d);
	if (nWrite != nSize)
	{
		fclose(fp_s);
		fclose(fp_d);
		return -3;
	}

	while( !feof(fp_s))
	{
		char readBuf[4096];
		int nRead = fread(readBuf, 1, 4096, fp_s);
		if (nRead > 0)
		{
			fwrite(readBuf, 1, nRead, fp_d);
		}

		nFileLen += nRead;
	}
	fseek(fp_d, 0L, SEEK_SET);

	DestionFileHeader.nRIFFLength = nFileLen - 8 + nSize;
	DestionFileHeader.nDataLength = nFileLen;
	nWrite = fwrite(&DestionFileHeader, 1, nSize, fp_d);
	if (nWrite != nSize)
	{
		fclose(fp_s);
		fclose(fp_d);
		return -4;
	}

	fclose(fp_s);
	fclose(fp_d);

	return nFileLen;
}

void AudioRecorder::InitMonitor()
{
	mFormatSound.setSampleSize(16); //set sample sze to 16 bit
	mFormatSound.setSampleType(QAudioFormat::UnSignedInt ); //Sample type as usigned integer sample
	mFormatSound.setByteOrder(QAudioFormat::LittleEndian); //Byte order
	mFormatSound.setCodec("audio/pcm"); //set codec as simple audio/pcm

	QAudioDeviceInfo infoIn(QAudioDeviceInfo::defaultInputDevice());
	if (!infoIn.isFormatSupported(mFormatSound))
	{
		//Default format not supported - trying to use nearest
		mFormatSound = infoIn.nearestFormat(mFormatSound);
	}

	QAudioDeviceInfo infoOut(QAudioDeviceInfo::defaultOutputDevice());
	if (!infoOut.isFormatSupported(mFormatSound))
	{
		//Default format not supported - trying to use nearest
		mFormatSound = infoOut.nearestFormat(mFormatSound);
	}

	CreateAudioInput();
	CreateAudioOutput();

	mpOutputDevSound = mpAudioOutputSound->start();
	mpInputDevSound = mpAudioInputSound->start();
	connect(mpInputDevSound, SIGNAL(readyRead()), SLOT(OnReadMore()));

	connect(ui.horizontalSlider, SIGNAL(valueChanged(int)),
		this, SLOT(OnSliderValueChanged(int)));
}

void AudioRecorder::CreateAudioInput()
{
	if (mpInputDevSound != 0) {
		disconnect(mpInputDevSound, 0, this, 0);
		mpInputDevSound = 0;
	}

	QAudioDeviceInfo inputDevice(QAudioDeviceInfo::defaultInputDevice());
	mpAudioInputSound = new QAudioInput(inputDevice, mFormatSound, this);
}

void AudioRecorder::CreateAudioOutput()
{
	QAudioDeviceInfo outputDevice(QAudioDeviceInfo::defaultOutputDevice());
	mpAudioOutputSound = new QAudioOutput(outputDevice, mFormatSound, this);
}

int AudioRecorder::ApplyVolumeToSample(short iSample)
{
	//Calculate volume, Volume limited to  max 30000 and min -30000
	return std::max(std::min(((iSample * miVolume) / 50) ,20000), -20000);
}

void AudioRecorder::OnSliderValueChanged(int value)
{
	miVolume = value;
}

void AudioRecorder::OnReadMore()
{
	//Return if audio input is null
	if(!mpAudioInputSound)
		return;

	QByteArray _Buffer(BufferSize, 0);
	//Check the number of samples in input buffer
	qint64 len = mpAudioInputSound->bytesReady();

	//Limit sample size
	if(len > 4096)
		len = 4096;

	//Read sound samples from input device to buffer
	qint64 l = mpInputDevSound->read(_Buffer.data(), len);
	if(l > 0) {
		//Assign sound samples to short array
		short* resultingData = (short*)_Buffer.data();

		short *outdata=resultingData;
		outdata[ 0 ] = resultingData [ 0 ];

		int iIndex;
		if(false) {
			//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 ];
			}
		}

		miMaxValue = 0;
		for ( iIndex=0; iIndex < len; iIndex++ ) {
			//Cange volume to each integer data in a sample
			int value = ApplyVolumeToSample( outdata[ iIndex ]);
			outdata[ iIndex ] = value;

			miMaxValue = miMaxValue>=value ? miMaxValue : value;
		}

		//write modified sond sample to outputdevice for playback audio
		mpOutputDevSound->write((char*)outdata, len);
		QTimer::singleShot(1000, this, SLOT(OnTimeOut()));
	}
}

void AudioRecorder::OnTimeOut()
{
	ui.progress->setValue(miMaxValue);
}




代码已上传: http://download.csdn.net/detail/robertkun/7421767

查看评论

Qt录音机QAudioInput

  • 2014年05月29日 17:10
  • 37KB
  • 下载

实时录音与播放的内存实现 Qt代码

过去的一个月,在找了若干代码和请教了若干编程高手,求助于各大论坛,qq群之后,终于实现了我需要的功能 ——实时录音并播放,录音到circular buffer再从circular buffer的同一个...
  • kakadiablo
  • kakadiablo
  • 2012-05-13 06:18:30
  • 9902

qt在windows下实现录音放音同步

qt在windows下实现录音放音同步本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.环境:主机:WIN8开发环境:Qt5 3.1.2说明:做一个类似...
  • jdh99
  • jdh99
  • 2014-09-11 11:17:09
  • 7266

用Qt录制音频数据

想要录制一段音频到文件,可以使用Q
  • str999_cn
  • str999_cn
  • 2014-06-04 18:40:17
  • 1731

Qt各种采样率录音 录音到内存

近段时间了解了Qt的录音模块,Qt的录音模块分为QAudioInput输入,QAudioOutput输出。输入用来录音,输出用于播放。当然还用其它的QMediaPlayer、QAudioRecorde...
  • wanghualin033
  • wanghualin033
  • 2017-11-18 11:53:09
  • 430

用Qt实现录音以及放音

本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境:Ubuntu10.04,Qt Creator 2.0.1,Qt 4.7.0   参考Qt...
  • jdh99
  • jdh99
  • 2011-03-06 01:18:00
  • 22587

QT常见报错和解决方法

QT报错: on-ASCII characters are not allowed outside of literals and identifiers 如果没有看到中文或者全角的字符,...
  • u013174689
  • u013174689
  • 2014-09-30 18:19:05
  • 2046

QT音频录音和播放

  • 2012年12月31日 11:50
  • 945KB
  • 下载

ios中将pcm转为wav

struct tagHXD_WAVFLIEHEAD { char RIFFNAME[4]; DWORD nRIFFLength; char WAVNAME[4]; ch...
  • zttjhm
  • zttjhm
  • 2014-12-18 08:57:31
  • 4077

如何在Ubuntu QML应用中进行语言录音

在QML API中,目前并没有一个相应的API来进行录音。我们必须使用Qt C++ API QAudioRecorder来进行录音的工作。在这篇文章中,我们来介绍如何使用这个API来进行录音。...
  • UbuntuTouch
  • UbuntuTouch
  • 2015-05-29 13:07:52
  • 1480
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 74万+
    积分: 9218
    排名: 2870
    博客专栏
    文章分类
    最新评论