AudioRecord.Read зависает бесконечно при запуске на физическом устройстве - PullRequest
0 голосов
/ 31 октября 2018

Я создаю приложение Xamarin.Android, которое обрабатывает аудио в режиме реального времени, поэтому я работаю над настройкой AudioRecord. У меня это работает в симуляторе, но когда я запускаю его на устройстве (Galaxy S9), вызов AudioRecord.Read () никогда не возвращается. Это озадачивает, потому что все contructor / StartRecording () работают нормально, без исключений, и отчеты о состоянии записи RECORDSTATE_RECORDING. Он думает, что записывает, но читать просто не может получить кадры. Кроме того, на симуляторе он работает нормально и успешно читает из буфера.

Вот код. Если вы хотите попробовать, создайте пустое приложение Xamarin.Android и замените содержимое MainActivity.cs следующим:

using Android.App;
using Android.OS;
using Android.Support.V7.App;
using Android.Media;
using Android;
using System.Threading;
using System.Linq;
using System;

namespace AndroidRecord
{
    [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
    public class MainActivity : AppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            SetContentView(Resource.Layout.activity_main);

            if (CheckSelfPermission(Manifest.Permission.RecordAudio) != Android.Content.PM.Permission.Granted)
            {
                throw new Exception($"need record permission");
            }

            StartRecording();
        }

        protected void OnDataUpdate(float[] data)
        {
            // consume thse data.
            var max = data.Max(sample => sample);
            System.Diagnostics.Debug.WriteLine($"{max}");
        }

        public void StartRecording()
        {
            new Thread(new ThreadStart(() =>
            {
                var audioSource = AudioSource.Mic;
                int sampleRate = 44100;
                var channelConfig = ChannelIn.Front;
                var encoding = Encoding.PcmFloat;
                int minBufferSize = AudioRecord.GetMinBufferSize(sampleRate, channelConfig, encoding);

                AudioRecord recorder = new AudioRecord(audioSource, sampleRate, channelConfig, encoding, minBufferSize);
                recorder.StartRecording();

                int chunkSize = 2048;
                while (true)
                {
                    float[] data = new float[chunkSize];
                    int i = recorder.Read(data, 0, chunkSize, (int)(int)AudioRecordReadOptions.Blocking);
                    RunOnUiThread(() => OnDataUpdate(data));
                }
            })).Start();
        }
    }

Пока я пробовал:

  1. Различные комбинации параметров AudioRecord (различные конфигурации каналов, аудиоисточники и кодировки)
  2. Различные размеры чанка (кажется, не имеет значения, потому что я не думаю, что есть что почитать)
  3. Измените вызов Read () на неблокирующий и проверьте возвращаемое значение. Он не записывает никаких значений и возвращает успех.
  4. Приостановите отладчик, чтобы увидеть, что говорит трассировка стека. Каждый раз, когда я перерываю, поток записи находится в одном и том же месте, ожидая вызова взаимодействия:

    0xFFFFFFFFFFFFFFFF in Java.Interop.NativeMethods.java_interop_jnienv_call_int_method_a
    0x54 in Java.Interop.JniEnvironment.InstanceMethods.CallIntMethod
    0x2C in Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualInt32Method
    0x70 in Android.Media.AudioRecord.Read
    0x61 in AndroidRecord.MainActivity.<StartRecording>b__2_0
    

Что еще я могу попытаться диагностировать эту проблему или хотя бы получить дополнительную информацию?

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Я создал пустое приложение Xamarin.Android и заменил содержимое MainActivity.cs вашим кодом, но я не воспроизвел вашу ошибку. Вместо этого я застрял в разделе проверки разрешений следующим образом

if (CheckSelfPermission(Manifest.Permission.RecordAudio) != Android.Content.PM.Permission.Granted)
            {
                throw new Exception($"need record permission");
            }

Я думаю, что-то не так с методом запроса разрешения, возможно , это может вам помочь.

0 голосов
/ 31 октября 2018

Я перезапустил свое устройство и попробовал еще раз, и пойди разберись, теперь он работает нормально. Мое единственное предположение состоит в том, что записывающее устройство как-то осталось в плохом состоянии, возможно, из-за принудительной остановки моего приложения в отладчике при предыдущем запуске. Просто предположение, хотя.

...