/*
*=================================================================
* FNAME: test.cc
* DESCP: <+Brief Descripation+>
* CREAT: 2015-08-18 15:39:21
* LC_AT: 2015-08-18 15:45:57
* VERNO: 1.0.4
* CNOTE: <+Latest Change+>
*=================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FOURCC_RIFF "RIFF"
#define FOURCC_WAVE "WAVE"
#define FOURCC_FMT "fmt "
#define FOURCC_DATA "data"
#define SUPPORTED_SAMPLE_RATE_8K 8000
#ifndef WAVE_FORMAT_PCM
#define WAVE_FORMAT_PCM 0x0001
#define WAVE_FORMAT_ALAW 0x0006
#define WAVE_FORMAT_MULAW 0x0007
#endif
//#ifdef DEBUG
//#define tDebug printf
//#else /* ----- not DEBUG ----- */
//#define tDebug //printf
//#endif /* ----- not DEBUG ----- */
#define tDebug printf
/**
* @brief
* 获取语音文件的头信息(包含 采样点数,语音文件的编码格式,声轨数目)
* @param fpWav
* @param nSampleNum
* @param nChanns
* @param nWavType
* @return
* 0, WAVE文件头正常,且此时文件指针(fpWav)指向实际声音数据的起始位置
* -1, 不是RIFF格式的文件
* -2, 文件是RIFF格式的非WAVE文件
* -3, 此WAVE文件的编码格式不是 PCM,ALAW,ULAW
* -4, 此WAVE文件的音轨数不是 1 也不是 2
* -5, 此WAVE文件的采样率不是 8K
* -6, 此WAVE文件的采样点的大小不是 8bit 也不是16bit
* -7, 此WAVE文件的具体格式 不是 8K_16BIT_PCM 也不是 8K_8BIT_ALAW
*/
int GetWaveHeader(FILE *fpWav, int &nSampleNum, short &nChanns, short &nWavType)
{
nSampleNum = -1;
nWavType = -1;
char magic[4] = {0};
fseek(fpWav, 0L, SEEK_SET); //确保输入的文件指针 fpWav 的位置是文件的初始位置
fread((void*) magic, 4, 1, fpWav);
if (0 != strncmp(FOURCC_RIFF, magic, 4)) {
tDebug("[Tip] Input file is not in RIFF format\n");
return -1;
}
int lng = 0;
fread((void*) &lng, 4, 1, fpWav);
fread((void*) magic, 4, 1, fpWav);
if (0 != strncmp(FOURCC_WAVE, magic, 4)) {
tDebug("[Tip] Input file is not in WAVE format\n");
return -2;
}
//look for FOURCC_FMT/FOURCC_DATA before end of file
int len = 0;
short blockAlign = 0, sampleSize = 0;
while (0 == feof(fpWav)) //not reach the end of this file
{
fread((void*) magic, 4, 1, fpWav); //read ChunkID
fread((void*) &len, 4, 1, fpWav); //read ChunkSize
if (0 == strncmp(FOURCC_DATA, magic, 4))
{//reach DATA Chunk,exit the while loop
nSampleNum = len / (sampleSize / 8); // 声音数据的采样点数目
break;
}
if (0 == strncmp(FOURCC_FMT, magic, 4))
{ //reach Fmt Chunk,and parse format informations
fread(&nWavType, 2, 1, fpWav); // 读取数据类型,例如: PCM, ALaw,Mulaw等
if (nWavType != WAVE_FORMAT_PCM && nWavType != WAVE_FORMAT_MULAW
&& nWavType != WAVE_FORMAT_ALAW)
{
tDebug("[Tip] Only standard PCM and ALAW supported.\n");
return -3;
}
fread(&nChanns, 2, 1, fpWav); //Number of Channels, 单通道或双通道
if (nChanns != 1 && nChanns != 2)
{
tDebug("[Tip] Wave file‘s channels is %d,NOT SUPPORTED\n", nChanns);
nChanns = -1;
return -4;
}
fread(&lng, 4, 1, fpWav); // Sample Rate , 采样率
if (lng != SUPPORTED_SAMPLE_RATE_8K)
{
tDebug("[Tip] Wave file‘s SampleRate(SR) is %d, NOT SUPPORTED! \n", lng);
return -5;
}
fread(&lng, 4, 1, fpWav); // 每秒的字节数。例如:8k16bit时为 8000×2=16000
fread(&blockAlign, 2, 1, fpWav); // Block align , Chunk 的对齐单位
fread(&sampleSize, 2, 1, fpWav); // Data size ,一个采样点的大小(比特数)
if (sampleSize != 16 && sampleSize != 8)
{
tDebug("[Tip] Only 8/16 bit audio supported!\n");
return -6;
}
// 类型检查
if ((nWavType == WAVE_FORMAT_PCM && sampleSize != 16)
|| ((nWavType == WAVE_FORMAT_MULAW || nWavType == WAVE_FORMAT_ALAW)
&& sampleSize != 8))
{
tDebug("[Tip] Only 8K_16BIT_PCM and 8K_8BIT_ALAW supported!\n");
return -7;
}
// 如果是扩展的RIFF格式,则"fmt "块的大小可能大于16字节
len -= 16;
}//end of if (0 == strncmp(FOURCC_FMT, magic, 4))
//fmt子块多余的信息,我们不感兴趣. 直接跳过剩余的fmt字节
for (char c; len > 0; len--)
{
fread(&c, 1, 1, fpWav);
}
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2025-01-01 12:05:10