#c# #xamarin.ios #avaudioengine
#c# #xamarin.ios #avaudioengine
Вопрос:
Я пытаюсь считывать аудиоданные из an AVAudioPCMBuffer
в массив float
значений. Ниже приведен метод расширения, который я создал для этой цели:
public static float[] ToFloatArray(this AVAudioPcmBuffer pcmBuffer)
{
if ((pcmBuffer != null) amp;amp;
(pcmBuffer.FloatChannelData != IntPtr.Zero))
{
int length = (Convert.ToInt32(pcmBuffer.FrameLength) * 2);
if (length > 0)
{
var data = new float[length];
Marshal.Copy(pcmBuffer.FloatChannelData, data, 0, length);
return data;
}
else return new float[0];
}
else return null;
}
Похоже, что метод возвращает данные соответствующей длины (8820 выборок при частоте дискретизации 44100), однако значения, по-видимому, не имеют смысла, причем многие из них являются NaN
.
Ниже приведен быстрый data
просмотр в приведенном выше методе сразу после Marshal.Copy
операции:
Я намеревался использовать float[]
значения для создания измерителя VU, но при мониторинге в режиме реального времени значения, похоже, существенно не меняются при вводе микрофона, и я не понимаю, почему многие значения не содержат Number ( NaN
) .
Я знаю, что AVAudioPcmBuffer
они содержат действительные аудиоданные, поскольку я отправляю их на SFSpeechAudioBufferRecognitionRequest
via Append(AVAudioPcmBuffer audioPcmBuffer)
, и распознавание речи работает отлично.
У меня есть подозрение, что Marshal.Copy
это может быть копирование неправильных данных. Может ли кто-нибудь подтвердить это и / или представить правильный способ доступа float[]
к значениям из AVAudioPcmBuffer
C # Xamarin для iOS?
Ответ №1:
FloatChannelData возвращает указатель на указатели с плавающей запятой, а не один указатель. Поэтому вам нужно разыменовать float **
, чтобы добраться до вашего float *
. Итак, предполагая, что в вашем примере вы имеете дело с mono, вам просто нужно изменить:
Marshal.Copy(pcmBuffer.FloatChannelData, data, 0, length)
Для
Marshal.Copy(pcmBuffer.FloatChannelData[0], data, 0, length)
Комментарии:
1. Я пытался это сделать, но
FloatChannelData
имеет типIntPtr
, который не может принимать индексатор. Я обновил свой код выше, чтобы попытаться прочитать какdouble
значения вместоfloat
(какnfloat
представляется, 64-разрядные), но прочитанные данные по-прежнему не являются допустимыми образцами звука. У вас есть какие-либо другие предложения?
Ответ №2:
FloatChannelData — это указатель на каналы, поэтому для получения байтов вам нужно сделать это —
var channels = (IntPtr*)buffer.FloatChannelData.ToPointer();
Marshal.Copy(channels[0], data, 0, length);