首页 > 其他分享 >WAV与PCM

WAV与PCM

时间:2023-06-07 09:22:18浏览次数:55  
标签:00 unsigned wChannels WAVE PCM WAV pcmFMT uiBitsPerSample

1、PCM格式介绍: 
PCM(Pulse Code Modulation)也被称为 脉码编码调制。PCM中的声音数据没有被压缩,如果是单声道的文件,采样数据按时间的先后顺序依次存入。(它的基本组织单位是BYTE(8bit)或WORD(16bit)) 
参考文献http://blog.csdn.net/ownwell/article/details/8114121/ 
2、WAV格式 
(1)格式介绍: 
WAVE文件格式是Microsoft的RIFF规范的一个子集,用于存储多媒体文件。WAVE文件通常只是一个具有单个“WAVE”块的RIFF文件,该块由两个子块(”fmt”子数据块和”data”子数据块)组成。 
如下图所示: 
这里写图片描述

(2)每个字段的的含义介绍:
   typedef struct{
       char          ChunkID[4];//内容为"RIFF"
       unsigned long ChunkSize;//存储文件的字节数(不包含ChunkID和ChunkSize这8个字节)
       char          Format[4];//内容为"WAVE"
   }WAVE_HEADER;

   typedef struct{
        char          Subchunk1ID[4];//内容为"fmt"
        unsigned long  Subchunk1Size;//存储该子块的字节数(不含前面的Subchunk1ID和Subchunk1Size这8个字节)
        unsigned short AudioFormat;//存储音频文件的编码格式,例如若为PCM则其存储值为1,若为其他非PCM格式的则有一定的压缩。
        unsigned short NumChannels;//通道数,单通道(Mono)值为1,双通道(Stereo)值为2,等等
        unsigned long  SampleRate;//采样率,如8k,44.1k等
        unsigned long  ByteRate;//每秒存储的bit数,其值=SampleRate * NumChannels * BitsPerSample/8
        unsigned short BlockAlign;//块对齐大小,其值=NumChannels * BitsPerSample/8
        unsigned short BitsPerSample;//每个采样点的bit数,一般为8,16,32等。
   }WAVE_FMT;
   typedef struct{
        char          Subchunk2ID[4];//内容为“data”
        unsigned long Subchunk2Size;//内容为接下来的正式的数据部分的字节数,其值=NumSamples * NumChannels * BitsPerSample/8
   }WAVE_DATA;

(3)一个WAVE例子 
这里是一个WAVE文件的开头72字节,字节显示为十六进制数字: 
52 49 46 46 24 08 00 00 57 41 56 45 66 6d 74 20 10 00 00 00 01 00 02 00 
22 56 00 00 88 58 01 00 04 00 10 00 64 61 74 61 00 08 00 00 00 00 00 00 
24 17 1e f3 3c 13 3c 14 16 f9 18 f9 34 e7 23 a6 3c f2 24 f2 11 ce 1a 0d 
字段解析: 
这里写图片描述 
参考文献1http://soundfile.sapp.org/doc/WaveFormat/ 
参考文献2http://www.lightlink.com/tjweber/StripWav/Canon.html 
参考文献3http://www.topherlee.com/software/pcm-tut-wavformat.html

3、用C语言实现PCM转WAVE

#include <stdio.h>
#include <string.h>

/**
 * Convert PCM16LE raw data to WAVE format
 * @param pcmpath       Input PCM file.
 * @param channels      Channel number of PCM file.
 * @param sample_rate   Sample rate of PCM file.
 * @param wavepath      Output WAVE file.
 */
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;

    if(channels==2 || sample_rate==0)
    {
        channels = 2;
        sample_rate = 44100;
    }
    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), 1);   //1=SEEK_CUR
    /* WAVE_FMT */
    memcpy(pcmFMT.fccID, "fmt ", strlen("fmt "));
    pcmFMT.dwSize = 16;
    pcmFMT.wFormatTag = 1;
    pcmFMT.wChannels = 2;
    pcmFMT.dwSamplesPerSec = sample_rate;
    pcmFMT.uiBitsPerSample = bits;
    /* ==dwSamplesPerSec*wChannels*uiBitsPerSample/8 */
    **pcmFMT.dwAvgBytesPerSec = pcmFMT.dwSamplesPerSec*pcmFMT.wChannels*pcmFMT.uiBitsPerSample/8;**
    /* ==wChannels*uiBitsPerSample/8 */
    **pcmFMT.wBlockAlign = pcmFMT.wChannels*pcmFMT.uiBitsPerSample/8;**


    fwrite(&pcmFMT, sizeof(WAVE_FMT), 1, fpout);

    /* WAVE_DATA */
    memcpy(pcmDATA.fccID, "data", strlen("data"));
    pcmDATA.dwSize = 0;
    fseek(fpout, sizeof(WAVE_DATA), SEEK_CUR);

    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;*/
    //修改时间:2018年1月5日
    pcmHEADER.dwSize = 36 + 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;
}

int main()
{
    simplest_pcm16le_to_wave("NocturneNo2inEflat_44.1k_s16le.pcm", 2, 44100, "output_nocture.wav");

    return 0;
}

 

结果如图所示: 
这里写图片描述

参考文献http://blog.csdn.net/leixiaohua1020/article/details/50534316 
2017年10月26日 星期四 修改

原74行代码:
**pcmFMT.dwAvgBytesPerSec = pcmFMT.dwSamplesPerSec*pcmFMT.wChannels*pcmFMT.uiBitsPerSample/8;**
改为
pcmFMT.dwAvgBytesPerSec = pcmFMT.dwSamplesPerSec*pcmFMT.wChannels*pcmFMT.uiBitsPerSample/8;

 

原76行:
**pcmFMT.wBlockAlign = pcmFMT.wChannels*pcmFMT.uiBitsPerSample/8;**
改为:
pcmFMT.wBlockAlign = pcmFMT.wChannels*pcmFMT.uiBitsPerSample/8;

标签:00,unsigned,wChannels,WAVE,PCM,WAV,pcmFMT,uiBitsPerSample
From: https://www.cnblogs.com/kn-zheng/p/17462349.html

相关文章

  • 基于FFmpeg的音频编码(PCM数据编码成AAC android)
    概述在Android上实现录音,并利用FFmpeg将PCM数据编码成AAC。详细之前做的一个demo,Android录音获取pcm数据(音频原始数据),然后利用FFmpeg将PCM数据编码成AAC。一、准备工作开发环境jdk1.8 EclipseLunaServiceRelease1(4.4.1)运行环境:华为荣耀6(Android4.4)、华为......
  • 如何将word图片粘贴到PHPCMS里面
    ​ 1.编辑器修改(可选)1.1在 ueditor/config.json 中添加代码块    /* 上传word配置 */    "wordActionName":"wordupload",/* 执行上传视频的action名称 */    "wordFieldName":"upfile",/* 提交的视频表单名称 */    "wordPathFormat":"/p......
  • GoldWave是什么软件?goldwave怎么设置中文
    本文参考资料:https://blog.csdn.net/weixin_55412152/article/details/130935207GoldWave6.68是一款专业的,集录音、编辑于一身的音频编辑软件,不仅提供了出色的编辑功能,还提供了丰富的音效选项,可进行混音、剪辑、音效制作等操作,是一款实用、界面友好的音频编辑软件。GoldWave编辑音......
  • 如何将word公式粘贴到PHPCMS里面
    ​ 自动导入Word图片,或者粘贴Word内容时自动上传所有的图片,并且最终保留Word样式,这应该是Web编辑器里面最基本的一个需求功能了。一般情况下我们将Word内容粘贴到Web编辑器(富文本编辑器)中时,编辑器都无法自动上传图片。需要用户手动一张张上传Word图片。如果只有一张图片还能够接......
  • phpcms系统连接mysql失败
    phpcmsv9安装程序代码对提交的密码中特殊字符(如:&$^!@#)未进行escape转义处理。解决办法:1、修改install/step5.tpl.php127行为:'&dbpw='+escape($('#dbpw').val())2、修改install/step6.tpl.php55行为:vardbpw=escape('<?=$dbpw?>');......
  • 掌握PHPcms采集技巧,轻松解决内容管理问题
    PHPcms是一款优秀的内容管理系统,它拥有强大的采集功能,可以轻松实现对目标网站的内容采集。本文将详细介绍PHPcms的content采集功能,包括如何进行配置、如何使用、以及常见问题解决方法等方面。1.配置在使用content采集功能之前,需要先进行一些配置操作。首先,在后台管理界面进入“......
  • phpcms常见问题解答
    phpcms常见问题解答1.为什么phpcms首页幻灯片怎么显示不出来?答:需要设置文章的标题图片如果设置标题图片,则可以在首页以及栏目页以图片方式链接到文章。2.自定义phpcms的标签只能是全HTML?答:在自定义标签内容中可以插入html代码,也可以插入多个函数标签或者变量标签。插入函......
  • Real-Time Water Waves With Wave Particles - cem yuksel - 2010
    摘要:Thisdissertationdescribesthewaveparticlestechniqueforsimulatingwatersurfacewavesandtwowayfluid-objectinteractionsforreal-timeapplications,suchasvideogames.本文描述了用于模拟水面波的波粒子技术和用于视频游戏等实时应用的双向流体-物体......
  • Wave Particles(波动粒子) - Cem Yuksel
    参考:http://www.cemyuksel.com/research/waveparticles/Thisiscapturedfromourreal-timesimulation,showingthreeboatsintheopenocean.Thedynamicsurfacewavesgeneratedduetoboatmotionaresimulatedusingwaveparticles.Inaddition,boatmotion......
  • Waves 14 Complete Mac (Waves混音效果全套插件)
    Waves14Complete是一款全功能的音频处理软件套装,包含超过140个插件,可用于各种音频处理和音乐制作任务。这个套装包含了多种不同类型的插件,包括均衡器、压缩器、混响、延迟、合成器、调制器等等。Waves14Complete还提供了许多专业级功能,如自适应限制、自动启动时间校准、360度......