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

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

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

\

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcm9iZXJ0a3Vu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

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

#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录音机的更多相关文章

  1. QT内省机制、自定义Model、数据库

    本文将介绍自定义Model过程中数据库数据源的获取方法,我使用过以下三种方式获取数据库数据源: 创建 存储对应数据库所有字段的 结构体,将结构体置于容器中返回,然后根据索引值(QModelIndex) ...

  2. Ubuntu 下安装QT

    Ubuntu 下安装QT 本文使用的环境 QT Library: qt-everywhere-opensource-src-4.7.4.tar.gz QT Creator: qt-creator-li ...

  3. Qt安装配置

    Qt Creator: 下载: Qt 5.5.1 for Windows 32-bit(MinGW 4.9.2, 1.0 GB):http://download.qt.io/official_rele ...

  4. Qt信号与槽自动关联机制

    参考链接1:http://blog.csdn.net/skyhawk452/article/details/6121407 参考链接2:http://blog.csdn.net/memory_exce ...

  5. 保持Qt GUI响应的几种方法

    最开始使用Qt时就遇到过QT Gui失去响应的问题,我是用多线程的方式解决的,然而通常来说,多线程是会降低程序的运行速度. 之后,在使用QSqlQuery::execBatch()函数时,Qt Gui ...

  6. Qt 中使用Singleton模式需小心

    在qt中,使用Singleton模式时一定要小心.因为Singleton模式中使用的是静态对象,静态对象是直到程序结束才被释放的,然而,一旦把该静态对象纳入了Qt的父子对象体系,就会导致不明确的行为. ...

  7. Qt——组件位置随窗口变化

    当我们用Qt Designer设计界面时,有时会面临这样一个问题:需要在窗口指定位置放置组件,并且当窗口位置大小改变时,该组件相对其父对象的位置是不变的,如下面两幅图所示 ,首先看上面这幅图,注意bu ...

  8. (转) Qt 出现“undefined reference to `vtable for”原因总结

    由于Qt本身实现的机制所限,我们在使用Qt制作某些软件程序的时候,会遇到各种各样这样那样的问题,而且很多是很难,或者根本找不到原因的,即使解决了问题,如果有人问你为什么,你只能回答--不知道. 今天我 ...

  9. qt中ui的 使用介绍

    1.什么是ui?ui通常是用Qt 设计师设计出来的界面文件的后缀.通常情况下ui是一个指向这个界面类的指针.ui-> 一般就是用来访问这个界面类里面的控件.例如你的ui文件里有一个叫okButt ...

随机推荐

  1. Fiddler抓包9-保存会话(save)【转载】

    本篇转自博客:上海-悠悠 原文地址:http://www.cnblogs.com/yoyoketang/tag/fiddler/ 前言 为什么要保存会话呢?举个很简单的场景,你在上海测试某个功能接口的 ...

  2. [BZOJ1997][Hnoi2010]Planar 2-sat (联通分量) 平面图

    1997: [Hnoi2010]Planar Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 2317  Solved: 850[Submit][Stat ...

  3. codeforces-540C

    题目连接:http://codeforces.com/problemset/problem/540/C C. Ice Cave time limit per test 2 seconds memory ...

  4. 51nod 1873 初中的算术【Java BigDecimal/高精度小数】

    1873 初中的算术 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题  收藏  关注 Noder现在上初三了,正在开始复习中考.他每天要计算型如 (a× a× a× ...

  5. Python的扩展接口[1] -> 串口通信

    串口通信 / Serial Communication 1 串口简介 / Serial Introduction 串行接口(Serial Interface)简称串口,通常为COM接口,数据发送方式为 ...

  6. Tarjan缩点+LCA【p2783】有机化学之神偶尔会做作弊

    Description 你翻到那一题:给定一个烃,只含有单键(给初中生的一个理解性解释:就是一堆碳用横线连起来,横线都是单条的). 然后炎魔之王拉格纳罗斯用他的火焰净化了一切环(???).所有的环状碳 ...

  7. 洛谷——P1991 无线通讯网

    P1991 无线通讯网 题目描述 国防部计划用无线网络连接若干个边防哨所.2 种不同的通讯技术用来搭建无线网络: 每个边防哨所都要配备无线电收发器:有一些哨所还可以增配卫星电话. 任意两个配备了一条卫 ...

  8. Oracle 查询每天执行慢的SQL

    本文转载自http://blog.itpub.net/28602568/viewspace-1364844/ 前言:  工作中的您是否有 想对每天慢的sql进行查询.汇总或者行优化等情况,如下SQL希 ...

  9. Guess Number Higher or Lower II -- LeetCode

    We are playing the Guess Game. The game is as follows: I pick a number from 1 to n. You have to gues ...

  10. 【bzoj1087】【互不侵犯King】状压dp裸题(浅尝ACM-D)

    [pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=54329606 向大(hei)佬(e)势力学(di ...