使用 NAudio 将 WAV 流转换为 Opus
Converting WAV Stream to Opus using NAudio
我正在使用 .Net 的 SpeechSynthesizer 从字符串生成 WAV 流。然后我需要将该流从 WaveStream 转换为 Opus。
我正在使用以下库:
- NAudio
- Opus .Net:https://github.com/JohnACarruthers/Opus.NET
我正在使用这个函数合成语音:
public static Stream Speak(string text)
{
SpeechSynthesizer s = new SpeechSynthesizer();
MemoryStream stream = new MemoryStream();
s.SetOutputToWaveStream(stream);
s.Speak(text);
s.SetOutputToNull();
return stream;
}
为了进行转换,我使用了以下函数:
public static Stream SpeakOgg(string text)
{
MemoryStream orgstream = Speak(text) as MemoryStream;
orgstream.Seek(0, SeekOrigin.Begin);
WaveFileReader reader = new WaveFileReader(orgstream);
WaveFormat newFormat = new WaveFormat(16000, reader.WaveFormat.Channels);
WaveFormatConversionStream newStream = new WaveFormatConversionStream(newFormat, reader);
WaveStream conv = WaveFormatConversionStream.CreatePcmStream(newStream);
byte[] bytes = new byte[conv.Length];
conv.Position = 0;
conv.Read(bytes, 0, (int)conv.Length);
OpusEncoder encoder = OpusEncoder.Create(newStream.WaveFormat.SampleRate, newStream.WaveFormat.Channels, Opus.Application.Voip);
int encodedLength = 0;
byte[] encoded = encoder.Encode(bytes, (int)conv.Length, out encodedLength);
MemoryStream finish = new MemoryStream();
finish.Write(encoded, 0, encodedLength);
return finish;
}
我的问题是 OpusEncoder 抛出异常:
Encoding failed - BadArg
并在对 "opus_encode" 的函数调用中抛出。
谁能帮我追踪问题?
编辑 1:
环顾四周后,我发现抛出的异常实际上是 Opus 的 API 中的一个定义,名为:"OPUS_BAD_ARG",文档中指出:
One or more invalid/out of range arguments.
我还是找不到错误的论点...
很可能是输入长度。
1. 请记住,输入长度是每个通道 16 位样本的计数,您的代码只是传递字节数。除以 (2 * numChannels)
2. 输入长度必须是有效的 Opus 帧大小(默认为 2.5、5、10、20、60ms,20)。因此,您需要根据输入的长度一遍又一遍地传递固定数量的样本。在 16khz 单声道的情况下 framesize 是 320.
我正在使用 .Net 的 SpeechSynthesizer 从字符串生成 WAV 流。然后我需要将该流从 WaveStream 转换为 Opus。
我正在使用以下库:
- NAudio
- Opus .Net:https://github.com/JohnACarruthers/Opus.NET
我正在使用这个函数合成语音:
public static Stream Speak(string text)
{
SpeechSynthesizer s = new SpeechSynthesizer();
MemoryStream stream = new MemoryStream();
s.SetOutputToWaveStream(stream);
s.Speak(text);
s.SetOutputToNull();
return stream;
}
为了进行转换,我使用了以下函数:
public static Stream SpeakOgg(string text)
{
MemoryStream orgstream = Speak(text) as MemoryStream;
orgstream.Seek(0, SeekOrigin.Begin);
WaveFileReader reader = new WaveFileReader(orgstream);
WaveFormat newFormat = new WaveFormat(16000, reader.WaveFormat.Channels);
WaveFormatConversionStream newStream = new WaveFormatConversionStream(newFormat, reader);
WaveStream conv = WaveFormatConversionStream.CreatePcmStream(newStream);
byte[] bytes = new byte[conv.Length];
conv.Position = 0;
conv.Read(bytes, 0, (int)conv.Length);
OpusEncoder encoder = OpusEncoder.Create(newStream.WaveFormat.SampleRate, newStream.WaveFormat.Channels, Opus.Application.Voip);
int encodedLength = 0;
byte[] encoded = encoder.Encode(bytes, (int)conv.Length, out encodedLength);
MemoryStream finish = new MemoryStream();
finish.Write(encoded, 0, encodedLength);
return finish;
}
我的问题是 OpusEncoder 抛出异常:
Encoding failed - BadArg
并在对 "opus_encode" 的函数调用中抛出。 谁能帮我追踪问题?
编辑 1:
环顾四周后,我发现抛出的异常实际上是 Opus 的 API 中的一个定义,名为:"OPUS_BAD_ARG",文档中指出:
One or more invalid/out of range arguments.
我还是找不到错误的论点...
很可能是输入长度。 1. 请记住,输入长度是每个通道 16 位样本的计数,您的代码只是传递字节数。除以 (2 * numChannels) 2. 输入长度必须是有效的 Opus 帧大小(默认为 2.5、5、10、20、60ms,20)。因此,您需要根据输入的长度一遍又一遍地传递固定数量的样本。在 16khz 单声道的情况下 framesize 是 320.