2012-02-18 8 views
0

Tao.Sdlで音を鳴らすための短いコードがあります。 LinuxとMac(Monoを使用)ではうまく動作しますが、Monoや.NETを使用してWindows7,64ビットでクラッシュします。ここでは、コードです:Tao.Sdl Windowsでオーディオクラッシュが発生する

using System; 
using System.Runtime.InteropServices; 
using Tao.Sdl; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     delegate void AudioSpecCallbackDelegate(IntPtr userData, IntPtr stream, int length); 
     static Sdl.SDL_AudioSpec desired; 
     static IntPtr specPtr; 
     static IntPtr obtained; 

     static void Main(string[] args) 
     { 
      Sdl.SDL_Init(Sdl.SDL_INIT_AUDIO); 
      desired = new Sdl.SDL_AudioSpec(); 
      desired.freq = 22050; 
      desired.format = (short)Sdl.AUDIO_S16LSB; 
      desired.channels = 1; 
      desired.samples = (short)1000; //(short)2205; 
      desired.callback = Marshal.GetFunctionPointerForDelegate((AudioSpecCallbackDelegate)DoCallback); 
      desired.userdata = null; 
      specPtr = Marshal.AllocHGlobal(Marshal.SizeOf(desired)); 
      Marshal.StructureToPtr(desired, specPtr, false); 
      obtained = IntPtr.Zero; 
      if (Sdl.SDL_OpenAudio((IntPtr)specPtr, (IntPtr)obtained) < 0) 
      { 
       Console.WriteLine("Error opening sdl_audio (1)"); 
       Console.WriteLine(Sdl.SDL_GetError()); 
      } 
      Sdl.SDL_PauseAudio(0); 
      Sdl.SDL_Delay(1000); 
      Sdl.SDL_PauseAudio(1); 
     } 

     public static void DoCallback(IntPtr userData, IntPtr stream, int len) 
     { 
      Console.WriteLine("{0}, ", len); 
      byte[] buffer = new byte[len]; 
      for (int i = 0; i < len; i++) 
       buffer[i] = 0; 
      Marshal.Copy(buffer, 0, stream, len); 
     } 
    } 
} 

それはWindows上で、それがコールバックを呼び出すためにしようとする第二の時間をクラッシュします。私が明らかに間違っている何かを見ることができますか?おそらく、私はfreqの正しい値、あるいはおそらくWindowsのフォーマットの問題を持っていませんか?

また、低レベルのコードをデバッグする方法がわかりません... Visual StudioまたはMonoDevelopでクラッシュするだけです。または、別のシステムを使用してこのコードを再実行することについての提案がある場合。目標:Mac、Windows、およびLinux上のC#でサウンドシステムを通じて再生されるバイトを処理できるようにする。

+0

どのような種類のクラッシュですか?それは 'NullReferenceException'なのでしょうか? – user1071136

+0

トレースはまったくありません...「Windowsがクラッシュしました」と表示されます。 –

答えて

1

SdlDotNetにコードを書き直しましたが、ウィンドウが存在する必要がある別のバグがありました。小さなウィンドウを作成し、ストリームを開いた後に閉じます。 LinuxとWindows7では以下のように動作します。 Macでテストする必要があります。私は上記のバグが何かを発見したことはありませんでした...おそらくそれはウィンドウの必要性に関連しています。以下には、トーンを生成するための実際のコードもあります。私はこれを行うには、SDLのかなりバグの例を見てきました。

public class AudioManager : IDisposable { 
    const int playbackFreq = 44100; 
    const int samples = 2048; 
    const double pi2 = 360 * Math.PI/180.0; 
    private bool disposed = false; 
    private bool initialized = false; 
    SdlDotNet.Audio.AudioStream stream; 
    byte[] buffer8; 

    double time = 0; 
    double volume; 
    double frequency1 = -1; 
    double frequency2 = -1; 
    SdlDotNet.Audio.AudioCallback audioCallback = new SdlDotNet.Audio.AudioCallback(Callback) 

    public AudioManager() 
    { 
     stream = new SdlDotNet.Audio.AudioStream(playbackFreq, 
          SdlDotNet.Audio.AudioFormat.Unsigned8, 
          SdlDotNet.Audio.SoundChannel.Mono, 
          samples, 
          audioCallback, 
          null); 
     buffer8 = new byte[samples]; 
     volume = 1.0; 

     // BUG: OpenAudio (or lower) apparently requires a visible screen for some reason: 
     SdlDotNet.Graphics.Video.SetVideoMode(1, 1); 
     SdlDotNet.Audio.Mixer.OpenAudio(stream); 
     // BUG: close (or hide) it 
     SdlDotNet.Graphics.Video.Close(); 
    } 

    public void beep(double duration, double freq) { 
     frequency1 = freq; 
     frequency2 = -1; 
     Tao.Sdl.Sdl.SDL_PauseAudio(0); 
     Tao.Sdl.Sdl.SDL_Delay((int)(duration * 1000)); 
     Tao.Sdl.Sdl.SDL_PauseAudio(1); 
    } 

    void Callback(IntPtr userData, IntPtr stream, int len) 
    { 
     double slice = 1.0/playbackFreq * pi2; 
     for (int buf_pos = 0; buf_pos < len; buf_pos++) 
     { 
      buffer8[buf_pos] = (byte)(127 + Math.Cos(time) * volume * 127); 
      time += frequency1 * slice; 
      if (time > pi2) 
       time -= pi2; 
     } 
     Marshal.Copy(buffer8, 0, stream, len); 
    } 
関連する問題