我是靠谱客的博主 矮小雪碧,最近开发中收集的这篇文章主要介绍#1 给PCM编码加上WAV头,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

(本文中的代码在VS2022中编译通过)


简单地实现一个给PCM编码加上WAV头的东西

(提前声明一下)

// 这是输入,输出和配置
FILE* in, * out, * conf;
// 缓冲区长度
unsigned char buffer[1048576];

首先,获取文件长度

// unsigned int i;
	fseek(in, 0, SEEK_END);
	i = ftell(in);
	fseek(in, 0, SEEK_SET);

写入RIFF标识

fwrite("RIFF", 1, 4, out);

RIFF块的数据长度,即WAV文件大小减8
(就是将所以子块的长度加上"WAVE"四个字节)
SIGN是我自定义的子块,实际不需要

c = /*fmt*/(16 + 8) +/*data*/(8 + i) +
/*Sign*/+(8 + sign_size) +/*WAVE*/4;
fwrite(&c, 4, 1, out);
fwrite("WAVEfmt ", 1, 8, out);

按顺序写入fmt子块

	c = 16;
	fwrite(&c, 4, 1, out);

	// Format
	//编码格式,1 是PCM编码
	fwrite(&AudioFormat, 2, 1, out);
	//声道数
	fwrite(&NumChannels, 2, 1, out);
	//采样率
	fwrite(&SampleRate, 4, 1, out);
	//(每秒的字节数)
	ByteRate = SampleRate * NumChannels * BitPerSample / 8;
	fwrite(&ByteRate, 4, 1, out);
	//对齐字节数,即一次采样所占用的字节数
	BlockAlign = NumChannels * BitPerSample / 8;
	fwrite(&BlockAlign, 2, 1, out);
	//采样深度
	fwrite(&BitPerSample, 2, 1, out);

我发现只要添加的子块正确,即
{子块标识符,子块数据大小,子块数据},
WAV应该还是可以播放的?
所以我添加了SIGN子块

// Sign
	fwrite("SIGN", 1, 4, out);
	fwrite(&sign_size, 4, 1, out);
	fwrite(sign, 1, sign_size, out);

data子块,即声音数据

//Data
	fwrite("data", 1, 4, out);
	fwrite(&i, 4, 1, out);
	
	do {
		c = fread(buffer, 1, 1048576, in);
		fwrite(buffer, 1, c, out);
	} while (c);

关于自定义子块
子块的定义

typedef struct _SubChunk{
	// 子块ID
	unsigned char m_id[4];
	// 子块数据大小
	unsigned int m_size;
	// 数据
	unsigned char *dat;
} SubChunk,*rSubChunk

注意,自定义子块的ID不能与特殊的ID重复
LIST块用于存储歌曲信息,如歌手等,这是一个可以包含子块的块,
它被包含于RIFF块


项目代码

#define _CRT_SECURE_NO_WARNINGS

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

unsigned char buffer[1048576];

FILE* in, * out, * conf;

char config[256];

char sign[256];

int main(int count, char* strings[]) {

	unsigned int SampleRate=64000;
	unsigned short int NumChannels=1;
	unsigned short int BitPerSample=8;
	unsigned int ByteRate;
	unsigned short BlockAlign;
	unsigned short AudioFormat = 1;


	unsigned int c;
	char get;
	unsigned int i;

	unsigned int sign_size;

	puts("Hanako - Wav Head Writer");

	if (count == 4) {
		in = fopen(strings[1], "rb");
		conf = fopen(strings[3], "r");
	}
	else {
		puts("wav-headwriter <input-file> <output-file> <config-file>");
		return -2;
	}

	if (in == NULL || conf == NULL) {
		puts("Cannot open file.");
		if (in)fclose(in);
		if (conf)fclose(conf);
		return -1;
	}

	out = fopen(strings[2], "wb");

	do {
		memset(config, 0, 256);
		for (i = 0; i < 255; i++) {
			config[i] = fgetc(conf);
			if (config[i] == EOF || config[i] == 'n') {
				config[i] = 0;
				break;
			}
		}

		if (i >= 255)while (fgetc(conf) == 'n' || fgetc(conf) == EOF);

		sscanf(config, "WAV.SampleRate=%u", &SampleRate);
		sscanf(config, "WAV.NumChannels=%hu", &NumChannels);
		sscanf(config, "WAV.BitPerSample=%hu", &BitPerSample);
		sscanf(config, "WAV.Signature=%s", sign);
	} while (feof(conf)==0);

	printf("SampleRate:%unNumChannels:%hunBitPerSample:%hunn", SampleRate, NumChannels, BitPerSample);
	printf("Signature:%snn", sign);

	sign_size = strlen(sign);

	fseek(in, 0, SEEK_END);
	i = ftell(in);
	fseek(in, 0, SEEK_SET);
	
	c = /*fmt*/(16 + 8) +/*data*/(8 + i) +/*Sign*/+(8 + sign_size) +/*WAVE*/4;

	// RIFF
	fwrite("RIFF", 1, 4, out);
	fwrite(&c, 4, 1, out);
	fwrite("WAVEfmt ", 1, 8, out);
	c = 16;
	fwrite(&c, 4, 1, out);

	// Format
	fwrite(&AudioFormat, 2, 1, out);
	fwrite(&NumChannels, 2, 1, out);
	fwrite(&SampleRate, 4, 1, out);
	ByteRate = SampleRate * NumChannels * BitPerSample / 8;
	fwrite(&ByteRate, 4, 1, out);
	BlockAlign = NumChannels * BitPerSample / 8;
	fwrite(&BlockAlign, 2, 1, out);
	fwrite(&BitPerSample, 2, 1, out);

	// Sign
	fwrite("SIGN", 1, 4, out);
	fwrite(&sign_size, 4, 1, out);
	fwrite(sign, 1, sign_size, out);

	//Data
	fwrite("data", 1, 4, out);
	fwrite(&i, 4, 1, out);
	
	do {
		c = fread(buffer, 1, 1048576, in);
		fwrite(buffer, 1, c, out);
	} while (c);


	if (in)fclose(in);
	if (conf)fclose(conf);
	if (out)fclose(out);
	return 0;
}

忘记写注释了呐


BLOG #1

最后

以上就是矮小雪碧为你收集整理的#1 给PCM编码加上WAV头的全部内容,希望文章能够帮你解决#1 给PCM编码加上WAV头所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(71)

评论列表共有 0 条评论

立即
投稿
返回
顶部