You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenAL结合libsndfile播放长音频时出现开头失真、突然中断问题求助

Let's break down the potential issues in your code that could be causing the start-up distortion and sudden playback interruptions. I'll walk through the most likely culprits first:

1. Not Updating Buffers Frequently Enough (Top Cause of Sudden Interruptions)

Your updateBufferStream() function is responsible for refilling buffers once OpenAL has finished playing them. If you don't call this function regularly (like every frame in your main game/app loop), OpenAL will run out of queued audio data and stop playback abruptly.

How often you need to call it depends on your buffer size: for example, if b_samples is set to 4096 and your audio is 44100Hz, each buffer holds ~93ms of audio. Aim to call updateBufferStream() every 50ms or so to ensure you never run dry. If you're only calling it once every few seconds, that's definitely the issue.

2. Small Buffer Size Causing Start-Up Distortion

If b_samples is set to a tiny value (like 256 or 512), the initial buffer fill might be too small to smooth out the start of playback. Try increasing it to a larger power of two—4096 or 8192 are standard choices for streaming audio. This will give OpenAL more data to work with upfront, reducing crackling or distortion at the start.

Also, double-check that b_samples is actually initialized somewhere in your code (it's not defined in the snippets you shared). An uninitialized variable could lead to weird buffer sizes and unexpected behavior.

3. Missing Error Checks for OpenAL Initialization

You're doing a good job checking errors after most OpenAL calls, but you skipped checking right after creating sources and buffers. If these calls fail silently, it could lead to broken playback:

alGenSources(1, &se_source);
if (alGetError() != AL_NO_ERROR) {
    throw("Failed to create OpenAL source");
}
alGenBuffers(num_buffers, se_buffers);
if (alGetError() != AL_NO_ERROR) {
    throw("Failed to create OpenAL buffers");
}

Adding these checks will help you rule out initialization issues.

4. Stale State Check in Underrun Handling

In updateBufferStream(), you check the source's playback state before refilling processed buffers. That means you're looking at a state that might not reflect the latest changes. Move the state check to after you've handled all processed buffers:

// After processing all queued buffers...
alGetSourcei(se_source, AL_SOURCE_STATE, &state);
if (state != AL_PLAYING && state != AL_PAUSED) {
    ALint queued;
    alGetSourcei(se_source, AL_BUFFERS_QUEUED, &queued);
    if (queued > 0) {
        alSourcePlay(se_source);
        if (alGetError() != AL_NO_ERROR) {
            throw("error restarting music playback");
        }
    }
}

This way, you're checking the state after ensuring any empty buffers are refilled, which reduces the chance of unnecessary playback stops.

5. Memory Leaks (Non-Critical but Worth Fixing)

You're using malloc() for se_membuf but there's no corresponding free() call. Over time, this will leak memory. Add a destructor to clean up all your resources properly:

musicBuffer::~musicBuffer() {
    if (se_sndfile) sf_close(se_sndfile);
    if (se_membuf) free(se_membuf);
    
    // Clean up OpenAL resources
    alSourceStop(se_source);
    alSourcei(se_source, AL_BUFFER, 0);
    alDeleteBuffers(num_buffers, se_buffers);
    alDeleteSources(1, &se_source);
}

This ensures you don't leave dangling resources behind.

6. Edge Case for Looping (If Needed)

If you want your audio to loop, your current code will stop playback once it reaches the end of the file. To fix this, rewind the file when you hit the end:

slen = sf_readf_short(se_sndfile, se_membuf, b_samples);
if (slen <= 0) {
    // Rewind to start for continuous looping
    sf_seek(se_sndfile, 0, SEEK_SET);
    slen = sf_readf_short(se_sndfile, se_membuf, b_samples);
}
if (slen > 0) {
    slen *= se_sfinfo.channels * (sf_count_t)sizeof(short);
    alBufferData(bufid, se_format, se_membuf, (ALsizei)slen, se_sfinfo.samplerate);
    alSourceQueueBuffers(se_source, 1, &bufid);
}

If you don't want looping, this isn't your issue—but sudden stops at the end of the file are expected behavior.

Quick Tests to Diagnose

  1. First, make sure updateBufferStream() is called every frame in your main loop.
  2. Try increasing b_samples to 4096 and see if the start-up distortion goes away.
  3. Add the missing error checks for alGenSources and alGenBuffers to rule out initialization failures.

内容的提问来源于stack exchange,提问作者AsianMario

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 00:13:12