精华内容
下载资源
问答
  • wav文件格式解析
    2021-03-19 20:21:57

    wav文件格式解析

    概述

    wav文件支持多种不同的比特率、采样率、多声道音频。
    wav是一种RIFF(resource interchange file format 资源互换文件格式,以chunk为单位组织文件)格式文件。在windows上,大部分多媒体文件都是RIFF文件。
    wav文件由RIFF chunk构成,fmt /data chunk是其必须的两个子chunk,除此以外还可以有fact等可选chunk,我们在做parse的时候,主要是分析fmt chunk的数据。

    wav标准结构

    wav文件一般结构
    1.wav文件都是由chunk组成,chunk的格式如下:

    size内容解释
    4 bytesID如“RIFF”
    4 byteschunk size N如标准fmt chunk为16字节
    N bytesdatachunk的内容

    2.只有“fmt ”、“data”两个子chunk的wav文件格式:

    size内容解释
    4 bytesRIFF文件类型格式
    4 bytesfilesize其值为filesize字段后的大小,真正的文件大小为filesize + 8 bytes
    4 bytesWAVE文件格式
    4 bytes"fmt "chunk id,fmt即format,这个chunk保存了音频的采样率、声道数、采样位数等关键信息
    4 bytesfmt chunk sizefmt chunk的大小,一般有16/18/20/22/40字节(也有超过40字节的情况,如果不知道后面部分的含义,直接跳过即可),超过16字节部分为扩展块
    2 bytesAudioFormat 编码格式代码,其值见 《常见编码格式》 表
    2 bytesNum channels声道数,一般有1-8
    4 bytesSample Rate采样率,8/11.025/12/16/22.05/24/32/44.1/48/64/88.2/96/176.4/192 kHZ
    4 bytesByte Rate传输速率,每秒的字节数,计算公式为:采样率*channels*采样位数/8
    2 bytesBlock Align块对齐,告知播放软件一次性需处理多少字节,公式为: 采样位数*声道数/8
    2 bytesBits Per Sample采样位数,一般有8/16/24/32/64,值越大,对声音的还原度越高
    4 bytes“data”data chunk id
    4 bytesData Size N原始音频数据的大小
    N bytesData原始音频数据,也是我们最终想获得的部分,数据保存方式见 pcm存储 表

    3.fmt 扩展块

    fmt chunk的大小一般为16/18/20/22/40字节,当其大小大于16字节时,多出的内容都保存在扩展块中。

    size内容解释
    2bytescbsize扩展块长度,为0时,fmt chunk size为18;为2时,fmt chunk size为20;为22时,fmt chunk size为40
    2bytes有效采样位数最大值为采样字节数*8
    4bytes声道掩码声道号与扬声器位置的映射掩码
    2bytescodec 真正的编码格式代码(相对于extension 的fmt codec为0xFFFE而言)
    14bytesunknown还不知道其含义,在mediainfo中与2字节的codec一起组成subformat

    示例

    以下代码为解析wave格式文件的示例,其功能为将wave文件中的数据部分取出并输出为文件,同时打印相关信息。
    output文件可命名为xxx.pcm。
    命令行使用:xxx.exe [input] [output]

    wav_type.h

    /*****************************************************
    File Name   :  wav_type.h
    Date        :  2020/10/27
    Author      :  l.hua
    Descriptions:  all the declarations used by wav_to_pcm.c
    
    Change log  :
    Date               Mender           Cause
    ******************************************************/
    #ifndef _WAV_TYPE_H_
    #define _WAV_TYPE_H_
    
    extern "C"
    {
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <windows.h>
    #include <direct.h>
    #include <stdint.h>
    }
    
    #define DECODE_FAIL -1
    #define COPY_FAIL -2
    #define READ_BUF_SIZE (1024*1024*4)                  
    
    #define WAVE_FORMAT_UNKNOWN             0x0000
    #define WAVE_FORMAT_UNKNOWN_DES         "WAVE_FORMAT_UNKNOWN" 
    #define WAVE_FORMAT_PCM                 0x0001
    #define WAVE_FORMAT_PCM_DES             "WAVE_FORMAT_PCM"
    #define WAVE_FORMAT_ADPCM               0x0002
    #define WAVE_FORMAT_ADPCM_DES           "WAVE_FORMAT_ADPCM"
    #define WAVE_FORMAT_IEEE_FLOAT          0x0003
    #define WAVE_FORMAT_IEEE_FLOAT_DES      "WAVE_FORMAT_IEEE_FLOAT"
    #define WAVE_FORMAT_ALAW                0x0006
    #define WAVE_FORMAT_ALAW_DES            "WAVE_FORMAT_ALAW"
    #define WAVE_FORMAT_MULAW               0x0007
    #define WAVE_FORMAT_MULAW_DES           "WAVE_FORMAT_MULAW"
    #define WAVE_FORMAT_DTS_MS              0x0008
    #define WAVE_FORMAT_DTS_MS_DES          "WAVE_FORMAT_DTS_MS"
    #define WAVE_FORMAT_WMAS                0x000A
    #define WAVE_FORMAT_WMAS_DES            "WAVE_FORMAT_WMAS"
    #define WAVE_FORMAT_IMA_ADPCM           0x0011
    #define WAVE_FORMAT_IMA_ADPCM_DES       "WAVE_FORMAT_IMA_ADPCM"
    #define WAVE_FORMAT_TRUESPEECH          0x0022
    #define WAVE_FORMAT_TRUESPEECH_DES      "WAVE_FORMAT_TRUESPEECH"
    #define WAVE_FORMAT_GSM610              0x0031
    #define WAVE_FORMAT_GSM610_DES          "WAVE_FORMAT_GSM610"
    #define WAVE_FORMAT_MSNAUDIO            0x0032
    #define WAVE_FORMAT_MSNAUDIO_DES        "WAVE_FORMAT_MSNAUDIO"
    #define WAVE_FORMAT_G726                0x0045
    #define WAVE_FORMAT_G726_DES            "WAVE_FORMAT_G726"
    #define WAVE_FORMAT_MPEG                0x0050
    #define WAVE_FORMAT_MPEG_DES            "WAVE_FORMAT_MPEG"
    #define WAVE_FORMAT_MPEGLAYER3          0x0055
    #define WAVE_FORMAT_MPEGLAYER3_DES      "WAVE_FORMAT_MPEGLAYER3"
    #define WAVE_FORMAT_UNKNOWN2            0x0070
    #define WAVE_FORMAT_UNKNOWN2_DES      "WAVE_FORMAT_UNKNOWN2"
    #define WAVE_FORMAT_UNKNOWN3            0x0072
    #define WAVE_FORMAT_UNKNOWN3_DES      "WAVE_FORMAT_UNKNOWN3"
    #define WAVE_FORMAT_DOLBY_AC3_SPDIF     0x0092
    #define WAVE_FORMAT_DOLBY_AC3_SPDIF_DES "WAVE_FORMAT_DOLBY_AC3_SPDIF"
    #define WAVE_FORMAT_A52                 0x2000
    #define WAVE_FORMAT_A52_DES             "WAVE_FORMAT_A52"
    #define WAVE_FORMAT_DTS                 0x2001
    #define WAVE_FORMAT_DTS_DES             "WAVE_FORMAT_DTS"
    #define WAVE_FORMAT_WMA1                0x0160
    #define WAVE_FORMAT_WMA1_DES            "WAVE_FORMAT_WMA1"
    #define WAVE_FORMAT_WMA2                0x0161
    #define WAVE_FORMAT_WMA2_DES            "WAVE_FORMAT_WMA2"
    #define WAVE_FORMAT_WMAP                0x0162
    #define WAVE_FORMAT_WMAP_DES            "WAVE_FORMAT_WMAP"
    #define WAVE_FORMAT_WMAL                0x0163
    #define WAVE_FORMAT_WMAL_DES            "WAVE_FORMAT_WMAL"
    #define WAVE_FORMAT_DIVIO_AAC           0x4143
    #define WAVE_FORMAT_DIVIO_AAC_DES       "WAVE_FORMAT_DIVIO_AAC"
    #define WAVE_FORMAT_AAC                 0x00FF
    #define WAVE_FORMAT_AAC_DES             "WAVE_FORMAT_AAC"
    #define WAVE_FORMAT_FFMPEG_AAC          0x7060
    #define WAVE_FORMAT_FFMPEG_AAC_DES      "WAVE_FORMAT_FFMPEG_AAC"
    #define WAVE_FORMAT_EXTENSIBLE          0xFFFE
    #define WAVE_FORMAT_EXTENSIBLE_DES      "WAVE_FORMAT_EXTENSIBLE"
    
    /******************************
    	STRUCTURE   DECLARATIONS
    ******************************/
    typedef struct {
    	uint16_t u16FormatTag;
    	uint16_t u16Channels;
    	uint32_t u32SamplesPerSec;
    	uint32_t u32BytePerSec;
    	uint16_t u16BlockAlign;
    	uint16_t u16BitsPerSample;
    }WavFmtCommTex_S;
    
    typedef struct {
    	WavFmtCommTex_S sFmtComm;
    	uint16_t u16ExtraSize;
    	uint16_t u16EffectiveBitsPerSample;
    	uint32_t u32Loudspeaker;
    	uint16_t u16RealCodecTag;
    	uint8_t u8Occupy[24];
    }WavFmtTex_S;
    
    typedef struct {
    	char cRiff[4];
    	uint32_t lFileSize;
    	char cWave[4];
    	char cFmtChunk[4];
    	uint32_t lChunkLen;
    }WavComTex_S;
    
    typedef struct {
    	WavComTex_S sComm;
    	WavFmtTex_S sFmt;
    }WavHeaderTex_S;
    
    /******************************
    	FUNCTION   DECLARATIONS
    ******************************/
    
    int WavDecode(FILE* FSrcFile, WavHeaderTex_S* pFormatInfo);
    
    int AudioSaveAs1(FILE* FSrcFile, FILE* FDesFile);
    
    int AudioSaveAs2(FILE* FSrcFile, FILE* FDesFile, int Len);
    
    #endif// _WAV_TYPE_H_#pragma once
    
    

    wav_type.c

    /*****************************************************
    File Name   :  wav_type.c
    Date        :  2020/10/27
    Author      :  l.hua
    Descriptions:  all the functions define used by wav_to_pcm.c
    
    Change log  :
    Date               Mender           Cause
    
    ******************************************************/
    #include "wav_type.h"
    
    /**************************************************************************
      Function Name: WavDecode
      Purposes: Gets format infomation from source file.
      Descriptions: Gets format infomation from source file.
      Arguments:
    	FSrcFile: [in] A file pointer to the sourcefile.
    	pFormatInfo: [out] A WavAddExtraTex_S pointer to saving format infomation.
      Returns:
    	success: Return data location in the source file.
    	fail: return DECODE_FAIL;
      See also:
    **************************************************************************/
    int WavDecode(FILE* FSrcFile, WavHeaderTex_S* pFormatInfo)
    {
    	int iSize = sizeof(WavComTex_S);
    	int iDataPos = 0;
    	char acChunkId[4];
    	int iChunkLen = 0;
    	int iRet = 0;
    	/* Move file pointer to the start of the file */
    	fseek(FSrcFile, 0, SEEK_SET);
    
    	/* Check that if FSrcFile or pFormatInfo is NULL */
    	if (FSrcFile == NULL || pFormatInfo == NULL) {
    		printf("DECODE FAIL.\n");
    		return DECODE_FAIL;
    	}
    
    	memset(pFormatInfo, 0, sizeof(WavHeaderTex_S));
    	if (fread(&pFormatInfo->sComm, 1, iSize, FSrcFile) != iSize) {
    		printf("FREAD RIFF FAIL.\n");
    		return DECODE_FAIL;
    	}
    	iDataPos += iSize;
    
    	if (strncmp(pFormatInfo->sComm.cWave, "WAVE", 4)) {
    		printf("Not support format[Didn't find 'WAVE'].\n");
    		return DECODE_FAIL;
    	}
    
    	/* Find "fmt" chunk */
    	strncpy(acChunkId, pFormatInfo->sComm.cFmtChunk, 4);
    	iChunkLen = pFormatInfo->sComm.lChunkLen;
    	while (strncmp(acChunkId, "fmt ", 4) != 0) {
    		/* Skip the chunk */
    		fseek(FSrcFile, iChunkLen, SEEK_CUR);
    		iDataPos += iChunkLen;
    		/* Try to find "fmt" */
    		if (fread(acChunkId, 1, 4, FSrcFile) != 4) {
    			printf("FREAD CHUNKID FAIL 1.\n");
    			return DECODE_FAIL;
    		}
    		if (fread((uint8_t*)&iChunkLen, 1, 4, FSrcFile) != 4) {
    			printf("FREAD CHUNKLEN FAIL 1.\n");
    			return DECODE_FAIL;
    		}
    		iDataPos += 8;
    	}
    
    	/* Copy "fmt " info to pFormatInfo->sComm */
    	strncpy(pFormatInfo->sComm.cFmtChunk, acChunkId, 4);
    	pFormatInfo->sComm.lChunkLen = iChunkLen;
    	/* Read sFmt chunk */
    	iSize = pFormatInfo->sComm.lChunkLen;
    	if (50 < iSize) {
    		printf("Not support format[Fmt chunk is greater than 50].\n");
    		return DECODE_FAIL;
    	}
    
    	if (fread(&pFormatInfo->sFmt, 1, iSize, FSrcFile) != iSize) {
    		printf("FREAD FMT FAIL.\n");
    		return DECODE_FAIL;
    	}
    	iDataPos += iSize;
    
    	/* Try to find "data" */
    	if (fread(acChunkId, 1, 4, FSrcFile) != 4) {
    		printf("FREAD CHUNKID FAIL 2.\n");
    		return DECODE_FAIL;
    	}
    	if (fread((uint8_t*)&iChunkLen, 1, 4, FSrcFile) != 4) {
    		printf("FREAD CHUNKLEN FAIL 2.\n");
    		return DECODE_FAIL;
    	}
    	iDataPos += 8;
    
    	while (strncmp(acChunkId, "data", 4) != 0) {
    		/* Skip the chunk */
    		fseek(FSrcFile, iChunkLen, SEEK_CUR);
    		iDataPos += iChunkLen;
    		/* Try to find "data" */
    		if (fread(acChunkId, 1, 4, FSrcFile) != 4) {
    			printf("%d\n", iChunkLen);
    			printf("%c%c%c%c\n", acChunkId[0], acChunkId[1], acChunkId[2], acChunkId[3]);
    			printf("FREAD CHUNKID FAIL 3.\n");
    			return DECODE_FAIL;
    		}
    		if (fread((uint8_t*)&iChunkLen, 1, 4, FSrcFile) != 4) {
    			printf("FREAD CHUNKLEN FAIL 3.\n");
    			return DECODE_FAIL;
    		}
    		iDataPos += 8;
    	}
    
    	return iDataPos;
    }
    
    /**************************************************************************
      Function Name: AudioSaveAs1
      Purposes: Copy from FSrcFile to the FDesfile.
      Descriptions: Copy the FSrcFile to the FDesfile.
      Arguments:
    	FSrcFile: [in] A file pointer to the sourcefile.
    	FDesFile: [out] A WavAddExtraTex_S pointer to saving format infomation.
      Returns:
    	success: Return the real length of the copy.
    	fail: return COPY_FAIL;
      See also:
    **************************************************************************/
    int AudioSaveAs1(FILE* FSrcFile, FILE* FDesFile)
    {
    	int iReadLen = 0, iWriteLen = 0;
    	int iLen = 0;
    	/* Buffer that copys FSrcFile to FDesFile. */
    	uint8_t* pu8ReadBuf = NULL;
    
    	pu8ReadBuf = (uint8_t*)malloc(READ_BUF_SIZE);
    	if (NULL == pu8ReadBuf) {
    		printf("MALLOC READBUF FAIL.\n");
    		return COPY_FAIL;
    	}
    
    	while (!feof(FSrcFile)) {
    		memset(pu8ReadBuf, 0, READ_BUF_SIZE);
    		iReadLen = fread(pu8ReadBuf, 1, READ_BUF_SIZE, FSrcFile);
    		iWriteLen = fwrite(pu8ReadBuf, 1, iReadLen, FDesFile);
    		if (iWriteLen != iReadLen) {
    			printf("WRITE TO FDesFile ERROR.\n");
    			if (pu8ReadBuf != NULL) {
    				free(pu8ReadBuf);
    			}
    			return COPY_FAIL;
    		}
    		iLen += iWriteLen;
    	}
    	if (pu8ReadBuf != NULL) {
    		free(pu8ReadBuf);
    	}
    
    	return iLen;
    }
    
    /**************************************************************************
      Function Name: AudioSaveAs2
      Purposes: Copy the Len length from FSrcFile to the FDesfile.
      Descriptions: Copy the Len length FSrcFile to the FDesfile.
      Arguments:
    	FSrcFile: [in] A file pointer to the sourcefile.
    	FDesFile: [out] A WavAddExtraTex_S pointer to saving format infomation.
    	Len: [in] the length will copy.
      Returns:
    	success: Return the real length of the copy.
    	fail: return COPY_FAIL;
      See also:
    **************************************************************************/
    int AudioSaveAs2(FILE* FSrcFile, FILE* FDesFile, int Len)
    {
    	size_t iReadLen = 0, iWriteLen = 0;
    	size_t iLen = 0;
    	/* Buffer that copys FSrcFile to FDesFile. */
    	uint8_t* pu8ReadBuf = NULL;
    
    	pu8ReadBuf = (uint8_t*)malloc(READ_BUF_SIZE);
    	if (NULL == pu8ReadBuf) {
    		printf("MALLOC READBUF FAIL.\n");
    		return COPY_FAIL;
    	}
    
    	while (Len > 0) {
    		memset(pu8ReadBuf, 0, READ_BUF_SIZE);
    
    		if (Len >= READ_BUF_SIZE) {
    			iReadLen = fread(pu8ReadBuf, 1, READ_BUF_SIZE, FSrcFile);
    		}
    		else {
    			iReadLen = fread(pu8ReadBuf, 1, Len, FSrcFile);
    		}
    		iWriteLen = fwrite(pu8ReadBuf, 1, iReadLen, FDesFile);
    		if (iWriteLen != iReadLen) {
    			printf("WRITE TO FDesFile FAIL.\n");
    			if (pu8ReadBuf != NULL) {
    				free(pu8ReadBuf);
    			}
    			return COPY_FAIL;
    		}
    		iLen += iWriteLen;
    		Len -= iWriteLen;
    
    		/* Check that if the file reads to the end */
    		if (feof(FSrcFile)) {
    			printf("Read to the end.\n");
    			break;
    		}
    	}
    	if (pu8ReadBuf != NULL) {
    		free(pu8ReadBuf);
    	}
    
    	return iLen;
    }
    

    wav_to_pcm.c

    /*****************************************************
    File Name   :  wav_to_pcm.c
    Date        :  2020/10/27
    Author      :  l.hua
    Descriptions:  1.Search all .wav files on disk D:\Mycode\resource,
    				 and save the file path to D:\Mycode\resource\filelist.txt;
    			   2.Read file paths from filelist.txt one by one;
    			   3.analyze the audio infomation in the files, and save to
    				 D:\Mycode\resource\description.txt;
    			   4.Read the sound data in the files and save it as .pcm files;
    
    Change log  :
    Date               Mender           Cause
    
    ******************************************************/
    #include "wav_type.h"
    
    /* Causes the compiler to ignore the 4996 warning. */
    //#pragma warning(disable:4996)          
    
    #define PARAM_ERROR -3
    #define PRINT_ERROR -4
    #define FILE_ERROR -5
    int PRT(const WavHeaderTex_S* pFormatInfo);
    
    int main(int argc, char *argv[])
    {
    	if (argc < 3){
    		printf("too few parametwrs.Need three parameters: xxx.exe xxx.wav xxx.pcm\n");
    		return PARAM_ERROR;
    	}
    
    	FILE* pFSrcFile = NULL;
    	FILE* pFDesFile = NULL;
    	WavHeaderTex_S* pFormatInfo = NULL;
    	int iHeaderSize = sizeof(WavHeaderTex_S);
    	int iDataLoc = 0;
    	int i = 0;
    
    	pFormatInfo = (WavHeaderTex_S*)malloc(iHeaderSize);
    	if (pFormatInfo == NULL) {
    		printf("MALLOC WavHeaderTex_S FAIL.\n");
    		return -1;
    	}
    
    	memset(pFormatInfo, 0, iHeaderSize);
    
    	/* Open .wav file with 'rb' mod */
    	pFSrcFile = fopen(argv[1], "rb");
    	if (NULL == pFSrcFile) {
    		printf("open [%s] failed.\n", argv[1]);
    		return FILE_ERROR;
    	}
    
    	/* Get wavheaderinfo */
    	iDataLoc = WavDecode(pFSrcFile, pFormatInfo);
    	if (iDataLoc == DECODE_FAIL) {
    		if (strncmp(pFormatInfo->sComm.cWave, "WAVE", 4)) {
    			printf("[%s] is not WAVE.\n", argv[1]);
    		}
    		fclose(pFSrcFile);
    		return FILE_ERROR;
    	}
    	/* Printf demux info */
    	if (PRT(pFormatInfo) == PRINT_ERROR) {
    		fclose(pFSrcFile);
    		return PRINT_ERROR;
    	}
    
    	/* Open .pcm file with 'w' mod, if there is no such file, create it frist */
    	pFDesFile = fopen(argv[2], "w");
    	if (NULL == pFDesFile) {
    		printf("OPEN %s FAIL.\n", argv[2]);
    		fclose(pFSrcFile);
    		return FILE_ERROR;
    	}
    
    	/* Copy .wav to .pcm */
    	fseek(pFSrcFile, iDataLoc, SEEK_SET);
    	if (AudioSaveAs1(pFSrcFile, pFDesFile) == COPY_FAIL) {
    		fclose(pFSrcFile);
    		fclose(pFDesFile);
    		return COPY_FAIL;
    	}
    
    	fclose(pFSrcFile);
    	fclose(pFDesFile);
    	if (pFormatInfo != NULL)
    		free(pFormatInfo);
    
    	return 0;
    }
    
    int PRT(const WavHeaderTex_S* pFormatInfo)
    {
    	if (pFormatInfo == NULL) {
    		printf("REDIRECTPRT PARAMETER IS NULL.\n");
    		return PRINT_ERROR;
    	}
    
    	switch (pFormatInfo->sFmt.sFmtComm.u16FormatTag) {
    	case WAVE_FORMAT_UNKNOWN:
    		printf("CODEID: %s\n", WAVE_FORMAT_UNKNOWN_DES);
    		break;
    	case WAVE_FORMAT_UNKNOWN2:
    		printf("CODEID: %s\n", WAVE_FORMAT_UNKNOWN2_DES);
    		break;
    	case WAVE_FORMAT_UNKNOWN3:
    		printf("CODEID: %s\n", WAVE_FORMAT_UNKNOWN3_DES);
    		break;
    	case WAVE_FORMAT_PCM:
    		printf("CODEID: %s\n", WAVE_FORMAT_PCM_DES);
    		break;
    	case WAVE_FORMAT_ADPCM:
    		printf("CODEID: %s\n", WAVE_FORMAT_ADPCM_DES);
    		break;
    	case WAVE_FORMAT_IEEE_FLOAT:
    		printf("CODEID: %s\n", WAVE_FORMAT_IEEE_FLOAT_DES);
    		break;
    	case WAVE_FORMAT_ALAW:
    		printf("CODEID: %s\n", WAVE_FORMAT_ALAW_DES);
    		break;
    	case WAVE_FORMAT_MULAW:
    		printf("CODEID: %s\n", WAVE_FORMAT_MULAW_DES);
    		break;
    	case WAVE_FORMAT_DTS_MS:
    		printf("CODEID: %s\n", WAVE_FORMAT_DTS_MS_DES);
    		break;
    	case WAVE_FORMAT_WMAS:
    		printf("CODEID: %s\n", WAVE_FORMAT_WMAS_DES);
    		break;
    	case WAVE_FORMAT_IMA_ADPCM:
    		printf("CODEID: %s\n", WAVE_FORMAT_IMA_ADPCM_DES);
    		break;
    	case WAVE_FORMAT_TRUESPEECH:
    		printf("CODEID: %s\n", WAVE_FORMAT_TRUESPEECH_DES);
    		break;
    	case WAVE_FORMAT_GSM610:
    		printf("CODEID: %s\n", WAVE_FORMAT_GSM610_DES);
    		break;
    	case WAVE_FORMAT_MSNAUDIO:
    		printf("CODEID: %s\n", WAVE_FORMAT_MSNAUDIO_DES);
    		break;
    	case WAVE_FORMAT_DOLBY_AC3_SPDIF:
    		printf("CODEID: %s\n", WAVE_FORMAT_DOLBY_AC3_SPDIF_DES);
    		break;
    	case WAVE_FORMAT_A52:
    		printf("CODEID: %s\n", WAVE_FORMAT_A52_DES);
    		break;
    	case WAVE_FORMAT_DTS:
    		printf("CODEID: %s\n", WAVE_FORMAT_DTS_DES);
    		break;
    	case WAVE_FORMAT_MPEGLAYER3:
    		printf("CODEID: %s\n", WAVE_FORMAT_MPEGLAYER3_DES);
    		break;
    	case WAVE_FORMAT_G726:
    		printf("CODEID: %s\n", WAVE_FORMAT_G726_DES);
    		break;
    	case WAVE_FORMAT_MPEG:
    		printf("CODEID: %s\n", WAVE_FORMAT_MPEG_DES);
    		break;
    	case WAVE_FORMAT_EXTENSIBLE:
    		switch (pFormatInfo->sFmt.u16RealCodecTag) {
    		case WAVE_FORMAT_PCM:
    			printf("CODEID: %s\n", WAVE_FORMAT_PCM_DES);
    			break;
    		case WAVE_FORMAT_ADPCM:
    			printf("CODEID: %s\n", WAVE_FORMAT_ADPCM_DES);
    			break;
    		case WAVE_FORMAT_IEEE_FLOAT:
    			printf("CODEID: %s\n", WAVE_FORMAT_IEEE_FLOAT_DES);
    			break;
    		case WAVE_FORMAT_ALAW:
    			printf("CODEID: %s\n", WAVE_FORMAT_ALAW_DES);
    			break;
    		case WAVE_FORMAT_MULAW:
    			printf("CODEID: %s\n", WAVE_FORMAT_MULAW_DES);
    			break;
    		case WAVE_FORMAT_IMA_ADPCM:
    			printf("CODEID: %s\n", WAVE_FORMAT_IMA_ADPCM_DES);
    			break;
    		case WAVE_FORMAT_GSM610:
    			printf("CODEID: %s\n", WAVE_FORMAT_GSM610_DES);
    			break;
    		case WAVE_FORMAT_MPEGLAYER3:
    			printf("CODEID: %s\n", WAVE_FORMAT_MPEGLAYER3_DES);
    			break;
    		case WAVE_FORMAT_G726:
    			printf("CODEID: %s\n", WAVE_FORMAT_G726_DES);
    			break;
    		case WAVE_FORMAT_MPEG:
    			printf("CODEID: %s\n", WAVE_FORMAT_MPEG_DES);
    			break;
    		default:
    			printf("UNSUPPORT FILE.\n");
    			return PRINT_ERROR;
    		}
    		break;
    	default:
    		printf("UNSUPPORT FILE.\n");
    		return PRINT_ERROR;
    	}
    
    	printf("FILESIZE : %d BYTES\n"
    		"FMTSIZE  : %u BYTES\n"
    		"FREQUENCY: %d HZ\n"
    		"BITSAMPLE: %d BITS\n"
    		"CHANNELS : %d\n\n"
    		, pFormatInfo->sComm.lFileSize
    		, pFormatInfo->sComm.lChunkLen
    		, pFormatInfo->sFmt.sFmtComm.u32SamplesPerSec
    		, pFormatInfo->sFmt.sFmtComm.u16BitsPerSample
    		, pFormatInfo->sFmt.sFmtComm.u16Channels);
    
    	return 0;
    }
    
    
    

    参考链接:https://www.cnblogs.com/ranson7zop/p/7657874.html

    更多相关内容
  • wav格式解析

    2013-06-16 12:59:03
    wav 头信息解析 详细介绍wav文件的解析,头信息对应的位置代表的信息
  • wav格式解析.doc

    2019-05-09 22:59:20
    WAV 格式详解学习用 头文件,头文件每个字节的意义都有说明
  • 文章目录WAV格式分析一、WAV格式概述音频文件参数二、WAV格式结构1. 文件标识块RIFF chunk2. 文件属性块Format chunk3. 文件数据块Data chunk三、案例分析1. RIFF chunk2. Format chunk3. Data chunk参考 一、WAV...

    WAV格式分析

    一、WAV格式概述

    ​ 波形音频文件(也称为WAV文件)是较流行的数字音频格式之一,并且是录音棚录制的黄金标准。WAV是最早的数字音频格式之一,并迅速成为所有平台的主要内容。尽管取得了数十年的进步,但它仍然保持着其作为世界领先的专业音频格式之一的地位。

    • WAV文件采用RIFF(Resource Interchange File Format,资源互换文件格式)结构,并符合(RIFF)规范。
    • WAV文件以最高质量捕获并重新创建原始音频波形,而不会以任何方式影响或改变声音的声音特征。WAV使用PCM(脉冲编码调制)对数据进行编码,方法是将数据切成小块以提供最高质量。这是一种无损文件格式,意味着没有任何数据丢失。因此,捕获和记录的是原始音频波形的最接近的数学/数字表示形式,在此过程中不会发生明显的音频质量损失。
    • WAV文件未压缩,这意味着数据以完全原始格式原样存储,不需要解码。这提供了巨大的多功能性,可以进行出色的编辑和操作。

    二、WAV格式结构

    WAV文件遵循RIFF规则,其内容以区块(chunk)为最小单位进行存储。

    WAV文件一般由3个区块组成:

    1. RIFF chunk
    2. Format chunk
    3. Data chunk

    另外,文件中还可能包含一些可选的区块,如:Fact chunk、Cue points chunk、Playlist chunk、Associated data list chunk等。

    1. 文件标识块RIFF chunk

    RIFF Chunk的作用是标识WAV文件。

    'RIFF'的ASCII码:0x52 49 46 46

    'WAVE'的ASCII码:0x57 41 56 45

    名称字节数端序说明
    ID4大端资源交换文件标志,标识RIFF
    Size4小端整个文件的长度减去IDSize的长度
    Type4大端标识文件格式,标识WAVE
    是WAVE则表示后面需要两个子块:Format区块和Data区块

    2. 文件属性块Format chunk

    format块描述了波形文件的属性,例如每个样本的声道数、采样频率、采样位数等等。

    'fmt'的ASCII码:0x66 6D 74 20

    名称字节数端序说明
    ID4大端波形格式标志,标识fmt
    Size4小端该区块数据的长度(不包含IDSize的长度)
    AudioFormat2小端音频格式,为1时表示线性PCM编码,大于1时表示有压缩的编码。
    NumChannels2小端声道数,1为单声道,2为双声道
    SampleRate4小端采样率
    ByteRate4小端每秒数据字节数
    比特率 = 采样频率×音频通道数 × 每个样本的数据位数/8
    BlockAlign2小端数据块对齐 = 通道数 × 每个样本的数据位数/8
    BitsPerSample2小端采样位数,每个样本的数据位数

    3. 文件数据块Data chunk

    Data块储存文件的实际数据。

    'data'的ASCII码:0x64 61 74 61

    名称字节数端序说明
    ID4大端标识data块
    Size4小端实际音频数据所占的大小 = ByteRate × 总时长
    Data可变小端实际的音频数据

    三、案例分析

    1. RIFF chunk

    读数时注意大小端

    含义说明
    资源交换文件标志ID52 49 46 46标识’RIFF’=52 49 46 46
    文件长度Size00 01 C8 24不包括ID和Size的长度为116772
    文件格式Type57 41 56 45标识’WAVE’=57 41 56 45

    在这里插入图片描述

    2. Format chunk

    含义说明
    ID66 6D 74 20标识’fmt’=66 6D 74 20
    Format 块长度Size00 00 00 10该区块数据的长度(不包含IDSize的长度)=16
    音频格式AudioFormat00 011表示线性PCM编码
    声道数NumChannels00 011为单声道
    采样率SampleRate00 00 BB 80采样率 = 48000Hz
    比特率ByteRate00比特率 =(48000×1×16)/8=96000 Byte/s
    BlockAlign00 02BlockAlign = 1×16/8=2
    采样位数BitsPerSample00 1016位量化

    Format chunk

    3. Data chunk

    含义说明
    ID64 61 74 61标识’data’=64 61 74 61
    Data块长度Size00 01 C8 00116736 Byte
    Data实际的音频数据

    在这里插入图片描述

    参考

    https://blog.csdn.net/imxiangzi/article/details/80265978

    展开全文
  • wav格式解析,vs201

    2018-08-19 14:54:25
    WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持,该格式也支持MSADPCM,...
  • WAV格式解析

    千次阅读 2019-05-12 22:55:00
    WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持, 该格式也支持MSADPCM,...

     

     WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持,

    该格式也支持MSADPCM,CCITT A LAW等多种压缩运算法,支持多种音频数字,取样频率和声道,标准格式化的WAV文件和CD格式一样,也是44.1K的取样频率,16位量化数字,因此在声音文件质量和CD相差无几。

     

    WAVE文件为了与RIFF保持一致,数据采用“chunk”来存储。

    因此,如果想要在WAVE文件中补充一些新的信息,只需要在在新chunk中添加信息,而不需要改变整个文件。这也是设计IFF最初的目的。

    对于一个基本的WAVE文件而言,最少包含以下三种Chunk:

    以上三个chunk 顺序固定,对于其它的chunk,顺序没有严格的限制。

     

    具体格式如下:

     

    然而,所有基于压缩编码的WAV文件必须含有fact块。此外所有其它块都是可选的。fmt,Data及fact块均为RIFF块的子块。WAV文件的文件格式类型标识符为“WAVE”。

     

     

    各个chunk中字段的意义如下:

    RIFF chunk

    IDbig-endianFOURCC 值为'R' 'I' 'F' 'F'
    Sizelittle-endiandata字段中数据的字节数
    Databig-endian包含其它的chunk

     

     

     

     

     

     

    Format chunk

    IDbig-endian   FOURCC 值为 'f' 'm' 't' ' '
    Sizelittle-endian     数据字段包含数据的大小。如无扩展块,则值为16;有扩展块,则值为 16 + 2字节扩展块长度 + 扩展块长度或者值为18(只有扩展块的长度为2字节,值为0)
    Datalittle-endianformat_tag2字节,表示音频数据的格式。如值为1,表示使用PCM格式。
    little-endianchannels2字节,声道数。值为1则为单声道,为2则是双声道。
    little-endiansamples_per_sec采样率,主要有22.05KHz,44.1kHz和48KHz。
    little-endianbytes_per sec音频的码率,每秒播放的字节数。samples_per_sec * channels * bits_per_sample / 8,可以估算出使用缓冲区的大小
    little-endianblock_align数据块对齐单位,一次采样的大小,值为声道数 * 量化位数 / 8,在播放时需要一次处理多个该值大小的字节数据。
    little-endianbits_per_sample音频sample的量化位数,有16位,24位和32位等。
     cbSize扩展区的长度
     扩展格式块内容22字节,具体介绍请看下面

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     其中 format_tag 可以取如下值:

    格式代码格式名称fmt 块长度fact 块
    1(0x0001)PCM/非压缩格式16 
    2(0x0002Microsoft ADPCM18
    3(0x0003)IEEE float18
    6(0x0006)ITU G.711 a-law18
    7(0x0007)ITU G.711 μ-law18
    49(0x0031)GSM 6.1020
    64(0x0040)ITU G.721 ADPCM 
    65,534(0xFFFE)见子格式块中的编码格式40 

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    其中的扩展格式块:

    当WAV文件使用的不是PCM编码方式是,就需要扩展格式块,它是在基本的Format chunk又添加一段数据。

    该数据的前两个字节,表示的扩展块的长度。紧接其后的是扩展的数据区,含有扩展的格式信息,其具体的长度取决于压缩编码的类型。

    当某种编码方式(如 ITU G.711 a-law)使扩展区的长度为0,扩展区的长度字段还必须保留,只是其值设置为0。

    扩展区的各个字节的含义如下:

    Size扩展区的数据长度 ,可以为0或22
    valid_bits_per_sample有效的采样位数,最大值为采样字节数 * 8。可以使用更灵活的量化位数,通常音频sample的量化位数为8的倍数,但是使用了WAVE_FORMAT_EXTENSIBLE时,量化的位数有扩展区中的valid bits per sample来描述,可以小于Format chunk中制定的bits per sample
    channle mask4字节,声道掩码
    sub format16字节,GUID,include the data format code,数据格式码。

     

     

     

    在Format chunk中的format_tag设置为0xFFFE时,表示使用扩展区中的sub_format来决定音频的数据的编码方式。在以下几种情况下必须要使用WAVE_FORMAT_EXTENSIBLE

    • PCM数据的量化位数大于16
    • 音频的采样声道大于2
    • 实际的量化位数不是8的倍数
    • 存储顺序和播放顺序不一致,需要指定从声道顺序到声卡播放顺序的映射情况。

     

     

    Fact chunk (可选)

    IDFOURCC 值为 'f' 'a' 'c' 't'
    Size数据域的长度,4(最小值为4)
    Data每个声道的采样总数 4字节

     

     

     

     

     

     

    Data chunk

    IDFOURCC 值为'd' 'a' 't' 'a'
    Size数据域的长度
    Data

    具体的音频数据存放在这里

     

     

     

     

     

     

    Data块中存放的是音频的采样数据。每个sample按照采样的时间顺序写入,对于使用多个字节的sample,使用小端模式存放(低位字节存放在低地址,高位字节存放在高地址)。对于多声道的sample采用交叉存放的方式。例如:立体双声道的sample存储顺序为:声道1的第一个sample,声道2的第一个sample;声道1的第二个sample,声道2的第二个sample;依次类推....。对于PCM数据,有以下两种的存储方式:

    • 单声道,量化位数为8,使用偏移二进制码
    • 除上面之外的,使用补码方式存储。

     

     

    描述WAVE文件的基本单元是“Sample”,一个Sample代表采样一次得到的数据。因此如果用44KHz采样,将在一秒中得到44000个Sample。

    每个Sample可以用8位、24位,甚至32位表示(位数没有限制,只要是8的整数倍即可),位数越高,音频质量越好。

    注意:8位代表无符号的数值,而16位或16位以上代表有符号的数值

     

     

    每秒数据大小(字节)=采样率 * 声道数 * sample比特数 / 8

     

    转载于:https://www.cnblogs.com/zoneofmine/p/10850465.html

    展开全文
  • WAV格式分析

    2022-04-08 15:34:13
    WAV格式简介 WAV是最常见的声音文件格式之一,是微软公司专门为Windows开发的一种标准数字音频文件,该文件能记录各种单声道或立体声的声音信息,并能保证声音不失真。它符合资源互换文件格式(RIFF)规范,用于...

    WAV格式简介

    WAV是最常见的声音文件格式之一,是微软公司专门为Windows开发的一种标准数字音频文件,该文件能记录各种单声道或立体声的声音信息,并能保证声音不失真。它符合资源互换文件格式(RIFF)规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持。Wave格式支持MSADPCM、CCITT A律、CCITT μ律和其他压缩算法,支持多种音频位数、采样频率和声道,是PC机上最为流行的声音文件格式;但其文件尺寸较大,多用于存储简短的声音片段。

    WAV的文件结构:

    WAV文件遵循RIFF规则,RIFF的英文全称是Resource Interchange File Format(资源交互文件格式),是由Microsoft提出的一种多媒体文件存储方式,不同编码的视频、音频文件按照RIFF保存,当提取文件时,可以根据RIFF的规则解析文件。

    RIFF格式是一种树状结构,主要由 FOURCC, CHUNK,LIST 组成。

    LIST:相当于目录,可以包含多个CHUNK或者多个LIST,包含关键字“LIST”。

    CHUNK:是数据保存的基本单元,可用于保存音视频数据或者一些参数信息。

    FOURCC:一个 FOURCC (four character code) 是占用 4 个字节的数据,一般表示 4 个 ASCII 字符。在 “RIFF” 文件格式中,块的起始标识等信息都是使用 FOURCC 表示的,如 “fmt”, “data”, “wav“等。

    RIFF文件结构最开始4个字节表示“RIFF”,接着4个字节表示该文件的大小,再下来的4个字节表示该文件的类型(AVI或者WAV等)。

    下面是各区块详解:

    RIFF:

     RIFF文件的基本组成类似于树形结构,其基本构成单元是chunk。

    chunk表示数据的一个基本逻辑单元,例如视频的一帧数据、音频的一帧数据等等。

    每个chunk包含FOURCC,用于标识chunk ID或chunk 类型;chunk中数据域长度(Size)以及数据域(data Field)。

    RIFF格式允许chunk嵌套,但只有ID为“RIFF”或者“LIST”的chunk允许拥有子块,其它的块不允许包含子块。即:RIFF文件第一个chunk开头标识符必须为RIFF,LIST的chunk只能表示subchunk。

    如下图所示,RIFFchunk,ID固定为RIFF,size为数据域的长度,数据域中包裹一个Listchunk。

    数据域开头的Form Type用于说明数据域的格式,比如“WAV”、“AVI”等。接着包含一个子块List chunk。 

    List chunk中,ID固定为LIST,size为数据域的长度,数据域中的包裹一个子块。listchunk数据域开头四字节码List Type,用于说明LIST数据域的数据内容。

    subchunk中,ID为chunk类型,size为子块数据域的长度,数据域存储文件数据。

    以’RIFF’为标识

    Size是整个文件的长度减去ID和Size的长度

    Type是WAVE表示后面需要两个子块:Format区块和Data区块

    FORMAT:

    以’fmt '为标识 

    Size表示该区块数据的长度(不包含ID和Size的长度)

    AudioFormat表示Data区块存储的音频数据的格式,PCM音频数据的值为1

    NumChannels表示音频数据的声道数,1:单声道,2:双声道

    SampleRate表示音频数据的采样率

    ByteRate每秒数据字节数 = SampleRate * NumChannels * BitsPerSample / 8

    BlockAlign每个采样所需的字节数 = NumChannels * BitsPerSample / 8

    BitsPerSample每个采样存储的bit数,8:8bit,16:16bit,32:32bit

    DATA:

    以’data’为标识

    Size表示音频数据的长度,N = ByteRate * seconds

    Data音频数据

    展开全文
  • WAV 文件格式分析 ( 逐个字节解析文件头 | 相关字段的计算公式 )
  • wav格式音频文件

    2016-10-12 17:27:06
    主要是几个不同的wav格式音频文件,用于解析wav文件头信息时需要用到,可以参考博客:Qt 之 解析wav文件的头信息(详细分析、对比不同wav文件的数据)...
  • 解析WAV文件,并设计双缓存,用来播放音乐,检测到一个缓存播放完,就填充该缓存,下个播放完,就填充下个
  • C语言解析wav文件格式

    千次阅读 2020-01-21 21:18:36
    1.wav文件的二进制格式解析 一个wav文件的二进制解析: 二进制文件,本质上就是一种使用二进制方式存储文件内容的文件统称,我们前面有讲过使用记事本等工具打开之后看到的是乱码,那么我们怎么分析他呢,可以使用...
  • Wav格式分析

    千次阅读 2018-07-22 20:43:35
    WAV文件是在PC机平台上很常见的、最经典的多媒体音频文件,最早于1991年8月出现在Windows 3.1操作系统上,文件扩展名为WAV,是WaveFom的简写,也称为...WAV文件格式简称WAV格式是一种存储声音波形的数字音频格式,是由...
  • WAV文件格式详解

    千次阅读 2022-03-19 13:33:36
    WAV文件格式简称WAV格式是一种存储声音波形的数字音频格式,是由微软公司和IBM联合设计的,经过了多次修订,可用于Windows,Macintosh,Linux等多种操作系统。WAV支持多种音频数字、取样频率和声道,标准格式化的WAV...
  • WAV文件格式解析

    万次阅读 2017-04-16 15:31:02
    本文通过翻译分析WAV的文件格式WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所...
  • wav文件格式分析详解

    2021-02-26 15:26:32
    wav文件格式分析详解作者:曹京日期:2006年7月17日一、综述WAVE文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个字节便...
  • 自己亲自测试,和winhex下16进制数据对比,确实正确!
  • 音频wav文件分析

    2018-11-08 22:05:12
    音频wav文件分析
  • wav文件解析

    千次阅读 2021-07-21 21:11:09
    wav文件采用RIFF(Resource Interchange File Format)文件格式结构。通常用来保存PCM格式的原始音频数据,所以通常被称为无损音频。但是严格意义上来讲,WAV也可以存储其它压缩格式的音频数据。 WAV文件遵循RIFF...
  • WAV文件数据格式分析

    2018-08-20 16:30:46
    在Windows环境下,大部分的多媒体文件都依循着一种结构来存放信息,这种结构称为"资源互换文件格式"(Resources lnterchange File Format),简称RIFF。例如声音的WAV文件、视频的AV1文件等等均是由此结构衍生出来的。...
  • WAV格式详解

    2022-01-23 17:10:13
    WAV即WAVE,是经典的Windows音频数据封装格式,由Microsoft开发。数据本身格式为PCM,也可以支持一些编码格式的数据,比如最近流行的AAC编码。如果是PCM,则为无损格式,文件会比较大,并且大小相对固定,可以使用...
  • WAV音频格式解析C代码

    2021-05-20 01:24:06
    /* Check wave header */ if ( (0==memcmp(hwav.ChunkID, "RIFF", 4)) &&(0==memcmp(hwav.Format, "WAVE", 4)) && (0==memcmp(hwav.SubChunk1ID, "fmt ", 4))) { headLen=sizeof(wav_pcm_header36)-...
  • WAV格式文件分析

    千次阅读 2022-03-16 12:39:23
    目录WAV格式文件分析概述一、WAV格式文件1、波形声音文件格式 WAV2、音频文件参数简介二、文件结构1、WAV文件的文件头2、WAV文件的数据体三、WAV格式文件数据体结构1、RIFF Chunk区块2、Format Chunk区块3、DATA区块...
  • wav格式分析

    2017-04-16 21:03:05
    概述Wave文件格式是用于存储数字音频数据的Windows本地文件格式。由于Windows的普及和为平台编写的大量程序,它已经成为PC上最广泛支持的数字音频文件格式之一。几乎每个可以打开和/或保存数字音频的现代程序都支持...
  • WAV文件格式分析

    2022-03-13 17:43:52
    目录 WAV简介 WAV的文件组成成分 RIFF Chunk FORMAT Chunk ... WAVE,又或者是因为扩展名而被大众所知的WAV,是微软与IBM公司所开发在个人电脑存储音频流的编码格式,在Windows平台的应用...
  • 数据压缩-WAV文件格式分析

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,469
精华内容 10,187
关键字:

wav格式解析

友情链接: 2048.zip