0

几个小时以来,我一直试图弄清楚这一点。

为了启动音频,我需要创建一个 SDL.AudioSpec 对象并将其传递给 SDL.Audio.Open。问题是,AudioSpec 是一个带有私有构造函数的类,所以当我尝试创建一个时,我得到:

sdl.vala:18.25-18.43: error: `SDL.AudioSpec' does not have a default constructor
        AudioSpec audiospec = new SDL.AudioSpec();
                              ^^^^^^^^^^^^^^^^^^^

如果我尝试像结构一样为其成员变量分配值(它是普通 sdl 中的结构),我得到:

sdl.vala:20.3-20.25: error: use of possibly unassigned local variable `audiospec'
        audiospec.freq = 22050;
        ^^^^^^^^^^^^^^^^^^^^^^^

我在这里找到了 valac 文档:http://valadoc.org/sdl/SDL.AudioSpec.html 它根本没有多大帮助。

有问题的代码块如下所示:

// setup the audio configuration
AudioSpec audiospec;
AudioSpec specback;
audiospec.freq = 22050;
audiospec.format = SDL.AudioFormat.S16LSB;
audiospec.channels = 2;
audiospec.samples = 512;

// try to initialize sound with these values
if (SDL.Audio.open(audiospec, specback) < 0)
{
    stdout.printf("ERROR! Check audio settings!\n");
    return 1;
}

任何帮助将不胜感激!

另一个更新,因为我仍然遇到一些麻烦。我已经更改了 vapi 文件,这就是我现在所拥有的:

public delegate void AudioCallback (out void* userdata, out uchar stream, int len);

[CCode (cname="SDL_AudioSpec")]
[Compact]
public struct AudioSpec {
    public int freq;
    public AudioFormat format;
    public uchar channels;
    public uchar silence;
    public uint16 samples;
    public uint16 padding;
    public uint32 size;
    public AudioCallback callback;
    public void* userdata;
}// AudioSpec

我有一个方法(尝试?)来满足这个函数签名:

public void callback(out void* userdata, out uchar stream, int len)
{
    stream = 0;
    userdata = null;
}

并将其分配为:

    audiospec.callback = gen.callback;

不用说,这仍然不起作用,得到很多错误:

/home/gukid/vala/soundgen.vala.c: In function ‘sound_gen_main’:
/home/gukid/vala/soundgen.vala.c:766:12: error: ‘SDL_AudioSpec’ has no member named ‘callback_target_destroy_notify’
/home/gukid/vala/soundgen.vala.c:766:72: error: ‘SDL_AudioSpec’ has no member named ‘callback_target_destroy_notify’
/home/gukid/vala/soundgen.vala.c:766:114: error: ‘SDL_AudioSpec’ has no member named ‘callback_target’
/home/gukid/vala/soundgen.vala.c:768:11: error: ‘SDL_AudioSpec’ has no member named ‘callback_target’
/home/gukid/vala/soundgen.vala.c:769:11: error: ‘SDL_AudioSpec’ has no member named ‘callback_target_destroy_notify’
/home/gukid/vala/soundgen.vala.c:770:21: warning: assignment from incompatible pointer type [enabled by default]
/home/gukid/vala/soundgen.vala.c:771:11: error: ‘SDL_AudioSpec’ has no member named ‘callback_target’
/home/gukid/vala/soundgen.vala.c:772:11: error: ‘SDL_AudioSpec’ has no member named ‘callback_target_destroy_notify’
error: cc exited with status 256

所以我又有点棘手。

第三个帖子:尤里卡!我有办法!(有争议:P)

首先,sdl.vapi 看起来像:

[CCode (cheader_filename = "SDL.h")]
public delegate void AudioCallback (void* userdata, uchar* stream, int len);

[CCode (cname="SDL_AudioSpec", has_type_id=false)]
public struct AudioSpec {
    public int freq;
    public AudioFormat format;
    public uchar channels;
    public uchar silence;
    public uint16 samples;
    public uint16 padding;
    public uint32 size;
    [CCode (delegate_target = false, type = "void*")]
    public weak AudioCallback callback;
    public void* userdata;
}// AudioSpec

然后我可以创建一个函数:

public static void callback(void* userdata, uchar* stream, int len)

和:

audiospec.callback = callback;

啊,终于我漂亮的白噪声发生器完成了!

4

2 回答 2

0

我认为这是 VAPI 中的错误。在 sdl.vapi 中,尝试更改

[Compact]
public class AudioSpec {

public struct AudioSpec {

[CCode (cname="SDL_OpenAudio")]
public static int open(AudioSpec desired, AudioSpec obtained);

[CCode (cname="SDL_OpenAudio")]
public static int open(AudioSpec desired, out AudioSpec obtained);

并使您的代码看起来像:

AudioSpec audiospec = AudioSpec();
AudioSpec specback;
audiospec.freq = 22050;
audiospec.format = SDL.AudioFormat.S16LSB;
audiospec.channels = 2;
audiospec.samples = 512;

// try to initialize sound with these values
if (SDL.Audio.open(audiospec, out specback) < 0)
{
    stdout.printf("ERROR! Check audio settings!\n");
    return 1;
}

并给它一个测试。它似乎根据 SDL 文档生成了正确的代码。如果可行,请考虑将 VAPI 更改提交到 Vala bugzilla。

于 2011-11-25T17:44:58.283 回答
0

好的,代表:

public delegate void AudioCallback (out void* userdata, out uchar stream, int len);

具有 C 类型:

void(*AudioCallback)(void**userdata, unsigned char* stream, int len);

其中 userdata 和 stream 是只写的,这并不是您真正想要的。

void (*callback)(void *userdata, Uint8 *stream, int len);

在此,userdata只是指向一些供您使用的东西的指针。用 Vala 的话来说,它是代表的目标。stream是一个数组,但 SDL 已经分配了它,所以它不是outlen是数组的长度,所以我们可以让 Vala 自动处理它uint8[] stream。把它们放在一起:

[CCode(instance_pos = 0)]
public delegate void AudioCallback(uint8[] stream);

instance_pos告诉 Vala 用户数据在哪里。它通常假定它是最后一个。至于结构:

[CCode (cname="SDL_AudioSpec", destroy_function = "")]
public struct AudioSpec {
  ...
  [CCode(delegate_target_cname = "userdata")]
  public AudioCallback callback;
}

这将创建一个回调,将目标存储在userdata. 现在,为了避免内存泄漏,Vala 将尝试为callback_target_destroy_notify...分配一个析构函数,现在我们被卡住了,因为我们没有成员。所以,让我们备份并重试:

[CCode(has_target = false)]
public delegate void AudioCallback(void* userdata, uint8[] stream);

has_target告诉 Vala 没有用户数据,我们手动包含它。至于结构:

[CCode (cname="SDL_AudioSpec", destroy_function = "")]
public struct AudioSpec {
  ...
  public AudioCallback callback;
  public void* userdata;
}

因此,用户数据将被传递给您的回调,但您必须自己转换它并且您必须管理内存。此外,当结构超出范围时,Vala 将调用销毁函数。通过指定一个空字符串,它什么也不做。通常,这会释放结构内部的内存,但我们不必担心。

于 2011-11-25T22:46:31.577 回答