0

C# で SNES SPC ファイルと FMOD を再生するはずの DLL がある場合、この呼び出しがsystem.createSound失敗するのはなぜですか?

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);

usercreatedsoundFMOD に付属のサンプルと比較してください。

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);

長さ、頻度...関係ありません。

編集: 少なくとも初期化が行われる限り、SPC プレーヤーが機能すること、および FMOD に付属のサンプルが正常にビルドおよび実行されることを確認済みです。実行するために設定をいじることを除けば、唯一の特に意味のある変更は、4.0 スタイルで記述したことです。

4

1 に答える 1

1

任意のサンプルレートの再生は、必ずしもすべてのサウンドカードで利用できるわけではありません。32Khzは、44.1、48、96などの「一般的な」レートではありません...

  • FMOD.MODE.SOFTWAREを試しましたか?
  • ASIO4ALLを使用して任意のサンプルレートを使用できる場合がありますが、ASIOに切り替える必要があります。

あなたはFMODに縛られていますか?そうでない場合は、BASS.NETを検討してください。そうすれば、FMODよりもはるかに多くの制御が可能になります。

BASSMixの使用例:以下の注釈を参照してください

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);
        }
    }
}

(最新の低音でVS2010で動作します)

いくつかの追加のヒント:

  • 最初にBASS.Bass_Initを呼び出す必要があります。

  • EXEの横にbass.dllとbassmix.dllをコピーすることを忘れないでください。

  • 私は個人的にBASS_SAMPLE_FLOATに固執しますが、ソースはそうではありません。最大の利点は、この形式ではクリッピングが発生しないことです。これは、APUの出力が非常に優れているNESemuのオーディオラッパーを作成したためです。動的」、それは役立つことが証明されました。また、それは物事をよりシンプルに、そして可能な限り最高の品質に保ちます。

  • あなたの場合、プッシュストリームを使用してSNES出力でフィードしたいと思うでしょう:Bass .. :: .. BASS_StreamCreatePush

  • 「標準」ミキサーストリーム(デコードストリームではない)を作成し、プッシュストリームを接続し、ミキサーを再生します

  • この例では、データを再生するのではなく処理する必要があるため、デコードストリームです。

  • BassExceptionは私が自分で作成したものです。好きなように変更してください

  • あなたの親友はCHMヘルプファイルだけでなく彼らのフォーラムにもなります。

  • このコードから始めて、問題が発生した場合は新しいコードを投稿することをお勧めします。

BASSは最初は把握するのが非常に難しいですが、最終的には非常にやりがいがあります。最近、OpenGL 3.Xを学んだとき、まったく同じ気持ちになりました。最初は理解できませんでしたが、今ではたくさんのことができるようになりました。BASSは3Dと同じようにOpenGLと同等だと思います。

申し訳ありませんが、前回からかなり具合が悪く、パソコンをほとんど使っていませんでしたが、あなたのメッセージを見て、早く対応したいと思いました。誰かが私の答えのレイアウトについてSOから不平を言った場合:後で修正します。

于 2012-06-02T15:43:43.217 に答える