找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 2083|回复: 8

【DirectX】基于XAudio2的midi合成器——XAMIDI

[复制链接]
发表于 2022-3-25 17:19:19 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
本帖最后由 系统消息 于 2022-3-25 17:53 编辑

原帖来源:【DirectX】基于XAudio2的midi合成器——XAMIDI https://www.0xaa55.com/thread-26601-1-1.html(出处:技术宅的结界,转载请保留出处。)
参考来源:【C语言】Midi文件播放器(可跨平台)https://www.0xaa55.com/thread-1489-1-1.html(出处:技术宅的结界)
游客,如果您要查看本帖隐藏内容请回复


在学习 DirectX 的道路上学完了图形接下来就是音频,早期 DX 的音频是用的 DSound,并且微软同时还给我们提供了基于 DSound 实现 midi 合成的 DMusic,两者结合就可以实现很强大的音乐音效系统。可是后来微软放弃了 DSound,并开发的了一下新的音频组件叫 XAudio(有两个大版本 XAudio1 和 XAudio2,原来的 DSound 则仅支持 Windows,而 XAudio1 仅支持 XBox,XAudio2 同时支持 Windows 和 XBox),XAudio2 比原来的 DSound 和 XAudio1 强大很多,可是当我们从 DSound 切换到 XAudio2 后却发现一个相当严重的问题,就是 XAudio2 没有提供对应的 midi 合成器,而 DMusic 又只能和 DSound 对接。这时如果开发新的游戏,我们想在游戏中使用 midi 功能怎么办呢?
1.退回到midiOut(功能很弱、延迟又高、还只能打开一个实例)。
2.继续用DMusic来合成 midi(这样 midi 只能走 DSound 输出,不能对接到 XAudio2)
3.用 Win10 的新 API Windows.Devices.Midi.h 的 MidiSynthesizer 对象(系统版本要求太高,而且还需要WinRT或UWP才能使用,最重要的是功能还不如 DMusic)
4.用 XAudio2 来模拟一个假的 DSound 来跟 DMusic 对接(咦,好像这个方案比较可行)
5.直接调用 dmsynth.dll 的底层API(这个比方案4更好,但是这里面都是非公开的 API)
6.调用第三方和 midi 合成器,再将合成结果流式写入到 XAudio2 中(这个方案好不好不好说,毕竟还要考虑版权等问题,还有就是可能第三方合成器太大,对小游戏开发者来说有点不划算)
目前 XAMIDI 采样的是方案4,如果将来我把 dmsynth.dll 研究透了,可能会更换为更好的方案5。我们先来看一下参考示例的运行截图吧:

XAEPiano(电钢琴)

XAEPiano(电钢琴)

XA3DMIDI(三维音效)

XA3DMIDI(三维音效)

XAMidPlay(播放器)

XAMidPlay(播放器)

在正式编程使用之前,再来看看 XAMIDI 的工作流程结构:

XAMIDI(工作流程)

XAMIDI(工作流程)

从上图可以看到有个比较有意思的地方,就是 XAudio2 的回调就是去调用对应的 XAMIDI 方法,而 XAMIDI 的回调又是去调用 XAudio2 的相关方法。它们之间的相互调用才实现了实时的 midi 合成工作,最后再由 XAudio2 将合成的音频流输出到声卡设备上。
User MIDI Player:代表用户自己编程实现的midi播放器
IXAMIDISynthesizer:为XAMIDI的合成器对象接口
IXAMIDISynthCallback:为XAMIDI的合成器回调接口
IXAudio2SourceVoice:为XAudio2的源语音对象接口
IXAudio2VoiceCallback:为XAudio2的源语音回调接口
IXAudio2SubmixVoice:为XAudio2的子语音对象接口
IXAudio2MasteringVoice:为XAudio2的主语音对象接口
System Audio Devices:代表最终的音频输出设备

XAMIDI 是一个基于 XAudio2 的 midi1.0 合成器,其接口同大多数DX组件采样了相同的工厂模式:组件自身只有一个创建工厂对象的全局函数,其它对象接口均是通过该工厂对象创建。
DSound、DMusicXAudio2、XAMIDI
WaveDirectSoundCreate→IDirectSound→IDirectSoundBufferXAudio2Create→IXAudio2→IXAudio2Voice
MIDICLSID_DirectMusic→IDirectMusic→IDirectMusicPortXAMIDICreate→IXAMIDI→IXAMIDISynthesizer
DSound 与 XAudio2 接口对应关系:
根对象缓冲区主缓冲区副缓冲区事件通知
IDirectSoundIDirectSoundBufferIDirectSoundBuffer+DSBCAPS_PRIMARYBUFFERIDirectSoundBuffer+其它IDirectSoundNotify
IXAudio2IXAudio2VoiceIXAudio2MasteringVoiceIXAudio2SourceVoiceIXAudio2VoiceCallback
DMusic 与 XAMIDI 接口对应关系:
根对象(工厂)合成器(端口)音色库(波表)音色(乐器)已下载音色
IDirectMusicIDirectMusicPortIDirectMusicCollectionIDirectMusicInstrumentIDirectMusicDownloadedInstrument
IXAMIDIIXAMIDISynthesizerIXAMIDITimbreBanksHXAMIDITimbreIXAMIDITimbreDownloaded

XAMIDI 接口描述:
接口描述
IXAMIDIXAMIDI的工厂接口,用于创建和管理其它的对象。
IXAMIDISynthesizerXAMIDI的合成器接口,用于将midi1.0消息合成波形音频流并输出到XAudio2上。
IXAMIDITimbreBanksXAMIDI的音色库接口,用于从波形文件中加载音色集合。
HXAMIDITimbreXAMIDI的音色接口,表示单个音色对象,用于下载到合成器对象中。
IXAMIDITimbreDownloadedXAMIDI的已下载音色接口,用于在不再需要使用时卸载。

对 XAMIDI 的工作流程及相关接口都已经了解的差不多了,现在可以来看看用法示例了:
游客,本帖隐藏的内容需要积分高于 1 才可浏览,您当前积分为 0

以上代码就是用 XAMIDI 在 XAudio2 上合成的经典菊花残音乐。顺便一提,其实 XAMIDI 不仅仅是支持输出到 XAudio2,只要自己实现相应的调用和回调处理,输出到别的音频 API 上也是可以的。
附件密码:XAMIDI-0000

XAMIDI-src.7z

14.95 KB, 阅读权限: 20, 下载次数: 6

售价: 2 个宅币  [记录]

XAMIDI 源码

XAMIDI.7z

1.73 MB, 阅读权限: 1, 下载次数: 13

XAMIDI 库和示例

回复

使用道具 举报

发表于 2022-5-6 11:59:42 | 显示全部楼层
最近也在学directx,参考借鉴
回复 赞! 1 靠! 0

使用道具 举报

发表于 2022-4-15 03:50:25 | 显示全部楼层
系统消息太棒了
回复 赞! 1 靠! 0

使用道具 举报

发表于 2022-3-28 11:02:14 | 显示全部楼层
6666666666666666666666666666666666666666666
回复 赞! 靠!

使用道具 举报

发表于 2022-4-20 15:03:03 | 显示全部楼层
感谢分享!!
回复

使用道具 举报

发表于 2022-6-24 23:58:19 | 显示全部楼层
看看老板的东西
回复 赞! 靠!

使用道具 举报

发表于 2024-7-24 09:26:28 | 显示全部楼层
ᕙ(•̤᷆ ॒ ູ॒•̤᷇)ᕘ
回复 赞! 靠!

使用道具 举报

发表于 2024-7-24 09:41:43 | 显示全部楼层
🤣🤣🤣
回复

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-11-21 20:48 , Processed in 0.041116 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表