21xrx.com
2024-11-05 19:00:21 Tuesday
登录
文章检索 我的文章 写文章
"C++音乐导入实例教程"
2023-07-10 00:03:28 深夜i     --     --
C++编程 音乐导入 实例教程 学习资源 编程技巧

随着数字时代的发展,音乐也成为了人们日常生活中不可或缺的一部分。但是,有时候我们可能需要自己定制一些音乐的播放方式,或者将特定的音乐导入到自己的程序中来实现更加丰富多样的功能。那么,在此我们推荐一篇详细的C++音乐导入实例教程来帮助你快速掌握这一技能。

首先,我们需要明确自己使用的操作系统,因为在C++中导入音乐的方法和Windows、Linux、MacOS等操作系统有所不同。在此,我们以Windows系统为例进行讲解。

第一步,引用头文件。我们需要在代码中先引用Windows API中的mmsystem.h头文件,该头文件包含了C++中处理声音的基本函数和结构体。


#include <mmsystem.h>

#pragma comment(lib,"winmm.lib") // 链接winmm.lib库

第二步,初始化音频设备。在打开音频文件之前,我们需要使用waveOutOpen函数初始化音频设备。该函数具有以下几个参数:

`uDeviceID`:音频设备的编号,0表示默认音频输出设备。

`lpFormat`:音频格式,可以是pcm格式或压缩格式(比如mp3、wma等),需要注意格式要与打开的音频文件相匹配。

`dwCallBack`:回调函数指针,可以为空。

`dwInstance`:用户自定义数据,可以为空。

`dwFlags`:标志位,使用WAVE_FORMAT_DIRECT表示直接从文件中读取音频数据。


HWND h_wnd = GetDesktopWindow(); // 获取桌面句柄

HANDLE hndl; // HANDLE定义

WAVEFORMATEX pcm; // 音频流格式结构体

pcm.wFormatTag = WAVE_FORMAT_PCM; // 音频格式(PCM)

pcm.nChannels = 2; // 音频通道数(2)

pcm.nSamplesPerSec = 44100; // 采样率(44100)

pcm.nAvgBytesPerSec = pcm.nSamplesPerSec * 16 / 8; // 每秒数据量(平均字节数)(176400)

pcm.nBlockAlign = 16 / 8 * pcm.nChannels; // 每块最大数据量(16)

pcm.wBitsPerSample = 16; // 每个采样点的数据位数(16位)

pcm.cbSize = 0; // 附加信息大小

DWORD ret = waveOutOpen(&hndl, WAVE_MAPPER, &pcm, (DWORD)h_wnd, 0, CALLBACK_NULL | WAVE_FORMAT_DIRECT);

if (ret != MMSYSERR_NOERROR)

{

waveOutClose(hndl);

}

第三步,打开音频文件。我们需要首先使用fopen函数打开音频文件,并在打开成功后使用fread函数读取文件中的音频数据。然后我们需要将读取到的音频数据存入指针数组中,并记录数据大小和读取次数。


FILE*fp = fopen("test.mp3", "rb"); // 打开文件

fseek(fp, 0, SEEK_END); // 指向文件末尾

DWORD dwFileSize = ftell(fp); // 获取文件大小

DWORD readFile = 0; // 所读取的总字节数

fseek(fp, 0, SEEK_SET); // 回到文件开头

BYTE* pBuffer = new BYTE[dwFileSize];

ZeroMemory(pBuffer, dwFileSize); // 将内存块的每个字节设置为零

while (readFile < dwFileSize)

{

readFile += fread(pBuffer + readFile, 1, dwFileSize - readFile, fp);

}

fclose(fp); // 关闭文件

dwFileSize = readFile; // 判断是否读取完文件

DWORD remainFile = dwFileSize;

DWORD readTime = 0;

BYTE** pPtrArray = new BYTE * [10];

while (remainFile > 0)

{

DWORD readNow = remainFile > 4096 ? 4096 : remainFile;

BYTE* ptr = pBuffer + readTime * 4096;

memcpy(ptr, pBuffer + readTime * 4096, readNow);

remainFile -= readNow;

readTime++;

pPtrArray[readTime - 1] = ptr;

}

delete[] pBuffer;

DWORD dwNumBuffers = readTime;

DWORD dwBufferSize = 4096; // 缓存大小

第四步,写入音频数据。我们需要使用waveOutPrepareHeader函数将音频数据块放入缓存中,并使用waveOutWrite函数向音频设备发送缓存。


WAVEHDR * pWaveHdrArray = new WAVEHDR[dwNumBuffers];

for (DWORD i = 0; i < dwNumBuffers; i++)

{

WAVEHDR * pWaveHdr = &pWaveHdrArray[i];

ZeroMemory(pWaveHdr, sizeof(WAVEHDR));

pWaveHdr->dwBufferLength = dwBufferSize;

pWaveHdr->lpData = (char*)pPtrArray[i];

pWaveHdr->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP; // 设置缓存播放方式

pWaveHdr->dwLoops = 0xFFFFFFFF; // 循环次数(0xFFFFFFFF则为无限循环)

waveOutPrepareHeader(hndl, pWaveHdr, sizeof(WAVEHDR));

waveOutWrite(hndl, pWaveHdr, sizeof(WAVEHDR));

}

第五步,清理资源。播放结束后,我们需要关闭音频设备并释放相应的资源。


while (waveOutUnprepareHeader(hndl, &pWaveHdrArray[dwNumBuffers - 1], sizeof(WAVEHDR)) == WAVERR_STILLPLAYING)

{

Sleep(1000);

}

waveOutClose(hndl);

for (DWORD i = 0; i < dwNumBuffers; i++)

{

delete[] pPtrArray[i];

}

delete[] pPtrArray;

delete[] pWaveHdrArray;

到此,我们就成功地实现了在C++中导入音乐并播放的功能。如果您想要进一步了解更多关于音频处理的方法和技巧,可以参考相关的教材或者在其他开发者的支持下进行学习和交流。祝您在编程的道路上越走越远!

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复