我正在撰写一个简单的方案,通过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。