Audio Recorder and Player

    Kartik Parashar

This guide wraps the procedure for the implementation of an Audio Recorder and an Audio Player in Xamarin. This tool has a broad audience with applications having a high emphasis on Multimedia. We are going to proceed Audio Recorder and Player using a DependencyService approach. This is done by creating an Interface with prototypes and describing those in native projects. DependencyService allows apps to call into platform-specific functionality from shared code. This functionality enables Xamarin.Forms apps to achieve anything that a native app can do.


Shared Code:

namespace AudioRecorderDemo.Interfaces
{
    interface IAudioRecorder
    {
        void StartRecording();
        void StopRecording();
        void PlayRecording();      
        
    }
}
IOS: In we have AVAudioRecorder class for recording and AVPlayer class for playback. 
[assembly: Xamarin.Forms.Dependency(typeof(AudioRecorder))]
namespace AudioRecorderDemo.iOS
{
    public class AudioRecorder : IAudioRecorder
    {
        AVAudioRecorder recorder;
        AVPlayer player;
        NSError error;
        NSUrl url;
        NSDictionary settings;
        string audioFilePath;

        public void StartRecording()
        {
            var audioSession = AVAudioSession.SharedInstance();
            var err = audioSession.SetCategory(AVAudioSessionCategory.PlayAndRecord); s
            string fileName = string.Format("Myfile{0}.wav", DateTime.Now.ToString("yyyyMMddHHmmss"));
            audioFilePath = Path.Combine(Path.GetTempPath(), fileName);
            url = NSUrl.FromFilename(audioFilePath);
            NSObject[] values = new NSObject[]
            {
                NSNumber.FromFloat(44100.0f),
                NSNumber.FromInt32 ((int)AudioToolbox.AudioFormatType.LinearPCM),//AVFormat
                NSNumber.FromInt32 (2), //Channels
                NSNumber.FromInt32 (16), //PCMBitDepth 
                NSNumber.FromBoolean (false), //IsBigEndianKey 
                NSNumber.FromBoolean (false) //IsFloatKey
            };
            NSObject[] keys = new NSObject[]
            {
                AVAudioSettings.AVSampleRateKey,
                AVAudioSettings.AVFormatIDKey,
                AVAudioSettings.AVNumberOfChannelsKey,
                AVAudioSettings.AVLinearPCMBitDepthKey,
                AVAudioSettings.AVLinearPCMIsBigEndianKey,
                AVAudioSettings.AVLinearPCMIsFloatKey
            };
            settings = NSDictionary.FromObjectsAndKeys(values, keys);
            recorder = AVAudioRecorder.Create(url, new AudioSettings(settings), out error);
            recorder.PrepareToRecord();
            recorder.Record();
        }

        public void StopRecording()
        {
            recorder.Stop();
            var asset = AVAsset.FromUrl(url);
            var playerItem = new AVPlayerItem(asset);
            player = new AVPlayer(playerItem);
            var playerLayer = AVPlayerLayer.FromPlayer(player);
            GetController().View.Layer.AddSublayer(playerLayer);
        }

        public async void PlayRecording()
        {
            player.Play();
        }


        private static UIViewController GetController()
        {
            var vc = UIApplication.SharedApplication.KeyWindow.RootViewController;
            while (vc.PresentedViewController != null)
                vc = vc.PresentedViewController;
            return vc;
        }
    }
}


Android: In we have AVAudioRecorder class for recording and AVPlayer class for playback.

[assembly: Xamarin.Forms.Dependency(typeof(AudioRecorder))]
namespace AudioRecorderDemo.Droid.DS
{
    class AudioRecorder : IAudioRecorder
    {
        static long Time { get; set; }
        MediaRecorder _recorder;
        MediaPlayer _player;
        string path = "/sdcard/test.3gpp";

        public AudioRecorder()
        {
            _recorder = new MediaRecorder();
            _player = new MediaPlayer();

            _player.Completion += (sender, e) =>
            {
                _player.Reset();
            };
        }

        public void StartRecording()
        {
            try
            {
                _recorder.SetAudioSource(AudioSource.Mic);
                _recorder.SetOutputFormat(OutputFormat.ThreeGpp);
                _recorder.SetAudioEncoder(AudioEncoder.AmrNb);
                _recorder.SetOutputFile(path);
                _recorder.Prepare();
                _recorder.Start();
            }
            catch (Exception e)
            {
                var str = e.Message;
            }

        }

        public void StopRecording()
        {
            try
            {
                _recorder.Stop();
                _recorder.Reset();
                _player.SetDataSource(path);
            }
            catch (Exception e)
            {
                var str = e.Message;
            }
        }

        public async void PlayRecording()
        {
            _player.Prepare();
            Time = _player.Duration;
            _player.Looping = true;
            _player.Start();
        }

    }
}

Find the Sample here.