从 Wav 文件中获取 AudioData 的第一种流行方式。
感谢 PI 用户的回答How to read the data in a wav file to an array,我已经解决了 UWP 项目中浮点数组中 wav 文件读取的问题。但是当它使用 AudioGraph 记录在 wav 文件中时,文件的结构不同于标准的结构(也许,只有在我的项目中存在这样的问题)。它导致不可预测的结果。我们收到 value1263424842 而不是可预测的 544501094 获取格式 ID。之后,以下所有值都显示不正确。我在字节中顺序搜索找到了正确的 id。我意识到 AudioGraph 在录制的 wav 文件中添加了额外的数据块,但录制的格式仍然是 PCM。这个额外的数据块看起来像关于文件格式的数据,但它也包含空值、空字节。我找不到任何相关信息,也许这里有人知道?PI 的解决方案我已经根据我的需要进行了更改。这就是我所拥有的:
using (FileStream fs = File.Open(filename, FileMode.Open))
{
BinaryReader reader = new BinaryReader(fs);
int chunkID = reader.ReadInt32();
int fileSize = reader.ReadInt32();
int riffType = reader.ReadInt32();
int fmtID;
long _position = reader.BaseStream.Position;
while (_position != reader.BaseStream.Length-1)
{
reader.BaseStream.Position = _position;
int _fmtId = reader.ReadInt32();
if (_fmtId == 544501094) {
fmtID = _fmtId;
break;
}
_position++;
}
int fmtSize = reader.ReadInt32();
int fmtCode = reader.ReadInt16();
int channels = reader.ReadInt16();
int sampleRate = reader.ReadInt32();
int byteRate = reader.ReadInt32();
int fmtBlockAlign = reader.ReadInt16();
int bitDepth = reader.ReadInt16();
int fmtExtraSize;
if (fmtSize == 18)
{
fmtExtraSize = reader.ReadInt16();
reader.ReadBytes(fmtExtraSize);
}
int dataID = reader.ReadInt32();
int dataSize = reader.ReadInt32();
byte[] byteArray = reader.ReadBytes(dataSize);
int bytesForSamp = bitDepth / 8;
int samps = dataSize / bytesForSamp;
float[] asFloat = null;
switch (bitDepth)
{
case 16:
Int16[] asInt16 = new Int16[samps];
Buffer.BlockCopy(byteArray, 0, asInt16, 0, dataSize);
IEnumerable<float> tempInt16 =
from i in asInt16
select i / (float)Int16.MaxValue;
asFloat = tempInt16.ToArray();
break;
default:
return false;
}
//For one channel wav audio
floatLeftBuffer.AddRange(asFloat);
从缓冲区到文件记录具有逆算法。目前,这是唯一一种用于处理 wav 文件的正确算法,它允许获取音频数据。使用这篇文章使用 AudioGraph - https://docs.microsoft.com/ru-ru/windows/uwp/audio-video-camera/audio-graphs。请注意,您可以使用从 MIC 到文件的 AudioEncodingQuality recirdung 设置记录格式的必要数据。
从 Nugget 包中使用 NAudio 获取 AudioData 的第二种方法。
我使用了 MediaFoundationReader 类。
float[] floatBuffer;
using (MediaFoundationReader media = new MediaFoundationReader(path))
{
int _byteBuffer32_length = (int)media.Length * 2;
int _floatBuffer_length = _byteBuffer32_length / sizeof(float);
IWaveProvider stream32 = new Wave16ToFloatProvider(media);
WaveBuffer _waveBuffer = new WaveBuffer(_byteBuffer32_length);
stream32.Read(_waveBuffer, 0, (int)_byteBuffer32_length);
floatBuffer = new float[_floatBuffer_length];
for (int i = 0; i < _floatBuffer_length; i++) {
floatBuffer[i] = _waveBuffer.FloatBuffer[i];
}
}
比较我注意到的两种方式:
- 收到的样本值相差 1/1 000 000。我不能说哪种方法更精确(如果你知道,会很高兴听到);
- 获取 AudioData 的第二种方法也适用于 MP3 文件。
如果您发现任何错误或对此有意见,欢迎。