话不多说,先上程序,上面是文件路径选择, 中间三个功能模块,最下面是个状态显示窗口,替换了cmd小黑窗,用起来相当丝滑
- 直接选择文件夹,写了个文件过滤,可以一键转换文件夹下所有pcm/wav文件
上代码
一、ui设计
脑子里先想好,设计出来的程序大概什么样,然后在Qt的GUI里面设计出来,大概就这样子
二、定义类
ui里设计好模块,再根据模块设计分别实现的类,也可以先手画一下类之间的关系;
我这里刚好是三个类对应三个功能,然后再加一个主界面,感觉也不需要什么菜单栏,状态栏,一个widget就满足我的需求了
三、类实现
pcm2wav.cpp
这里具体实现就是在pcm裸数据,加上一个44字节的wav头
我这里直接搞了一个函数实现,方便其他程序调用pcm2WavFile(QString pathWav,QString pathPcm,const int NumChannels,const int SampleRate,const int BitsPerSample )
记得python里面有个wave的包,直接调用就可以,无奈苦逼c++还得手撸
#include "pcm2wav.h"
#include <iostream>
#include <string.h>
#include <fstream>
#include <QString>
#include <QFileInfo>
#include <QDebug>
using namespace std;
pcm2wav::pcm2wav(QObject *parent) : QObject(parent)
{
}
//参数:wav文件路径、pcm文件路径、声道数、采样率、位数
void pcm2wav::pcm2WavFile(QString pathWav,QString pathPcm,const int NumChannels,const int SampleRate,const int BitsPerSample )
{
// 准备文件
QFileInfo fi;
fi = QFileInfo(pathPcm);
QString fiName = fi.fileName();
// const int NumChannels = 1; //通道数,
// const int SampleRate = 16000; //采样率
// const int BitsPerSample = 24; //每个采样点的bit数,一般为8,16,32等
QString wavPCM = pathWav+fiName.left(fiName.size()-3)+"wav";//设置wav的文件名
ifstream pcmIn(qPrintable(pathPcm), ios::in|ios::binary);
ofstream wavOut(qPrintable(wavPCM),ios::out | ios::binary);
if(!wavOut.is_open())
{
cout<<"open wavfile erro"<<endl;
return ;
}
if(!pcmIn.is_open())
{
cout<<"open pcmfile erro"<<endl;
return ;
}
WAVE_HEADER pcmHEADER;
WAVE_FMT pcmFMT;
WAVE_DATA pcmDATA;
// 1. /* WAVE_HEADER */
//获取文件尺寸
pcmIn.seekg(0,ios::end);
unsigned long pcmSize = pcmIn.tellg();
pcmHEADER.ChunkSize = 36 + pcmSize;
memcpy(pcmHEADER.ChunkID, "RIFF", strlen("RIFF"));
memcpy(pcmHEADER.Format, "WAVE", strlen("WAVE"));
wavOut.write((char*)&pcmHEADER,sizeof(WAVE_HEADER));
//2. /* WAVE_FMT */
memcpy(pcmFMT.Subchunk1ID, "fmt ", strlen("fmt "));
pcmFMT.Subchunk1Size = 16;
pcmFMT.AudioFormat = 1;
pcmFMT.NumChannels = NumChannels;
pcmFMT.SampleRate = SampleRate;
pcmFMT.BitsPerSample = BitsPerSample;
pcmFMT.ByteRate = pcmFMT.SampleRate*pcmFMT.NumChannels*pcmFMT.BitsPerSample/8;
pcmFMT.BlockAlign = pcmFMT.NumChannels*pcmFMT.BitsPerSample/8;
wavOut.write((char*)&pcmFMT,sizeof(WAVE_FMT));
//3. /* WAVE_DATA */
memcpy(pcmDATA.Subchunk2ID, "data", strlen("data"));
pcmDATA.Subchunk2Size = pcmSize;
wavOut.write((char*)&pcmDATA,sizeof(WAVE_DATA));
//4. //数据拷贝
char *temp= new char[pcmSize];
pcmIn.seekg(0,ios::beg);
pcmIn.read(temp, pcmSize);
wavOut.write(temp, pcmSize);
delete temp;
pcmIn.close();
wavOut.close();
}
wav2pcm.cpp
直接删掉文件头
#ifndef WAV2PCM_H
#define WAV2PCM_H
#include <QObject>
class wav2pcm : public QObject
{
Q_OBJECT
public:
explicit wav2pcm(QObject *parent = nullptr);
void wav2pcmFiles(QString pathWav,QString pathPcm,int waveSize);
signals:
public slots:
};
#endif // WAV2PCM_H
audiobitconv.h
#ifndef AUDIOBITCONV_H
#define AUDIOBITCONV_H
#include <QObject>
class audioBitConv : public QObject
{
Q_OBJECT
public:
explicit audioBitConv(QObject *parent = nullptr);
void bitConverFiles(QString,QString,int,int);
signals:
public slots:
};
#endif // AUDIOBITCONV_H
audiobitconv.cpp
#include "audiobitconv.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <math.h>
#include <QFileInfo>
#define N 44
using namespace std;
audioBitConv::audioBitConv(QObject *parent) : QObject(parent)
{
}
void audioBitConv::bitConverFiles(QString initBitPcm,QString _converbitpcm,
int initBit,int conveBit)
{
QFileInfo fi;
fi = QFileInfo(initBitPcm);
QString fiName = fi.fileName();
QString converBitPcm = _converbitpcm+fiName.left(fiName.size()-4)+QString::number(conveBit)+".pcm";
//24位PCM转为量化电平读入内存v1
ifstream bit24PcmIn(qPrintable(initBitPcm),ios::in| ios::binary);
if(!bit24PcmIn.is_open())
{
cout<<"open 24file erro"<<endl;
return ;
}
vector<int>v1;
while (!bit24PcmIn.eof())
{
int temp;
bit24PcmIn.read((char*)&temp,initBit/8);
v1.push_back(temp);
}
v1.pop_back();
bit24PcmIn.close();
// 高位电平转低位,二进制存盘
.......待续
}
还没写完。。。
需要用,可先下载https://download.csdn.net/download/db1403600882/34039836