首页 > 解决方案 > 从 SDL2 音频回调函数调用 Chicken Scheme 函数挂起

问题描述

我正在尝试将 Chicken Scheme 嵌入到 C 程序中,以生成要使用 SDL2 的音频系统播放的声音。我本来想使用sdl2 egg,但它似乎还不支持音频(尽管文档中提到了'audio该函数的标志init!)。

起初,我使用C 中的SDL_QueueAudio,将我在 C 中分配的缓冲区传递给它,然后填充到 Scheme。这很好用,将 a 传递给Scheme,Sint16 *然后size_t使用pointer-s16-set!from Scheme 填充它并返回 asize_t以记录填充了多少单元格。

然后,当我意识到使用回调 api生成音频更适合于此时,我尝试切换到它(之前已经在 C 中使用过它),只是为了永远不会输入 Scheme 函数。在调用 Scheme 之前在回调函数中记录某些内容,但直接在 Scheme 函数中或在 Scheme 调用之后记录,从未发生过。

我只能想象这是由于 SDL2 的音频回调在单独的线程上运行,并且以某种方式调用 Scheme 搞砸了。考虑到这一点,我尝试CHICKEN_run(C_toplevel);在第一次调用回调函数时从回调函数中调用,但这只会导致总线错误。

所以我的问题是:有没有办法从 SDL2 的音频回调中调用嵌入式鸡方案?

我在 macOS 10.13.6 High Sierra 上,安装了 SDL2 和 chicken,并通过 Homebrew 更新。

我编译(正如我所说,这在使用队列音频 api 时工作正常):

csc code.c codescm.scm -embedded -o code -L -lSDL2

我的简化代码如下:

#include <chicken.h>
#include "SDL2/SDL.h"

extern size_t fill_sound_buffer(Sint16 *buffer, size_t buffer_length);

void fill_sound_callback(void *user_data, Uint8 *stream, int stream_length)
{
    // Logging here prints to the console
    fill_sound_buffer((Sint16 *)stream, stream_length / 2);
    // Logging here does not print to the console
}

void play(void)
{
    SDL_AudioSpec audio_want;
    SDL_zero(audio_want);
    audio_want.freq = 44100;
    audio_want.format = AUDIO_S16SYS;
    audio_want.channels = 1;
    audio_want.samples = 2048;
    audio_want.callback = fill_sound_callback;

    SDL_AudioSpec audio_have;
    SDL_AudioDeviceID audio_device = SDL_OpenAudioDevice(NULL, 0, &audio_want, &audio_have, 0);

    SDL_PauseAudioDevice(audio_device, 0);
    SDL_Delay(5000);
    // Logging here shows up after 5 seconds, but the program then continues to wait
    SDL_CloseAudioDevice(audio_device);
}

int main(int argc, char *argv[])
{
    SDL_Init(SDL_INIT_AUDIO);
    CHICKEN_run(C_toplevel);
    play();
    SDL_Quit();
    return 0;
}
(import (chicken format)
        (chicken foreign)
        (chicken memory)
        (chicken platform))

(define-external (fill_sound_buffer ((c-pointer short) buffer) (size_t buffer_length)) size_t
 ; This never prints when using the callback api
 (printf "In Scheme~%")
 ; Removed the code that calculates a sine wave and fills the buffer with it, which works
 0)

(return-to-host)

标签: caudioschemesdl-2chicken-scheme

解决方案


推荐阅读