2017-02-15 2 views
1

J'utilise SpeechSynthesizer de .Net pour générer un flux WAV à partir d'une chaîne. J'ai alors besoin de convertir ce flux de WaveStream à Opus.Conversion de flux WAV en Opus en utilisant NAudio

J'utilise les bibliothèques suivantes:

Je synthétisant le discours en utilisant cette fonction:

public static Stream Speak(string text) 
{ 
    SpeechSynthesizer s = new SpeechSynthesizer(); 
    MemoryStream stream = new MemoryStream(); 
    s.SetOutputToWaveStream(stream); 
    s.Speak(text); 
    s.SetOutputToNull(); 
    return stream; 
} 

Et Afin de faire la conversion, j'utilise la fonction suivante:

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; 
} 

Mon problème est que le OpusEncoder lance une exception en disant:

encodage a échoué - BadArg

et il est jeté sur l'appel de fonction à la "opus_encode". Quelqu'un peut-il m'aider à suivre le problème?

Edit 1:

Après avoir regardé autour, je trouve que l'exception levée est en fait une définition dans l'API de l'Opus appelé: "OPUS_BAD_ARG", sur lequel les états de documentation:

Un ou plusieurs invalides/arguments hors de portée.

Je ne peux pas trouver l'argument qui ne va pas ...

Répondre

2

Il est très probablement la longueur d'entrée. 1. N'oubliez pas que la longueur d'entrée est un nombre d'échantillons de 16 bits par canal, où votre code ne fait que passer le nombre d'octets. Diviser par (2 * numChannels) 2. La longueur d'entrée doit être une taille d'image Opus valide (2,5, 5, 10, 20, 60ms, 20 est la valeur par défaut). Vous devez donc passer un nombre fixe d'échantillons à plusieurs reprises pour la durée de votre entrée. Dans le cas de 16khz mono, cette taille est de 320.