Skip to content

Commit

Permalink
Recording options and Bug Fixes (#108)
Browse files Browse the repository at this point in the history
* Add support for AudioRecording Options

* delete raw file on android after recording stopped and throw exception on ios

* ensure recordings and other audio can be played on iOS after a recording session.

EnableRate on iOS to ensure speed value can be changed.

* fixes #32 : load audio from files on android

* fix navigation issue in setter

* Try fix CI

* Revert "Try fix CI"

This reverts commit 10cda9b.

* Update Plugin.Maui.Audio.Sample.csproj

Co-authored-by: Gerald Versluis <gerald@verslu.is>

* Update AudioRecorderPageViewModel.cs

Co-authored-by: Gerald Versluis <gerald@verslu.is>

* Update AudioPlayer.macios.cs

Co-authored-by: Gerald Versluis <gerald@verslu.is>

* Update AudioPlayer.macios.cs

Co-authored-by: Gerald Versluis <gerald@verslu.is>

* Update AudioRecordingOptions.cs

Co-authored-by: Gerald Versluis <gerald@verslu.is>

* Update AudioRecordingOptions.cs

Co-authored-by: Gerald Versluis <gerald@verslu.is>

* Update AudioRecordingOptions.cs

Co-authored-by: Gerald Versluis <gerald@verslu.is>

* Update AudioRecordingOptions.cs

Co-authored-by: Gerald Versluis <gerald@verslu.is>

* Update AudioRecordingOptions.cs

Co-authored-by: Gerald Versluis <gerald@verslu.is>

* support for windows recording options

* trace error message

* bug fixes on windows & support of Alac & Flac

* reset csproj

* replace observable collections with lists

* fix error on ios and final merges

* remove redundant code

* Apply suggestions from code review

---------

Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com>
Co-authored-by: Gerald Versluis <gerald@verslu.is>
  • Loading branch information
3 people authored Apr 26, 2024
1 parent b343328 commit d88f00d
Show file tree
Hide file tree
Showing 23 changed files with 744 additions and 334 deletions.
90 changes: 52 additions & 38 deletions samples/Plugin.Maui.Audio.Sample/Pages/AudioRecorderPage.xaml
Original file line number Diff line number Diff line change
@@ -1,41 +1,55 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewmodels="clr-namespace:Plugin.Maui.Audio.Sample.ViewModels"
xmlns:converters="clr-namespace:Plugin.Maui.Audio.Sample.Converters"
x:Class="Plugin.Maui.Audio.Sample.Pages.AudioRecorderPage"
Title="Audio Recorder"
x:DataType="viewmodels:AudioRecorderPageViewModel">

<ContentPage.Resources>
<converters:SecondsToStringConverter x:Key="SecondsToStringConverter" />
</ContentPage.Resources>

<Grid>
<VerticalStackLayout
HorizontalOptions="Center"
VerticalOptions="Center">

<Button
Text="Start"
Command="{Binding StartCommand}" />

<Button
Text="Stop"
Command="{Binding StopCommand}" />

<Button
Text="Play"
Command="{Binding PlayCommand}" />

<Button
Text="StopPlay"
Command="{Binding StopPlayCommand}" />

<Label
Text="{Binding RecordingTime, Converter={StaticResource SecondsToStringConverter}}" />
</VerticalStackLayout>

</Grid>

xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewmodels="clr-namespace:Plugin.Maui.Audio.Sample.ViewModels"
xmlns:converters="clr-namespace:Plugin.Maui.Audio.Sample.Converters"
x:Class="Plugin.Maui.Audio.Sample.Pages.AudioRecorderPage"
Title="Audio Recorder"
x:DataType="viewmodels:AudioRecorderPageViewModel">

<ContentPage.Resources>
<converters:SecondsToStringConverter x:Key="SecondsToStringConverter" />
</ContentPage.Resources>

<ScrollView>
<VerticalStackLayout HorizontalOptions="Center"
Spacing="10"
VerticalOptions="Center">

<Picker Title="Select Sample Rate"
ItemsSource="{Binding SampleRates}"
SelectedItem="{Binding SelectedSampleRate, Mode=TwoWay}" />

<Picker Title="Select Channels"
ItemsSource="{Binding ChannelTypes}"
SelectedItem="{Binding SelectedChannelType, Mode=TwoWay}"
ItemDisplayBinding="{Binding Name}" />

<Picker Title="Select Bit Depth"
ItemsSource="{Binding BitDepths}"
SelectedItem="{Binding SelectedBitDepth, Mode=TwoWay}"
ItemDisplayBinding="{Binding Name}" />

<Picker Title="Select Encoding"
ItemsSource="{Binding EncodingOptions}"
SelectedItem="{Binding SelectedEconding, Mode=TwoWay}"
ItemDisplayBinding="{Binding Name}" />

<Button Text="Start"
Command="{Binding StartCommand}" />

<Button Text="Stop"
Command="{Binding StopCommand}" />

<Button Text="Play"
Command="{Binding PlayCommand}" />

<Button Text="StopPlay"
Command="{Binding StopPlayCommand}" />

<Label Text="{Binding RecordingTime, Converter={StaticResource SecondsToStringConverter}}" />
</VerticalStackLayout>

</ScrollView>

</ContentPage>
105 changes: 57 additions & 48 deletions samples/Plugin.Maui.Audio.Sample/Pages/MyLibraryPage.xaml
Original file line number Diff line number Diff line change
@@ -1,57 +1,66 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewmodels="clr-namespace:Plugin.Maui.Audio.Sample.ViewModels"
x:Class="Plugin.Maui.Audio.Sample.Pages.MyLibraryPage"
Title="My Library"
x:DataType="viewmodels:MyLibraryPageViewModel">
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewmodels="clr-namespace:Plugin.Maui.Audio.Sample.ViewModels"
x:Class="Plugin.Maui.Audio.Sample.Pages.MyLibraryPage"
Title="My Library"
x:Name="Page"
x:DataType="viewmodels:MyLibraryPageViewModel">

<ContentPage.Resources>
<Style x:Key="border_gallery_card" TargetType="Border">
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" />
<Setter Property="Padding" Value="16" />
<Setter Property="StrokeThickness" Value="1" />
<Setter Property="StrokeShape" Value="RoundRectangle 8" />
</Style>
</ContentPage.Resources>
<ContentPage.Resources>
<Style x:Key="border_gallery_card"
TargetType="Border">
<Setter Property="Stroke"
Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
<Setter Property="BackgroundColor"
Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" />
<Setter Property="Padding"
Value="16" />
<Setter Property="StrokeThickness"
Value="1" />
<Setter Property="StrokeShape"
Value="RoundRectangle 8" />
</Style>
</ContentPage.Resources>

<Grid
RowDefinitions="60,*">
<Grid RowDefinitions="60,*">

<Button
Text="Create Recording"
HorizontalOptions="End"
Margin="10"
Command="{Binding AddRecordingCommand}" />
<Button Text="Create Recording"
HorizontalOptions="End"
Margin="10"
Command="{Binding AddRecordingCommand}" />

<CollectionView ItemsSource="{Binding Music}"
Grid.Row="1"
SelectionMode="Single"
SelectedItem="{Binding SelectedMusicItem}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewmodels:MusicItemViewModel">
<Border Style="{StaticResource border_gallery_card}">
<Grid ColumnDefinitions="75,*"
RowDefinitions="3*,2*"
ColumnSpacing="8">
<!-- Placeholder for imagery -->
<Image BackgroundColor="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}"
Grid.RowSpan="2" />
<CollectionView ItemsSource="{Binding Music}"
Grid.Row="1"
SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="viewmodels:MusicItemViewModel">
<Border Style="{StaticResource border_gallery_card}">
<Border.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.OpenMusicCommand, Source={x:Reference Page}}"
CommandParameter="{Binding .}" />
</Border.GestureRecognizers>
<Grid ColumnDefinitions="75,*"
InputTransparent="True"
RowDefinitions="3*,2*"
ColumnSpacing="8">
<!-- Placeholder for imagery -->
<Image BackgroundColor="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}"
Grid.RowSpan="2" />

<Label Text="{Binding Title}"
FontSize="32"
FontAttributes="Bold"
Grid.Column="1" />
<Label Text="{Binding Title}"
FontSize="32"
FontAttributes="Bold"
Grid.Column="1" />

<Label Text="{Binding Artist}"
FontSize="20"
Grid.Column="1"
Grid.Row="1" />
</Grid>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
<Label Text="{Binding Artist}"
FontSize="20"
Grid.Column="1"
Grid.Row="1" />
</Grid>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage>
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,76 @@ public AudioRecorderPageViewModel(
this.dispatcher = dispatcher;
}

ChannelTypesViewModel selectedChannelType;
public ChannelTypesViewModel SelectedChannelType
{
get => selectedChannelType;
set
{
selectedChannelType = value;
NotifyPropertyChanged();
}
}
public List<ChannelTypesViewModel> ChannelTypes { get; set; } = new List<ChannelTypesViewModel>(Enum.GetValues(typeof(ChannelType)).Cast<ChannelType>().Select(x => new ChannelTypesViewModel()
{
ChannelType = x,
Name = x.ToString()
}).ToList());

BitDepthViewModel selectedBitDepth;
public BitDepthViewModel SelectedBitDepth
{
get => selectedBitDepth;
set
{
selectedBitDepth = value;
NotifyPropertyChanged();
}
}
public List<BitDepthViewModel> BitDepths { get; set; } = new List<BitDepthViewModel>(Enum.GetValues(typeof(BitDepth)).Cast<BitDepth>().Select(x => new BitDepthViewModel()
{
BitDepth = x,
Name = x.ToString()
}).ToList());


EncodingViewModel selectedEconding;
public EncodingViewModel SelectedEconding
{
get => selectedEconding;
set
{
selectedEconding = value;
NotifyPropertyChanged();
}
}

public List<EncodingViewModel> EncodingOptions { get; set; } = new List<EncodingViewModel>(Enum.GetValues(typeof(Encoding)).Cast<Encoding>().Select(x => new EncodingViewModel()
{
Encoding = x,
Name = x.ToString()
}).ToList());


int selectedSampleRate = -1;
public int SelectedSampleRate
{
get => selectedSampleRate;
set
{
selectedSampleRate = value;
NotifyPropertyChanged();
}
}
public List<int> SampleRates { get; set; } =
[
8000,
16000,
44100,
48000
];


async void PlayAudio()
{
if (audioSource != null)
Expand All @@ -76,8 +146,29 @@ async void Start()
if (await CheckPermissionIsGrantedAsync<Microphone>())
{
audioRecorder = audioManager.CreateRecorder();

await audioRecorder.StartAsync();

var options = new AudioRecordingOptions()
{
SampleRate = SelectedSampleRate == -1 ? AudioRecordingOptions.DefaultSampleRate : SelectedSampleRate,
Channels = SelectedChannelType?.ChannelType ?? AudioRecordingOptions.DefaultChannels,
BitDepth = SelectedBitDepth?.BitDepth ?? AudioRecordingOptions.DefaultBitDepth,
Encoding = SelectedEconding?.Encoding ?? AudioRecordingOptions.DefaultEncoding,
ThrowIfNotSupported = true
};

try
{
await audioRecorder.StartAsync(options);
}
catch
{
var res = await AppShell.Current.DisplayActionSheet("Options not supported. Use Default?", "Yes", "No");
if (res != "Yes")
{
return;
}
await audioRecorder.StartAsync();
}
}

recordingStopwatch.Restart();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Plugin.Maui.Audio.Sample.ViewModels;

public class BitDepthViewModel
{
public string Name { get; set; }
public BitDepth BitDepth { get; set; }
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Plugin.Maui.Audio.Sample.ViewModels;

public class ChannelTypesViewModel
{
public string Name { get; set; }
public ChannelType ChannelType { get; set; }
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Plugin.Maui.Audio.Sample.ViewModels;

public class EncodingViewModel
{
public string Name { get; set; }
public Encoding Encoding { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;

namespace Plugin.Maui.Audio.Sample.ViewModels;
namespace Plugin.Maui.Audio.Sample.ViewModels;

public class MusicItemViewModel : BaseViewModel
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
using System.ComponentModel;
using Microsoft.Maui.Dispatching;
using Plugin.Maui.Audio;

namespace Plugin.Maui.Audio.Sample.ViewModels;
namespace Plugin.Maui.Audio.Sample.ViewModels;

public class MusicPlayerPageViewModel : BaseViewModel, IQueryAttributable, IDisposable
{
Expand Down Expand Up @@ -170,12 +166,15 @@ void Pause()

void Stop()
{
if (audioPlayer.IsPlaying)
{
audioPlayer.Stop();
bool wasPlaying = audioPlayer.IsPlaying;
audioPlayer.Stop();
AnimationProgress = TimeSpan.Zero;
CurrentPosition = 0;

AnimationProgress = TimeSpan.Zero;
NotifyPropertyChanged(nameof(CurrentPosition));

if (wasPlaying)
{
NotifyPropertyChanged(nameof(IsPlaying));
}
}
Expand Down
Loading

0 comments on commit d88f00d

Please sign in to comment.