سؤال

انا استخدم System.speech.synthesis.speechsynthesizer لتحويل النص إلى الكلام. وبسبب توثيق فقر الدم من Microsoft (انظر الرابط الخاص بي ، لا توجد ملاحظات أو أمثلة رمز) أواجه مشكلة في جعل رؤوس أو ذيول الفرق بين طريقتين:

setOutputToAudioStream و SetotutTowAvestream.

هذا ما استنتجته:

يأخذ SetOutputToAudioStream دفقًا ومثالًا لـ PoundiAudioFormatinFo يحدد تنسيق ملف الموجة (عينات في الثانية ، وتتخل في الثانية ، والقنوات الصوتية ، وما إلى ذلك) ويكتب النص إلى الدفق.

يأخذ SetOutputTowaVestream مجرد دفق ويكتب ملف موجة Mono و Mono و 22 كيلو هرتز و PCM إلى الدفق. لا توجد وسيلة لتمرير PoundiAudioformatinfo.

مشكلتي هي SetOutputToAudioStream لا تكتب ملف موجة صالح للدفق. على سبيل المثال ، أحصل على invalidoperationException ("رأس الموجة فاسد") عند تمرير الدفق إلى system.media.soundplayer. إذا كتبت الدفق إلى القرص ومحاولة تشغيله مع WMP ، أحصل على "Windows Media Player لا يمكن تشغيل الملف ..." لكن الدفق المكتوب بواسطة SetOutputTowAvestream يلعب بشكل صحيح في كليهما. نظريتي هي أن setotuttoaudioStream لا يكتب رأسًا (صالحًا).

من الغريب أن اتفاقيات التسمية لـ setotutto* blah* غير متسقة. SetOutputTowaveFile يأخذ PoundiAudioformatinfo بينما لاوتوتورتوفيستريس لا.

أحتاج إلى أن أكون قادرًا على كتابة ملف موجة مونو بحجم 8 كيلو هرتز أو 16 بت إلى دفق ، وهو ما لا يسمح لي SetOutputToAudioStream أو SetOutputTowAvestream بالقيام بذلك. هل لدى أي شخص نظرة ثاقبة على الكلام مع هاتين الطريقتين؟

للإشارة ، إليك بعض التعليمات البرمجية:

Stream ret = new MemoryStream();
using (SpeechSynthesizer synth = new SpeechSynthesizer())
{
  synth.SelectVoice(voiceName);
  synth.SetOutputToWaveStream(ret);
  //synth.SetOutputToAudioStream(ret, new SpeechAudioFormatInfo(8000, AudioBitsPerSample.Sixteen, AudioChannel.Mono));
  synth.Speak(textToSpeak);
}

المحلول:

شكرًا جزيلاً لـ @hans passant ، إليك جوهر ما أستخدمه الآن:

Stream ret = new MemoryStream();
using (SpeechSynthesizer synth = new SpeechSynthesizer())
{
  var mi = synth.GetType().GetMethod("SetOutputStream", BindingFlags.Instance | BindingFlags.NonPublic);
  var fmt = new SpeechAudioFormatInfo(8000, AudioBitsPerSample.Sixteen, AudioChannel.Mono);
  mi.Invoke(synth, new object[] { ret, fmt, true, true });
  synth.SelectVoice(voiceName);
  synth.Speak(textToSpeak);
}
return ret;

للاختبار الخشن الخاص بي ، يعمل بشكل رائع ، على الرغم من أن استخدام الانعكاس أمر أفضل قليلاً من كتابة الملف إلى القرص وفتح دفق.

هل كانت مفيدة؟

المحلول

قصاصة الكود الخاصة بك مغمورة ، فأنت تستخدم موالفة بعد التخلص منه. لكن هذه ليست المشكلة الحقيقية أنا متأكد. تنتج SetOutputToAudioStream صوت PCM الخام ، "الأرقام". بدون تنسيق ملف حاوية (رؤوس) مثل ما هو مستخدم في ملف .wav. نعم ، لا يمكن لعب ذلك مع برنامج وسائط عادية.

إن التحميل الزائد المفقود لـ SetotutTowAvestream الذي يأخذ خطابًا chebioformatinfo أمر غريب. يبدو الأمر وكأنه إشراف بالنسبة لي ، على الرغم من أن هذا أمر نادر للغاية في إطار .NET. لا يوجد سبب مقنع لعدم عمله ، فإن واجهة SAPI الأساسية تدعمها. يمكن اختراقه مع انعكاس للاتصال بالطريقة الخاصة بـ SetOutputStream. لقد عمل هذا بشكل جيد عندما اختبرته ولكن لا يمكنني أن أؤكد ذلك:

using System.Reflection;
...
            using (Stream ret = new MemoryStream())
            using (SpeechSynthesizer synth = new SpeechSynthesizer()) {
                var mi = synth.GetType().GetMethod("SetOutputStream", BindingFlags.Instance | BindingFlags.NonPublic);
                var fmt = new SpeechAudioFormatInfo(8000, AudioBitsPerSample.Eight, AudioChannel.Mono);
                mi.Invoke(synth, new object[] { ret, fmt, true, true });
                synth.Speak("Greetings from stack overflow");
                // Testing code:
                using (var fs = new FileStream(@"c:\temp\test.wav", FileMode.Create, FileAccess.Write, FileShare.None)) {
                    ret.Position = 0;
                    byte[] buffer = new byte[4096];
                    for (;;) {
                        int len = ret.Read(buffer, 0, buffer.Length);
                        if (len == 0) break;
                        fs.Write(buffer, 0, len);
                    }
                }
            }

إذا كنت غير مرتاح للاختراق ، فاستخدم Path.getTempFilename () لدفقه مؤقتًا إلى ملف بالتأكيد.

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