jfversluis / Plugin.Maui.Audio

Plugin.Maui.Audio provides the ability to play audio inside a .NET MAUI application
MIT License
245 stars 39 forks source link

Generate the wav file header once recording stopped #115

Open rezamohamed opened 1 month ago

rezamohamed commented 1 month ago

I am currently storing the audio in my backend storage server as a byte array. The following code works fine for this purpose:

var recordedAudio = await audioRecorder.StopAsync();

using (var stream = new MemoryStream())
                {
                    await recordedAudio.GetAudioStream().CopyToAsync(stream);
                    myByteArray = stream.ToArray();
                }

I can later pull down the byte array from my backend, and then play it back as follows:

                using (var stream = new MemoryStream(myByteArray))
                {
                    var player = AudioManager.Current.CreatePlayer(stream);
                    player.Play();
                }

However, I can't seem to play it in my storage where the raw files are saved.

I was previously using https://github.com/NateRickard/Plugin.AudioRecorder in Xamarin where the files I have stored seemed to play fine. I believe its something to do with the wav header not being written as documented here https://github.com/NateRickard/Plugin.AudioRecorder?tab=readme-ov-file#concurrent-streaming

Is there a way to write said wav header file in this plugin? or am I doing something incorrectly?

To further complicate things, I can't get this method to work on Android for recording/playback.

bijington commented 1 month ago

What platform are you recording the audio on before sending it to your server?

rezamohamed commented 1 month ago

On iOS currently. Also using the newer beta release, tried the older one as well but same thing. Able to record and playback the stream. The stream can’t be played back directly where I am saving on the backend. Files that were recorded by the other plugin mentioned above can be played back directly and also by the currently player.

On Android - the code seems to record. But the playback doesn’t work. Maybe something to do with the header since audio data that was recorded using the other plugin mentioned above can be played back using this player.

Update: Added a zip that contains the file recorded using the other plugin and this one Archive.zip

bijington commented 1 month ago

On iOS we don't do any writing of the header we leave it up to the AVAudioRecorder.

What are you seeing fail when you try to play the files? An exception?

rezamohamed commented 3 weeks ago

I am realizing what the issue is. If the audio is recorded on an iOS device, it will not play on an Android device with this plugin. This is especially true if you customize the options in iOS. As an example, these options generate a small file size in iOS simulator, but cause an exception when played on the Android simulator.

                var options = new AudioRecordingOptions
                {
                    SampleRate = 16000,
                    Channels = ChannelType.Stereo,
                    BitDepth = BitDepth.Pcm16bit,
                    Encoding = Encoding.Flac,
                    ThrowIfNotSupported = true
                };

In the format saved when I was using https://github.com/NateRickard/Plugin.AudioRecorder it works just fine across any device. There is something about the header I believe.

The Android developer docs however to say that the above format should be fine: https://developer.android.com/media/platform/supported-formats

Here is the exception:

Java.IO.IOException: Prepare failed.: status=0x1 at Java.Interop.JniEnvironment.InstanceMethods.CallVoidMethod(JniObjectReference instance, JniMethodInfo method, JniArgumentValue args) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/obj/Release/net7.0/JniEnvironment.g.cs:line 20370 at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualVoidMethod(String encodedMember, IJavaPeerable self, JniArgumentValue parameters) in /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethodsInvoke.cs:line 66 at Android.Media.MediaPlayer.Prepare() in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net8.0/android-34/mcw/Android.Media.MediaPlayer.cs:line 3857 at Plugin.Maui.Audio.AudioPlayer.PrepareAudioSource() at Plugin.Maui.Audio.AudioPlayer..ctor(Stream audioStream, AudioPlayerOptions audioPlayerOptions) at Plugin.Maui.Audio.AudioManager.CreatePlayer(Stream audioStream, AudioPlayerOptions options) at MyAppName.ViewModels.MyVM.MyVMPageViewModel.PlayVoiceSound(FileData record) in /Users/MyUserName/Development/Repos/MyAppName/MyAppName/ViewModels/MyVM/MyVMPageViewModel.cs:line 116 at CommunityToolkit.Mvvm.Input.RelayCommand`1[[MyAppName.Models.FileData, MyAppName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].Execute(Object parameter) in //src/CommunityToolkit.Mvvm/Input/RelayCommand{T}.cs:line 115 at DevExpress.Maui.CollectionView.DXCollectionView.ItemTap(Int32 visibleIndex) at DevExpress.Maui.CollectionView.DXCollectionView.DevExpress.Maui.CollectionView.Internal.IDXCollectionView.ItemTap(Int32 visibleIndex) at DevExpress.Maui.CollectionView.Android.Internal.ListViewDelegate.DevExpress.Android.CollectionView.IListViewListener.ItemTap(Int32 visibleIndex) at DevExpress.Android.CollectionView.IListViewListenerInvoker.n_ItemTap_I(IntPtr jnienv, IntPtr native__this, Int32 p0) at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPI_V(_JniMarshal_PPI_V callback, IntPtr jnienv, IntPtr klazz, Int32 p0) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:line 55 --- End of managed Java.IO.IOException stack trace --- java.io.IOException: Prepare failed.: status=0x1 at android.media.MediaPlayer._prepare(Native Method) at android.media.MediaPlayer.prepare(MediaPlayer.java:1337) at crc64a3de810b23927aec.ListViewDelegate.n_itemTap(Native Method) at crc64a3de810b23927aec.ListViewDelegate.itemTap(ListViewDelegate.java:116) at com.devexpress.dxlistview.DXVirtualScrollView.raiseItemTap(DXVirtualScrollView.kt:310) at com.devexpress.dxlistview.core.DragDropManager.onSingleTapUp(DragDropManager.kt:134) at com.devexpress.dxlistview.core.GestureListener.onSingleTapUp(GestureListener.java:119) at android.view.GestureDetector.onTouchEvent(GestureDetector.java:754) at com.devexpress.dxlistview.core.GestureListener.onTouchEvent(GestureListener.java:48) at com.devexpress.dxlistview.DXVirtualScrollView.processTouchEvent(DXVirtualScrollView.kt:305) at com.devexpress.dxlistview.VirtualScrollPanel.dispatchTouchEvent(VirtualScrollPanel.kt:58) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at com.devexpress.dxlistview.DXListViewNative.dispatchTouchEvent(DXListViewNative.kt:339) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:490) at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1904) at android.app.Activity.dispatchTouchEvent(Activity.java:4377) at crc6488302ad6e9e4df1a.MauiAppCompatActivity.n_dispatchTouchEvent(Native Method) at crc6488302ad6e9e4df1a.MauiAppCompatActivity.dispatchTouchEvent(MauiAppCompatActivity.java:57) at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:70) at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:448) at android.view.View.dispatchPointerEvent(View.java:15919) at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:7021) at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:6815) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6229) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6286) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6252) at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:6417) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6260) at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:6474) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6233) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6286) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6252) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6260) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6233) at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:9211) at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:9162) at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:9131) at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:9337) at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:267) at android.os.MessageQueue.nativePollOnce(Native Method) at android.os.MessageQueue.next(MessageQueue.java:335) at android.os.Looper.loopOnce(Looper.java:162) at android.os.Looper.loop(Looper.java:294) at android.app.ActivityThread.main(ActivityThread.java:8177) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)

--- End of managed Java.IO.IOException stack trace --- java.io.IOException: Prepare failed.: status=0x1 at android.media.MediaPlayer._prepare(Native Method) at android.media.MediaPlayer.prepare(MediaPlayer.java:1337) at crc64a3de810b23927aec.ListViewDelegate.n_itemTap(Native Method) at crc64a3de810b23927aec.ListViewDelegate.itemTap(ListViewDelegate.java:116) at com.devexpress.dxlistview.DXVirtualScrollView.raiseItemTap(DXVirtualScrollView.kt:310) at com.devexpress.dxlistview.core.DragDropManager.onSingleTapUp(DragDropManager.kt:134) at com.devexpress.dxlistview.core.GestureListener.onSingleTapUp(GestureListener.java:119) at android.view.GestureDetector.onTouchEvent(GestureDetector.java:754) at com.devexpress.dxlistview.core.GestureListener.onTouchEvent(GestureListener.java:48) at com.devexpress.dxlistview.DXVirtualScrollView.processTouchEvent(DXVirtualScrollView.kt:305) at com.devexpress.dxlistview.VirtualScrollPanel.dispatchTouchEvent(VirtualScrollPanel.kt:58) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at com.devexpress.dxlistview.DXListViewNative.dispatchTouchEvent(DXListViewNative.kt:339) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801) at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:490) at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1904) at android.app.Activity.dispatchTouchEvent(Activity.java:4377) at crc6488302ad6e9e4df1a.MauiAppCompatActivity.n_dispatchTouchEvent(Native Method) at crc6488302ad6e9e4df1a.MauiAppCompatActivity.dispatchTouchEvent(MauiAppCompatActivity.java:57) at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:70) at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:448) at android.view.View.dispatchPointerEvent(View.java:15919) at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:7021) at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:6815) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6229) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6286) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6252) at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:6417) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6260) at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:6474) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6233) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6286) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6252) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6260) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6233) at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:9211) at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:9162) at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:9131) at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:9337) at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:267) at android.os.MessageQueue.nativePollOnce(Native Method) at android.os.MessageQueue.next(MessageQueue.java:335) at android.os.Looper.loopOnce(Looper.java:162) at android.os.Looper.loop(Looper.java:294) at android.app.ActivityThread.main(ActivityThread.java:8177) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)

further, I am seeing messages like this in Debug output when playing in iOS, so it may be that the header doesn't get written:

[AudioMetadata] AudioQueueObject.cpp:5942 DetermineMetadataTimestamp unable to obtain valid timestamp, estimate:54459.000000

rezamohamed commented 3 weeks ago

In addition to the above, I have noticed that the recording on Android specifically has issues: (1) the voice is recorded at a really low volume (3) there is a crackling sound (2) there is a repeat of the last few seconds of the recording always

I created a sample repo to test this (this commit is with this plugin) https://github.com/rezamohamed/MauiAudioTest/tree/fcdba6aafb663a371f73098f55e7e39edad567a2

The Android documentation says that FLAC encoding does work. https://developer.android.com/media/platform/supported-formats

however, when encoding with FLAC, there is an exception thrown:

System.NotSupportedException: Encoding type not supported at Plugin.Maui.Audio.AudioRecorder.SharedEncodingToAndroidEncoding(Encoding type, BitDepth bitDepth, Boolean throwIfNotSupported) at Plugin.Maui.Audio.AudioRecorder.StartAsync(String filePath, AudioRecordingOptions options) at Plugin.Maui.Audio.AudioRecorder.StartAsync(AudioRecordingOptions options) at AudioTest.MainPage.RecordBtn_OnClicked(Object sender, EventArgs e) in /Users/rezamohamed/Development/Projects/AudioTest/AudioTest/MainPage.xaml.cs:line 54 at System.Threading.Tasks.Task.<>c.b128_0(Object state) at Android.App.SyncContext.<>c__DisplayClass2_0.b0() in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.App/SyncContext.cs:line 36 at Java.Lang.Thread.RunnableImplementor.Run() in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Java.Lang/Thread.cs:line 36 at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net8.0/android-34/mcw/Java.Lang.IRunnable.cs:line 84 at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PP_V(_JniMarshal_PP_V callback, IntPtr jnienv, IntPtr klazz) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:line 22

UPDATE: this plugin to record audio actually works fine on Android and iOS and doesnt have the issues outlined here. https://github.com/NateRickard/Plugin.AudioRecorder The only issue is that the encoding is hard coded so the data is of a bigger size.

This is the commit after switching to this older plugin https://github.com/rezamohamed/MauiAudioTest/commit/64ec94e611535581b3698543cae463692567b728

pierre-galaup commented 2 days ago

Hello,

I too have problems with the repeat of the last few seconds of the recording and the crackling sound at the beginning. As far as I'm concerned, this doesn't happen every time, but very often, especially on very short recordings of 1/2 second or less.

Is there a solution?