int simplest_pcm16le_to_wave(const char *pcmpath, int channels, int sample_rate, const char *wavepath)
{
typedef struct WAVE_HEADER{
char fccID[4]; //內容爲""RIFF
unsigned long dwSize; //最後填寫,WAVE格式音頻的大小
char fccType[4]; //內容爲"WAVE"
}WAVE_HEADER;
typedef struct WAVE_FMT{
char fccID[4]; //內容爲"fmt "
unsigned long dwSize; //內容爲WAVE_FMT佔的字節數,爲16
unsigned short wFormatTag; //如果爲PCM,改值爲 1
unsigned short wChannels; //通道數,單通道=1,雙通道=2
unsigned long dwSamplesPerSec;//採用頻率
unsigned long dwAvgBytesPerSec;/* ==dwSamplesPerSec*wChannels*uiBitsPerSample/8 */
unsigned short wBlockAlign;//==wChannels*uiBitsPerSample/8
unsigned short uiBitsPerSample;//每個採樣點的bit數,8bits=8, 16bits=16
}WAVE_FMT;
typedef struct WAVE_DATA{
char fccID[4]; //內容爲"data"
unsigned long dwSize; //==NumSamples*wChannels*uiBitsPerSample/8
}WAVE_DATA;
int bits = 16;
WAVE_HEADER pcmHEADER;
WAVE_FMT pcmFMT;
WAVE_DATA pcmDATA;
unsigned short m_pcmData;
FILE *fp, *fpout;
fp = fopen(pcmpath, "rb+");
if (fp == NULL)
{
printf("Open pcm file error.\n");
return -1;
}
fpout = fopen(wavepath, "wb+");
if (fpout == NULL)
{
printf("Create wav file error.\n");
return -1;
}
/* WAVE_HEADER */
memcpy(pcmHEADER.fccID, "RIFF", strlen("RIFF"));
memcpy(pcmHEADER.fccType, "WAVE", strlen("WAVE"));
fseek(fpout, sizeof(WAVE_HEADER), SEEK_CUR); //1=SEEK_CUR ??????
/* WAVE_FMT */
#if 1
memcpy(pcmFMT.fccID, "fmt ", strlen("fmt "));
pcmFMT.dwSize = 16;
pcmFMT.wFormatTag = 1;
pcmFMT.wChannels = 1;
pcmFMT.dwSamplesPerSec = sample_rate;
pcmFMT.uiBitsPerSample = bits;
pcmFMT.dwAvgBytesPerSec = pcmFMT.dwSamplesPerSec*pcmFMT.wChannels*pcmFMT.uiBitsPerSample / 8;
pcmFMT.wBlockAlign = pcmFMT.wChannels*pcmFMT.uiBitsPerSample / 8;
fwrite(&pcmFMT, sizeof(WAVE_FMT), 1, fpout); //????????????
#endif
/* WAVE_DATA */
memcpy(pcmDATA.fccID, "data", strlen("data"));
pcmDATA.dwSize = 0;
fseek(fpout, sizeof(WAVE_DATA), SEEK_CUR);//????????????????????????
fstream readData(pcmpath, ios::in);
vector<double>pcmData;
double dPCMData = 0.0;
if (readData.is_open())
{
string temp = "";
while (getline(readData, temp))
{
if (temp.length() > 1)
{
pcmData.push_back(atof(temp.c_str()));
dPCMData = atof(temp.c_str());
pcmDATA.dwSize += 2;
if (dPCMData < 0)
{
m_pcmData = dPCMData * 32768;
}
else
{
m_pcmData = dPCMData * 32767;
}
fwrite(&m_pcmData, sizeof(unsigned short), 1, fpout);
}
}
}
//fread(&m_pcmData, sizeof(unsigned short), 1, fp);
//while (!feof(fp))
//{
// pcmDATA.dwSize += 2;
// fwrite(&m_pcmData, sizeof(unsigned short), 1, fpout);
// fread(&m_pcmData, sizeof(unsigned short), 1, fp);
//}
pcmHEADER.dwSize = 44 + pcmDATA.dwSize;
rewind(fpout);
fwrite(&pcmHEADER, sizeof(WAVE_HEADER), 1, fpout);
fseek(fpout, sizeof(WAVE_FMT), SEEK_CUR);
fwrite(&pcmDATA, sizeof(WAVE_DATA), 1, fpout);
fclose(fp);
fclose(fpout);
return 0;
}
PCM數據格式:http://blog.csdn.net/ownwell/article/details/8114121/
視音頻數據處理入門:PCM音頻採樣數據處理:http://blog.csdn.net/leixiaohua1020/article/details/50534316