Add multiple audio backend framework

This commit is contained in:
Matt Nadareski
2021-10-04 21:50:44 -07:00
parent 0b060efd4a
commit 93a38ec9e9
6 changed files with 210 additions and 9 deletions

View File

@@ -0,0 +1,30 @@
namespace RedBookPlayer.Models.Hardware
{
public interface IAudioBackend
{
/// <summary>
/// Pauses the audio playback
/// </summary>
void Pause();
/// <summary>
/// Starts the playback.
/// </summary>
void Play();
/// <summary>
/// Stops the audio playback
/// </summary>
void Stop();
/// <summary>
/// Get the current playback state
/// </summary>
PlayerState GetPlayerState();
/// <summary>
/// Set the new volume value
/// </summary>
void SetVolume(float volume);
}
}

View File

@@ -0,0 +1,52 @@
using CSCore.SoundOut;
namespace RedBookPlayer.Models.Hardware.Linux
{
public class AudioBackend : IAudioBackend
{
/// <summary>
/// Sound output instance
/// </summary>
private ALSoundOut _soundOut;
public AudioBackend() { }
public AudioBackend(PlayerSource source)
{
_soundOut = new ALSoundOut(100);
_soundOut.Initialize(source);
}
#region IAudioBackend Implementation
/// <inheritdoc/>
public void Pause() => _soundOut.Pause();
/// <inheritdoc/>
public void Play() => _soundOut.Play();
/// <inheritdoc/>
public void Stop() => _soundOut.Stop();
/// <inheritdoc/>
public PlayerState GetPlayerState()
{
return (_soundOut?.PlaybackState) switch
{
PlaybackState.Paused => PlayerState.Paused,
PlaybackState.Playing => PlayerState.Playing,
PlaybackState.Stopped => PlayerState.Stopped,
_ => PlayerState.NoDisc,
};
}
/// <inheritdoc/>
public void SetVolume(float volume)
{
if (_soundOut != null)
_soundOut.Volume = volume;
}
#endregion
}
}

View File

@@ -0,0 +1,52 @@
using CSCore.SoundOut;
namespace RedBookPlayer.Models.Hardware.Mac
{
public class AudioBackend : IAudioBackend
{
/// <summary>
/// Sound output instance
/// </summary>
private ALSoundOut _soundOut;
public AudioBackend() { }
public AudioBackend(PlayerSource source)
{
_soundOut = new ALSoundOut(100);
_soundOut.Initialize(source);
}
#region IAudioBackend Implementation
/// <inheritdoc/>
public void Pause() => _soundOut.Pause();
/// <inheritdoc/>
public void Play() => _soundOut.Play();
/// <inheritdoc/>
public void Stop() => _soundOut.Stop();
/// <inheritdoc/>
public PlayerState GetPlayerState()
{
return (_soundOut?.PlaybackState) switch
{
PlaybackState.Paused => PlayerState.Paused,
PlaybackState.Playing => PlayerState.Playing,
PlaybackState.Stopped => PlayerState.Stopped,
_ => PlayerState.NoDisc,
};
}
/// <inheritdoc/>
public void SetVolume(float volume)
{
if (_soundOut != null)
_soundOut.Volume = volume;
}
#endregion
}
}

View File

@@ -1,8 +1,6 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using CSCore.SoundOut;
using NWaves.Audio;
using ReactiveUI;
using RedBookPlayer.Models.Discs;
@@ -92,7 +90,7 @@ namespace RedBookPlayer.Models.Hardware
/// <summary>
/// Sound output instance
/// </summary>
private ALSoundOut _soundOut;
private IAudioBackend _soundOut;
/// <summary>
/// Filtering stage for audio output
@@ -183,7 +181,7 @@ namespace RedBookPlayer.Models.Hardware
public int ProviderRead(byte[] buffer, int offset, int count)
{
// Set the current volume
_soundOut.Volume = (float)Volume / 100;
_soundOut.SetVolume((float)Volume / 100);
// If we have an unreadable track, just return
if(_opticalDisc.BytesPerSector <= 0)
@@ -230,7 +228,7 @@ namespace RedBookPlayer.Models.Hardware
/// </summary>
public void Play()
{
if(_soundOut.PlaybackState != PlaybackState.Playing)
if(_soundOut.GetPlayerState() != PlayerState.Playing)
_soundOut.Play();
PlayerState = PlayerState.Playing;
@@ -241,7 +239,7 @@ namespace RedBookPlayer.Models.Hardware
/// </summary>
public void Pause()
{
if(_soundOut.PlaybackState != PlaybackState.Paused)
if(_soundOut.GetPlayerState() != PlayerState.Paused)
_soundOut.Pause();
PlayerState = PlayerState.Paused;
@@ -252,7 +250,7 @@ namespace RedBookPlayer.Models.Hardware
/// </summary>
public void Stop()
{
if(_soundOut.PlaybackState != PlaybackState.Stopped)
if(_soundOut.GetPlayerState() != PlayerState.Stopped)
_soundOut.Stop();
PlayerState = PlayerState.Stopped;
@@ -368,8 +366,14 @@ namespace RedBookPlayer.Models.Hardware
if(_source == null)
{
_source = new PlayerSource(ProviderRead);
_soundOut = new ALSoundOut(100);
_soundOut.Initialize(_source);
#if LINUX
_soundOut = new Linux.AudioBackend(_source);
#elif MACOS
_soundOut = new Mac.AudioBackend(_source);
#elif WINDOWS
_soundOut = new Windows.AudioBackend(_source);
#endif
}
else
{

View File

@@ -0,0 +1,53 @@
using CSCore.SoundOut;
using PortAudioSharp;
namespace RedBookPlayer.Models.Hardware.Windows
{
public class AudioBackend : IAudioBackend
{
/// <summary>
/// Sound output instance
/// </summary>
private ALSoundOut _soundOut;
public AudioBackend() { }
public AudioBackend(PlayerSource source)
{
_soundOut = new ALSoundOut(100);
_soundOut.Initialize(source);
}
#region IAudioBackend Implementation
/// <inheritdoc/>
public void Pause() => _soundOut.Pause();
/// <inheritdoc/>
public void Play() => _soundOut.Play();
/// <inheritdoc/>
public void Stop() => _soundOut.Stop();
/// <inheritdoc/>
public PlayerState GetPlayerState()
{
return (_soundOut?.PlaybackState) switch
{
PlaybackState.Paused => PlayerState.Paused,
PlaybackState.Playing => PlayerState.Playing,
PlaybackState.Stopped => PlayerState.Stopped,
_ => PlayerState.NoDisc,
};
}
/// <inheritdoc/>
public void SetVolume(float volume)
{
if (_soundOut != null)
_soundOut.Volume = volume;
}
#endregion
}
}

View File

@@ -5,6 +5,16 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64'">
<DefineConstants>LINUX</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'osx-x64'">
<DefineConstants>MAC</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'win-x64'">
<DefineConstants>WINDOWS</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aaru.CommonTypes" Version="5.3.0" />
<PackageReference Include="Aaru.Decoders" Version="5.3.0" />