c语言 文件 long double 读取,读取*.wav音频文件
1、wav音頻文件的格式
wav文件由文件頭和采樣數據2部分組成。
文件頭又分為RIFF(Resource Interchange File Format)、WAVE文件標識段 和 聲音數據格式說明段組成。
各段的起始地址分別由RIFF標識符、WAVE標識符、以及波形格式標識符(FMT)標定。
(1)文件頭格式
注意:下面的地址是連續的
(2)數據格式
雖然上圖給出的數據標識符起始地址剛好是文件頭的末地址+1,但并不代表總是這樣。
因此,我們在讀取數據時最好是找到數據標識符,該標識符的4個字節剛好是'd'、‘a’、‘t’、‘a’。
2、C語言讀取wav文件
首先對一些類型使用了重定義
typedef unsigned char uchar;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;
typedef char sint8;
typedef short sint16;
typedef long sint32;
typedef float fp32;
typedef double fp64;
typedef enum BOOLEAN
{
TRUE = 1,
FALSE = 0
} boolean;
(1)wav結構體定義
//wave文件頭
typedef struct WaveHeader
{
uint8 riff[4]; //資源交換文件標志
uint32 size; //從下個地址開始到文件結尾的字節數
uint8 wave_flag[4]; //wave文件標識
uint8 fmt[4]; //波形格式標識
uint32 fmt_len; //過濾字節(一般為00000010H)
uint16 tag; //格式種類,值為1時,表示PCM線性編碼
uint16 channels; //通道數,單聲道為1,雙聲道為2
uint32 samp_freq; //采樣頻率
uint32 byte_rate; //數據傳輸率 (每秒字節=采樣頻率×每個樣本字節數)
uint16 block_align; //塊對齊字節數 = channles * bit_samp / 8
uint16 bit_samp; //bits per sample (又稱量化位數)
} wave_header_t;
typedef struct WaveStruct
{
FILE *fp; //file pointer
wave_header_t header; //header
uint8 data_flag[4]; //數據標識符
uint32 length; //采樣數據總數
uint32 *pData; //data
} wave_t;
wave_t wave;
(2)讀取文件頭信息
/*
* open *.wav file
*/
void WaveOpen(char *file, int raw, int mono_stereo)
{
uchar temp = 0;
uint8 read_bytes = 0;
char *channel_mappings[] = {NULL,"mono","stereo"};
uint32 total_time = 0;
struct PlayTime //播放時間
{
uint8 hour;
uint8 minute;
uint8 second;
} play_time;
if(NULL == (wave.fp=fopen(file, "rb"))) /* open file */
{
printf("file %s open failure!\n", file);
}
/* read heade information */
if(4 != fread(wave.header.riff, sizeof(uint8), 4, wave.fp)) /* RIFF chunk */
{
printf("read riff error!\n");
return;
}
if(1 != fread(&wave.header.size, sizeof(uint32), 1, wave.fp)) /* SIZE : from here to file end */
{
printf("read size error!\n");
return;
}
if(4 != fread(wave.header.wave_flag, sizeof(uint8), 4, wave.fp)) /* wave file flag */
{
printf("read wave_flag error!\n");
return;
}
if(4 != fread(wave.header.fmt, sizeof(uint8), 4, wave.fp)) /* fmt chunk */
{
printf("read fmt error!\n");
return;
}
if(1 != fread(&wave.header.fmt_len, sizeof(uint32), 1, wave.fp)) /* fmt length */
{
printf("read fmt_len error!\n");
return;
}
if(1 != fread(&wave.header.tag, sizeof(uint16), 1, wave.fp)) /* tag : PCM or not */
{
printf("read tag error!\n");
return;
}
if(1 != fread(&wave.header.channels, sizeof(uint16), 1, wave.fp)) /* channels */
{
printf("read channels error!\n");
return;
}
if(1 != fread(&wave.header.samp_freq, sizeof(uint32), 1, wave.fp)) /* samp_freq */
{
printf("read samp_freq error!\n");
return;
}
if(1 != fread(&wave.header.byte_rate, sizeof(uint32), 1, wave.fp)) /* byte_rate : decode how many bytes per second */
{ /* byte_rate = samp_freq * bit_samp */
printf("read byte_rate error!\n");
return;
}
if(1 != fread(&wave.header.block_align, sizeof(uint16), 1, wave.fp)) /* quantize bytes for per samp point */
{
printf("read byte_samp error!\n");
return;
}
if(1 != fread(&wave.header.bit_samp, sizeof(uint16), 1, wave.fp)) /* quantize bits for per samp point */
{ /* bit_samp = byte_samp * 8 */
printf("read bit_samp error!\n");
return;
}
/* jump to "data" for reading data */
do
{
fread(&temp, sizeof(uchar), 1, wave.fp);
}
while('d' != temp);
wave.data_flag[0] = temp;
if(3 != fread(&wave.data_flag[1], sizeof(uint8), 3, wave.fp)) /* data chunk */
{
printf("read header data error!\n");
return;
}if(1 != fread(&wave.length, sizeof(uint32), 1, wave.fp)) /* data length */
{
printf("read length error!\n");
}
/* jduge data chunk flag */
if(!StrCmp(wave.data_flag, "data", 4))
{
printf("error : cannot read data!\n");
return;
}
total_time = wave.length / wave.header.byte_rate;
play_time.hour = (uint8)(total_time / 3600);
play_time.minute = (uint8)((total_time / 60) % 60);
play_time.second = (uint8)(total_time % 60);
/* printf file header information */
printf("%s %ldHz %dbit, DataLen: %ld, Rate: %ld, Length: %2ld:%2ld:%2ld\n",
channel_mappings[wave.header.channels], //聲道
wave.header.samp_freq, //采樣頻率
wave.header.bit_samp, //每個采樣點的量化位數
wave.length,
wave.header.byte_rate,
play_time.hour,play_time.minute,play_time.second);
//fclose(wave.fp); /* close wave file */
}
按結構體一點點的讀出文件頭的信息,請注意
/* jump to "data" for reading data */
的那一段,“先識別data標識符,再接著往下讀取”。
(3)讀數據
在讀完數據長度之后就全是數據了,直接使用fread按uint32格式讀取數據即可,我這里每次讀取1152個數據(即一幀)。
/*
* get wave data
*/
uint32* GetWave(void)
{
static uint32 buffer[1152] = {0};
uint16 n = 0;
uint16 p = 0;
p = fread(buffer, sizeof(uint32), n, wave.fp);
if(!p)
{
return 0;
}
else
{
for(; p
{
buffer[p] = 0;
}
return buffer;
}
}
上面程序中注意幾點,
(1)不要定義大容量的局部變量,因為局部變量存放在堆棧中。如果一定要定義,要定義成static類型。
(2)不要返回局部變量的的地址,因為在堆棧中的地址值是不確定的。
上面的程序返回局部數組的指針,前提是 已經將數據存放在靜態數據存儲區。
但不管怎樣,返回局部變量的地址總是不好的。
總結
以上是生活随笔為你收集整理的c语言 文件 long double 读取,读取*.wav音频文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 顺序查找计时函数C语言,用C语言编二分查
- 下一篇: 红帽子怎么vi编译c语言,在RedHat