使 SDL_AudioCallback 无缝(即没有打嗝)?

问题描述 投票:0回答:1

我正在编写一个简单的程序来通过 SDL 播放声音:

#include <iostream>
#include <SDL.h>


float sine_freq = 200.0f;
float audio_volume = 1.0f;
float audio_frequency;

void SineAudioCallback(void* userdata, Uint8* stream, int len) {
    float* buf = (float*)stream;
    for (int i = 0; i < len / 4; ++i) {
        buf[i] = (float)(audio_volume * sin(2 * M_PI * i * audio_frequency));
    }
    std::cout << "here" << std::endl;
    return;
}

int main(int argc, char* argv[])
{
    if (SDL_Init(SDL_INIT_AUDIO)) {
        return 1;
    }

    std::cout << "[SDL] Audio driver: " << SDL_GetCurrentAudioDriver() << std::endl;

    SDL_AudioSpec want, have;
    SDL_zero(want);

    want.freq = 5000;
    want.format = AUDIO_F32;
    want.channels = 2;
    want.samples = 4096;
    want.callback = SineAudioCallback;

    std::cout <<"[SDL] Desired - frequency: " << want.freq
        << ", format: f " << SDL_AUDIO_ISFLOAT(want.format)  << " s " << SDL_AUDIO_ISSIGNED(want.format) << " be " << SDL_AUDIO_ISBIGENDIAN(want.format) << " sz " << SDL_AUDIO_BITSIZE(want.format)
        << ", channels: " << (int)want.channels << ", samples: " << want.samples << std::endl;


    SDL_AudioDeviceID dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE);

    if (!dev) {
        SDL_Quit();
        return 1;
    }


    std::cout << "[SDL] Desired - frequency: " << have.freq
        << ", format: f " << SDL_AUDIO_ISFLOAT(have.format) << " s " << SDL_AUDIO_ISSIGNED(have.format) << " be " << SDL_AUDIO_ISBIGENDIAN(have.format) << " sz " << SDL_AUDIO_BITSIZE(have.format)
        << ", channels: " << (int)have.channels << ", samples: " << have.samples << std::endl;

    audio_frequency = sine_freq / have.freq;

    SDL_PauseAudioDevice(dev, 0);
    SDL_Delay(10000);

    SDL_CloseAudioDevice(dev);
    SDL_Quit();

    return 0;
}

这很好用;然而,当我运行这个程序时,我注意到调用回调时有一个非常轻微但可察觉的“无声打嗝”。我猜测,由于只有在缓冲区本身用完数据时才会调用回调,因此沉默是重新填充缓冲区所需的轻微延迟。

我想摆脱这种“无声的打嗝”。我的用例是这样的:我接收音频数据流(来自其他地方);我想同时用这些数据填充此 SDL 音频缓冲区,同时允许 SDL 消耗该缓冲区。然而,我似乎无法访问实际的流/缓冲区,除非它在回调中,但到那时,缓冲区已经用完了数据。

有更优雅的解决方案吗?如果可能的话,我宁愿不使用 SDL_mixer。

c++ sdl sdl-2
1个回答
0
投票

但是,我似乎无法访问实际的流/缓冲区,除非它在回调中

这就是

SDL_QueueAudio
功能的作用,你可以接管缓冲区上传时间。

© www.soinside.com 2019 - 2024. All rights reserved.