2016-06-07 16 views
0

Ich verwende C# in Universal Windows App, um einen Watson Speech-to-Text-Dienst zu schreiben. Für den Moment, anstatt den Watson-Dienst zu verwenden, schreibe ich in die Datei und lese es dann in Audacity, um zu bestätigen, dass es im richtigen Format ist, da der Watson-Dienst die richtigen Antworten nicht an mich zurücksendet, und das folgende erklärt warum.Audiokodierung Konvertierungsprobleme mit PCM 32-Bit-PCM 16-Bit

Aus irgendeinem Grund, wenn ich 16-Bit-PCM-Codierungseigenschaften erstellen und Puffer lesen, kann ich nur Daten als 32-Bit-PCM lesen, und es funktioniert gut, aber wenn ich es in 16-Bit-PCM lesen ist in Zeitlupe, und die ganze Sprache ist im Grunde korrupt.

Ich weiß nicht wirklich, was genau getan werden muss, von 32-Bit auf 16-Bit zu konvertieren, aber hier ist es, was ich in meiner C# Anwendung habe:

//Creating PCM Encoding properties 
var pcmEncoding = AudioEncodingProperties.CreatePcm(16000, 1, 16); 
var result = await AudioGraph.CreateAsync(
    new AudioGraphSettings(AudioRenderCategory.Speech) 
    { 
     DesiredRenderDeviceAudioProcessing = AudioProcessing.Raw, 
     AudioRenderCategory = AudioRenderCategory.Speech, 
     EncodingProperties = pcmEncoding 
    } 
); 
graph = result.Graph; 

//Initialize microphone 
var microphone = await DeviceInformation.CreateFromIdAsync(MediaDevice.GetDefaultAudioCaptureId(AudioDeviceRole.Default)); 
var micInputResult = await graph.CreateDeviceInputNodeAsync(MediaCategory.Speech, pcmEncoding, microphone); 

//Create frame output node 
frameOutputNode = graph.CreateFrameOutputNode(pcmEncoding); 

//Callback function to fire when buffer is filled with data 
graph.QuantumProcessed += (s, a) => ProcessFrameOutput(frameOutputNode.GetFrame()); 
frameOutputNode.Start(); 

//Make the microphone write into the frame node 
micInputResult.DeviceInputNode.AddOutgoingConnection(frameOutputNode); 
micInputResult.DeviceInputNode.Start(); 

graph.Start(); 

Initialisierungsschritt auf dies geschehen ist Bühne. Jetzt funktioniert das Lesen aus dem Puffer und das Schreiben in die Datei nur, wenn ich 32-Bit-PCM-Codierung mit der folgenden Funktion verwende (auskommentiert ist der PCM-16-Bit-Code, der zu einer Zeitlupen-Sprachausgabe führt):

private void ProcessFrameOutput(AudioFrame frame) 
{ 
    //Making a copy of the audio frame buffer 
    var audioBuffer = frame.LockBuffer(AudioBufferAccessMode.Read); 
    var buffer = Windows.Storage.Streams.Buffer.CreateCopyFromMemoryBuffer(audioBuffer); 
    buffer.Length = audioBuffer.Length; 

    using (var dataReader = DataReader.FromBuffer(buffer)) 
    { 
     dataReader.ByteOrder = ByteOrder.LittleEndian; 

     byte[] byteData = new byte[buffer.Length]; 
     int pos = 0; 

     while (dataReader.UnconsumedBufferLength > 0) 
     { 
      /*Reading Float -> Int 32*/ 
      /*With this code I can import raw wav file into the Audacity 
       using Signed 32-bit PCM Encoding, and it is working well*/ 
      var singleTmp = dataReader.ReadSingle(); 
      var int32Tmp = (Int32)(singleTmp * Int32.MaxValue); 
      byte[] chunkBytes = BitConverter.GetBytes(int32Tmp); 
      byteData[pos++] = chunkBytes[0]; 
      byteData[pos++] = chunkBytes[1]; 
      byteData[pos++] = chunkBytes[2]; 
      byteData[pos++] = chunkBytes[3]; 

      /*Reading Float -> Int 16 (Slow Motion)*/ 
      /*With this code I can import raw wav file into the Audacity 
       using Signed 16-bit PCM Encoding, but when I play it, it's in 
       a slow motion*/ 
      //var singleTmp = dataReader.ReadSingle(); 
      //var int16Tmp = (Int16)(singleTmp * Int16.MaxValue); 
      //byte[] chunkBytes = BitConverter.GetBytes(int16Tmp); 
      //byteData[pos++] = chunkBytes[0]; 
      //byteData[pos++] = chunkBytes[1]; 
     } 

     WriteBytesToFile(byteData); 
    } 
} 

Kann jemand an einen Grund denken, warum dies geschieht? Liegt es daran, dass Int32 PCM größer ist und wenn ich Int16 verwende, verlängert es es und macht den Sound länger? Oder nehme ich es nicht richtig auf?

Hinweis: Ich habe versucht, Bytes direkt aus dem Puffer zu lesen, und dann als Rohdaten zu verwenden, aber es ist nicht als PCM auf diese Weise codiert. Das direkte Lesen von Int16/32 aus dem Puffer funktioniert auch nicht. Im obigen Beispiel verwende ich nur den Frame-Ausgangsknoten. Wenn ich einen Dateiausgabeknoten erstelle, der automatisch in die Raw-Datei schreibt, funktioniert er wirklich gut als 16-Bit-PCM, also stimmt etwas in meiner Callback-Funktion nicht, was bewirkt, dass es sich in einer langsamen Bewegung befindet.

Dank

+1

Für die Zukunft zu überprüfen, wenn Sie eine beschädigte Rohdaten Probe zur Verfügung stellen würde, wäre Ihre Probleme leichter zu lösen. –

Antwort

1
//Creating PCM Encoding properties 
var pcmEncoding = AudioEncodingProperties.CreatePcm(16000, 1, 16); 
var result = await AudioGraph.CreateAsync(
    new AudioGraphSettings(AudioRenderCategory.Speech) 
    { 
     DesiredRenderDeviceAudioProcessing = AudioProcessing.Raw, 
     AudioRenderCategory = AudioRenderCategory.Speech, 
     EncodingProperties = pcmEncoding 
    } 
); 
graph = result.Graph; 

pcmEncoding viel Sinn hier nicht machen, da nur Codierung Float wird durch AudioGraph unterstützt.

 byte[] byteData = new byte[buffer.Length]; 

sollte es sein buffer.Length/2, da Sie von Float-Daten mit 4 Byte pro Probe zu int16 Daten mit 2 Bytes pro Probe konvertieren

 /*Reading Float -> Int 16 (Slow Motion)*/ 
     /*With this code I can import raw wav file into the Audacity 
      using Signed 16-bit PCM Encoding, but when I play it, it's in 
      a slow motion*/ 
     var singleTmp = dataReader.ReadSingle(); 
     var int16Tmp = (Int16)(singleTmp * Int16.MaxValue); 
     byte[] chunkBytes = BitConverter.GetBytes(int16Tmp); 
     byteData[pos++] = chunkBytes[0]; 
     byteData[pos++] = chunkBytes[1]; 

Diese richtigen Code ist, sollte es funktionieren. Ihre "Zeitlupe" bezieht sich höchstwahrscheinlich auf die Puffergröße, die Sie zuvor falsch eingestellt haben.

Ich muss zugeben, Microsoft jemand braucht, um ihre aufgeblähten APIs

+0

Vielen Dank für Ihren Kommentar. Ich mache die Konvertierung auf die gleiche Weise unter meinem Int32-Code. Entschuldigung, es ist nur auskommentiert, um zu zeigen, dass es in Zeitlupe war. Update 1: Ich beschleunigte die Audio-Datei 2x, und es klingt nicht wie die ursprüngliche Stimme - es sieht aus wie es einige Audio-Chunks darin fehlt. –

+1

Ich aktualisierte die Antwort –

+0

Ich verbrachte 2 Tage mit dem Versuch, dies herauszufinden, und einfach Hinzufügen von "/ 2" machte alles funktioniert. Ich habe es gerade mit Watson-Service getestet und funktioniert wie ein Zauber. Danke vielmals! –