コンテンツパイプラインなしでXNAにサウンドをロードする


7

私は、ユーザーがゲームで使用する独自のアセットをインポートするWindows用の「ゲームメーカー」タイプのアプリケーションに取り組んでいます。実行時にエンジン側でこのコンテンツをロードできるようにする必要があります。

ただし、ユーザーがXNAランタイム以外のものをインストールする必要がないので、実行時にコンテンツパイプラインを呼び出すことはできません。

画像の場合、Texture2D.FromStreamを使用して問題ありません。

また、XNA 4.0 は、SoundEffectクラスにFromStreamメソッドを追加しましたが、PCMウェーブファイルしか受け入れないことにも気付きました。

でも、少なくともMP3では、waveファイル以上のものをサポートしたいと思っています。

何かお勧めですか?おそらく、PCMウェーブフォーマットへのデコードを行うC#ライブラリがいくつかあります。


XNAランタイム自体には、サウンドエフェクト用にMP3をデコードする方法がないことは注目に値します。XNA Game Studioは、コンテンツのビルド時にPCM(非圧縮)または圧縮形式(MP3ではありませんが、現在の形式を正確に忘れています)への変換を処理します。(一方、音楽はMP3を再生できるメディアプレーヤーに渡されます。)
Andrew Russell

回答:


3

FromStreamメソッドに気づかなかったので、覚えておいてください。FromStreamとDynamicSoundEffectInstanceを使用することに興味があります。理論的には、両方のメソッドで多くの同じ作業を実行できるからです。

Googleがこのライブラリを作成しました: http //robburke.net/mle/mp3sharp/また、アプリ内からlame.exeを呼び出してサウンドをデコードすることもできます。

しかし、MP3には注意が必要ですが、それはワームの合法的な缶です。アドビは、Flashで使用する権利についてフラウンホーファーに多額の料金を支払います。Ogg Vorbisは優れたフォーマットであり、無料のオープンソースソフトウェアを使用してmp3から簡単に変換できます。また、C#/。Netデコーダーライブラリがもっとたくさんあるようです。


ありがとう!私はMP3を使用することの法的意味合いを漠然と認識していましたが、それによって問題は解決しました。それらのライブラリーを実際にMP3からOGGにデコードできるかどうか(ユーザーがアセットをインポートするときに行われます)、次にOGGからPCMに(ランタイム/ロード時に)試せるようにします。結果を報告します。
David Gouveia

oggライブラリはできませんが、lameでデコードしてからOgg Vorbisに変換できます。LAMEは含めず、Audacityと同じようにしてください。「mp3デコーダーが必要です。どこで入手するかは問題ではありません。入手場所はわかっているかもしれませんが、入手するのはあなたの責任です」。免責事項:私は弁護士ではありません。
michael.bartnett

私は、SoundEffect.FromStreamがPCMウェーブファイル(ヘッダーを含む)および非常に特定の形式を想定していることに気づきました。上記のライブラリの1つを使用してOGGファイルをデコードしましたが、例外をスローせずにFromStreamでそれを受け入れることができないようです。代わりにFMODなどの外部Sound APIを使用する必要があるのか​​と思い始めています。
David Gouveia

Windows PhoneまたはXBLIGをターゲットにすることを気にしない場合は、その価値があるかもしれません。また、DynamicSoundEffectInstanceを試してみると、サンプルが少なくなるたびにサンプルを要求するイベントがスローされるだけです。
michael.bartnett 2011

1
私は実際に、DynamicSoundEffectInstanceを使用して他の何か(thisthisなど)を作成したことがあります。:)ただし、サンプルを非常に特殊な形式(インターリーブされた16ビットサンプル)で送信する必要もあります。これは、デコードされたOGGストリームの形式かどうかはわかりません。Windowsサポートのみが必要なため、FMODルートを使用しました。FMODを使用して私のソリューションを1分後に投稿します。
David Gouveia

7

今日、この問題をもう一度試すことにし、最終的に実行時にOGGファイルをSoundEffectオブジェクトにロードすることに成功しました。これが私がしたことです!まず、OGGファイルをデコードできるクラスを含む以下のライブラリをダウンロードします。

前提条件-ライブラリのダウンロード

ライブラリにはすでにサンプルがDynamicSoundEffectInstanceありますが、オーディオを使用してストリーミングします。しかし、それを通常のSoundEffectオブジェクトに一度にロードしたかったので、プロセスは少し異なりました。

ステップ1-ファイルをデコードする

最初にのインスタンスを作成OggDecoderし、ファイルで初期化します。

decoder = new OggDecoder();
decoder.Initialize(TitleContainer.OpenStream(@"sound.ogg"));

ステップ2-デコードされたデータを取得する

すべてのデータをバッファに読み込みます。これは、ファイルのデコードされた生PCMデータです。

byte[] data = decoder.SelectMany(chunk => chunk.Bytes.Take(chunk.Length)).ToArray();

手順3-完全なWaveファイルヘッダーを含むストリームからSoundEffectを作成する

ただし、そのストリーム SoundEffect必要なは、生データだけでなく、完全なWaveファイルヘッダーも含まれ必要があります。このヘルパーメソッドを使用して、ヘッダーとデータを書き込むことができます。

private static void WriteWave(BinaryWriter writer, int channels, int rate, byte[] data)
{
    writer.Write(new char[4] { 'R', 'I', 'F', 'F' });
    writer.Write((int)(36 + data.Length));
    writer.Write(new char[4] { 'W', 'A', 'V', 'E' });

    writer.Write(new char[4] { 'f', 'm', 't', ' ' });
    writer.Write((int)16);
    writer.Write((short)1);
    writer.Write((short)channels);
    writer.Write((int)rate);
    writer.Write((int)(rate * ((16 * channels) / 8)));
    writer.Write((short)((16 * channels) / 8));
    writer.Write((short)16);

    writer.Write(new char[4] { 'd', 'a', 't', 'a' });
    writer.Write((int)data.Length);
    writer.Write(data);
}

そのメソッドを使用して、データをフィード可能なストリームに書き込みます。 SoundEffect.FromStream

using (MemoryStream stream = new MemoryStream())
using(BinaryWriter writer = new BinaryWriter(stream))
{
    WriteWave(writer, decoder.Stereo ? 2 : 1, decoder.SampleRate, data);
    stream.Position = 0;
    soundEffect = SoundEffect.FromStream(stream);
}

ステップ4-通常どおりSoundEffectを使用する

OGGファイルがSoundEffect読み込まれ、コンテンツパイプラインを通じて読み込まれた他のファイルと同じように使用できます。

soundEffect.Play();

パーフェクト!サイトの例は正しく動作しません。3分30秒で1つの曲を試しましたが、ファイル全体が再生されません。しかし、あなたの解決策は完璧に機能しました!元の例よりもロードは遅くなりますが、許容できます。
エミールリマ14

oggsharpリンクは、非推奨であり、代わりに「NVorbisを使用する」と言っています。誰かがそれを試しましたか?また、それを機能させるために必要な「使用法」(参照)を明示的にリストするとよいでしょう。
DrZ214 2015年

@EmirLimaは、リンクと同じバージョンのoggsharpを使用したかどうかを確認できますか?それとも新しいNVorbisバージョンだったのですか?
DrZ214 2015年

@ DrZ214同じバージョンのサイトを使用しました。しかし、David Gouveiaのソリューションは非常にうまく機能します(OggをデコードしてSoundEffectをインスタンス化します)。
エミールリマ2015年

@EmirLimaそうだね。まさに私も欲しいものだ。SoundEffectには.ogg音楽ファイルがロードされている。どこでOggSharp dllを入手しましたか?oggsharp.codeplex.comでは、見つけることができる唯一のダウンロードボタンは.exeの例を含むzipファイルを提供し、
dllは提供し

2

Windowsのみを対象にしている場合、最も簡単な方法は、XNA Audio APIを完全にバイパスして、別のものを使用することです。

FMOD APIがこれに最適であることがわかりました。これには、C#ラッパーが既にバンドルされています。私は彼らの周りに自分のラッパーを追加しました、そしてここにあなたがファイルからサウンドをロードしてそれを再生するために必要な最低限のものがあります:

ラッパー:

namespace YourNamespace
{
    using System;
    using FMOD;

    public class SoundSystem
    {
        public SoundSystem()
        {
            RESULT result = Factory.System_Create(ref _system);
            if(result != RESULT.OK) 
                throw new Exception("Create SoundSystem Failed");

            uint version = 0;
            result = System.getVersion(ref version);
            if (result != RESULT.OK || version < VERSION.number)
                throw new Exception("Create SoundSystem Failed");

            result = System.init(32, INITFLAGS.NORMAL, (IntPtr)null);
            if (result != RESULT.OK)
                throw new Exception("Create SoundSystem Failed");
        }

        public System System 
        {
            get { return _system; }
        }

        private readonly System _system;
    }

    public class Sound
    {
        public Sound(SoundSystem system, string path)
        {
            _system = system;
            RESULT result = system.System.createSound(path, MODE.HARDWARE, ref _sound);
            if (result != RESULT.OK)
                throw new Exception("Create Sound Failed");
        }

        public void Play()
        {
            Channel channel = null;
            RESULT result = _system.System.playSound(CHANNELINDEX.FREE, _sound, false, ref channel);
            if (result != RESULT.OK)
                throw new Exception("Play Sound Failed");
        }

        private readonly SoundSystem _system;
        private readonly FMOD.Sound _sound;
    }
}

そしてそれを使用する方法:

SoundSystem system = new SoundSystem();
Sound sound = new Sound(system, "song.mp3");
sound.Play();

もちろん、そのラッパーは最低限のものですが、必要な他の機能を公開するために簡単に拡張できるはずです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.