Skip to content

Instantly share code, notes, and snippets.

@Expack3
Last active August 29, 2015 14:01
Show Gist options
  • Save Expack3/bf17450ad15a05a48cdf to your computer and use it in GitHub Desktop.
Save Expack3/bf17450ad15a05a48cdf to your computer and use it in GitHub Desktop.
/*The following method is designed to play a given line of sound samples as fast as possible.
This code was taken from the source code of XMOD, a simple, high-speed sound module/MIDI hybrid designed using the XACT subset utilized by the XNA game framework.
*/
//Variables used:
private int currLine; //indicates the current line in a song
public short playbackStatus = 0; //Used to store the current playback status. 0 = stop, 1 = pause, 2 = play, 3 = loop
private int LPS; //used to store the current tempo, or lines per second (LPS).
private Cue[] cueBank; //used to store up to 4 cues, XACT's language for "instances of a loaded sound file with playback metadata", to be used for a song; can be updated as needed
private String[] cueNames; //used to store the names of all cues to be used for a song
public int[,] soundCache; //used to store all commands required to playback a song
private void playLine()
{
if (currLine >= soundCache.GetLength(0)) //First, check to see if the current line number (currLine) exceeds the length of the first dimension of soundCache, the XMOD player's 2D command cache.
currLine = 0; //If so, reset currLine to 0.
for (int x = 0, y = 0; x < soundCache.GetLength(1); x = x + 2, y++) /*Next, create a FOR loop using integers x and y, initalized to 0.
Continue eval if x is less than the length of the second dimension of soundCache.
Since commands stored in soundCache are arranged in groups of two (commandNumber, commandParameter), increase x by 2 and y by 1 at the end of each eval.*/
{
switch (soundCache[currLine, x]) //Determine what kind of command is stored in row currLine, column x of soundCache.
{
case -3: //-3 indicates a change in tempo (internally called LPS or Lines Per Second)
lps += soundCache[currLine, x + 1]; //change LPS using the command's parameter (stored in row currLine, column x +1 of soundCache)
break;
case -2: //-2 indicates the EOF (End-Of-File) of the song.
if (playbackStatus != 3)//Check to see if the value of playbackStatus isn't equal to 3, which would indicate the song is to be looped indefinitely
{
stopXMOD(); //If is, tell the player to stop playback
}
else
loopFile(); //Otherwise, tell the player to loop the file (by setting currLine to 0)
return; //exit early from the current method
case -1: //-1 indicates no processing is to take place for the current row/column combination.
break;
default: //Otherwise, the command is referring to an instrument
if (cueBank[y] != null && cueBank[y].IsPlaying) //Is there an instance of a sound loaded into position x of cueBank, a fixed-size cache storing loaded audio file instances and accessible as an array, and is the currently-loaded instance playing?
//The latter check is important since XACT generates an exception if the program tries to stop a loaded sound file which isn't being played.
{
cueBank[y].Stop(AudioStopOptions.AsAuthored); //If both are true, stop playing the sound immediately as intended by the instance's metadata
}
loadInstance(soundCache[currLine, x], soundCache[currLine, x + 1], y); //Load a new instance of the sound at row currLine, column x in soundCache,
//the matching pitch at row currLine, column x in soundCache, and y to indicate the position to store the instance in cueBank
audioEngine.Update();
cueBank[y].Play(); //play instance y on the current line
break;
}
}
currLine++; //increment currLine by 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment