Play an Audio File on Linux with ALSA
On Linux there is no WASAPI or WaveOut. The NAudio.Alsa package adds
AlsaOut, an IWavePlayer that plays through ALSA. It is referenced
explicitly (it is not part of the NAudio meta-package, and the runtime
needs libasound — sudo apt install libasound2):
dotnet add package NAudio.Alsa
AlsaOut plays any IWaveProvider, so the format you can play depends
on the reader you give it. AudioFileReader, Mp3FileReader and
MediaFoundationReader are Windows-only; on Linux use the cross-platform
NAudio.Core readers (WaveFileReader, AiffFileReader,
RawSourceWaveStream) for PCM, and the NAudio.SoundFile package's
SoundFileReader for FLAC/Ogg/Opus/MP3 (see below). So for a WAV file,
use WaveFileReader:
using NAudio.Wave;
using NAudio.Wave.Alsa;
using (var audioFile = new WaveFileReader("test.wav"))
using (var outputDevice = new AlsaOut()) // default device
{
outputDevice.Init(audioFile);
outputDevice.Play();
while (outputDevice.PlaybackState == PlaybackState.Playing)
{
Thread.Sleep(200);
}
}
To play to a specific device, pass an ALSA PCM name to the constructor,
or pick one from the enumerator. Prefer default or a plughw: name
for arbitrary sample rates/formats — those go through ALSA's plug layer,
which converts; a bare hw: device only accepts rates and formats it
supports natively (the backend negotiates the nearest rate but will not
resample):
foreach (var device in AlsaDeviceEnumerator.GetPlaybackDevices())
{
Console.WriteLine($"{device.Name} - {device.Description}");
}
// var outputDevice = new AlsaOut("sysdefault:CARD=PCH");
Playing compressed formats
The cross-platform NAudio.SoundFile
package is the Linux equivalent of MediaFoundationReader: its
SoundFileReader (a WaveStream / ISampleProvider over libsndfile)
decodes FLAC, Ogg-Vorbis, Opus and MP3. It needs a system libsndfile
(sudo apt install libsndfile1); SoundFileCapabilities reports which
codecs the installed build supports:
// dotnet add package NAudio.SoundFile
using NAudio.SoundFile;
using var audioFile = new SoundFileReader("test.flac");
using var outputDevice = new AlsaOut();
outputDevice.Init(audioFile);
outputDevice.Play();
(AAC/M4A/ALAC/WMA remain out of scope — that is FFmpeg territory.)
Alternatively, MP3 alone can be played with no native dependency by
plugging a fully-managed frame decompressor such as
NLayer into Mp3FileReaderBase:
// dotnet add package NLayer.NAudioSupport
using NLayer.NAudioSupport;
using var mp3 = new Mp3FileReaderBase("test.mp3",
waveFormat => new Mp3FrameDecompressor(waveFormat));
using var outputDevice = new AlsaOut();
outputDevice.Init(mp3);
outputDevice.Play();
AlsaOut.Volume is a software gain (1.0f = unity), so you can set it
before or during playback. Handle PlaybackStopped to be notified when
playback ends or fails — its Exception is null on a normal end of
stream or an explicit Stop().