0

无论我使用什么音频文件,它总是会切断大约四分之一的路径。我有一种感觉,这是因为我将解码的音频转换为 a Uint8*,但如果我不这样做,音频播放速度非常快,它仍然只播放大约一半的文件。此外,由于某种原因,使用SDL_MixAudio代替SDL_memcpy会导致一堆声音副本相互播放。

Uint8* audio_pos;
Uint32 audio_len;

void audioCallback(void* userdata, Uint8* stream, int len) {
    if (audio_len == 0) return;
    len = (len > audio_len ? audio_len : len);
    SDL_memcpy(stream, audio_pos, len);
    audio_pos += len;
    audio_len -= len;
}

int main(int argc, char *argv[]) {
    ...
    short* decoded;
    int channels, rate, len;
    len = stb_vorbis_decode_filename(RealPath("music.ogg").c_str(), &channels, &rate, &decoded);

    SDL_AudioSpec spec;
    spec.freq = rate;
    spec.format = AUDIO_S16;
    spec.channels = channels;
    spec.samples = 2048;
    spec.callback = audioCallback;
    spec.userdata = NULL;

    audio_pos = (Uint8*)decoded;
    audio_len = len;

    if (SDL_OpenAudio(&spec, NULL) < 0) {
        std::cout << "failed to open audio device: " << SDL_GetError() << '\n';
        SDL_GL_DeleteContext(context);
        SDL_Quit();
        return -1;
    }

    SDL_PauseAudio(0);

    SDL_Event windowEvt;
    while (true) {
        if (audio_len == 0) break;
        if (SDL_PollEvent(&windowEvt)) {
            if (windowEvt.type == SDL_QUIT) break;
            if (windowEvt.type == SDL_KEYUP && windowEvt.key.keysym.sym == SDLK_ESCAPE) break;
        }
        SDL_GL_SwapWindow(window);
    }
    ...
}
4

1 回答 1

0

stb_vorbis_decode_filename返回关于 a 的“解码样本数”,int16不包括通道因子。您正在寻找:

int32 length = stb_vorbis_decode_filename("thing.ogg", &channels, &rate, &decoded);
int32 audio_length = length * channels * (sizeof(int16) / sizeof(uint8));

对于声音重叠的SDL_MixAudiovs SDL_memcpy,您需要使用静音值显式清除流。例如,SDL_memset当您输入 SDL 音频回调时。

void audioCallback(void* userdata, Uint8* stream, int len) 
{
    SDL_memset(stream, 0, len);// silence the stream
    if (audio_len == 0) return;
    len = (len > audio_len ? audio_len : len);
    SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);// this takes a volume argument
    audio_pos += len;
    audio_len -= len;
}

调用时传递给的零SDL_memset应该与您在其中创建的静音值相同。SDL_AudioSpecSDL_OpenAudioDevice

于 2017-03-12T18:54:14.663 回答