上午导师给个任务,用c++写个程序,完成对wav格式的二进制读写

占戈云鬼 2014-03-04 02:09:54
上午导师给个任务,用c++写个程序,完成对wav格式的二进制读写,要求输入任何一首wav格式的歌曲,能从wav的二进制格式头文件读出歌曲属性,比如声道,比特率等,编程菜鸟,求助
...全文
272 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
勤奋的小游侠 2014-03-05
  • 打赏
  • 举报
回复
啊,代码都贴出来了。真给力
JiMoKuangXiangQu 2014-03-05
  • 打赏
  • 举报
回复
需要WAV格式的文档说明,才好看上面的代码,呵呵。 前面的兄弟们已经提供了链接了。
JiMoKuangXiangQu 2014-03-05
  • 打赏
  • 举报
回复
供参考。
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>


#pragma warning(disable:4996) /* _CRT_SECURE_NO_WARNINGS */


/*
 * Each .wav file has got 4 types of block:
 * . RIFF block
 * . fmt block
 * . fact block(optional)
 * . data block
 * and each start with the block IDs defined as follows:
 */
#define CHUNK_ID_RIFF	"RIFF"
#define CHUNK_ID_FMT	"fmt "
#define CHUNK_ID_FACT	"fact"
#define CHUNK_ID_DATA	"data"

#define RIFF_FMT_WAV	"WAVE"

/*
 * RIFF block.
 */
struct RIFF_HEADER
{
	char 	szRiffID[4];   		// 'R','I','F','F'
	DWORD 	dwRiffSize;
	char 	szRiffFormat[4]; 	// 'W','A','V','E'
};


struct WAVE_FORMAT
{
   WORD 	wFormatTag;
   WORD 	wChannels;
   DWORD 	dwSamplesPerSec;
   DWORD 	dwAvgBytesPerSec;
   WORD 	wBlockAlign;
   WORD 	wBitsPerSample;
};

/*
 * Format block. 
 */
struct FMT_BLOCK
{
	char   				szFmtID[4]; // 'f','m','t',' '
	DWORD   			dwFmtSize;
	struct WAVE_FORMAT	wavFormat;
};


/*
 * fact block
 */
struct FACT_BLOCK
{
   char		szFactID[4]; // 'f','a','c','t'
   DWORD   	dwFactSize;
   char		data[4];
};


/*
 * data block
 */
struct DATA_BLOCK
{
	char 	szDataID[4]; // 'd','a','t','a'
	DWORD 	dwDataSize;
};


enum { OFMT_BIN, OFMT_CFILE };



static void usage(const char *progname);
static int  wave_dump(const char *wavefile, const char *outfile, int outfmt, int dump_chs);



int main(int argc, char *argv[])
{
	int outfmt = OFMT_CFILE; // output file format: default to 'OFMT_CFILE'
	int dump_chs = 0;		 // defalut to disable dump data for each channel
	int i;

#ifdef _DEBUG
	argc = 3;
	argv[1] = "sample.wav";
	//argv[1] = "AlienStorm.wav";
	//argv[2] = "-dc";
	//argv[3] = "AlienStorm.c";
	argv[2] = "sample.c";
	//argv[3] = "sample.c";
	//argv[3] = "-fb";
	//argv[4] = "sample.bin";
	//argv[4] = "AlienStorm.bin";
	//argv[2] = "AlienStorm.bin";
#endif
	
	if (argc < 3 || argc > 5) {
		usage(argv[0]);
		exit(EXIT_FAILURE);
	}
	
	/* parse parameters */
	for (i = 2; i < argc - 1; i++)
	{
		if (_strnicmp(argv[i], "-f", 2) == 0) /* output file format */
		{
			switch (argv[i][2]) {
			case 'b': case 'B': outfmt = OFMT_BIN; break;
			case 'c': case 'C': outfmt = OFMT_CFILE; break;
			default: usage(argv[0]); exit(EXIT_FAILURE); break;
			}
		}
		else if (stricmp("-dc", argv[i]) == 0) /* check if user wants to dump data for each channel at the same time */
		{
			dump_chs = 1;
		}
		else
		{
			fprintf(stderr, "unknown option %s\n\n", argv[i]);
			usage(argv[0]);
			exit(EXIT_FAILURE);
		}
	}	
	

	/* dump wave data */
	if (!wave_dump(argv[1], argv[argc - 1], outfmt, dump_chs))
		return 1;
	

#ifdef _DEBUG
	getch();
#endif
	return 0;
}


static void usage(const char *progname)
{
	fprintf(stderr, 
			"USAGE: %s wave-file [options] output-file\n"
			"options:\n"
			"-f<c,b>: output file format, \n"
			"         -fc means output a c file, it's default\n"
			"         -fb means output a binary file\n"
			"-dc    : dump data for each channel at the same time, default to disabled\n", 
			progname);
}

static int wave_dump(const char *wavefile, const char *outfile, int outfmt, int dump_chs)
{
#define BUF_UNIT_SZ		32 // must make sure: (BUF_UNIT_SZ % 16 == 0)
#ifdef _DEBUG
#define BUF_UNITS		1
#else
#define BUF_UNITS		(8192 / BUF_UNIT_SZ)
#endif
#define BUF_SZ			(BUF_UNIT_SZ * BUF_UNITS)
#define DUMP_UNITS_AT_LINE	16 // 16 bytes at each line when dumped with 'OFMT_CFILE'

	FILE *istream, *ostream;
	FILE *ostream_lc, *ostream_rc;
	unsigned char buf[BUF_SZ];
	unsigned char buf_lc[BUF_SZ / 2], buf_rc[BUF_SZ / 2];
	size_t n;
	char dn[_MAX_PATH];
	char lcf[_MAX_PATH], rcf[_MAX_PATH];
	unsigned int i, j;

	struct RIFF_HEADER riffheader;
	struct FMT_BLOCK fmtblk;
	int hasfactblk = 0;
	struct FACT_BLOCK factblk;
	struct DATA_BLOCK datablk;

	int	ret = 1;

	
	if (wavefile == NULL || outfile == NULL)
	{
		fprintf(stderr, "input or output file can't be NULL\n");
		return 0;
	}
	if (outfmt != OFMT_CFILE && outfmt != OFMT_BIN)
	{
		fprintf(stderr, "output format must be 'OFMT_CFILE' or 'OFMT_BIN'\n");
		return 0;
	}
	
	/* open wave file */
	if ((istream = fopen(wavefile, "rb")) == NULL)
	{
		fprintf(stderr, "open file %s failed\n", wavefile);
		return 0;
	}
	

	/* read the wave file header and parse them */
	while (n = fread(buf, sizeof(char), sizeof(buf), istream))
	{
		if (strncmp(buf, CHUNK_ID_RIFF, strlen(CHUNK_ID_RIFF)) == 0) /* RIFF chunk */
		{
			fseek(istream, -(long)n, SEEK_CUR);
			fread(&riffheader, sizeof(struct RIFF_HEADER), 1, istream);
			if (strncmp(riffheader.szRiffFormat, RIFF_FMT_WAV, strlen(RIFF_FMT_WAV)) != 0)
			{
				fprintf(stderr, "file %s is not a RIFF format .wav file\n", wavefile);
				ret = 0;
				goto QUIT;
			}
		}
		else if (strncmp(buf, CHUNK_ID_FMT, strlen(CHUNK_ID_FMT)) == 0) /* fmt chunk */
		{
			fseek(istream, -(long)n, SEEK_CUR);
			fread(&fmtblk, sizeof(struct FMT_BLOCK), 1, istream);
			if (fmtblk.wavFormat.wChannels == 1) dump_chs = 0;

		//#ifdef _DEBUG
			printf("%s: \n"
				   "FmtID         : %c%c%c%c\n"
				   "FmtSize       : %d bytes\n"
				   "FormatTag     : %s\n"
				   "Channels      : %s\n"
				   "SamplesPerSec : %f KHZ\n"
				   "AvgBytesPerSec: %ld\n"
				   "BlockAlign    : %d\n"
				   "BitsPerSample : %d\n", 
				   wavefile, 
				   fmtblk.szFmtID[0], fmtblk.szFmtID[1], fmtblk.szFmtID[2], fmtblk.szFmtID[3], 
				   fmtblk.dwFmtSize, 
				   fmtblk.wavFormat.wFormatTag ? "PCM" : "ADPCM", 
				   fmtblk.wavFormat.wChannels == 1 ? "MONO" : "STEREO", 
				   (float)fmtblk.wavFormat.dwSamplesPerSec / 1000, 
				   fmtblk.wavFormat.dwAvgBytesPerSec, 
				   fmtblk.wavFormat.wBlockAlign, 
				   fmtblk.wavFormat.wBitsPerSample);
			/* check if we got a extra FMT_BLOCK information */
			if (fmtblk.dwFmtSize > sizeof(struct FMT_BLOCK))
			{
				WORD wExtraInfo;
				fread(&wExtraInfo, sizeof(WORD), 1, istream);
				printf("ExtraInfo     : %#06X\n\n", wExtraInfo);
			}
			else
			{
				printf("ExtraInfo     : None\n\n");
			}
		//#endif
		}
		else if (strncmp(buf, CHUNK_ID_FACT, strlen(CHUNK_ID_FACT)) == 0) /* fact chunk */
		{
			hasfactblk = 1;

			fseek(istream, -(long)n, SEEK_CUR);
			fread(&factblk, sizeof(struct FACT_BLOCK), 1, istream);
		}
		else if (strncmp(buf, CHUNK_ID_DATA, strlen(CHUNK_ID_DATA)) == 0) /* data chunk */
		{
			fseek(istream, -(long)n, SEEK_CUR);
			fread(&datablk, sizeof(struct DATA_BLOCK), 1, istream);
		//#ifdef _DEBUG
			printf("wave data size is %ld bytes\n\n", datablk.dwDataSize);
		//#endif
			break;
		}
	}


	/* dump wave data stream to output file */

	memset(dn, 0, sizeof(dn));
	strncpy(dn, outfile, strchr(outfile, '.') - outfile);

	/* make L,R channel output file name */
	if (dump_chs)
	{
		strcpy(lcf, dn);
		strcat(lcf, "_lc");
		strcat(lcf, strchr(outfile, '.'));

		strcpy(rcf, dn);
		strcat(rcf, "_rc");
		strcat(rcf, strchr(outfile, '.'));
	}

	if (outfmt == OFMT_CFILE)
	{
		ostream = fopen(outfile, "w");
		fprintf(ostream, "const unsigned char %s[] = {\n", dn); /* write data header */

		if (dump_chs)
		{
			/* L channel */
			ostream_lc = fopen(lcf, "w");
			fprintf(ostream_lc, "const unsigned char %s_lc[] = {\n", dn); /* write data header */

			/* R channel */
			ostream_rc = fopen(rcf, "w");
			fprintf(ostream_rc, "const unsigned char %s_rc[] = {\n", dn); /* write data header */
		}
	}
	else if (outfmt == OFMT_BIN)
	{
		ostream = fopen(outfile, "wb");
		if (dump_chs)
		{
			ostream_lc = fopen(lcf, "wb");
			ostream_rc = fopen(rcf, "wb");
		}
	}

	while (n = fread(buf, sizeof(char), sizeof(buf), istream))
	{
		if (dump_chs) assert(n % 2 == 0);

		if (outfmt == OFMT_CFILE)
		{
			for (i = 0; i < n/DUMP_UNITS_AT_LINE; i++)
			{
				fprintf(ostream, "\t");
				if (dump_chs && i % 2 == 0)
				{
					fprintf(ostream_lc, "\t");
					fprintf(ostream_rc, "\t");
				}
				for (j = 0; j < DUMP_UNITS_AT_LINE; j++)
				{
					fprintf(ostream, "0X%02X, ", (unsigned char)(buf[i * DUMP_UNITS_AT_LINE + j]));
					if (dump_chs)
					{
						if (j % 2 == 0)
							fprintf(ostream_lc, "0X%02X, ", (unsigned char)(buf[i * DUMP_UNITS_AT_LINE + j]));
						else
							fprintf(ostream_rc, "0X%02X, ", (unsigned char)(buf[i * DUMP_UNITS_AT_LINE + j]));
					}
				}
				fprintf(ostream, "\n");
				if (dump_chs && (i + 1) % 2 == 0)
				{
					fprintf(ostream_lc, "\n");
					fprintf(ostream_rc, "\n");
				}
			}

			if (n % DUMP_UNITS_AT_LINE)
			{
				fprintf(ostream, "\t");
				for (j = 0; j < n % DUMP_UNITS_AT_LINE; j++)
				{
					fprintf(ostream, "0X%02X, ", (unsigned char)(buf[i * DUMP_UNITS_AT_LINE + j]));
					if (dump_chs)
					{
						if (j % 2 == 0)
							fprintf(ostream_lc, "0X%02X, ", (unsigned char)(buf[i * DUMP_UNITS_AT_LINE + j]));
						else
							fprintf(ostream_rc, "0X%02X, ", (unsigned char)(buf[i * DUMP_UNITS_AT_LINE + j]));
					}
				}
				fprintf(ostream, "\n");
				if (dump_chs)
				{
					fprintf(ostream_lc, "\n");
					fprintf(ostream_rc, "\n");
				}
			}
		}
		else if (outfmt == OFMT_BIN)
		{
			if (fwrite(buf, sizeof(char), n, ostream) != n)
			{
				fprintf(stderr, "write file %s failed\n", outfile);
				ret = 0;
				goto QUIT;
			}

			if (dump_chs)
			{
				for (i = 0; i < n / 2; i++)
				{
					buf_lc[i] = buf[i * 2];
					buf_rc[i] = buf[i * 2 + 1];
				}

				if (fwrite(buf_lc, sizeof(char), i, ostream_lc) != i)
				{
					fprintf(stderr, "write file %s failed\n", lcf);
					ret = 0;
					goto QUIT;
				}

				if (fwrite(buf_rc, sizeof(char), i, ostream_rc) != i)
				{
					fprintf(stderr, "write file %s failed\n", rcf);
					ret = 0;
					goto QUIT;
				}
			}
		}
	}

	if (outfmt == OFMT_CFILE) fprintf(ostream, "};");
	if (dump_chs) { fprintf(ostream_lc, "};"); fprintf(ostream_rc, "};"); }
	
QUIT:
	fclose(istream);
	fclose(ostream);
	if (dump_chs)
	{
		fclose(ostream_lc);
		fclose(ostream_rc);
	}
	

	return ret;
}
翅膀又硬了 2014-03-05
  • 打赏
  • 举报
回复
要是完全自己分析,就先学会怎么读写文件,怎么以二进制方式读写。然后再研究那种文件的格式
adfaksdf 2014-03-05
  • 打赏
  • 举报
回复
网上说不定有现成的库,可以找找看啊
孤影品茗 2014-03-04
  • 打赏
  • 举报
回复
系统有mmio系列函数,可以直接读取wav的chunk,这样解析会方便很多
oneleafpz 2014-03-04
  • 打赏
  • 举报
回复
先研究结构,再按结构读数据不就行了,初学者都能干
占戈云鬼 2014-03-04
  • 打赏
  • 举报
回复
引用 1 楼 truelance 的回复:
参考 http://blog.csdn.net/zhihu008/article/details/7854529
这个我看过,可主要是程序无从下手,不知道怎么写
占戈云鬼 2014-03-04
  • 打赏
  • 举报
回复
惭愧,是的,可程序不会编,学的时候学的都是些基础的,用的时候就什么都不会了
derekrose 2014-03-04
  • 打赏
  • 举报
回复
引用 2 楼 mujiok2003 的回复:
你确定你是研究生?
别这样。。
mujiok2003 2014-03-04
  • 打赏
  • 举报
回复
你确定你是研究生?

64,676

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧