Issues with Restarting Audio Recording in .NET 7 MAUI App Using Android AudioRecord

167 views Asked by At

I am capturing audio in a .NET 7 MAUI application using the Android AudioRecord library. I am dependency-injecting my service, which contains the Android AudioRecord, into my ViewModel.

The Scenario: In my app, I want to click a button to start the audio recording and then click another button to stop the recording. After that, I want to be able to click the start button again to resume audio recording.

The Problem: When I click "start" the first time, I receive an audio stream from the microphone as desired. However, after stopping the audio and starting it again, I don't receive anything.

What I Have Tried:

I have tried registering the service as Transient, Scoped, and Singleton. I have attempted to initialize the AudioRecord both in the constructor and each time the "start" button is pressed. I've pinpointed the problem to the audioRecord.Stop() method. When I comment this out, everything works fine. I have tried to implement the AudioRecord directly inside the viewModel. Everything works just fine with the .stop() method then.

The code:

#if ANDROID
    using Android.Media;
    
    namespace Neuron.Nexus.Services;
    public interface IAndroidAudioRecordService : IDisposable
    {
        void StartRecording();
        void StopRecording();
        Task<(byte[] buffer, int bytesRead)> GetAudioStream();
        bool IsRecording { get; }
    }
    
    public class AndroidAudioRecordService : IAndroidAudioRecordService
    {
        private AudioRecord audioRecord;
        private readonly int sampleRate = 44100;
        private readonly int bufferSize = 1024;
        private readonly ChannelIn channelConfig = ChannelIn.Mono;
        private readonly Encoding audioFormat = Encoding.Pcm16bit;
        private readonly byte[] audioBuffer;
    
        public bool IsRecording { get; private set; }
    
        public AndroidAudioRecordService()
        {
            audioBuffer = new byte[bufferSize];
        }
    
        public void StartRecording()
        {
            if (audioRecord != null)
            {
                audioRecord.Stop();
                audioRecord.Release();
                audioRecord.Dispose();
                audioRecord = null;
    
            }
    
            audioRecord = new AudioRecord(AudioSource.Mic, sampleRate, channelConfig, audioFormat, bufferSize);
    
            if (audioRecord != null && audioRecord.State == State.Initialized)
            {
                audioRecord.StartRecording();
                IsRecording = true;
            }
        }
    
        public void StopRecording()
        {
            if (audioRecord != null && audioRecord.RecordingState == RecordState.Recording)
            {
                audioRecord.Stop();
                IsRecording = false;
            }
        }
    
        public async Task<(byte[] buffer, int bytesRead)> GetAudioStream()
        {
            if (audioRecord == null)
            {
                throw new InvalidOperationException("AudioRecord is not initialized or not in recording state.");
            }
    
            int bytesRead = await audioRecord.ReadAsync(audioBuffer, 0, audioBuffer.Length);
            return (audioBuffer, bytesRead);
        }
    
    
        public void Dispose()
        {
            if (audioRecord != null)
            {
                if (IsRecording)
                {
                    audioRecord.Stop();
                }
    
                audioRecord.Release();
                audioRecord.Dispose();
                audioRecord = null;
                IsRecording = false;
            }
        }
    }
    #endif

If I have missed to share anything please let me know.

0

There are 0 answers