Music 专为长时间背景音乐设计,流式解码、低内存占用,支持循环、淡入淡出、暂停恢复。
Music 与 Sound 的核心区别:
• Sound:全部解码到内存,低延迟,适合短音效
• Music:流式解码,内存占用恒定(不随文件时长增长),适合 3~10 分钟的背景音乐
同一时刻通常只有一首 Music 在播放,切换曲目时用 Fade 实现平滑过渡。
| 函数 | 说明 |
|---|---|
int xgeMusicLoad(xge_music pMusic, const char* sPath) | 加载音乐文件 |
int xgeMusicLoadGroup(xge_music pMusic, const char* sPath, xge_audio_group pGroup) | 加载到分组 |
int xgeMusicPlay(xge_music pMusic) | 播放 |
int xgeMusicStop(xge_music pMusic) | 停止 |
int xgeMusicPause(xge_music pMusic) | 暂停 |
int xgeMusicResume(xge_music pMusic) | 恢复 |
void xgeMusicSetLoop(xge_music pMusic, int bLoop) | 设置循环 |
void xgeMusicSetVolume(xge_music pMusic, float fVolume) | 设置音量 |
void xgeMusicFade(xge_music pMusic, float fFrom, float fTo, int iMilliseconds) | 音量渐变 |
int xgeMusicIsPlaying(xge_music pMusic) | 是否正在播放 |
void xgeMusicFree(xge_music pMusic) | 释放 |
gcc -O2 -I. -o ch111.exe ch111_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch111.exe
// 加载两首背景音乐
xge_music_t bgmMenu, bgmBattle;
xgeMusicLoad(&bgmMenu, "music/menu.ogg");
xgeMusicLoad(&bgmBattle, "music/battle.ogg");
// 主菜单:循环播放,淡入
xgeMusicSetLoop(&bgmMenu, 1);
xgeMusicSetVolume(&bgmMenu, 0.0f);
xgeMusicPlay(&bgmMenu);
xgeMusicFade(&bgmMenu, 0.0f, 0.7f, 1500);
// 进入战斗:淡出菜单 → 淡入战斗
void enterBattle(void) {
xgeMusicFade(&bgmMenu, 0.7f, 0.0f, 1000);
xgeMusicSetLoop(&bgmBattle, 1);
xgeMusicSetVolume(&bgmBattle, 0.0f);
xgeMusicPlay(&bgmBattle);
xgeMusicFade(&bgmBattle, 0.0f, 0.8f, 1000);
}
// 暂停/恢复(如打开设置菜单)
xgeMusicPause(&bgmBattle);
xgeMusicResume(&bgmBattle);
// 退出时释放
xgeMusicFree(&bgmMenu);
xgeMusicFree(&bgmBattle);将以下代码保存为 ch111_main.c,编译后运行即可看到背景音乐播放与场景切换效果:
#include "xge.h"
static xge_music_t g_bgmMenu;
static xge_music_t g_bgmBattle;
static xge_font g_font = NULL;
static int g_scene = 0; // 0=menu, 1=battle
static void switchScene(int scene) {
if (scene == g_scene) return;
g_scene = scene;
if (scene == 1) {
// 淡出菜单音乐,淡入战斗音乐
xgeMusicFade(&g_bgmMenu, 0.7f, 0.0f, 1000);
xgeMusicSetVolume(&g_bgmBattle, 0.0f);
xgeMusicPlay(&g_bgmBattle);
xgeMusicFade(&g_bgmBattle, 0.0f, 0.8f, 1000);
} else {
xgeMusicFade(&g_bgmBattle, 0.8f, 0.0f, 1000);
xgeMusicSetVolume(&g_bgmMenu, 0.0f);
xgeMusicPlay(&g_bgmMenu);
xgeMusicFade(&g_bgmMenu, 0.0f, 0.7f, 1000);
}
}
static int onFrame(void* pUser) {
(void)pUser;
xgeClear(0x081114FF);
// 按键切换场景
if (xgeKeyPressed('1')) switchScene(0);
if (xgeKeyPressed('2')) switchScene(1);
if (xgeKeyPressed('P')) {
if (g_scene == 0) xgeMusicPause(&g_bgmMenu);
else xgeMusicPause(&g_bgmBattle);
}
if (xgeKeyPressed('R')) {
if (g_scene == 0) xgeMusicResume(&g_bgmMenu);
else xgeMusicResume(&g_bgmBattle);
}
// HUD
xgeTextDraw(g_font, "1:Menu 2:Battle P:Pause R:Resume",
50, 50, 0xFFFFFFFF);
char buf[64];
sprintf(buf, "Scene: %s",
g_scene == 0 ? "Menu" : "Battle");
xgeTextDraw(g_font, buf, 50, 90, 0xFFFFFFFF);
return XGE_OK;
}
int main(void) {
xge_desc_t d = {0};
d.iWidth = 800;
d.iHeight = 600;
d.sTitle = "ch111 - Music";
d.iFlags = XGE_INIT_VSYNC;
xgeInit(&d);
xgeAudioInit();
// 加载两首背景音乐
xgeMusicLoad(&g_bgmMenu, "music/menu.ogg");
xgeMusicLoad(&g_bgmBattle, "music/battle.ogg");
xgeMusicSetLoop(&g_bgmMenu, 1);
xgeMusicSetLoop(&g_bgmBattle, 1);
// 开始播放菜单音乐(淡入)
xgeMusicSetVolume(&g_bgmMenu, 0.0f);
xgeMusicPlay(&g_bgmMenu);
xgeMusicFade(&g_bgmMenu, 0.0f, 0.7f, 1500);
g_font = xgeFontLoad("res/font/default.ttf", 24);
xgeRun(onFrame, NULL);
xgeMusicFree(&g_bgmMenu);
xgeMusicFree(&g_bgmBattle);
xgeFontFree(g_font);
xgeAudioUnit();
xgeUnit();
return 0;
}权威源码为 examples/tutorial_capture/ch111_main1.c。它用自生成 WAV 验证 xgeMusicLoad 的流式音乐路径、循环、音量、播放、暂停、恢复和停止。教学测试验证状态机;实际音乐资源应使用有授权的长音频文件。
