C#を使用してストリームからオーディオを再生する
質問
C#で System.IO.Stream は、たとえば、データを一時的にディスクに保存せずにWebRequestから復元されましたか?
NAudio のソリューション
NAudio 1.3を使用すると、次のことが可能になります。
- MP3ファイルをURLからMemoryStreamに読み込む
- MP3データを完全に読み込んだ後、waveデータに変換します
- NAudio のWaveOutクラス を使用して、Waveデータを再生します
半分ロードされたMP3ファイルを再生することさえできれば良かったのですが、これは NAudio ライブラリデザイン。
そして、これは仕事をする関数です:
public static void PlayMp3FromUrl(string url)
{
using (Stream ms = new MemoryStream())
{
using (Stream stream = WebRequest.Create(url)
.GetResponse().GetResponseStream())
{
byte[] buffer = new byte[32768];
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
}
ms.Position = 0;
using (WaveStream blockAlignedStream =
new BlockAlignReductionStream(
WaveFormatConversionStream.CreatePcmStream(
new Mp3FileReader(ms))))
{
using (WaveOut waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()))
{
waveOut.Init(blockAlignedStream);
waveOut.Play();
while (waveOut.PlaybackState == PlaybackState.Playing )
{
System.Threading.Thread.Sleep(100);
}
}
}
}
}
解決
編集:最新バージョンのNAudioの変更を反映するように更新された回答
NAudio オープンソースの.NETオーディオライブラリを使用して作成できます。変換を行うためにPCでACMコーデックを探します。 NAudioで提供されるMp3FileReaderは、現在、ソースストリーム内で再配置できることを想定しているため(MP3フレームのインデックスを前もって作成します)、ネットワーク経由のストリーミングには適していません。ただし、NAudioの MP3Frame
および AcmMp3FrameDecompressor
クラスを使用して、ストリーミングMP3をその場で解凍できます。
ブログに NAudioを使用してMP3ストリームを再生する方法。基本的に、MP3フレームをダウンロードして解凍し、 BufferedWaveProvider
に保存する1つのスレッドがあります。次に、別のスレッドが BufferedWaveProvider
を入力として使用して再生します。
他のヒント
SoundPlayer クラスでこれを実行できます。あなたがしなければならないのは、その Stream プロパティをストリームに設定し、 Play
を呼び出すことだけです。
編集
ただし、MP3ファイルを再生できるとは思わない。 .wavに限定されているようです。フレームワークにMP3ファイルを直接再生できるものがあるかどうかはわかりません。私が見つけたすべてのことには、WMPコントロールの使用またはDirectXとの対話が含まれます。
Bass はこれを行うことができます。メモリ内のByte []から再生するか、データを返すファイルデリゲートを使用して、再生を開始するのに十分なデータがあればすぐに再生できます。
トピックスターターソースを少し変更したため、完全にロードされていないファイルを再生できるようになりました。ここにあります(これは単なるサンプルであり、開始点であることに注意してください。ここでいくつかの例外とエラー処理を行う必要があります):
private Stream ms = new MemoryStream();
public void PlayMp3FromUrl(string url)
{
new Thread(delegate(object o)
{
var response = WebRequest.Create(url).GetResponse();
using (var stream = response.GetResponseStream())
{
byte[] buffer = new byte[65536]; // 64KB chunks
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
var pos = ms.Position;
ms.Position = ms.Length;
ms.Write(buffer, 0, read);
ms.Position = pos;
}
}
}).Start();
// Pre-buffering some data to allow NAudio to start playing
while (ms.Length < 65536*10)
Thread.Sleep(1000);
ms.Position = 0;
using (WaveStream blockAlignedStream = new BlockAlignReductionStream(WaveFormatConversionStream.CreatePcmStream(new Mp3FileReader(ms))))
{
using (WaveOut waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()))
{
waveOut.Init(blockAlignedStream);
waveOut.Play();
while (waveOut.PlaybackState == PlaybackState.Playing)
{
System.Threading.Thread.Sleep(100);
}
}
}
}
NAudioはWaveOutXXXX APIをラップします。私はソースを見ていませんが、NAudioが各呼び出しで自動的に再生を停止しない方法でwaveOutWrite()関数を公開する場合、あなたは本当にやりたいことができるはずです、それは再生を開始することですすべてのデータを受信する前のオーディオストリーム。
waveOutWrite()関数を使用すると、「先読み」ができます。オーディオの小さなチャンクを出力キューにダンプします-Windowsは自動的にチャンクをシームレスに再生します。コードは、圧縮されたオーディオストリームを取得し、その場でWAVオーディオの小さな塊に変換する必要があります。この部分は本当に難しいでしょう。これまで見たすべてのライブラリとコンポーネントは、一度にファイル全体をMP3からWAVに変換します。おそらくあなたの唯一の現実的なチャンスは、マルチメディアSDKの周りに簡単なC#ラッパーを書くことができるため、MP3ではなくWMAを使用してこれを行うことです。
質問に投稿されたソースを微調整して、GoogleのTTS APIで使用できるようにし、質問に回答するこちら:
bool waiting = false;
AutoResetEvent stop = new AutoResetEvent(false);
public void PlayMp3FromUrl(string url, int timeout)
{
using (Stream ms = new MemoryStream())
{
using (Stream stream = WebRequest.Create(url)
.GetResponse().GetResponseStream())
{
byte[] buffer = new byte[32768];
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
}
ms.Position = 0;
using (WaveStream blockAlignedStream =
new BlockAlignReductionStream(
WaveFormatConversionStream.CreatePcmStream(
new Mp3FileReader(ms))))
{
using (WaveOut waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()))
{
waveOut.Init(blockAlignedStream);
waveOut.PlaybackStopped += (sender, e) =>
{
waveOut.Stop();
};
waveOut.Play();
waiting = true;
stop.WaitOne(timeout);
waiting = false;
}
}
}
}
次で起動:
var playThread = new Thread(timeout => PlayMp3FromUrl("http://translate.google.com/translate_tts?q=" + HttpUtility.UrlEncode(relatedLabel.Text), (int)timeout));
playThread.IsBackground = true;
playThread.Start(10000);
次で終了:
if (waiting)
stop.Set();
上記のコードで ParameterizedThreadDelegate
を使用しており、スレッドが playThread.Start(10000);
で開始されていることに注意してください。 10000は、再生されるオーディオの最大10秒を表すため、ストリームの再生に時間がかかる場合は微調整する必要があります。 NAudioの現在のバージョン(v1.5.4.0)には、ストリームの再生がいつ完了するかを決定する際に問題があると思われるため、これが必要です。それは後のバージョンで修正されるか、おそらく私が見つけるのに時間をかけなかった回避策があるかもしれません。
非商用での使用は無料であり、うまく機能するので、私はいつもこのようなものにFMODを使用しています。
そうは言っても、もっと小さく(FMODは約300k)、オープンソースのものに喜んで切り替えます。 .exeでコンパイル/マージでき、他のプラットフォームへの移植性を得るために特別な注意を払う必要がないように、完全に管理されている場合のスーパーボーナスポイント...
(FMODも移植性を実現しますが、プラットフォームごとに異なるバイナリが必要になることは明らかです)
WebRequestからは試していませんが、 Windows Media Player < href = "http://en.wikipedia.org/wiki/ActiveX" rel = "nofollow noreferrer"> ActiveX およびMediaElement( WPF )コンポーネントは、MP3ストリームを再生およびバッファリングできます。
SHOUTcast ストリームからのデータを再生するために使用し、うまく機能しました。ただし、提案されたシナリオで機能するかどうかはわかりません。