Code:
Public Class Audio
Implements IDisposable
Private booAbortMusic As Boolean
Private t As Threading.Thread
Private Const BASS_POS_BYTE As UInteger = 0
Private Const BASS_DEVICE_DEFAULT As UInteger = 2
'Directory my music and sounds are in.
Private Const MUSICDIR As String = "Music"
Private Const SOUNDDIR As String = "Sound"
Private Declare Function BASS_Init Lib "bass.dll" (ByVal device As Integer, ByVal freq As UInteger, ByVal flags As UInteger, ByVal win As IntPtr, ByVal clsid As UInteger) As Boolean
Private Declare Function BASS_Free Lib "bass.dll" () As Boolean
Private Declare Function BASS_ChannelStop Lib "bass.dll" (ByVal handle As IntPtr) As Boolean
Private Declare Function BASS_ChannelGetLength Lib "bass.dll" (ByVal handle As IntPtr, ByVal mode As Integer) As Integer
Private Declare Function BASS_StreamFree Lib "bass.dll" (ByVal handle As IntPtr) As Boolean
Private Declare Function BASS_ChannelGetPosition Lib "bass.dll" (ByVal handle As IntPtr, ByVal mode As Integer) As Integer
Private Declare Function BASS_ChannelPlay Lib "bass.dll" (ByVal handle As IntPtr, ByVal restart As Boolean) As Boolean
Private Declare Function BASS_SetVolume Lib "bass.dll" (ByVal volume As Single) As Boolean
Private Declare Function BASS_StreamCreateFile Lib "bass.dll" Alias "BASS_StreamCreateFile" (ByVal mem As Boolean, ByVal file As String, ByVal offset As UInteger, ByVal offsethigh As UInteger, ByVal length As UInteger, ByVal lengthhigh As UInteger, ByVal flags As UInteger) As IntPtr
Private Declare Function BASS_SampleLoad Lib "bass.dll" Alias "BASS_SampleLoad" (ByVal mem As Boolean, ByVal file As String, ByVal offset As UInteger, ByVal offsethigh As UInteger, ByVal length As UInteger, ByVal max As UInteger, ByVal flags As UInteger) As IntPtr
Private Declare Function BASS_SampleFree Lib "bass.dll" (ByVal handle As IntPtr) As Boolean
Private Declare Function BASS_SampleGetChannel Lib "bass.dll" (ByVal handle As IntPtr, ByVal onlynew As Boolean) As IntPtr
Private Declare Function BASS_SampleStop Lib "bass.dll" (ByVal handle As IntPtr) As Boolean
Private dSounds As New Dictionary(Of Integer, IntPtr)
Public Sub New()
BASS_Init(-1, 44100, BASS_DEVICE_DEFAULT, IntPtr.Zero, Nothing)
'Preload my sound effects into memory so they can be triggered quickly.
dSounds.Add(1, BASS_SampleLoad(False, String.Format("{0}\{1}\{2}", Application.StartupPath, SOUNDDIR, "Gameover.wav"), 0, 0, 0, 5, 0))
dSounds.Add(2, BASS_SampleLoad(False, String.Format("{0}\{1}\{2}", Application.StartupPath, SOUNDDIR, "LevelUp.wav"), 0, 0, 0, 5, 0))
End Sub
Public Sub PlaySound(ByVal Key As Integer)
'Play a sound effect from memory.
BASS_ChannelPlay(BASS_SampleGetChannel(dSounds(Key), False), False)
End Sub
Public Sub PlayMusic()
'Start up the music.
booAbortMusic = False
t = New Threading.Thread(AddressOf MusicThread)
t.Name = "BackgroundMusic"
t.IsBackground = True
t.Start()
End Sub
Public Sub StopMusic()
'Stop the music.
booAbortMusic = True
If t.IsAlive Then t.Join(1000)
End Sub
Public Sub Dispose() Implements System.IDisposable.Dispose
'Get rid of the Audio object.
For Each d As KeyValuePair(Of Integer, IntPtr) In dSounds
BASS_SampleFree(d.Value)
Next
StopMusic()
BASS_Free()
End Sub
Private Function Shuffle(ByVal strTempList As List(Of String)) As List(Of String)
'Shuffle a list of music randomly.
Dim rand As New Random
Dim strResult As New List(Of String)
Dim i As Integer
For j As Integer = 1 To strTempList.Count
i = rand.Next(0, strTempList.Count)
strResult.Add(strTempList.Item(i))
strTempList.RemoveAt(i)
Next
Return strResult
End Function
Private Sub MusicThread()
'This is the actual routine that's playing the music. I use a background thread to play it.
Dim strPath As String = String.Format("{0}\{1}\", Application.StartupPath, MUSICDIR)
Dim strDirs As New List(Of String)
Dim intLength As Long
Dim stream As IntPtr
strDirs.AddRange(IO.Directory.GetFiles(strPath, "*.mp3"))
strDirs.AddRange(IO.Directory.GetFiles(strPath, "*.ogg"))
strDirs = Shuffle(strDirs)
For i As Integer = 0 To strDirs.Count - 1
stream = BASS_StreamCreateFile(False, strDirs(i), 0, 0, 0, 0, 0)
intLength = BASS_ChannelGetLength(stream, BASS_POS_BYTE)
If booAbortMusic Then Exit For
If stream <> IntPtr.Zero Then
BASS_SetVolume(0.5)
BASS_ChannelPlay(stream, False)
Do Until BASS_ChannelGetPosition(stream, BASS_POS_BYTE) = intLength OrElse booAbortMusic
Threading.Thread.Sleep(1000)
Loop
End If
BASS_StreamFree(stream)
If booAbortMusic Then Exit For
Next
BASS_ChannelStop(stream)
End Sub
End Class