سؤال

هل هناك طريقة في C# لتشغيل الصوت (على سبيل المثال ، MP3) direcly من النظام.IO.تيار هذا على سبيل المثال كان returend من WebRequest دون حفظ البيانات مؤقتا إلى القرص ؟


الحل مع NAudio

مع مساعدة من NAudio 1.3 فمن الممكن أن:

  1. تحميل ملف MP3 من رابط في MemoryStream
  2. تحويل MP3 البيانات إلى موجه البيانات بعد أن تم تحميلها بالكامل
  3. تشغيل موجه البيانات باستخدام NAudio's WaveOut الدرجة

كان من الجميل أن تكون قادرة على أن تلعب حتى النصف تحميل ملف 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 مفتوحة المصدر .صافي المكتبة الصوتية كنت قد كتبت.يبدو على ACM الترميز على جهاز الكمبيوتر الخاص بك للقيام التحويل.على Mp3FileReader الموردة مع NAudio حاليا يتوقع أن تكون قادرة على إعادة داخل مصدر تيار (فإنه يبني مؤشر MP3 إطارات الجبهة) ، لذلك فإنه ليس من المناسب للبث عبر الشبكة.ومع ذلك ، لا يزال بإمكانك استخدام MP3Frame و AcmMp3FrameDecompressor دروس في NAudio لضغط المتدفقة MP3 على الطاير.

كنت قد نشرت مقالا في مدونتي شرح كيفية تشغيل MP3 تيار باستخدام NAudio.أساسا لديك موضوع واحد تحميل MP3 الإطارات ، ضغطها وتخزينها في BufferedWaveProvider.موضوع آخر ثم يلعب مرة أخرى باستخدام BufferedWaveProvider كمدخل.

نصائح أخرى

على SoundPlayer فئة يمكن أن تفعل هذا.يبدو أن كل ما عليك القيام به هو تعيين تيار مكان الإقامة إلى تيار ، ثم اتصل Play.

تحرير
أنا لا أعتقد أنه يمكن تشغيل ملفات MP3 على الرغم ؛ يبدو محدودا .wav.لست متأكدا إذا كان هناك أي شيء في الإطار الذي يمكن أن تلعبه ملف MP3 مباشرة.كل ما وجدت عن ذلك ينطوي إما باستخدام ومب التحكم أو التفاعل مع DirectX.

باس أن تفعل هذا فقط.اللعب من 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 تحويل كامل ملف في وقت واحد.ربما فرصة واقعية هو أن تفعل هذا باستخدام WMA بدلا من MP3, لأنه يمكنك كتابة بسيطة C# مغلفة حول الوسائط المتعددة SDK.

لقد أنب مصدر شارك في السؤال للسماح للاستخدام مع جوجل تحويل النص إلى كلام 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) يبدو أن لديك مشكلة في تحديد متى تيار ويتم اللعب.قد تكون ثابتة في إصدار لاحق أو ربما هناك حلا لم تأخذ من الوقت للعثور على.

أنا ملفوفة MP3 مكتبة فك وجعلها متاحة .صافي المطورين mpg123.net.

وشملت العينات لتحويل ملفات MP3 إلى PCM, و قراءة ID3 العلامات.

لقد استعملت دائما FMOD على مثل هذه الامور لانها مجانية للاستخدام غير التجاري و يعمل بشكل جيد.

وقال أود بكل سرور التبديل إلى شيء أصغر (FMOD هو ~300k) و مفتوحة المصدر.سوبر نقاط المكافأة إذا كانت مدارة بالكامل حتى استطيع تجميع / دمج ذلك مع بلدي .exe وليس من الضروري أن تأخذ الرعاية الإضافية للحصول على قابلية إلى منصات أخرى...

(FMOD لا قابلية جدا ولكن سوف تحتاج من الواضح ثنائيات مختلفة على منصات مختلفة)

أنا لم أجربها من WebRequest ، ولكن كل ويندوز ميديا بلاير ActiveX و MediaElement (من WPF) مكونات قادرون على اللعب التخزين المؤقت MP3 تيارات.

إلى البيانات القادمة من شوتكاست تيار وعملت كبيرة.ومع ذلك أنا لست متأكدا مما إذا كان سوف يعمل في السيناريو تقترح.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top