界面就是几个按钮,和几个label组成的
1.头文件
#ifndef WAVE_HEAD_H
#define WAVE_HEAD_H
struct wave_riff{
char cid[4];
unsigned long cs;
char format[4];
};
struct wave_fmt{
char sid[4];
unsigned long s1s;
unsigned short int af;
unsigned short int nc;
unsigned int sr;
unsigned int br;
unsigned short int ba;
unsigned short int bps;
};
struct wave_data{
char s2id[4];
unsigned long s2s;
};
#endif // WAVE_HEAD_H
wave pcm头 格式
没有这个也可以播放,添加wave头之后计算机可以播放wave文件否则,播放器不识别。
2.widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QFile>
#include <QAudioFormat>
#include <QAudioOutput>
#include <QAudioInput>
#include <QTimer>
#include <QTimeEdit>
#include <QtDebug>
#include <QPainter>
#include <QPaintEvent>
#include <QEvent>
#include <WAVE_HEAD.h>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_pushButton_clicked();
void on_inpput_clicked();
void stopRecording();
void handleStateChanged(QAudio::State newState);
void on_stop_clicked();
void on_button_stop_clicked();
void on_button_see_clicked();
protected:
bool eventFilter(QObject *obj,QEvent *event) override;
void timerEvent(QTimerEvent* e) override;
void paintEvent(QPaintEvent *event) override;
void paint();
private:
Ui::Widget *ui;
QAudioInput* audio;
QAudioOutput* audioOut;
QFile destinationFile; // Class member
QFile sourceFile;
QByteArray ba;
int tid;
int r,g,b;
int r1,g1,b1;
int r2,g2,b2;
wave_riff riff;
wave_fmt fmt;
wave_data data;
private:
void ini_wave_head();
};
#endif // WIDGET_H
3.widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
:QWidget(parent)
,ui(new Ui::Widget)
{
ui->setupUi(this);
audio=nullptr;
audioOut=nullptr;
ui->label->installEventFilter(this);
}
Widget::~Widget()
{
delete ui;
}
//播放
void Widget::on_pushButton_clicked()
{
sourceFile.setFileName("/test.pcm");
bool bl = sourceFile.open(QIODevice::ReadOnly);
if(bl == true){
QAudioFormat format;
format.setSampleRate(44100);
format.setChannelCount(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);
audioOut = new QAudioOutput(format,0);
connect(audioOut,SIGNAL(stateChanged(QAudio::State)),this, SLOT(handleStateChanged(QAudio::State)));
audioOut->start(&sourceFile);
ui->state->setText("开始播放");
}else
{
qDebug()<<"no file";
}
}
//录制
void Widget::on_inpput_clicked()
{
{
destinationFile.setFileName("/test12.pcm");
destinationFile.open( QIODevice::WriteOnly | QIODevice::Truncate);
ini_wave_head();
destinationFile.write((char *)&riff);
destinationFile.write((char *)&fmt);
destinationFile.write((char *)&data);
QAudioFormat format;
// Set up the desired format, for example:
//设置采样率
format.setSampleRate(11025);
//设置通道数
format.setChannelCount(1);
//设置采样大小,一般为8位或16位
format.setSampleSize(16);
//设置编码方式
format.setCodec("audio/pcm");
//设置字节序
format.setByteOrder(QAudioFormat::LittleEndian);
//设置样本数据类型
format.setSampleType(QAudioFormat::UnSignedInt);
QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
info.supportedCodecs();
if(!info.isFormatSupported(format)){
qWarning() << "Default format not supported, trying to use the nearest.";
format = info.nearestFormat(format);
}else{
audio = new QAudioInput(format, this);
audio->start(&destinationFile);
qDebug()<<audio->bufferSize();
ui->state->setText("开始录制");
}
}
}
void Widget::stopRecording()
{
audio->stop();
destinationFile.close();
delete audio;
}
void Widget::handleStateChanged(QAudio::State newState)
{
switch(newState) {
case QAudio::StoppedState:
if (audio->error() != QAudio::NoError||audioOut->error()!=QAudio::NoError) {
// Error handling
qDebug()<<audio->error()<<audioOut->error();
} else {
// Finished recording
}
break;
case QAudio::ActiveState:
ui->state->setText("活动状态");
break;
case QAudio::IdleState:
ui->state->setText("空闲状态");
break;
case QAudio::SuspendedState:
ui->state->setText("暂停状态");
break;
default:
// ... other cases as appropriate
break;
}
}
void Widget::on_stop_clicked()
{
audio->stop();
destinationFile.close();
delete audio;
ui->state->setText("录制结束文件保存在/");
}
void Widget::on_button_stop_clicked()
{
if(ui->button_stop->text()=="暂停"){
ui->button_stop->setText("继续");
audioOut->suspend();
}else{
audioOut->start(&sourceFile);
}
}
//显示波形
void Widget::on_button_see_clicked()
{
QFile file("/test.pcm");
if(file.open(QFile::ReadOnly)){
ba = file.readAll();
tid = this->startTimer(10);
ui->state->setText("文件已加载");
ui->pushButton->click();
}
r=qrand()%255;
g=qrand()%255;
b=qrand()%255;
r1=qrand()%255;
g1=qrand()%255;
b1=qrand()%255;
r2=qrand()%255;
g2=qrand()%255;
b2=qrand()%255;
file.close();
}
bool Widget::eventFilter(QObject *obj, QEvent *event)
{
if(obj ==ui->label && event->type() == QEvent::Paint)
paint();
return QWidget::eventFilter(obj,event);
}
void Widget::timerEvent(QTimerEvent *e)
{
if(tid == e->timerId()){
//paint();
update();
//qDebug()<<tid<<e->timerId();
}
}
void Widget::paintEvent(QPaintEvent *event)
{
}
void Widget::paint()
{
static int start_index=0;
const int n = 1764;
static int v = 0;
static int starty=ui->label->height();
qsrand(time(NULL));
QPainter *p = new QPainter(ui->label);
QByteArray temp;
/*从start_index开始截取n个字节*/
temp = ba.mid(start_index,n);
if(temp.length()>0&&start_index<ba.length()){
for(int i=0;i<temp.length();i++){
v=ui->label->height()/2 - temp.at(i);
/*画数据*/
p->setRenderHint(QPainter::Antialiasing,true);
QLinearGradient lg(i,starty,i,v);
lg.setColorAt(0.236029032, QColor(r,g,b));
lg.setColorAt(0.381924, QColor(r1,g1,b1));
lg.setColorAt(0.618, QColor(r2,g2,b2));
p->setPen(QPen(QBrush(lg),1));
p->drawLine(i,starty,i,v);
}
/*从start_index位置+n个字节*/
start_index+=n;
}else if(temp.length()==0){
/*如果没有数据则重置start_index*/
start_index=0;
/*关闭定时器*/
tid=-1;
}
p->end();
}
void Widget::ini_wave_head()
{
{
riff.cid[0]='R';
riff.cid[1]='I';
riff.cid[2]='F';
riff.cid[3]='F';
riff.cs=123123;
riff.format[0]='W';
riff.format[1]='A';
riff.format[2]='V';
riff.format[3]='E';
}
{
fmt.sid[0]='f';
fmt.sid[1]='m';
fmt.sid[2]='t';
fmt.sid[3]=' ';
fmt.s1s=16;
fmt.af=1;
fmt.nc=1;
fmt.sr=11025;
fmt.br=1231;
fmt.ba=123;
fmt.bps=16;
}
{
data.s2id[0]='d';
data.s2id[1]='a';
data.s2id[2]='t';
data.s2id[3]='a';
data.s2s=123123;
}
}
最终样子