VS语音信号处理(4) C语言WAV格式语音存为PCM格式语音工程实例

article/2025/9/30 19:24:31

VS语音信号处理(4) C语言WAV格式语音存为PCM格式语音工程实例

  • 前言
  • 一. 工程实现
  • 二. 生成编译
  • 三. 小结

前言

语音识别相关算法一般在MATLAB上进行仿真验证与实验,在工程上一般还是在VS中进行实现落地,本系列将介绍语音信号处理在C语言中的一系列应用,后期将以此为基础,再落地移植到嵌入式平台。

今天介绍WAV格式语音存为PCM格式语音的工程应用。两种格式语音的唯一区别在于WAV语音包含文件头信息,而PCM格式语音仅包含语音数据流。语音格式转换也算是一种比较常见的应用,可以让我们更好的理解语音文件的格式信息。

一. 工程实现

打开VS2015
在这里插入图片描述
点击新建一个项目(工程),输入项目名:Wav2pcm
在这里插入图片描述
点击“确定”,创建项目
在这里插入图片描述
左侧解决方案资源管理器视图中,源文件栏右键添加新建项,
在这里插入图片描述
点击C++文件,新建一个源文件Wav2pcm.cpp,点击“添加”
在这里插入图片描述
输入代码如下:

// Wav2pcm.cpp
// wav格式语音文件转存为pcm格式语音
// date:2022-5-9 22:32:21
// author : C.S#include <stdio.h>  
#include <string.h>  
#include <stdlib.h>#pragma warning (disable :4996)#define  uint32_t       unsigned int  
#define  uint16_t       unsigned short   typedef struct _riff_t {char riff[4];	/* "RIFF" (ASCII characters) */uint32_t len;	/* Length of package (binary, little endian) */char wave[4];	/* "WAVE" (ASCII characters) */
} riff_t;/* The FORMAT chunk */typedef struct _format_t {char  fmt[4];		/* "fmt_" (ASCII characters) */uint32_t   len;	/* length of FORMAT chunk (always 0x10) */uint16_t  type;		/* codec type*/uint16_t channel;	/* Channel numbers (0x01 = mono, 0x02 = stereo) */uint32_t   rate;	/* Sample rate (binary, in Hz) */uint32_t   bps;	/* Average Bytes Per Second */uint16_t blockalign;	/*number of bytes per sample */uint16_t bitpspl;	/* bits per sample */
} format_t;typedef struct _data_t {char data[4];   /* "data" (ASCII characters) */uint32_t len;  /* length of data */
}data_t;typedef struct _wav_head
{riff_t riff;format_t format;data_t   data;
}wav_head;int main(int argc, char **argv)
{char *src_file = "test.wav";uint32_t pcm_data_size = 0;int pcm_channel = 0;int pcm_samplerate = 0;//以下是为了建立.wav头而准备的变量    wav_head header;FILE   *fp = NULL, *fpCpy = NULL;int flen;if ((fp = fopen(src_file, "rb")) == NULL) //读取文件    {printf("open wav file %s error\n", argv[1]);return -1;}if ((flen = fread(&header.riff.riff, 1, 4, fp)) != 4)goto error;if (memcmp(&header.riff.riff, "RIFF", 4))goto error;if ((flen = fread(&header.riff.len, 1, 4, fp)) != 4)goto error;if ((flen = fread(&header.riff.wave, 1, 4, fp)) != 4)goto error;if (memcmp(&header.riff.wave, "WAVE", 4))goto error;if ((flen = fread(&header.format.fmt, 1, 4, fp)) != 4)goto error;if (memcmp(&header.format.fmt, "fmt ", 4))goto error;if ((flen = fread(&header.format.len, 1, 4, fp)) != 4){goto error;}if (header.format.len != 0x10){printf("header.format.len!=0x10 :value:%d\n", header.format.len);}if ((flen = fread(&header.format.type, 1, 2, fp)) != 2){goto error;}if (header.format.type != 0x1){printf("header.format.type != 0x1 :value:%d\n", header.format.type);}if ((flen = fread(&header.format.channel, 1, 2, fp)) != 2){goto error;}pcm_channel = header.format.channel;if ((flen = fread(&header.format.rate, 1, 4, fp)) != 4){goto error;}pcm_samplerate = header.format.rate;if ((flen = fread(&header.format.bps, 1, 4, fp)) != 4){goto error;}if ((flen = fread(&header.format.blockalign, 1, 2, fp)) != 2){goto error;}if ((flen = fread(&header.format.bitpspl, 1, 2, fp)) != 2){goto error;}int p = 0;//后面的结构可能不是直接为“data”do {if ((flen = fread(&header.data.data, 1, 4, fp)) != 4){goto error;}if (memcmp(&header.data.data, "data", 4) == 0){printf("find data chunk.");if ((flen = fread(&header.data.len, 1, 4, fp)) != 4){goto error;}pcm_data_size = header.data.len;break;}elsep += 4;} while (!feof(fp));printf("解析成功,二段PCM数据长度分别为:%d, %d\n", pcm_data_size, header.riff.len - 36);int otherdataSize = header.riff.len - 36 - pcm_data_size;if (otherdataSize>0){printf("多余的数据部分大小:%d , %d", p, otherdataSize);char *otherdata = (char *)malloc(otherdataSize + 1);memset(otherdata, 0, otherdataSize + 1);fseek(fp, -otherdataSize - 8, SEEK_CUR);fread(otherdata, 1, otherdataSize, fp);*(otherdata + otherdataSize) = '\0';fseek(fp, 8, SEEK_CUR);printf("   other data:%s", otherdata);}fseek(fp, otherdataSize + 44, SEEK_SET);//fseek(fp, 0, SEEK_CUR);unsigned char *buffer = (unsigned char*)malloc((pcm_data_size) * sizeof(char));memset(buffer, 0, pcm_data_size);int count1 = fread(buffer, 1, pcm_data_size, fp);char output[1024] = { 0 };sprintf(output, "%d_%d_.pcm", pcm_samplerate, pcm_channel);if ((fpCpy = fopen(output, "wb+"))){//fwrite(buffer, 1, sizeof(buffer), fpCpy);  写了段常犯错的代码fwrite(buffer, 1, pcm_data_size, fpCpy);}elsegoto error;free(buffer);fclose(fp); //关闭文件    fclose(fpCpy);   //关闭文件    return 0;error:if (fp){fclose(fp);}if (fpCpy){fclose(fpCpy);}return -1;
}

二. 生成编译

点击目录栏“生成”中“生成解决方案”
在这里插入图片描述
生成成功!找一个WAV格式语音,命名为test.wav,放在Wav2pcm.cpp同目录下,点击调试运行,生成一个48000_2_.pcm文件,调用成功。
在这里插入图片描述
在这里插入图片描述

三. 小结

最近项目上需要对语音信号进行处理,这个是对语音格式进行转换的工程,可以正常跑通,相对也比较简单,值得注意的是,如果没有将test.wav导入的话,工程不会报警提示,所以有需要的同学在应用的时候需要注意一下,没有源语音是得不到pcm语音的。


http://chatgpt.dhexx.cn/article/vJwGZA3q.shtml

相关文章

PCM格式详解

PCM格式详解 简介&#xff1a; PCM(Pulse Code Modulation)&#xff0c;脉冲编码调制。人耳听到的是模拟信号&#xff0c;PCM是把声音从模拟信号转化为数字信号的技术。原理是用一个固定的频率对模拟信号进行采样&#xff0c;采样后的信号在波形上看就像一串连续的幅值不一的…

PCM数据格式

1. 音频简介 经常见到这样的描述: 44100HZ 16bit stereo 或者 22050HZ 8bit mono 等等. 44100HZ 16bit stereo: 每秒钟有 44100 次采样, 采样数据用 16 位(2字节)记录, 双声道(立体声); 22050HZ 8bit mono: 每秒钟有 22050 次采样, 采样数据用 8 位(1字节)记录, 单声道; 当然…

PCM编码格式

目录 一、PCM音频编码格式 1. 相关英文单词 2. PCM数据结构 2.1 单声道数据 2.2 多声道数据 2.3 小结 二、WAV音频文件格式 一、PCM音频编码格式 1. 相关英文单词 Amplitude&#xff1a;幅度 PAM&#xff1a;Pulse Amplitude Modulation 脉冲幅度调制(数字信号过程采样…

音频处理——详解PCM数据格式

目录 知识储备什么是PCM采样采样率重采样 量化编码PCM常用指标 PCM数据流 知识储备 音频处理——音频编码原理简介 音频处理——音频处理的基本概念 什么是PCM PCM全称Pulse-Code Modulation&#xff0c;翻译一下是脉冲调制编码。 在音视频中&#xff0c;PCM是一种用数字表…

PCM格式介绍

转自&#xff1a;http://www.cnblogs.com/cheney23reg/archive/2010/08/08/1795067.html http://wiki.multimedia.cx/index.php?titlePCM PCM数据格式 PCM(Pulse Code Modulation)也被称为 脉码编码调制。PCM中的声音数据没有被压缩&#xff0c;如果是单声道的文件&#xff…

PCM文件格式简介(比较专业)

PCM文件&#xff1a;模拟音频信号经模数转换&#xff08;A/D变换&#xff09;直接形成的二进制序列&#xff0c;该文件没有附加的文件头和文件结束标志。Windows的Convert工具可以把PCM音频格式的文件转换成Microsoft的WAV格式的文件。 脉冲编码调制PCM文件格式简介 将音频数…

PCM数据格式介绍

目录 什么是PCM Sampling&#xff08;采样&#xff09; 采样率(Sample rate) Quantization&#xff08;量化&#xff09; Encoding&#xff08;编码&#xff09; PCM数据常用量化指标 PCM数据流 音量控制 采样率调整 什么是PCM PCM全称Pulse-Code Modulation&#xff…

PCM音频数据格式介绍

1. What is PCM? PCM(Pulse-code-modulation)是模拟信号以固定的采样频率转换成数字信号后的表现形式。 Sample Rate : 采样频率单位为&#xff1a;Hz。采样频率越高&#xff0c;音频质量越好&#xff0c;占用空间也越大。 Sign : 音频数据是否是有符号的。通常情况下都是有…

单调栈图文详解(附Java模板)

啥是"单调栈"&#xff0c;它能解决什么样的问题&#xff1f; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微风撞见云的博客&#x1f390; &#x1f433; 数据结构与算法专栏的文章图文并茂&#x1f995;生动形象&#…

算法之单调栈常见题目

什么时候需要使用单调栈&#xff1f; 通常是一维数组&#xff0c;要寻找任意一个右边或者左边第一个比自己大或小的元素的位置&#xff0c;此时我们就想到可以使用单调栈了。 单调栈的本质是空间换时间&#xff0c;因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高…

单调栈及单调栈的应用

什么是单调栈 单调递增栈&#xff1a;单调递增栈就是从栈底到栈顶数据是从大到小单调递减栈&#xff1a;单调递减栈就是从栈底到栈顶数据是从小到大 解决那类问题 要知道单调栈的适用于解决什么样的问题&#xff0c;我们首先需要知道单调栈的作用。单调栈分为单调递增栈和单调…

理解单调栈与单调队列

单调栈 单调栈&#xff1a;栈内的元素按照某种方式排序下单调递增或单调递减&#xff0c;如果新入栈的元素破坏的单调性&#xff0c;就弹出栈内元素&#xff0c;直到满足单调性。 单调栈分为单调递增栈和单调递减栈&#xff1a; 单调递增栈&#xff1a;栈中数据入栈或出栈的…

【栈 单调栈】浅谈单调栈与单调栈的理解

单调栈 定义&#xff1a; 单调栈&#xff0c;顾名思义&#xff0c;是栈内元素保持一定单调性&#xff08;单调递增或单调递减&#xff09;的栈。这里的单调递增或递减是指的从栈顶到栈底单调递增或递减。既然是栈&#xff0c;就满足后进先出的特点。与之相对应的是单调队列。 …

单调栈(一)

单调栈基本概念及实现 方案1&#xff1a;对于每一个数&#xff0c;遍历其左右位置&#xff0c;时间复杂度为O(N^2) 方案2&#xff1a;单调栈&#xff0c;每个元素入栈一次出栈一次&#xff0c;时间复杂度为O(N) &#xff08;一&#xff09;数组中没有重复值 示例&#xff1a;[…

第九章:单调栈与单调队列

单调栈与单调队列 一、单调栈1、什么是单调栈&#xff1f;2、单调栈的模板&#xff08;1&#xff09;问题&#xff1a;&#xff08;2&#xff09;分析&#xff1a; 二、单调队列1、什么是单调队列2、单调队列模板&#xff08;1&#xff09;问题&#xff08;2&#xff09;分析 一…

单调栈算法详解

单调栈算法详解 单调栈使用模板 stack<int> st; //此处一般需要给数组最后添加结束标志符&#xff0c;具体下面例题会有详细讲解 for (遍历这个数组){if (栈空 || 栈顶元素大于等于当前比较元素){入栈;}else{while (栈不为空 && 栈顶元素小于当前元素){栈顶元素…

单调队列和单调栈详解

这里是我的blog&#xff1a;有更多算法分享。排版可能也会更好看一点v https://endlesslethe.com/monotone-queue-and-stack-tutorial.html 前言 单调栈和单调队列算是栈和队列的高级应用吧&#xff0c;在公司面试中应该是不怎么会出现的&#xff08;除非算法岗&#xff1f;…

什么是单调栈

什么是单调栈 单调栈就是单调递增或者单调递减的栈&#xff0c;也就是栈底到栈顶递增或递减&#xff0c;根据单调栈的的这种结构&#xff0c;可以很容易想到运用单调栈可以很容易的把O(n)的时间复杂度优化到O(n),如果使用数组的话&#xff0c;相对的空间复杂度也不会太高 示例 …

Java实现之单调栈

目录 一.单调栈 二.每日温度 1.题目描述 2.问题分析 3.代码实现 三.下一个更大元素 I 1.题目描述 2.问题分析 3.代码实现 四.下一个更大元素 II 1.题目描述 2.问题分析 3.代码实现 一.单调栈 通常是一维数组&#xff0c;要寻找任一个元素的右边或者左边第一个比自…

[数据结构]单调栈

单调栈 这是笔者的第一篇博客&#xff0c;由于笔者自身水平的限制。用词可能不够准确&#xff0c;句子不太通顺&#xff0c;代码水平可能也不太行&#xff0c;敬请指出&#xff0c;感激不尽&#xff01; 我们都知道栈&#xff08;Stack&#xff09;是一种先入后出的数据结构&am…