-
Notifications
You must be signed in to change notification settings - Fork 7
Audio Streaming
It is highly recommended to check the Basic Setup page if you haven't already.
The features mentioned in this page will not work if MonoSound has not been initialized.
| Table of Contents |
|---|
| Preface |
| How to Stream Audio |
| XACT Support |
| StreamPackage |
| SegmentedOggStream |
| Other Methods |
| Stream Sources |
Audio files are large, especially XACT Wave Banks.
Hence, loading the entire file at once may take a while, and that could be undesirable for things like background music.
To remedy this predicament, MonoSound provides an API via the MonoSound.StreamLoader class which allows you to create audio streams from a file.
Audio streams are represented by the StreamPackage class, which is loaded by StreamLoader.
To load an audio stream, call StreamLoader.GetStreamedSound():
StreamPackage stream = StreamLoader.GetStreamedSound("Content/chill.ogg", looping: true);
stream.Play();By default, MonoSound supports streaming audio files from the following formats:
- WAVE (
.wav) - OGG Vorbis (
.ogg) - MPEG Audio Layer III (
.mp3) - Compiled SoundEffect (
.xnb) - XACT Banks
- Raw PCM Audio (
.pcm) viaclass PcmFormat : CustomAudioFormat
Custom audio formats outside of these can also be supported, although they have to be registered if they want to be detected by this method.
See the Custom Audio Formats page for more information.
The legacy Cross-platform Audio Creation Tool (XACT) format is also supported by MonoSound, except it uses special methods.
To load an audio stream from XACT audio files, you first need the Wave Bank (.xwb) and corresponding Sound Bank (.xsb) files.
The Sound Engine (.xgs) file generated by XACT is not used by MonoSound and can be ignored.
Then, to load the stream from the banks, call StreamLoader.GetStreamedXACTSound():
StreamPackage stream = StreamLoader.GetStreamedXACTSound("Content/Sound Bank.xsb", "Content/Wave Bank.xwb", "music", looped: true);
stream.Play();The StreamPackage class manages everything related to the audio stream, such as the sound instance used to play it, the current time of the stream in the audio, and more.
Listed below is every important API that you should be aware of:
-
SoundMetrics Metrics { get; }- The metrics for the sound
- Contains volume, pan, pitch, sound state and whether the sound has been disposed
-
AudioType type- The classification of the audio stream
-
bool IsLooping { get; set; }- Whether the stream will attempt to loop once it has reached the end of the audio data
- Deriving classes can override the looping behavior
- Default behavior when a loop is attempted due to the stream reaching the end of the audio data:
-
truemakes the audio loop -
falsedisposes the sound instance and frees the stream
-
-
TimeSpan CurrentDuration { get; }- The current location of the audio stream in the audio data
- Does not work with
Mp3Stream
-
TimeSpan MaxDuration { get; }- The length of the audio data
- Does not work with
Mp3Stream
-
void Play()- Plays or resumes the audio stream
-
void Pause()- Pauses the audio stream
-
void Resume()- Resumes the audio stream if it is paused
-
view Stop()- Stops the audio stream
- Resets the audio stream to the start
- Automatically calls
void Reset()
-
void Reset()-
virtualmethod - Called whenever the audio stream is stopped or attempts a loop
- Check
if (Metrics.State == SoundState.Stopped)for if the reset was caused by stopping the stream
-
-
void ApplyImmediateJump(double)-
protectedmethod - Intended to be used whenever the audio stream jumps to somewhere in the audio stream
- Automatically called by
void SetStreamPosition(double) - Necessary to make
CurrentDurationrecognize the position jump
-
-
void ReadSamples(double, out byte[], out int, out bool)-
abstractmethod - Reads samples from the audio stream
-
-
void SetStreamPosition(double)-
virtualmethod - Sets the location of the next batch of samples to read
- Automatically calls
void ApplyImmediateJump(double)
-
-
void ApplyFilters(params int[])- Applies the specified filter IDs to all audio data that will be read, or removes any active filters if
nullis passed - Can be called while the stream is playing
- Audio streaming currently only supports the Low Pass, High Pass and Band Pass filter types
- Applies the specified filter IDs to all audio data that will be read, or removes any active filters if
-
void AcquireLock()- Acquires a lightweight lock for use in controlling access to critical variables
- Blocks the current thread until the lock is released, unless the thread which acquired the lock is the current thread
- Must be paired with a call to
ReleaseLock() -
Accesses to and modifications on any variables used by the above methods AND outside the class should be locked
- For an example, check the source code for
SegmentedOggStream
- For an example, check the source code for
-
void ReleaseLock()- Releases the lock acquired by
AcquireLock() - Does nothing if no lock is present; otherwise, throws an exception if the current thread wasn't the thread which acquired the lock
- Releases the lock acquired by
This type in the MonoSound.Default namespace represents an .ogg stream that can have multiple (optionally) looping sections.
Example uses can be found within the MonoSound.Tests project in this repository.
To load a stream of this type, the MonoSound.Default.SegmentedOggFormat type is used. Since .ogg is already covered, this format cannot be registered.
Shown below is a snippet from MonoSound.Tests that loads the stream:
streamedSegmentedSound = (SegmentedOggStream)StreamLoader.GetStreamedSound("Content/bonetrousle.ogg", new SegmentedOggFormat(), true, new IAudioSegment[] {
// Intro
new StartSegment(TimeSpan.FromSeconds(31.95)),
// Main loop
new Segment(TimeSpan.FromSeconds(31.95), TimeSpan.FromSeconds(89.55)),
// Ending
new EndSegment(TimeSpan.FromSeconds(89.55))
});StartSegment, Segment and EndSegment are predefined types that use the MonoSound.Default.IAudioSegment interface.
Jumping to another segment can be performed immediately, or after the current segment ends.
The following methods can be used to jump to a segment:
-
void JumpTo(int, bool)- Jumps to the provided segment number
-
void JumpToStart(bool)- Jumps to the start of the first segment
-
void JumpToNextLoopSection(bool)- Jumps to the next segment
- Does nothing if the stream is in the final segment
-
void JumpToDelayedSection()- Immediately performs a jump if one is currently being delayed
There are a few additional variables and types not covered in the previous subsections.
They are listed below:
-
event OnDelayedSectionStart- This event fires whenever a delayed segment jump happens, and is then set to
null
- This event fires whenever a delayed segment jump happens, and is then set to
-
SegmentedOggStream.SegmentTracker tracker- Helper class for managing which segment the stream is currently playing
-
int TargetSegment { get; set; }- Which segment to loop through, should it loop
- Stream can be located between segments, in which case it will be updated to the first segment whose end point is after the stream's read location
-
int Count { get; }- How many segments are present in the stream
-
IAudioSegment CurrentSegment { get; }- The current segment that the stream is using
-
void GetLoopBounds(out TimeSpan, out TimeSpan)- Gets the start and loop points for the current segment
-
void GetLoopBounds(int, out TimeSpan, out TimeSpan)- Gets the start and loop points for a given segment
StreamLoader also contains other methods not related to loading streams:
-
bool IsStreaming(StreamPackage)- Returns
falseif the stream isnull, was disposed, or wasn't created viaGetStreamedSound/GetStreamedXACTSound - Returns
trueotherwise
- Returns
-
void FreeStreamedSound(ref StreamPackage)- Stops the streamed sound, disposes it, removes it from the tracked streams collection and then sets the stream to
null
- Stops the streamed sound, disposes it, removes it from the tracked streams collection and then sets the stream to
-
void FreeStreamedSound<T>(ref T) where T : StreamPackage- Generic variant for the previous method
MonoSound also supports loading audio from System.IO.Stream objects, although the API is slightly different.
For non-XACT audio, an additional MonoSound.AudioType constant has to be provided to indicate what format the stream is in.
The aforementioned methods have the following definitions when loading from Stream objects:
GetStreamedSound
StreamPackage GetStreamedSound(Stream sampleSource, AudioType fileIdentifier, bool looping)GetStreamedXACTSound
StreamPackage GetStreamedXACTSound(Stream soundBankSource, string soundBankIdentifier, Stream waveBankSource, string waveBankIdentifier, string cueName, bool looping)