1 Star 1 Fork 0

chenhaoyang2019/pcmPlayer

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
mainwindow.cpp 9.30 KB
一键复制 编辑 原始数据 按行查看 历史
chenhaoyang2019 提交于 2021-04-18 14:31 +08:00 . fix crash when stopping after pause.
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QFileDialog>
#include <QTextCodec>
#include <QDebug>
#define DELETE_OBJ(object) if(nullptr != object)\
{\
delete object;\
object = nullptr;\
}
inline QString GBK2UTF8(const char *inStr)
{
QTextCodec *gbk = QTextCodec::codecForName("GBK");
QString g2u;
if(nullptr != gbk)
{
g2u = gbk->toUnicode(inStr);
}
else
{
g2u = inStr;
}
return g2u;
}
inline QString UTF82GBK(const char *inStr)
{
QTextCodec *utf8 = QTextCodec::codecForName("UTF-8");
QString utf2gbk;
if(nullptr != utf8)
{
utf2gbk = utf8->toUnicode(inStr);
}
else
{
utf2gbk = inStr;
}
return utf2gbk;
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
m_audioOutput(nullptr),
m_streamOut(nullptr),
m_perFrameSize(0),
workThread(nullptr),
worked(false)
{
ui->setupUi(this);
ui->comboBox->addItem(GBK2UTF8("unsigned int"));
ui->comboBox->addItem(GBK2UTF8("signed int"));
ui->comboBox->addItem(GBK2UTF8("float"));
ui->comboBox_2->addItem(GBK2UTF8("8"));
ui->comboBox_2->addItem(GBK2UTF8("16"));
}
int MainWindow::playFrame(const char *data, unsigned int len)
{
if(nullptr != m_audioOutput &&
m_audioOutput->state() != QAudio::StoppedState &&
m_audioOutput->state() != QAudio::SuspendedState)
{
unsigned int writeLen = 0;
while ((len - writeLen) > 0)
{
/* 音频设备剩余的空间是否可以写"一段"音频 */
if (m_audioOutput->bytesFree() < m_audioOutput->periodSize())
{
QThread::msleep(1);
if ( m_audioOutput->state() == QAudio::StoppedState ||
m_audioOutput->state() == QAudio::SuspendedState){
return 0;
}
continue;
}
if ((len - writeLen) >= m_audioOutput->periodSize())
{
//写入到扬声器
m_streamOut->write(data + writeLen, m_audioOutput->periodSize());
}
else
{
//将最后剩下的数据写入到扬声器
m_streamOut->write(data + writeLen, len - writeLen);
break;
}
writeLen += m_audioOutput->periodSize();
}
return 0;
}
return -1;
}
const char *MainWindow::getFileName()
{
return m_fileName.c_str();
}
unsigned int MainWindow::getFrameSize()
{
return m_perFrameSize;
}
unsigned int MainWindow::getPorgressParTotal()
{
return ui->progressBar->maximum();
}
void MainWindow::setPorgressParValue(unsigned int value)
{
if(value <= ui->progressBar->maximum())
{
ui->progressBar->setValue(value);
}
}
void MainWindow::setPorgressParMaxValue(unsigned int maxValue)
{
ui->progressBar->setMaximum( maxValue);
}
void MainWindow::stopPlay()
{
if(true == worked)
{
ui->progressBar->setValue(0);
m_audioOutput->stop();
m_audioOutput->reset();
worked = false;
ui->play->setText(GBK2UTF8("开始播放"));
DELETE_OBJ(m_audioOutput);
}
}
MainWindow::~MainWindow()
{
on_pushButton_2_clicked();
DELETE_OBJ(m_audioOutput);
DELETE_OBJ(workThread);
delete ui;
}
void MainWindow::on_actionOpen_triggered()
{
m_fileName = QFileDialog::getOpenFileName(this, GBK2UTF8("打开文件") ,tr(""), GBK2UTF8("音频裸流文件(*.pcm);;所有文件(*.*)")).toStdString();
if(false == m_fileName.empty())
{
//QMessageBox::information(this, GBK2UTF8("文件名称"), m_fileName.c_str());
ui->labelFileName->setText(m_fileName.c_str());
}
}
void MainWindow::on_play_clicked()
{
if(m_fileName.empty())
{
return;
}
if(worked == true && m_audioOutput->state() == QAudio::ActiveState)
{
ui->play->setText(GBK2UTF8("继续"));
m_audioOutput->suspend();
return;
}
if(worked == true && m_audioOutput->state() == QAudio::SuspendedState)
{
ui->play->setText(GBK2UTF8("暂停"));
m_audioOutput->resume();
return;
}
//设置采样格式
QAudioFormat audioFormat;
if(ui->lineEdit->text().toInt() <= 0)
{
return;
}
//设置采样率
audioFormat.setSampleRate(ui->lineEdit->text().toInt());
if(ui->lineEdit_2->text().toInt() <= 0)
{
return;
}
//设置通道数
audioFormat.setChannelCount(ui->lineEdit_2->text().toInt());
if(ui->lineEdit_2->text().toInt() <= 0)
{
return;
}
if(QString::compare("unsigned int", ui->comboBox->currentText()) == 0)
{
//设置样本数据类型
audioFormat.setSampleType(QAudioFormat::UnSignedInt);
}
else if(QString::compare("signed int", ui->comboBox->currentText()) == 0)
{
//设置样本数据类型
audioFormat.setSampleType(QAudioFormat::SignedInt);
}
else
{
//设置样本数据类型
audioFormat.setSampleType(QAudioFormat::Float);
}
//设置采样大小,一般为8位或16位
audioFormat.setSampleSize(ui->comboBox_2->currentText().toInt());
//设置编码方式
audioFormat.setCodec("audio/pcm");
//设置字节序
audioFormat.setByteOrder(QAudioFormat::LittleEndian);
m_perFrameSize = audioFormat.sampleRate() * audioFormat.channelCount() * ui->comboBox_2->currentText().toInt() / 8 ;
//音频设备信息
QAudioDeviceInfo info = QAudioDeviceInfo::defaultOutputDevice();
if (!info.isFormatSupported(audioFormat))
{
qDebug()<<"default format not supported try to use nearest";
audioFormat = info.nearestFormat(audioFormat);
}
m_audioOutput = new QAudioOutput(audioFormat, 0);
m_streamOut = m_audioOutput->start();
workThread = new AudioPlayThread(this);
if(nullptr != workThread)
{
workThread->start();
worked = true;
connect(workThread, &AudioPlayThread::updatePregressValue, this, &MainWindow::setPorgressParValue);
connect(this, &MainWindow::stop, workThread, &AudioPlayThread::stopPlay);
connect(workThread, &AudioPlayThread::playEnd, this, &MainWindow::stopPlay);
}
qDebug() << "periodSize:" << m_audioOutput->periodSize() << "bytesFree:" << m_audioOutput->bytesFree();
ui->play->setText(GBK2UTF8("暂停"));
}
void MainWindow::on_pushButton_2_clicked()
{
if(true == worked)
{
DELETE_OBJ(workThread);
stopPlay();
}
}
AudioPlayThread::AudioPlayThread(MainWindow *parent):m_parent(parent),QThread(parent),m_isExit(true)
{
}
void AudioPlayThread::stopPlay()
{
m_isExit = true;
}
AudioPlayThread::~AudioPlayThread()
{
m_isExit = true;
if ( this->isRunning()){
this->requestInterruption();
this->quit();
this->wait();
}
}
void AudioPlayThread::run()
{
if(nullptr == m_parent || m_isExit == false)
{
return;
}
m_isExit = false;
int ret = 0;
//获取文件的指针
const char *fileName = m_parent->getFileName();
if(nullptr == fileName)
{
qDebug()<< "file name is empty";
return;
}
FILE *file = fopen(fileName,"rb");
if(!file)
{
qDebug()<< "Open Failed";
return;
}
//把指针移动到文件的结尾 ,获取文件长度
fseek(file, 0, SEEK_END);
//获取文件长度
unsigned int fileLength = ftell(file);
unsigned int frameSize = m_parent->getFrameSize();
m_parent->setPorgressParMaxValue(fileLength);
//定义数组长度
char *fileBuffer = new char[frameSize];
memset(fileBuffer, 0 , frameSize);
//把指针移动到文件开头 因为我们一开始把指针移动到结尾,如果不移动回来 会出错
rewind(file);
int progressParPerAddNum = frameSize;
unsigned int progressCurrentValue = 0;
qDebug()<< "frameSize:" << frameSize << " fileLength:" << fileLength << " progressParPerAddNum:" << progressParPerAddNum ;
//读文件
ret = fread(fileBuffer, 1, frameSize, file);
while (ret > 0 && m_isExit == false)
{
while( m_parent->playFrame(fileBuffer, ret) != 0 && m_isExit == false)
{
QThread::msleep(1);
}
progressCurrentValue += progressParPerAddNum;
emit updatePregressValue(progressCurrentValue);
/* seek 1 frame(1 seconds) */
//fseek(file, frameSize, SEEK_CUR);
//读文件
ret = fread(fileBuffer, 1, frameSize, file);
}
emit updatePregressValue(m_parent->getPorgressParTotal());
//关闭文件
fclose(file);
//QMessageBox::information(m_parent, GBK2UTF8("提示"), "播放完成");
delete fileBuffer;
qDebug()<<fileLength << " ret:" << ret << GBK2UTF8("播放完成");
emit playEnd();
}
void MainWindow::resizeEvent(QResizeEvent *e)
{
ui->progressBar->resize( this->width() - ui->progressBar->x() *2, ui->progressBar->height());
ui->labelFileName->resize( this->width() - ui->labelFileName->x() *2, ui->labelFileName->height());
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/chenhaoyang2019/pcmPlayer.git
[email protected]:chenhaoyang2019/pcmPlayer.git
chenhaoyang2019
pcmPlayer
pcmPlayer
master

搜索帮助