我在Universal Windows App中使用C#来编写Watson语音到文本服务。 现在,不是使用Watson服务,而是写入文件,然后在Audacity中读取它以确认它的格式正确,因为Watson服务没有向我返回正确的响应,以下内容解释了原因。
出于某种原因,当我创建16位PCM编码属性和读取缓冲区时,我只能将数据读取为32位PCM,并且它运行良好,但如果我在16位PCM中读取它,那么慢动作,所有的讲话基本上都是腐败的。
我真的不知道从32位转换到16位究竟需要做些什么,但这就是我在C#应用程序中所拥有的:
//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();
初始化步骤在此阶段完成。现在,实际上从缓冲区读取并写入文件只有在我使用具有以下功能的32位PCM编码时才会起作用(注释掉是导致慢动作语音输出的PCM 16位代码):
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);
}
}
有谁能想到这种情况发生的原因?是因为Int32 PCM的尺寸更大,当我使用Int16时,它会扩展它并使声音更长?或者我没有正确抽样?
注意:我尝试直接从缓冲区读取字节,然后将其用作原始数据,但它不是以这种方式编码为PCM。 直接从缓冲区读取Int16 / 32也不起作用。 在上面的例子中,我只使用Frame Output节点。如果我创建一个自动写入原始文件的文件输出节点,它可以很好地用作16位PCM,因此我的回调函数出现问题导致它处于慢速运动状态。
由于
答案 0 :(得分:2)
//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在这里没有多大意义,因为AudioGraph只支持Float编码。
byte[] byteData = new byte[buffer.Length];
它应该是buffer.Length / 2
,因为你从每个样本4个字节的浮点数据转换为每个样本2个字节的int16数据
/*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];
这是正确的代码,它应该工作。您的“慢动作”很可能与之前错误设置的缓冲区大小有关。
我必须承认微软需要有人来审核其膨胀的API