学习笔记-C语言关于waveout接口的使用(二)

本文介绍了在C语言中使用waveout接口播放音乐时,如何避免一次性加载整个文件到内存,通过while循环分块读取文件,减少内存消耗,但会导致播放卡顿。后续内容将探讨优化方法以解决这个问题。
摘要由CSDN通过智能技术生成

书接上文,在学习笔记-C语言关于waveout接口的使用(一)中我们展示了如何正确但是有点不惜代价地使用waveOut接口播放音乐,而在(二)篇中,我们将展示如何一次只读取文件的一小部分,即不使用跟音乐文件大小相当的内存来播放音乐。

那么该怎么做呢,聪明的读者肯定想到了,哎我用while循环疯狂向设备写入小部分数据不就好了。的确,这样确实可以,但是每两次waveOutwrite之间会有让人无法忍受的间隔,各位可以动手改改试试。不想改也行,体贴的我已经为大伙准备好了对应的代码,直接运行就行。

#include <stdio.h>
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib,"Winmm.lib")

int main()
{
	HWAVEOUT device;				//设备句柄
	WAVEFORMATEX wfx;				//结构体初始化设置
	WAVEHDR wave_buff;				//wave缓存区设置
	FILE* file;
	int buffsize = 44100;			//缓冲区大小
	int file_tile;					//文件结尾位置

	wfx.nSamplesPerSec = 44100;		//采样频率
	wfx.wBitsPerSample = 16;		//采样位深
	wfx.nChannels = 2;				//音道
	wfx.cbSize = 0;					//附加信息
	wfx.wFormatTag = WAVE_FORMAT_PCM;      //PCM编码格式,也可以赋1
	wfx.nBlockAlign = wfx.wBitsPerSample * wfx.nChannels / 8;
	wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;

	if(waveOutOpen(&device,WAVE_MAPPER,&wfx,0,0,CALLBACK_NULL)!=MMSYSERR_NOERROR)
	{
		fprintf(stderr, "unable to open WAVE_MAPPER device\n");
		return 0;
	}
	printf("The Wave Mapper device was opened successfully!\n");

	//打开文件
	file = fopen("text.wav", "rb+");
	if (file == NULL)
	{
		printf("无法打开文件\n");
		return 0;
	}

	ZeroMemory(&wave_buff, sizeof(WAVEHDR));		//清空结构体数组内容
	wave_buff.dwBufferLength = buffsize;
	wave_buff.lpData = (unsigned char*)malloc(buffsize);
	if (wave_buff.lpData == NULL)return NULL;

	fseek(file, 0, SEEK_END);
	file_tile = ftell(file);	//获取文件大小

	//跳过头文件
	fseek(file, 44, SEEK_SET);
	//将文件内容输入缓存并把缓存输出到设备
	while (1)
	{
		//判断是否读到文件末尾
		if (ftell(file) + buffsize >= file_tile)
		{
			buffsize = file_tile - ftell(file);
			wave_buff.dwBufferLength = buffsize;
		}
		printf("%d %d\n", ftell(file),buffsize);
		//读取音频文件数据
		fread(wave_buff.lpData, sizeof(unsigned char), buffsize, file);
		//准备要播放的缓冲区
		waveOutPrepareHeader(device, &wave_buff, sizeof(WAVEHDR));
		//将缓冲区写入设备
		waveOutWrite(device, &wave_buff, sizeof(WAVEHDR));
		//等待音乐播放结束,然后清理缓冲区
		while(waveOutUnprepareHeader(device,&wave_buff,sizeof(WAVEHDR))==WAVERR_STILLPLAYING)
			Sleep(10);

		if (ftell(file) + buffsize >= file_tile)break;
	}

	waveOutClose(device);
	fclose(file);
	free(wave_buff.lpData);
	return 0;
}

大伙运行就会发现这音乐怎么这么卡啊,确定,直接用while循环就会导致每次写入时来不及准备和清理缓冲区,所以接下来我们就得更深入的去使用更加美妙的代码了,敬请期待:

学习笔记-C语言关于waveout接口的使用(三)

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很好的问题!让我来解答。 首先,让我们来了解一下 `Comparable` 接口。这个接口是 Java 中的一个接口,它只有一个方法 `compareTo()`。这个方法的作用是定义类的自然排序顺序。 如果我们要对一个对象集合进行排序,只需要让这个类实现 `Comparable` 接口,并且重写 `compareTo()` 方法。这个方法返回一个整型值,表示该对象与另一个对象的大小关系。如果该对象小于另一个对象,则返回负整数;如果两个对象相等,则返回零;如果该对象大于另一个对象,则返回正整数。 下面是一个简单的例子,展示如何使用 `Comparable` 接口进行排序。 ```java public class Student implements Comparable<Student> { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } // 重写 compareTo 方法 @Override public int compareTo(Student o) { // 按照年龄从小到大排序 return this.age - o.getAge(); } } ``` 在这个例子中,我们定义了一个 `Student` 类,并且让它实现了 `Comparable` 接口。我们重写了 `compareTo()` 方法,按照年龄从小到大排序。 现在,我们可以使用 `Collections.sort()` 方法对 `Student` 对象进行排序了: ```java List<Student> students = new ArrayList<>(); students.add(new Student("Tom", 20)); students.add(new Student("Jerry", 18)); students.add(new Student("Alice", 22)); Collections.sort(students); for (Student student : students) { System.out.println(student.getName() + " " + student.getAge()); } ``` 输出结果为: ``` Jerry 18 Tom 20 Alice 22 ``` 可以看到,我们成功地按照年龄从小到大对 `Student` 对象进行了排序。 希望这个例子能够帮助你理解如何使用 `Comparable` 接口进行排序。如果你还有其他问题,请随时提出!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值