Skip to content

Commit a14b07c

Browse files
jonmdevbijington
andauthored
Add Audio Compression (AAC in M4A/MP4) Support in Android/iOS/Windows (#155)
* test project added working * Working AAC/M4A Compression * Update AudioRecordingOptions.cs * Update Encoding.cs * Simplified the sample application * Remove the unnecessary sample project * Add obsolete encoding option back in * Remove unused CompressionQuality * Consolidate multiple options classes * Tidy up more options related bits * Fix some warnings * A bit more tidy up and fix merge issues * Correct text * Update supported versions * Default to Wav which was the original encoding * Remove warning * Patch up for Windows --------- Co-authored-by: Shaun Lawrence <[email protected]>
1 parent e786462 commit a14b07c

17 files changed

+314
-260
lines changed

samples/Plugin.Maui.Audio.Sample/Pages/AudioRecorderPage.xaml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,15 @@
2222

2323
<Picker Title="Select Channels"
2424
ItemsSource="{Binding ChannelTypes}"
25-
SelectedItem="{Binding SelectedChannelType, Mode=TwoWay}"
26-
ItemDisplayBinding="{Binding Name}" />
25+
SelectedItem="{Binding SelectedChannelType, Mode=TwoWay}" />
2726

2827
<Picker Title="Select Bit Depth"
2928
ItemsSource="{Binding BitDepths}"
30-
SelectedItem="{Binding SelectedBitDepth, Mode=TwoWay}"
31-
ItemDisplayBinding="{Binding Name}" />
29+
SelectedItem="{Binding SelectedBitDepth, Mode=TwoWay}" />
3230

3331
<Picker Title="Select Encoding"
3432
ItemsSource="{Binding EncodingOptions}"
35-
SelectedItem="{Binding SelectedEconding, Mode=TwoWay}"
36-
ItemDisplayBinding="{Binding Name}" />
33+
SelectedItem="{Binding SelectedEncoding, Mode=TwoWay}" />
3734

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

samples/Plugin.Maui.Audio.Sample/ViewModels/AudioRecorderPageViewModel.cs

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ public AudioRecorderPageViewModel(
5252
this.dispatcher = dispatcher;
5353
}
5454

55-
ChannelTypesViewModel selectedChannelType;
56-
public ChannelTypesViewModel SelectedChannelType
55+
ChannelType selectedChannelType;
56+
public ChannelType SelectedChannelType
5757
{
5858
get => selectedChannelType;
5959
set
@@ -62,14 +62,10 @@ public ChannelTypesViewModel SelectedChannelType
6262
NotifyPropertyChanged();
6363
}
6464
}
65-
public List<ChannelTypesViewModel> ChannelTypes { get; set; } = new List<ChannelTypesViewModel>(Enum.GetValues(typeof(ChannelType)).Cast<ChannelType>().Select(x => new ChannelTypesViewModel()
66-
{
67-
ChannelType = x,
68-
Name = x.ToString()
69-
}).ToList());
65+
public List<ChannelType> ChannelTypes { get; set; } = Enum.GetValues(typeof(ChannelType)).Cast<ChannelType>().ToList();
7066

71-
BitDepthViewModel selectedBitDepth;
72-
public BitDepthViewModel SelectedBitDepth
67+
BitDepth selectedBitDepth;
68+
public BitDepth SelectedBitDepth
7369
{
7470
get => selectedBitDepth;
7571
set
@@ -78,30 +74,20 @@ public BitDepthViewModel SelectedBitDepth
7874
NotifyPropertyChanged();
7975
}
8076
}
81-
public List<BitDepthViewModel> BitDepths { get; set; } = new List<BitDepthViewModel>(Enum.GetValues(typeof(BitDepth)).Cast<BitDepth>().Select(x => new BitDepthViewModel()
82-
{
83-
BitDepth = x,
84-
Name = x.ToString()
85-
}).ToList());
77+
public List<BitDepth> BitDepths { get; set; } = Enum.GetValues(typeof(BitDepth)).Cast<BitDepth>().ToList();
8678

87-
88-
EncodingViewModel selectedEconding;
89-
public EncodingViewModel SelectedEconding
79+
Encoding selectedEncoding;
80+
public Encoding SelectedEncoding
9081
{
91-
get => selectedEconding;
82+
get => selectedEncoding;
9283
set
9384
{
94-
selectedEconding = value;
85+
selectedEncoding = value;
9586
NotifyPropertyChanged();
9687
}
9788
}
9889

99-
public List<EncodingViewModel> EncodingOptions { get; set; } = new List<EncodingViewModel>(Enum.GetValues(typeof(Encoding)).Cast<Encoding>().Select(x => new EncodingViewModel()
100-
{
101-
Encoding = x,
102-
Name = x.ToString()
103-
}).ToList());
104-
90+
public List<Encoding> EncodingOptions { get; set; } = Enum.GetValues(typeof(Encoding)).Cast<Encoding>().ToList();
10591

10692
int selectedSampleRate = -1;
10793
public int SelectedSampleRate
@@ -113,6 +99,7 @@ public int SelectedSampleRate
11399
NotifyPropertyChanged();
114100
}
115101
}
102+
116103
public List<int> SampleRates { get; set; } =
117104
[
118105
8000,
@@ -147,15 +134,19 @@ async void Start()
147134
{
148135
audioRecorder = audioManager.CreateRecorder();
149136

150-
var options = new AudioRecordingOptions()
137+
var options = new AudioRecorderOptions
151138
{
152-
SampleRate = SelectedSampleRate == -1 ? AudioRecordingOptions.DefaultSampleRate : SelectedSampleRate,
153-
Channels = SelectedChannelType?.ChannelType ?? AudioRecordingOptions.DefaultChannels,
154-
BitDepth = SelectedBitDepth?.BitDepth ?? AudioRecordingOptions.DefaultBitDepth,
155-
Encoding = SelectedEconding?.Encoding ?? AudioRecordingOptions.DefaultEncoding,
139+
Channels = SelectedChannelType,
140+
BitDepth = SelectedBitDepth,
141+
Encoding = SelectedEncoding,
156142
ThrowIfNotSupported = true
157143
};
158144

145+
if (SelectedSampleRate != -1)
146+
{
147+
options.SampleRate = SelectedSampleRate;
148+
}
149+
159150
try
160151
{
161152
await audioRecorder.StartAsync(options);

samples/Plugin.Maui.Audio.Sample/ViewModels/BitDepthViewModel.cs

Lines changed: 0 additions & 7 deletions
This file was deleted.

samples/Plugin.Maui.Audio.Sample/ViewModels/ChannelTypesViewModel.cs

Lines changed: 0 additions & 13 deletions
This file was deleted.

samples/Plugin.Maui.Audio.Sample/ViewModels/EncodingViewModel.cs

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/Plugin.Maui.Audio/AudioPlayer/AudioPlayer.android.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Plugin.Maui.Audio;
88

99
partial class AudioPlayer : IAudioPlayer
1010
{
11-
readonly MediaPlayer player;
11+
readonly MediaPlayer player; // For broader format support (FLAC, etc.), consider using ExoPlayer instead in future
1212
double volume = 0.5;
1313
double balance = 0;
1414
string cachePath = string.Empty;

src/Plugin.Maui.Audio/AudioPlayer/AudioPlayer.macios.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,19 @@ public bool Loop
6666

6767
public bool CanSeek => true;
6868

69-
static NSData _emptySource;
69+
static NSData? emptySource;
7070

7171
internal AudioPlayer(AudioPlayerOptions audioPlayerOptions)
7272
{
73-
if (_emptySource == null)
73+
if (emptySource == null)
7474
{
7575
byte[] empty = new byte[16];
7676
int sampleRate = 44100;
7777
var source = new RawAudioSource(empty, sampleRate, 1);
78-
_emptySource = NSData.FromArray(source.Bytes);
78+
emptySource = NSData.FromArray(source.Bytes);
7979
}
8080

81-
player = AVAudioPlayer.FromData(_emptySource)
81+
player = AVAudioPlayer.FromData(emptySource)
8282
?? throw new FailedToLoadAudioException("Unable to create AVAudioPlayer from data.");
8383

8484
this.audioPlayerOptions = audioPlayerOptions;

src/Plugin.Maui.Audio/AudioPlayer/IAudio.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,23 @@ public interface IAudio : IDisposable
2525
///</Summary>
2626
double Balance { get; set; }
2727

28-
///<Summary>
29-
/// Gets the playback speed where 1 is normal speed. <see cref="MinimumSpeed"/> and <see cref="MaximumSpeed"/> can be used to determine the minumum and maximum value for each platform.
30-
/// Sets the playback speed where 1 is normal speed. <see cref="MinimumSpeed"/> and <see cref="MaximumSpeed"/> can be used to determine the minumum and maximum value for each platform.
31-
/// </summary>
28+
///<summary>
29+
/// Gets the playback speed where 1 is normal speed. <see cref="MinimumSpeed"/> and <see cref="MaximumSpeed"/> can be used to determine the minimum and maximum value for each platform.
30+
/// Sets the playback speed where 1 is normal speed. <see cref="MinimumSpeed"/> and <see cref="MaximumSpeed"/> can be used to determine the minimum and maximum value for each platform.
31+
///</summary>
3232
///<remarks>
33-
/// The minimum and maximum speeds that can be set here are different per platform. Setting values ouside of these ranges will not throw an exception, it will clamp to the minimum or maximum value.
33+
/// The minimum and maximum speeds that can be set here are different per platform. Setting values outside of these ranges will not throw an exception, it will clamp to the minimum or maximum value.
3434
///<para>- Android: between 0 and 2.5. Setting the value to 0 will pause playback, playback will not be resumed when incrementing the value again.</para>
3535
///<para>- iOS: between 0.5 and 2.</para>
3636
///<para>- Windows: between 0 and 8. Setting the value to 0 will pause playback, playback will be resumed when incrementing the value again.</para>
3737
///</remarks>
3838
double Speed { get; set; }
3939

4040
/// <summary>
41-
/// Sets the playback speed where 1 is normal speed. <see cref="MinimumSpeed"/> and <see cref="MaximumSpeed"/> can be used to determine the minumum and maximum value for each platform.
41+
/// Sets the playback speed where 1 is normal speed. <see cref="MinimumSpeed"/> and <see cref="MaximumSpeed"/> can be used to determine the minimum and maximum value for each platform.
4242
/// </summary>
4343
///<remarks>
44-
/// The minimum and maximum speeds that can be set here are different per platform. Setting values ouside of these ranges will not throw an exception, it will clamp to the minimum or maximum value.
44+
/// The minimum and maximum speeds that can be set here are different per platform. Setting values outside of these ranges will not throw an exception, it will clamp to the minimum or maximum value.
4545
///<para>- Android: between 0 and 2.5. Setting the value to 0 will pause playback, playback will not be resumed when incrementing the value again.</para>
4646
///<para>- iOS: between 0.5 and 2.</para>
4747
///<para>- Windows: between 0 and 8. Setting the value to 0 will pause playback, playback will be resumed when incrementing the value again.</para>

0 commit comments

Comments
 (0)