2012-02-18 3 views
0

Tao.Sdl을 통해 음색을 재생하는 짧은 코드가 있습니다. 그것은 리눅스와 맥 (모노를 사용)에서 잘 작동하지만, 윈도우 7, 모노 또는. NET에서 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); 
     } 
    } 
} 

두 번째로 콜백을 호출 할 때 충돌합니다. 내가 분명히 잘못하고있는 것을 볼 수 있니? 아마도 저는 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); 
    } 
관련 문제