2017-12-23 11 views
0

요청시 웨이브 파일을 생성하기 위해 SpeechSynthesizer를 사용하지만 필자는 지직 거리는 소리에 문제가 있습니다. 이상한 일은 사운드 카드에 직접 출력하는 것이 좋습니다.파일 및 스트림으로 출력 할 때 Microsoft SpeechSynthesizer가 깨집니다.

이 짧은 powershell 스크립트는 C#으로 프로그램을 작성하고 있지만이 문제를 보여줍니다. 이 어떻게해야

Add-Type -AssemblyName System.Speech 
$speech = New-Object System.Speech.Synthesis.SpeechSynthesizer 
$speech.Speak('Guybrush Threepwood, mighty pirate!') 
$speech.SetOutputToWaveFile("${PSScriptRoot}\foo.wav") 
$speech.Speak('Guybrush Threepwood, mighty pirate!') 

는 스피커로 출력하고 다음 스크립트에 "foo.wav"로 같은 소리를 저장합니다.

소리가 스피커로 출력 된 다음 낡은 녹음기 사운드 버전이 웨이브 파일로 저장됩니다. 세 가지 다른 컴퓨터에서 이것을 테스트 해 보았습니다. 기본적으로 서로 다른 음성을 선택했는데 (모두 Microsoft에서 기본 음성을 제공했습니다) 웨이브 파일의 계단에서 쓰레기가 떨어지는 것처럼 들립니다.

왜?

편집 : Windows 10 Pro에서 작업 표시 줄의 성가신 "사람"버튼을 추가하는 최신 업데이트를 테스트하고 있습니다.

편집 2 : Here's a link to an example sound generated with the above script. Notice the crackling voice, that's not there when the script outputs directly to the speakers.

편집 3 : It's even more noticeable with a female voice

EDIT 4 : The same voice as above, saved to file with TextAloud 3 - no cracking, no vertical spikes.

+2

재생할 수 없습니다. 결과를 파일에 저장하거나 음성을 바로 재생하더라도 상관 없습니다. – vonPryz

+0

wav 파일을 어딘가에 업로드 하시겠습니까? 내가 사용한 사이트는 매우 간단하며 등록이 필요하지 않습니다. 단순히 사운드 카드 나 WAV 파일 재생 설정이라면 wav 파일이 내 것과 동일해야합니다. 또는 내 웨이브를 딱딱 거리는 소리가 들리니? – bolt

+1

https://instaud.io/1zsv에서 foo.wav 파일을 공유했다고 생각합니다 – lit

답변

0

이것은 SpeechSynthesizer API의 문제입니다. SpeechSynthesizer API는 위의 샘플에서 볼 수 있듯이 품질이 좋지 않고 딱딱 거리는 오디오를 제공하기 만합니다. 솔루션은 SpeechLib COM 개체를 직접 사용하는 TextAloud의 기능을 수행하는 것입니다.

"Microsoft Speech Object Library (5.4)"에 COM 참조를 추가하면됩니다.

public new static byte[] GetSound(Order o) 
{ 
    const SpeechVoiceSpeakFlags speechFlags = SpeechVoiceSpeakFlags.SVSFlagsAsync; 
    var synth = new SpVoice(); 
    var wave = new SpMemoryStream(); 
    var voices = synth.GetVoices(); 
    try 
    { 
     // synth setup 
     synth.Volume = Math.Max(1, Math.Min(100, o.Volume ?? 100)); 
     synth.Rate = Math.Max(-10, Math.Min(10, o.Rate ?? 0)); 
     foreach (SpObjectToken voice in voices) 
     { 
      if (voice.GetAttribute("Name") == o.Voice.Name) 
      { 
       synth.Voice = voice; 
      } 
     } 
     wave.Format.Type = SpeechAudioFormatType.SAFT22kHz16BitMono; 
     synth.AudioOutputStream = wave; 
     synth.Speak(o.Text, speechFlags); 
     synth.WaitUntilDone(Timeout.Infinite); 

     var waveFormat = new WaveFormat(22050, 16, 1); 
     using (var ms = new MemoryStream((byte[])wave.GetData())) 
     using (var reader = new RawSourceWaveStream(ms, waveFormat)) 
     using (var outStream = new MemoryStream()) 
     using (var writer = new WaveFileWriter(outStream, waveFormat)) 
     { 
      reader.CopyTo(writer); 
      return o.Mp3 ? ConvertToMp3(outStream) : outStream.GetBuffer(); 
     } 
    } 
    finally 
    { 
     Marshal.ReleaseComObject(voices); 
     Marshal.ReleaseComObject(wave); 
     Marshal.ReleaseComObject(synth); 
    } 
} 

이 MP3에 웨이브 파일을 변환하는 코드는 다음과 같습니다 TextAloud과 동일한 품질의 오디오 클립을 생산하고 내가 함께 결국 코드의 조각이다. Nuget의 NAudio.Lame을 사용합니다.

internal static byte[] ConvertToMp3(Stream wave) 
{ 
    wave.Position = 0; 
    using (var mp3 = new MemoryStream()) 
    using (var reader = new WaveFileReader(wave)) 
    using (var writer = new LameMP3FileWriter(mp3, reader.WaveFormat, 128)) 
    { 
     reader.CopyTo(writer); 
     mp3.Position = 0; 
     return mp3.ToArray(); 
    } 
} 
1

나는 힘든이 포쉬 문제가 믿고 찾을 수 있습니다. PoSH가 디스크 직렬화에 대한 인코딩을 수행하지 않습니다. 사용중인 API/클래스. 은 MSDN 당으로

'msdn.microsoft.com/en-us/library/system.speech.synthesis.speechsynthesizer(v=vs.110).aspx'

는을 제어하는 ​​옵션이 없습니다 인코딩, 비트 전송률 등.

.wav는 본사 본 적이 없습니다. 그래서, 만약 당신이 품질 문제를 해결한다면 .mp3 또는 mp4로 만들기 위해 변환기를 통해 .wav를 가져 가는지 궁금합니다. 그러나 이것은 또한 사용자 시스템에서 변환기를 가져 오는 것을 의미합니다.

두 번째로, Win8부터 기본 플레이어는 .wav를 올바르게 재생하거나 전혀 재생하지 않습니다. 물론 여전히 .wav의 기본 재생을 Windows Media Player로 설정하거나 VLC를 통해 파일을 호출 할 수는 있지만 여전히 .wav 파일입니다. 그러나 모든 대상 시스템에서 Media Player 할당을 설정해야한다는 의미이기도합니다.

+0

C#에서도 그렇듯이 실제로는 API 문제이다. 그러나 웨이브 파일의 품질에 대해서는 틀 렸으며 API에는 [SetOutputToAudioStream 메서드] (https://msdn.microsoft.com/en-us/library/system)를 사용할 때의 품질 설정 옵션이 있습니다. speech.synthesis.speechsynthesizer.setoutputtoaudiostream (v = vs.110) .aspx). 품질에 관해서는 웨이브는 일반적으로 느린 컴퓨터에서 처리 능력의 한계로 인해 mp3로 CD 오디오를 직접 인코딩 할 수 없었던 것입니다. 품질을 떨어 뜨리지는 않습니다 (mp3에서도 마찬가지입니다). – bolt

+0

나는 그 SetOutputToAudioStream을 엉망으로 만들었고, 시도한 어떤 시도에서도 차이를 만들지 않았다. 그러므로 이전의 나의 반응. 하지만 너는 나보다 더 많은 시간을 보낸 것 같아. 그래서 나는 너의 말을 받아 들여야 해. 그러나 라이브 또는 직렬화를 사용하면 .mp3/mp4 형식에 문제가 없었습니다. – postanote

+0

각 음성은 일반적으로 그 자체로 제한되어 있으므로별로 할 수 없습니다. 예를 들어, [Ivona] (https://www.ivona.com/)의 음성은 일반적으로 22kHz 또는 더 정확하게 22050Hz입니다. 즉, 44.1kHz로 샘플링하면 모두 각 샘플은 파일에서 두 배나 큽니다. 그래도 귀를 싫어하면 샘플을 적게 실행할 수 있습니다. – bolt

관련 문제