2012-06-02 3 views
0

C#에서 SNES SPC 파일과 FMOD를 재생해야하는 DLL이있는 이유는 무엇입니까? system.createSound에 대한 호출이 실패하는 이유는 무엇입니까?사용자가 만든 스트림으로 FMOD CreateSound

FMOD.MODE mode = (FMOD.MODE._2D | FMOD.MODE.DEFAULT 
       | FMOD.MODE.OPENUSER | FMOD.MODE.LOOP_NORMAL 
       | FMOD.MODE.HARDWARE); 
//snip 
createsoundexinfo.cbsize   = Marshal.SizeOf(createsoundexinfo); 
createsoundexinfo.fileoffset  = 0; 
createsoundexinfo.length   = frequency * channels * 2 * 2; 
createsoundexinfo.numchannels  = (int)channels; 
createsoundexinfo.defaultfrequency = (int)frequency; 
createsoundexinfo.format   = FMOD.SOUND_FORMAT.PCM16; 
createsoundexinfo.pcmreadcallback = pcmreadcallback; 
createsoundexinfo.pcmsetposcallback = pcmsetposcallback; 
createsoundexinfo.dlsname   = null; 
//snop 
result = system.createSound(
    (string)null, 
    (mode | FMOD.MODE.CREATESTREAM), 
    ref createsoundexinfo, 
    ref sound); 

길이, 주파수 ... 중요하지 않습니다

var ret = system.init(32, FMOD.INITFLAGS.NORMAL, (IntPtr)null); 
var soundEx = new FMOD.CREATESOUNDEXINFO() 
{ 
    cbsize = Marshal.SizeOf(soundEx), 
    fileoffset = 0, 
    length = ~0U, 
    numchannels = 2, 
    defaultfrequency = 32000, 
    format = FMOD.SOUND_FORMAT.PCM16, 
    pcmreadcallback = pcmreadcallback, 
    pcmsetposcallback = pcmsetposcallback, 
    dlsname = null, 
}; 
var mode = FMOD.MODE.DEFAULT | FMOD.MODE.OPENUSER 
     | FMOD.MODE.LOOP_NORMAL | FMOD.MODE.CREATESTREAM; 
ret = system.createSound((string)null, mode, ref soundEx, ref sound); 
//^-- ERR_INVALID_PARAM 
ret = system.playSound(FMOD.CHANNELINDEX.FREE, sound, false, ref channel); 

는 FMOD와 함께 제공되는 usercreatedsound 샘플 것을 비교.

편집 : SPC 플레이어가 작동하는 것을 이미 확인했습니다. 적어도 초기화가 진행되면 FMOD와 함께 제공된 샘플이 올바르게 빌드되고 실행됩니다. 특히 의미있는 변경 사항은 설정을 실행하기 위해 설정을 왜곡하지 않고 4.0 스타일로 작성하는 것입니다.

답변

1

모든 사운드 카드에서 임의의 샘플링 속도를 재생할 수있는 것은 아닙니다. 32Khz는 44.1, 48, 96 등의 '일반적인'속도가 아닙니다.

  • FMOD.MODE.SOFTWARE를 시도 했습니까?
  • ASIO4ALL을 사용하여 중재 샘플 속도를 사용할 수는 있지만 ASIO로 전환해야합니다.

FMOD에 묶여 있습니까? 그렇지 않다면 BASS.NET을 고려해보십시오. 그런 것들을하기 위해 FMOD보다 훨씬 더 많은 조정을 할 수 있습니다. (최신 저음 VS2010에서 작품)

using System; 
using Un4seen.Bass; 
using Un4seen.Bass.AddOn.Mix; 

namespace XXX 
{ 
    public class Resampler : IDisposable 
    { 
     private readonly int _channels; 
     private readonly string _filename; 
     private readonly int _samplerate; 

     public Resampler(string filename, int samplerate, int channels) 
     { 
      if (filename == null) throw new ArgumentNullException("filename"); 
      if (samplerate <= 0) throw new ArgumentNullException("samplerate"); 
      if (channels <= 0) throw new ArgumentNullException("channels"); 

      #region Initialize BASS stuff 

      #endregion 

      _filename = filename; 
      _samplerate = samplerate; 
      _channels = channels; 
     } 

     #region IDisposable Members 

     public void Dispose() 
     { 
      throw new NotImplementedException(); 
     } 

     #endregion 

     public void Resample(string filename) 
     { 
      if (filename == null) throw new ArgumentNullException("filename"); 
      Exceptions.ThrowIfPathInvalid(filename); 

      #region Create stream and mixer 

      int channel = Bass.BASS_StreamCreateFile(filename, 0, 0, 
                BASSFlag.BASS_STREAM_PRESCAN | BASSFlag.BASS_STREAM_DECODE | 
                BASSFlag.BASS_SAMPLE_FLOAT); 
      if (channel == 0) 
       throw new BassException("Couldn't create stream."); 

      var mixer = BassMix.BASS_Mixer_StreamCreate(22050, 1, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); 
      if (mixer == 0) 
       throw new BassException("Couldn't create mixer stream."); 

      if (!BassMix.BASS_Mixer_StreamAddChannel(mixer, channel, 
                BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_MIXER_FILTER | 
                BASSFlag.BASS_MIXER_NORAMPIN)) 
       throw new BassException("Couldn't add stream channel to mixer."); 

      #endregion 

      int sr = 22050; 
      int secs = 20; 
      int samples0 = sr * secs; 
      var buffer = new float[samples0]; 
      int length = sizeof(float) * buffer.Length; 
      var getData = Bass.BASS_ChannelGetData(mixer, buffer, length | (int)BASSData.BASS_DATA_FLOAT); 
      if (getData != length) 
      { 
       throw new BassException(""); 
      } 
      var bassMixerChannelRemove = BassMix.BASS_Mixer_ChannelRemove(channel); 
      var streamFree = Bass.BASS_StreamFree(channel); 
      var bassStreamFree = Bass.BASS_StreamFree(mixer); 
     } 
    } 
} 

아래 발언

일부 추가 힌트를 참조하십시오 :

  • 먼저 BASS.Bass_Init를 호출해야합니다 BASSMix를 사용하는

    예 ,

  • py bass.dll 및 bassmix.dll (EXE 옆)

  • 소스가 아니더라도 개인적으로 BASS_SAMPLE_FLOAT에 충실 하겠지만 가장 큰 이점은이 형식으로 클리핑되지 않는다는 것입니다. APU의 출력이 꽤 동적 인 NES emu 용 오디오 래퍼를 만들었 기 때문에 이것은 도움이되는 것으로 입증되었습니다. 또한 이것은 물건을 더 간단하고 최상의 품질로 유지합니다. 귀하의 경우에는

  • 당신이 푸시 스트림을 사용하고 SNES의 출력을 먹이고 싶은 것 :

  • 가 '표준'믹서 스트림 (안 디코딩을 만들기 BASS_StreamCreatePush을베이스를 .. :: ..), 푸시 스트림을 연결하고 믹서를 재생하십시오. 예를 들어, 데이터를 처리하고 다시 재생하지 않아야하므로 디코딩 스트림입니다.

  • BassException

  • 당신의 가장 친한 친구는 CHM 도움말 파일뿐만 아니라, 자신의 포럼이 될 것입니다 원하는대로로 변경, 나 자신을 만든 뭔가입니다.

  • 이 코드로 뭔가를 시작한 다음 문제가 있으면 새 코드를 게시하는 것이 좋습니다.

나는 BASS가 처음에는 이해하기가 어렵지만 결국에는 매우 보람이라고 말해야 만한다. OpenGL 3.X를 배울 때 나는 정확히 같은 감정을 가지고있었습니다. 그것은 처음에는 이해할 수 없었지만 지금은 많은 일을 할 수 있습니다. 나는 BASS가 3D와 함께 OpenGL과 동등하다고 말한다.

미안하지만 지난번 이후로 아주 아팠지만 PC를 거의 사용하지는 않았지만 귀하의 메시지를 보았고 신속하게 대응할 수 있기를 바랍니다. 누군가가 내 대답의 레이아웃에 대해 SO에게 불평해야합니까? 나중에 해결할 것입니다.

+0

소프트웨어 모드 및/또는 44.1Khz로 변경되지 않았습니다. 이제 BASS.NET을 조금 쳐다 보겠습니다. – Kawa

+0

기본적으로 BassMix addon이 필요합니다. 44.1Khz 믹서를 만든 다음 32Khz 소스를 추가하십시오. 마침내 당신은 그 믹서를 연주합니다. 그것에 대해 도움이 필요하면 그냥 물어보십시오. – Aybe

+0

작동시킬 샘플을 얻을 수 없습니다. ( – Kawa