BenMakesGames.PlayPlayMini.NAudio 0.6.0

Prefix Reserved
dotnet add package BenMakesGames.PlayPlayMini.NAudio --version 0.6.0                
NuGet\Install-Package BenMakesGames.PlayPlayMini.NAudio -Version 0.6.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="BenMakesGames.PlayPlayMini.NAudio" Version="0.6.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add BenMakesGames.PlayPlayMini.NAudio --version 0.6.0                
#r "nuget: BenMakesGames.PlayPlayMini.NAudio, 0.6.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install BenMakesGames.PlayPlayMini.NAudio as a Cake Addin
#addin nuget:?package=BenMakesGames.PlayPlayMini.NAudio&version=0.6.0

// Install BenMakesGames.PlayPlayMini.NAudio as a Cake Tool
#tool nuget:?package=BenMakesGames.PlayPlayMini.NAudio&version=0.6.0                

What Is It?

Seamlessy-looping music is important for many games, but MonoGame's built-in music player isn't able to consistently loop music - more often than not, it lags, adding a short, but noticeable delay before looping.

PlayPlayMini.NAudio allows you to use NAudio to play music, resolving this issue, and adding support for playing multiple songs at once, and cross-fading between songs!

Hey, Listen! PlayPlayMini.NAudio is in early release; the API may change dramatically even between minor version numbers.

Buy Me a Coffee at ko-fi.com

How To Use

Required Setup

  1. Install this package.
    • dotnet add package BenMakesGames.PlayPlayMini.NAudio
  2. Do NOT add your songs to the MCGB content pipeline tool (remove them if they're already there); instead, ensure your songs are set to "copy if newer" in the project's properties.
    • You can add something like the following to your .csproj file to automatically include all songs; change the path as needed, of course:
      <ItemGroup>
         <None Update="Content\Music\**\*.*">
           <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
         </None>
      </ItemGroup>
      
  3. When adding assets to your game's GameStateManagerBuilder, use new NAudioSongMeta(...) instead of new SongMeta(...). When using new NAudioSongMeta(...), you must specify the extension of the song.
    • For example, new NAudioSongMeta("TitleTheme", "Content/Music/TitleTheme.mp3").
  4. Update your .AddServices(...) call as follows:
    .AddServices((s, c, serviceWatcher) => {
    
       ...
    
       // WaveOutEvent is only supported by Windows; for other OSes, replace WaveOutEvent with alternatives from this thread: https://github.com/naudio/NAudio/issues/585
       s.RegisterType<NAudioMusicPlayer<WaveOutEvent>>().As<INAudioMusicPlayer>()
           .SingleInstance()
           .OnActivating(audio => serviceWatcher.RegisterService(audio.Instance));
    })
    
  5. In your startup state, where you wait for content loaders to finish loading, get an INAudioMusicPlayer, and wait for it to be .FullyLoaded, too.

Hey, Listen! All songs you load must have the same sample rate (typically 44.1khz) and channel count (typically 2). When songs are loading, an error will be logged if they do not all match, and not all songs will be loaded.

Optional Setup

.mp3, .aiff, and .wav files are supported out of the box. For other formats, you will need to install additional NAudio packages and do a little extra configuration:

Add Ogg Vorbis (.ogg) Support

Add the NAudio.Vorbis package to your project.

In your game's .AddServices(...) configuration, add the following line:

s.RegisterInstance(new NAudioFileLoader("ogg", f => new VorbisWaveReader(f)));
Add FLAC (.flac) Support

Add the NAudio.Flac package to your project.

In your game's .AddServices(...) configuration, add the following line:

s.RegisterInstance(new NAudioFileLoader("flac", f => new FlacReader(f)));

Use

In your game state or services, get an INAudioMusicPlayer via the constructor (just as you would any other service), and use it to play and stop songs.

Example:

NAudioMusicPlayer
    .StopAllSongs(1000) // stop all songs, fading them out over 1 second
    .PlaySong("TitleTheme", 0); // start the TitleTheme with no fade-in time

Refer to the reference, below, for a list of available methods.

INAudioMusicPlayer Method Reference

Hey, Listen! Negative fade-in and fade-out times are treated as 0.

INAudioMusicPlayer PlaySong(string name, int fadeInMilliseconds = 0)

Starts playing the specific song, fading it in over the specified number of milliseconds.

Songs which are already playing will not be stopped! You must explicitly stop them using StopAllSongs or StopSong (below).

If the song is already playing, it will not be played again (you cannot currently play two copies of the same song at the same time). If the song is fading in, its fade-in time will not be changed.

INAudioMusicPlayer StopAllSongs(int fadeOutMilliseconds = 0)

Stops all songs, fading them out over the specified number of milliseconds.

Songs which are already fading out will not have their fade-out time changed. A fade-out time of 0 will always immediately stops all songs, however.

To cross-fade between songs, you can chain StopSongs and PlaySong calls. For example:

musicPlayer // an instance of INAudioMusicPlayer
    .StopAllSongs(1000)
    .PlaySong("TitleTheme");

INAudioMusicPlayer StopAllSongsExcept(string[] songsToContinue, int fadeOutMilliseconds = 0)

Works like StopAllSongs (above), but does NOT stop the songs named in songsToContinue.

INAudioMusicPlayer StopAllSongsExcept(string name, int fadeOutMilliseconds = 0)

Works like StopAllSongs (above), but does NOT stop the named song.

INAudioMusicPlayer StopSong(string name, int fadeOutMilliseconds = 0)

Like StopAllSongs (above), but stops only the named song.

INAudioMusicPlayer SetVolume(float volume)

Changes the volume for all songs.

bool IsPlaying(string name)

Returns true if the specific song is currently playing.

string[] GetPlayingSongs()

Returns an array of the names of all songs currently playing.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.6.0 100 10/6/2024
0.5.0 125 8/17/2024
0.4.0 115 6/2/2024
0.3.1 119 5/28/2024
0.2.0 123 4/21/2024
0.1.0 127 3/31/2024