2011-11-25 49 views
0

我一直試圖找出現在幾個小時。如何使用Vala/SDL初始化音頻

爲了啓動音頻,我需要創建一個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(); 
           ^^^^^^^^^^^^^^^^^^^ 

如果我嘗試只值分配給它的成員乏就像一個結構(它在一個struct正常SDL)我得到:

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

我在這裏找到了華劣克DOC: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 

所以我有點另一個粘滯點。

3rd post:EUREKA!我有一個解決方案! (值得商榷: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; 

啊,終於我美麗的白色噪音發生器完成了!

回答

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。

+0

這對於編譯它非常有用!我仍然無法讓聲音打開,但我認爲這可能與沒有回調指針的枚舉有關。在原始sdl中: typedef struct ... void(* callback)(void * userdata,Uint8 * stream,int len); 我會看看我是否可以找到一種方法將其添加到sdl.vapi中。 – ioev

0

好吧,委託:

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

具有C類型:

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

,其中用戶數據和數據流是隻寫的,這是不是真的,你想要什麼。

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告訴瓦拉沒有用戶數據和我們手動包括它。至於結構:

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

因此,用戶數據會得到傳遞給你的回調,但你必須給自己投它,你就會有管理的內存。另外,當結構超出範圍時,Vala將調用一個銷燬函數。通過指定一個空字符串,它將不會執行任何操作。通常情況下,這會釋放結構中的內存,但我們不需要擔心。

+0

謝謝你的所有信息!我實際上已經做了一些研究,並提出了一個解決方案,編譯並給了我一些噪音。這很可能是內存泄漏或某些東西(我的解決方案),但現在我並不擔心這一點。再次感謝您的全力幫助,我從未想過這件事! – ioev