Считывать аудиоданные AVAudioPcmBuffer как плавающее [] в C # Xamarin.iOS - PullRequest
0 голосов
/ 17 апреля 2019

Я пытаюсь прочитать аудиоданные из AVAudioPCMBuffer в массив значений float. Ниже приведен метод расширения, который я создал для этой цели:

public static float[] ToFloatArray(this AVAudioPcmBuffer pcmBuffer)
{
    if ((pcmBuffer != null) && 
        (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.

Ниже приведен QuickWatch на data в вышеуказанном методе сразу после операции Marshal.Copy:

QuickWatch on data output from AVAudioPcmBuffer

Я намеревался использовать значения float[] для создания измерителя уровня громкости, но при мониторинге в режиме реального времени значения, по-видимому, существенно не меняются с микрофонным входом, и при этом я не понимаю, почему многие значения содержат Не номер (NaN).

Я знаю, что AVAudioPcmBuffer содержит действительные аудиоданные, так как я отправляю на SFSpeechAudioBufferRecognitionRequest через Append(AVAudioPcmBuffer audioPcmBuffer), и распознавание речи работает отлично.

У меня есть подозрение, что Marshal.Copy может копировать неверные данные. Может ли кто-нибудь подтвердить это и / или представить правильный способ доступа к float[] значениям из AVAudioPcmBuffer в C # Xamarin для iOS?

1 Ответ

0 голосов
/ 17 апреля 2019

FloatChannelData возвращает указатель на указатели с плавающей точкой, а не один указатель.Поэтому вам нужно разыменовать float **, чтобы добраться до вашего float *.Итак, предполагая, что в вашем примере вы имеете дело с моно, вам просто нужно изменить:

Marshal.Copy(pcmBuffer.FloatChannelData, data, 0, length)

на

Marshal.Copy(pcmBuffer.FloatChannelData[0], data, 0, length)

...