diff --git a/samples/Plugin.Maui.Audio.Sample/ViewModels/AudioRecorderPageViewModel.cs b/samples/Plugin.Maui.Audio.Sample/ViewModels/AudioRecorderPageViewModel.cs
index 3db2bb1..2ec8c4e 100644
--- a/samples/Plugin.Maui.Audio.Sample/ViewModels/AudioRecorderPageViewModel.cs
+++ b/samples/Plugin.Maui.Audio.Sample/ViewModels/AudioRecorderPageViewModel.cs
@@ -111,7 +111,7 @@ public int SelectedSampleRate
async void PlayAudio()
{
- if (audioSource != null)
+ if (audioSource is not null)
{
audioPlayer = this.audioManager.CreateAsyncPlayer(((FileAudioSource)audioSource).GetAudioStream());
diff --git a/samples/Plugin.Maui.Audio.Sample/ViewModels/MusicPlayerPageViewModel.cs b/samples/Plugin.Maui.Audio.Sample/ViewModels/MusicPlayerPageViewModel.cs
index 66202d8..46bea99 100644
--- a/samples/Plugin.Maui.Audio.Sample/ViewModels/MusicPlayerPageViewModel.cs
+++ b/samples/Plugin.Maui.Audio.Sample/ViewModels/MusicPlayerPageViewModel.cs
@@ -130,7 +130,7 @@ public double Volume
get => audioPlayer?.Volume ?? 1;
set
{
- if (audioPlayer != null)
+ if (audioPlayer is not null)
{
audioPlayer.Volume = value;
}
@@ -142,7 +142,7 @@ public double Balance
get => audioPlayer?.Balance ?? 0;
set
{
- if (audioPlayer != null)
+ if (audioPlayer is not null)
{
audioPlayer.Balance = value;
}
diff --git a/src/Plugin.Maui.Audio/AudioMixer/AudioMixer.cs b/src/Plugin.Maui.Audio/AudioMixer/AudioMixer.cs
index 267ce98..92e2355 100644
--- a/src/Plugin.Maui.Audio/AudioMixer/AudioMixer.cs
+++ b/src/Plugin.Maui.Audio/AudioMixer/AudioMixer.cs
@@ -45,11 +45,15 @@ public class AudioMixer : IDisposable
/// The number of audio channels to manage.
public AudioMixer(IAudioManager audioManager, int numberOfChannels)
{
- if (audioManager == null)
+ if (audioManager is null)
+ {
throw new ArgumentNullException(nameof(audioManager));
+ }
if (numberOfChannels <= 0)
+ {
throw new ArgumentOutOfRangeException(nameof(numberOfChannels), "Number of channels must be positive.");
+ }
this.audioManager = audioManager;
ChannelCount = numberOfChannels;
@@ -94,8 +98,10 @@ public void Play(int channelIndex, bool loop = false)
public void Play(int channelIndex, IAudioSource audioClip, bool loop = false)
{
ValidateChannelIndex(channelIndex);
- if (audioClip == null)
+ if (audioClip is null)
+ {
throw new ArgumentNullException(nameof(audioClip));
+ }
var player = channels[channelIndex];
player.Stop();
@@ -177,8 +183,10 @@ public void PlayAll()
public void SetSource(int channelIndex, IAudioSource audioClip)
{
ValidateChannelIndex(channelIndex);
- if (audioClip == null)
+ if (audioClip is null)
+ {
throw new ArgumentNullException(nameof(audioClip));
+ }
var player = channels[channelIndex];
player.Stop();
@@ -244,7 +252,9 @@ public void SetVolume(int channelIndex, float volume)
void ValidateChannelIndex(int channelIndex)
{
if (channelIndex < 0 || channelIndex >= ChannelCount)
+ {
throw new ArgumentOutOfRangeException(nameof(channelIndex), $"Channel index must be between 0 and {ChannelCount - 1}.");
+ }
}
///
@@ -307,7 +317,9 @@ public float GetDistanceDecay(float dist)
protected virtual void Dispose(bool disposing)
{
if (IsDisposed)
+ {
return;
+ }
foreach (var player in channels)
{
diff --git a/src/Plugin.Maui.Audio/AudioPlayer/AudioPlayer.android.cs b/src/Plugin.Maui.Audio/AudioPlayer/AudioPlayer.android.cs
index 0fafc9f..e773acc 100644
--- a/src/Plugin.Maui.Audio/AudioPlayer/AudioPlayer.android.cs
+++ b/src/Plugin.Maui.Audio/AudioPlayer/AudioPlayer.android.cs
@@ -142,12 +142,12 @@ public bool Loop
void PrepareAudioSource()
{
- if (audioBytes == null && string.IsNullOrWhiteSpace(file))
+ if (audioBytes is null && string.IsNullOrWhiteSpace(file))
{
throw new ArgumentException("audio source is not set");
}
- if (audioBytes != null && OperatingSystem.IsAndroidVersionAtLeast(23))
+ if (audioBytes is not null && OperatingSystem.IsAndroidVersionAtLeast(23))
{
stream = new MemoryStream(audioBytes);
var mediaSource = new StreamMediaDataSource(stream);
@@ -172,6 +172,11 @@ void PrepareAudioSource()
}
else
{
+ if (file is null)
+ {
+ throw new FailedToLoadAudioException("Provided file was null");
+ }
+
AssetFileDescriptor afd = Android.App.Application.Context.Assets?.OpenFd(file)
?? throw new FailedToLoadAudioException("Unable to create AssetFileDescriptor.");
diff --git a/src/Plugin.Maui.Audio/AudioPlayer/AudioPlayer.macios.cs b/src/Plugin.Maui.Audio/AudioPlayer/AudioPlayer.macios.cs
index 1b3c755..cb93389 100644
--- a/src/Plugin.Maui.Audio/AudioPlayer/AudioPlayer.macios.cs
+++ b/src/Plugin.Maui.Audio/AudioPlayer/AudioPlayer.macios.cs
@@ -104,7 +104,7 @@ public bool Loop
internal AudioPlayer(AudioPlayerOptions audioPlayerOptions)
{
- if (emptySource == null)
+ if (emptySource is null)
{
byte[] empty = new byte[16];
int sampleRate = 44100;
@@ -127,7 +127,7 @@ internal AudioPlayer(AudioPlayerOptions audioPlayerOptions)
/// Thrown when the audio stream cannot be loaded.
public void SetSource(Stream audioStream)
{
- if (player != null)
+ if (player is not null)
{
player.FinishedPlaying -= OnPlayerFinishedPlaying;
player.DecoderError -= OnPlayerError;
diff --git a/src/Plugin.Maui.Audio/AudioRecorder/AudioRecorder.android.cs b/src/Plugin.Maui.Audio/AudioRecorder/AudioRecorder.android.cs
index 6fa5fde..a312615 100644
--- a/src/Plugin.Maui.Audio/AudioRecorder/AudioRecorder.android.cs
+++ b/src/Plugin.Maui.Audio/AudioRecorder/AudioRecorder.android.cs
@@ -39,7 +39,7 @@ public AudioRecorder(AudioRecorderOptions options)
var packageManager = Android.App.Application.Context.PackageManager;
CanRecordAudio = packageManager?.HasSystemFeature(Android.Content.PM.PackageManager.FeatureMicrophone) ?? false;
- this.audioRecorderOptions = options;
+ audioRecorderOptions = options;
}
public Task StartAsync(AudioRecorderOptions? options = null) => StartAsync(GetTempFilePath(), options);
@@ -57,7 +57,7 @@ public Task StartAsync(string filePath, AudioRecorderOptions? recordingOptions =
if (recordingOptions is not null)
{
- this.audioRecorderOptions = recordingOptions;
+ audioRecorderOptions = recordingOptions;
}
audioFilePath = filePath;
@@ -65,9 +65,9 @@ public Task StartAsync(string filePath, AudioRecorderOptions? recordingOptions =
// solve some parameters needed for AudioRecord/MediaRecorder
ChannelIn channelIn =
SharedChannelTypesToAndroidChannelTypes(audioRecorderOptions.Channels, audioRecorderOptions.ThrowIfNotSupported);
- this.sampleRate = audioRecorderOptions.SampleRate;
- this.bitDepth = (int)audioRecorderOptions.BitDepth;
- this.channels = channelIn == ChannelIn.Mono ? 1 : 2;
+ sampleRate = audioRecorderOptions.SampleRate;
+ bitDepth = (int)audioRecorderOptions.BitDepth;
+ channels = channelIn == ChannelIn.Mono ? 1 : 2;
int bitRate = audioRecorderOptions.BitRate;
int numChannels = (int)audioRecorderOptions.Channels;
@@ -124,10 +124,22 @@ public Task StartAsync(string filePath, AudioRecorderOptions? recordingOptions =
}
// Create MediaRecorder
- mediaRecorder =
- new MediaRecorder(Platform.CurrentActivity
- .ApplicationContext); //needs context, obsoleted without context https://stackoverflow.com/questions/73598179/deprecated-mediarecorder-new-mediarecorder#73598440
-
+ if (OperatingSystem.IsAndroidVersionAtLeast(31))
+ {
+ if (Platform.CurrentActivity?.ApplicationContext is null)
+ {
+ throw new FailedToStartRecordingException("Android ApplicationContext is null");
+ }
+
+ //needs context, obsoleted without context https://stackoverflow.com/questions/73598179/deprecated-mediarecorder-new-mediarecorder#73598440
+ mediaRecorder =
+ new MediaRecorder(Platform.CurrentActivity.ApplicationContext);
+ }
+ else
+ {
+ mediaRecorder = new MediaRecorder();
+ }
+
mediaRecorder.Reset();
mediaRecorder.SetAudioSource(AudioSource.Mic);
mediaRecorder.SetOutputFormat(outputFormat);
diff --git a/src/Plugin.Maui.Audio/AudioRecorder/AudioRecorder.windows.cs b/src/Plugin.Maui.Audio/AudioRecorder/AudioRecorder.windows.cs
index 799c23c..4a58812 100644
--- a/src/Plugin.Maui.Audio/AudioRecorder/AudioRecorder.windows.cs
+++ b/src/Plugin.Maui.Audio/AudioRecorder/AudioRecorder.windows.cs
@@ -11,7 +11,7 @@ partial class AudioRecorder : IAudioRecorder
string audioFilePath = string.Empty;
public bool CanRecordAudio { get; private set; } = true;
- public bool IsRecording => mediaCapture != null;
+ public bool IsRecording => mediaCapture is not null;
AudioRecorderOptions audioRecorderOptions;
static readonly AudioRecorderOptions defaultOptions = new AudioRecorderOptions();
@@ -56,7 +56,7 @@ public async Task StartAsync(string filePath, AudioRecorderOptions? options = nu
CanRecordAudio = false;
DeleteMediaCapture();
- if (ex.InnerException != null && ex.InnerException.GetType() == typeof(UnauthorizedAccessException))
+ if (ex.InnerException is not null && ex.InnerException.GetType() == typeof(UnauthorizedAccessException))
{
throw ex.InnerException;
}
@@ -152,7 +152,7 @@ async Task InitMediaCapture(MediaCaptureInitializationSettings settings)
public async Task StopAsync()
{
- if (mediaCapture == null)
+ if (mediaCapture is null)
{
throw new InvalidOperationException("No recording in progress");
}
diff --git a/src/Plugin.Maui.Audio/AudioStreamer/AudioStream.macios.cs b/src/Plugin.Maui.Audio/AudioStreamer/AudioStream.macios.cs
index 72add02..d14c53c 100644
--- a/src/Plugin.Maui.Audio/AudioStreamer/AudioStream.macios.cs
+++ b/src/Plugin.Maui.Audio/AudioStreamer/AudioStream.macios.cs
@@ -46,7 +46,7 @@ public Task Start()
BufferOperation(() => audioQueue.AllocateBuffer(bufferByteSize, out bufferPtr), () =>
{
- BufferOperation(() => audioQueue.EnqueueBuffer(bufferPtr, bufferByteSize, null), () => Debug.WriteLine("AudioQueue buffer enqueued :: {0} of {1}", index + 1, countAudioBuffers));
+ BufferOperation(() => audioQueue.EnqueueBuffer(bufferPtr, bufferByteSize, null!), () => Debug.WriteLine("AudioQueue buffer enqueued :: {0} of {1}", index + 1, countAudioBuffers));
});
}
@@ -150,11 +150,12 @@ void QueueInputCompleted(object? sender, InputCompletedEventArgs e)
// check if active again, because the auto stop logic may stop the audio queue from within this handler!
if (Active)
{
- BufferOperation(() => audioQueue.EnqueueBuffer(e.IntPtrBuffer, null), null, status =>
- {
- Debug.WriteLine("AudioStream.QueueInputCompleted() :: audioQueue.EnqueueBuffer returned non-Ok status :: {0}", status);
- OnException?.Invoke(this, new Exception($"audioQueue.EnqueueBuffer returned non-Ok status :: {status}"));
- });
+ BufferOperation(() => audioQueue?.EnqueueBuffer(e.IntPtrBuffer, null!) ?? AudioQueueStatus.InvalidBuffer,
+ null, status =>
+ {
+ Debug.WriteLine("AudioStream.QueueInputCompleted() :: audioQueue.EnqueueBuffer returned non-Ok status :: {0}", status);
+ OnException?.Invoke(this, new Exception($"audioQueue.EnqueueBuffer returned non-Ok status :: {status}"));
+ });
}
}
catch (Exception ex)
diff --git a/src/Plugin.Maui.Audio/AudioStreamer/AudioStreamer.net.cs b/src/Plugin.Maui.Audio/AudioStreamer/AudioStreamer.net.cs
index c9ad170..7165fc8 100644
--- a/src/Plugin.Maui.Audio/AudioStreamer/AudioStreamer.net.cs
+++ b/src/Plugin.Maui.Audio/AudioStreamer/AudioStreamer.net.cs
@@ -8,38 +8,43 @@ public partial class AudioStreamer : IAudioStreamer
///
/// Gets whether the device is capable of streaming audio.
///
- public bool CanStreamAudio => false;
+ public bool CanStreamAudio => throw new PlatformNotSupportedException();
///
/// Gets whether the streamer is currently streaming audio.
///
- public bool IsStreaming => false;
+ public bool IsStreaming => throw new PlatformNotSupportedException();
///
/// Gets the audio streaming options.
///
- public AudioStreamOptions Options { get; } = AudioManager.Current.DefaultStreamerOptions;
+ public AudioStreamOptions Options => throw new PlatformNotSupportedException();
///
/// Captured linear PCM audio (raw WAV audio)
///
- public event EventHandler? OnAudioCaptured;
+ public event EventHandler? OnAudioCaptured
+ {
+ add
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ remove
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
///
/// Start streaming audio to .
///
/// A task representing the asynchronous operation.
- public Task StartAsync()
- {
- return Task.CompletedTask;
- }
+ public Task StartAsync() => throw new PlatformNotSupportedException();
///
/// Stop streaming.
///
/// A task representing the asynchronous operation.
- public Task StopAsync()
- {
- return Task.CompletedTask;
- }
+ public Task StopAsync() => throw new PlatformNotSupportedException();
}
\ No newline at end of file
diff --git a/src/Plugin.Maui.Audio/Plugin.Maui.Audio.csproj b/src/Plugin.Maui.Audio/Plugin.Maui.Audio.csproj
index 2dd8a41..769bbe4 100644
--- a/src/Plugin.Maui.Audio/Plugin.Maui.Audio.csproj
+++ b/src/Plugin.Maui.Audio/Plugin.Maui.Audio.csproj
@@ -70,7 +70,7 @@
-
+
diff --git a/src/Plugin.Maui.Audio/RawAudioSource.cs b/src/Plugin.Maui.Audio/RawAudioSource.cs
index 805a0ed..d4e3e77 100644
--- a/src/Plugin.Maui.Audio/RawAudioSource.cs
+++ b/src/Plugin.Maui.Audio/RawAudioSource.cs
@@ -26,12 +26,12 @@ public enum BitsPerSample
///
public class RawAudioSource : IAudioSource
{
- readonly byte[] _soundData;
- readonly int _sampleRate;
- readonly int _nbOfChannels;
- readonly BitsPerSample _bitsPerSample;
+ readonly byte[] soundData;
+ readonly int sampleRate;
+ readonly int nbOfChannels;
+ readonly BitsPerSample bitsPerSample;
- byte[] _withHeader;
+ byte[]? withHeader;
///
/// Initializes a new instance of the class with 8-bit samples.
@@ -54,27 +54,34 @@ public RawAudioSource(ReadOnlySpan soundData, int sampleRate, int nbOfChan
/// Bits per sample (e.g., 8 or 16).
public RawAudioSource(byte[] soundData, int sampleRate, int nbOfChannels = 1, BitsPerSample bitsPerSample = BitsPerSample.Bit8)
{
- if (soundData == null)
- throw new ArgumentNullException(nameof(soundData));
+ ArgumentNullException.ThrowIfNull(soundData);
if (sampleRate <= 0)
+ {
throw new ArgumentOutOfRangeException(nameof(sampleRate), "Sample rate must be positive.");
+ }
if (nbOfChannels <= 0)
+ {
throw new ArgumentOutOfRangeException(nameof(nbOfChannels), "Number of channels must be positive.");
+ }
if (bitsPerSample != BitsPerSample.Bit8 && bitsPerSample != BitsPerSample.Bit16)
+ {
throw new NotSupportedException($"Unsupported BitsPerSample: {bitsPerSample}. Only 8-bit and 16-bit are supported.");
+ }
// Validate sound data length based on bits per sample and number of channels
int bytesPerSample = bitsPerSample == BitsPerSample.Bit8 ? 1 : 2;
if (soundData.Length % (nbOfChannels * bytesPerSample) != 0)
+ {
throw new ArgumentException("Sound data length is not aligned with the specified number of channels and bits per sample.", nameof(soundData));
+ }
- _soundData = soundData;
- _sampleRate = sampleRate;
- _nbOfChannels = nbOfChannels;
- _bitsPerSample = bitsPerSample;
+ this.soundData = soundData;
+ this.sampleRate = sampleRate;
+ this.nbOfChannels = nbOfChannels;
+ this.bitsPerSample = bitsPerSample;
}
///
@@ -93,12 +100,9 @@ public byte[] Bytes
{
get
{
- if (_withHeader == null)
- {
- _withHeader = BuildWavFile();
- }
+ withHeader ??= BuildWavFile();
- return _withHeader;
+ return withHeader;
}
}
@@ -108,12 +112,12 @@ public byte[] Bytes
/// Byte array containing the complete WAV file.
byte[] BuildWavFile()
{
- int dataSize = _soundData.Length;
- int bytesPerSample = _bitsPerSample == BitsPerSample.Bit8 ? 1 : 2;
- int byteRate = _sampleRate * _nbOfChannels * bytesPerSample;
- short blockAlign = (short)(_nbOfChannels * bytesPerSample);
+ int dataSize = soundData.Length;
+ int bytesPerSample = this.bitsPerSample == BitsPerSample.Bit8 ? 1 : 2;
+ int byteRate = sampleRate * nbOfChannels * bytesPerSample;
+ short blockAlign = (short)(nbOfChannels * bytesPerSample);
short audioFormat = 1; // PCM
- short bitsPerSample = (short)_bitsPerSample;
+ short bitsPerSample = (short)this.bitsPerSample;
int fileSize = dataSize + 44 - 8; // Total file size minus "RIFF" and size field itself
byte[] wavHeader = new byte[44];
@@ -125,8 +129,8 @@ byte[] BuildWavFile()
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes("fmt "), 0, wavHeader, 12, 4);
Buffer.BlockCopy(BitConverter.GetBytes(16), 0, wavHeader, 16, 4);
Buffer.BlockCopy(BitConverter.GetBytes(audioFormat), 0, wavHeader, 20, 2);
- Buffer.BlockCopy(BitConverter.GetBytes((short)_nbOfChannels), 0, wavHeader, 22, 2);
- Buffer.BlockCopy(BitConverter.GetBytes(_sampleRate), 0, wavHeader, 24, 4);
+ Buffer.BlockCopy(BitConverter.GetBytes((short)nbOfChannels), 0, wavHeader, 22, 2);
+ Buffer.BlockCopy(BitConverter.GetBytes(sampleRate), 0, wavHeader, 24, 4);
Buffer.BlockCopy(BitConverter.GetBytes(byteRate), 0, wavHeader, 28, 4);
Buffer.BlockCopy(BitConverter.GetBytes(blockAlign), 0, wavHeader, 32, 2);
Buffer.BlockCopy(BitConverter.GetBytes(bitsPerSample), 0, wavHeader, 34, 2);
@@ -136,9 +140,8 @@ byte[] BuildWavFile()
byte[] wavSoundData = new byte[wavHeader.Length + dataSize];
Buffer.BlockCopy(wavHeader, 0, wavSoundData, 0, wavHeader.Length);
- Buffer.BlockCopy(_soundData, 0, wavSoundData, wavHeader.Length, dataSize);
+ Buffer.BlockCopy(soundData, 0, wavSoundData, wavHeader.Length, dataSize);
return wavSoundData;
}
}
-