Stream 是通用流式播放器,兼具 Music 的低内存和 Sound 的 3D 定位能力,适合长语音、环境音。
Stream 是 Sound 与 Music 的混合体:
• 像 Music 一样流式解码(低内存)
• 像 Sound 一样支持 3D 空间定位(SetPosition)
典型场景:长语音对话、环境音(瀑布、风声)、NPC 对话音频。
生命周期用 Open/Close(而非 Load/Free)。
| 函数 | 说明 |
|---|---|
int xgeStreamOpen(xge_stream pStream, const char* sPath) | 打开音频流 |
int xgeStreamOpenGroup(xge_stream pStream, const char* sPath, xge_audio_group pGroup) | 打开到分组 |
int xgeStreamPlay(xge_stream pStream) | 播放 |
int xgeStreamStop(xge_stream pStream) | 停止 |
int xgeStreamPause(xge_stream pStream) | 暂停 |
int xgeStreamResume(xge_stream pStream) | 恢复 |
void xgeStreamClose(xge_stream pStream) | 关闭流 |
void xgeStreamSetLoop(xge_stream pStream, int bLoop) | 设置循环 |
void xgeStreamSetVolume(xge_stream pStream, float fVolume) | 设置音量 |
void xgeStreamSetPosition(xge_stream pStream, float fX, float fY, float fZ) | 3D 位置 |
void xgeStreamFade(xge_stream pStream, float fFrom, float fTo, int iMilliseconds) | 音量渐变 |
int xgeStreamIsPlaying(xge_stream pStream) | 是否正在播放 |
gcc -O2 -I. -o ch112.exe ch112_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch112.exe
// 打开瀑布环境音(3D 定位)
xge_stream_t stmWaterfall;
xgeStreamOpen(&stmWaterfall, "ambience/waterfall.ogg");
xgeStreamSetLoop(&stmWaterfall, 1);
xgeStreamSetPosition(&stmWaterfall,
500.0f, 300.0f, 0);
xgeStreamSetVolume(&stmWaterfall, 0.6f);
xgeStreamPlay(&stmWaterfall);
// NPC 对话语音(一次性播放)
xge_stream_t stmVoice;
xgeStreamOpen(&stmVoice, "voice/npc_greeting.ogg");
xgeStreamSetPosition(&stmVoice,
npc.x, npc.y, 0);
xgeStreamPlay(&stmVoice);
// 每帧更新:玩家靠近时音量增大
void onFrame(void) {
float dist = distance(player, waterfall);
float vol = 1.0f - dist / 800.0f;
if (vol < 0) vol = 0;
xgeStreamSetVolume(&stmWaterfall, vol);
}
// 关闭
xgeStreamClose(&stmWaterfall);
xgeStreamClose(&stmVoice);将以下代码保存为 ch112_main.c,编译后运行即可看到流式音频 3D 环境音效果:
#include "xge.h"
#include <math.h>
static xge_stream_t g_stmWater;
static xge_stream_t g_stmWind;
static xge_font g_font = NULL;
static float g_time = 0.0f;
static int onFrame(void* pUser) {
(void)pUser;
g_time += 0.016f;
xgeClear(0x081114FF);
// 玩家位置(绕圈移动)
float px = 400.0f + 250.0f * cosf(g_time * 0.5f);
float py = 300.0f + 180.0f * sinf(g_time * 0.5f);
// 更新听者位置
xge_audio_listener_t lis = { 0 };
lis.fX = px; lis.fY = py;
xgeAudioListenerSet(&lis);
// 根据距离调整瀑布音量
float dx = px - 600.0f, dy = py - 200.0f;
float dist = sqrtf(dx*dx + dy*dy);
float vol = 1.0f - dist / 600.0f;
if (vol < 0) vol = 0;
xgeStreamSetVolume(&g_stmWater, vol);
// 绘制场景
xgeShapeCircleFill(600, 200, 20, 0x4488FFFF);
xgeShapeCircleFill(200, 400, 16, 0x88FF88FF);
xgeShapeCircleFill(px, py, 10, 0xFFB454FF);
// HUD
char buf[128];
sprintf(buf, "Waterfall vol: %.2f | dist: %.0f", vol, dist);
xgeTextDraw(g_font, buf, 50, 50, 0xFFFFFFFF);
xgeTextDraw(g_font, "Blue=Waterfall Green=Wind Yellow=Player",
50, 90, 0xFFFFFFFF);
return XGE_OK;
}
int main(void) {
xge_desc_t d = {0};
d.iWidth = 800;
d.iHeight = 600;
d.sTitle = "ch112 - Stream";
d.iFlags = XGE_INIT_VSYNC;
xgeInit(&d);
xgeAudioInit();
// 打开环境音流
xgeStreamOpen(&g_stmWater, "ambience/waterfall.ogg");
xgeStreamSetLoop(&g_stmWater, 1);
xgeStreamSetPosition(&g_stmWater, 600, 200, 0);
xgeStreamPlay(&g_stmWater);
xgeStreamOpen(&g_stmWind, "ambience/wind.ogg");
xgeStreamSetLoop(&g_stmWind, 1);
xgeStreamSetPosition(&g_stmWind, 200, 400, 0);
xgeStreamSetVolume(&g_stmWind, 0.4f);
xgeStreamPlay(&g_stmWind);
g_font = xgeFontLoad("res/font/default.ttf", 24);
xgeRun(onFrame, NULL);
xgeStreamClose(&g_stmWater);
xgeStreamClose(&g_stmWind);
xgeFontFree(g_font);
xgeAudioUnit();
xgeUnit();
return 0;
}权威源码为 examples/tutorial_capture/ch112_main1.c。它打开一个 stream,设置循环、音量和三维位置,再验证播放、暂停、恢复和停止。短 WAV 只用于可重复验证;真实场景应以持续解码的媒体文件评估内存与 I/O。
