PCM音频处理(3)——格式转换

一、PCM16转PCM8

PCM16LE格式的采样数据的取值范围是-32768到32767,而PCM8格式的采样数据的取值范围是0到255。所以PCM16LE转换到PCM8需要经过两个步骤:

  1. 第一步是将-32768到32767的16bit有符号数值转换为-128到127的8bit有符号数值。
  2. 第二步是将-128到127的8bit有符号数值转换为0到255的8bit无符号数值。
#include <stdio.h>
#include <stdlib.h>

int pcm16_pcm8(char* fileName)
{
	FILE *fp = fopen(fileName,"rb+");
	FILE* fp1 = fopen("pcm8.pcm","wb+");

	int cnt = 0;
	unsigned char* readBuf = malloc(4);

	while (!feof(fp))
	{
		short* readBuf16 = NULL;

		char readBuf8 = 0;

		unsigned char *readBuf8_u = 0;
		fread(readBuf, 1, 4, fp);
		//符号数值转换
		//存储左声道的数据
		readBuf16 = (short*)readBuf;
		readBuf8 = (*readBuf16)>>8;
		readBuf8_u = readBuf8 + 128;
		//左声道
		fwrite(&readBuf8_u,1,1,fp1);
		//存储右声道的数据
		readBuf16 = (short*)(readBuf+2);
		readBuf8 = (*readBuf16) >> 8;
		readBuf8_u = readBuf8 + 128;
 		//右
		fwrite(&readBuf8_u,1,1, fp1);
		cnt++;
	}
	printf("readBuf cnt :%d\n",cnt);
	free(readBuf);
	fclose(fp);
	fclose(fp1);
	return 0;
}
int main()
{
	pcm16_pcm8("shishi.pcm");
	return 0;
}

在这里插入图片描述这里可以看出我们的内存大小也不一样,这就是我们平时下载的音乐的高品质和低品质的差距吧,专业人员听这两个的音频应该会听出差距,但我听了半天也没听出啥差距。。。

二、PCM转AVE

PCM转MAVE类似于将rgb格式图片存为bmp,在程序前面加一段函数,让他能够被封装起来。

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

int pcm16_mave(const char *pcmpath,int channels, int sample_rate,const char *wavepath)
{
	typedef struct 
	{
		char fccID[4];
		unsigned int dwSize;
		char fccType[4];
	}WAVE_HEADER;
	typedef struct
	{
		char fccID[4];
		unsigned int dwSize;
		unsigned short  wFormatTag;
		unsigned short wChannels;
		unsigned int dwSamplesPerSec;
		unsigned int dwAvgBytesPerSec;
		unsigned short wBlockAlign;
		unsigned short uiBitsPerSample;
	}WAVE_FMT;
	typedef struct
	{
		char fccID[4];
		unsigned int dwSize;
	}WAVE_DATA;
	if (channels == 0 || 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 = fopen(pcmpath,"rb+");
	FILE* fp1 = fopen(wavepath,"wb+");

	if (NULL == fp)
	{
		printf("open pcm file error\n");
		return -1;
	}
	if (NULL == fp1)
	{
		printf("open mave file error\n");
		return -1;
	}
	memcpy(pcmHEADER.fccID, "RIFF", strlen("RIFF"));
	memcpy(pcmHEADER.fccType, "WAVE", strlen("WAVE"));
	fseek(fp1, sizeof(WAVE_HEADER), 1);
	
	pcmFMT.dwSamplesPerSec = sample_rate;
	pcmFMT.dwAvgBytesPerSec = pcmFMT.dwSamplesPerSec * sizeof(m_pcmData);
	pcmFMT.uiBitsPerSample = bits;
	memcpy(pcmFMT.fccID, "fmt ", strlen("fmt"));
	pcmFMT.dwSize = 16;
	pcmFMT.wBlockAlign = 2;
	pcmFMT.wChannels = channels;
	pcmFMT.wFormatTag = 1;
	
	fwrite(&pcmFMT, sizeof(WAVE_FMT), 1, fp1);

	memcpy(pcmDATA.fccID, "data", strlen("data"));
	pcmDATA.dwSize = 0;
	fseek(fp1, 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, fp1);
		fread(&m_pcmData, sizeof(unsigned short), 1, fp);
	}

	pcmHEADER.dwSize = 44 + pcmDATA.dwSize;

	rewind(fp1);
	fwrite(&pcmHEADER, sizeof(WAVE_HEADER), 1, fp1);
	fseek(fp1, sizeof(WAVE_FMT), SEEK_CUR);
	fwrite(&pcmDATA, sizeof(WAVE_DATA), 1, fp1);

	fclose(fp);
	fclose(fp1);
	
	return 0;
}
int main()
{
	pcm16_mave("shishi.pcm",2,44100,"shishi.wav");
	return 0;
}

这里我转化出来的wave是播放不了的,我想应该是封装函数有问题,后面再去解决,因为之前YUV图片封装也是这样,后面我找到原因再解决。

1、Java实现wav音频文件换为pcm音频文件(AudioUtils.java) 2、Java实现播放pcm音频文件(PCMPlay.java) WAV:wav是一种无损的音频文件格式,WAV符合 PIFF(Resource Interchange File Format)规范。所有的WAV都有一个文件头,这个文件头音频流的编码参数。WAV对音频流的编码没有硬性规定,除了PCM之外,还有几乎所有支持ACM规范的编码都可以为WAV的音频流进行编码。 PCM:PCM(Pulse Code Modulation----脉码调制录音)。所谓PCM录音就是将声音等模拟信号变成符号化的脉冲列,再予以记录。PCM信号是由[1]、[0]等符号构成的数字信号,而未经过任何编码和压缩处理。与模拟信号比,它不易受传送系统的杂波及失真的影响。动态范围宽,可得到音质相当好的影响效果。 简单来说:wav是一种无损的音频文件格式,pcm是没有压缩的编码方式。 WAV和PCM的关系 WAV可以使用多种音频编码来压缩其音频流,不过我们常见的都是音频流被PCM编码处理的WAV,但这不表示WAV只能使用PCM编码,MP3编码同样也可以运用在WAV中,和AVI一样,只要安装好了相应的Decode,就可以欣赏这些WAV了。在Windows平台下,基于PCM编码的WAV是被支持得最好的音频格式,所有音频软件都能完美支持,由于本身可以达到较高的音质的要求,因此,WAV也是音乐编辑创作的首选格式,适合保存音乐素材。因此,基于PCM编码的WAV被作为了一种中介的格式,常常使用在其他编码的相互换之中,例如MP3换成WMA。 简单来说:pcm是无损wav文件中音频数据的一种编码方式,但wav还可以用其它方式编码。
### 将MP3格式录音文件换为PCM格式 为了实现从MP3PCM换,可以采用多种工具和技术栈来完成这一过程。一种常见的方式是利用FFmpeg库来进行这种换操作。FFmpeg是一个开源多媒体框架,能够处理视频、音频以及各种流媒体协议。 对于具体的换流程而言,在命令行环境中可以直接通过调用FFmpeg执行相应的指令: ```bash ffmpeg -i input.mp3 output.pcm ``` 这条命令会读取名为`input.mp3`的源文件并将其解码成原始音频样本存储于`output.pcm`之中[^1]。 如果是在Java编程环境下,则可能更倾向于使用专门针对此目的设计的小型库——例如LAME。下面给出了一段基于JUnit框架编写的测试案例片段用于展示如何借助Mp3ToWav类实例化对象进而实施由MP3至WAV(内部封装有PCM数据)之间的变: ```java @Test public void mp3ToWav() { try { int r = ThreadLocalRandom.current().nextInt(1000); Mp3ToWav mw = new Mp3ToWav(); mw.run("recordFiles/file_19.mp3", "recordFiles/" + "file_" + r + ".wav"); } catch (IOException ex) { LOG.warn("encode error: {}.", ex); } } ``` 值得注意的是上述代码最终产生的并非纯粹意义上的`.pcm`文件而是带有波形头信息的标准Waveform Audio File Format(`.wav`)文件;不过由于.wav本质上也是包含了未经压缩线性量化采样点序列的数据结构形式之一,所以同样适用于后续大多数应用场景下的需求[^5]。 当涉及到更为复杂的场景比如微信小程序内嵌逻辑里需要对录制下来的Silk编码语音消息先行变为通用性强些的中间状态即PCM后再上传给诸如百度AI平台作进一步分析解读的话,则除了考虑选用合适的算法外还需兼顾效率因素考量整体架构设计方案的选择[^2][^3].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永不秃头的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值