Answered by:
How to play sounds not in background?

Question
-
Hello.
I want to have a background music and to when a button is clicked to play another sound. But My.Computer.Audio.Play only plays sounds in background, that will stop the music. Maybe using SoundPlayer.. but how to use it?
Thanks.
Greetings
Friday, June 3, 2016 5:57 PM
Answers
-
As has been mentioned, the Media.MediaPlayer can be used to do this, however there are other methods that can be used but, they will require a bit more code to build a sound player class. Below is a stripped down version of a class i designed for Game Sounds which can play several sounds at one time. For example, some background music that will keep looping at the same time the user is blasting the enemy with a Machine Gun.
If you want to test it out, you can create a new Form project and add a Class to it named MultiSoundPlayer. Then use the code below for it.
Imports System.Runtime.InteropServices Public Enum MCI_NOTIFY As Integer SUCCESSFUL = &H1 'the sound ended by playing all the way to the end SUPERSEDED = &H2 'the sound ended because of another mciSendString command being executed on the sound ABORTED = &H4 'the sound ended because the Stop method was called FAILURE = &H8 'the sound failed End Enum Public Class MultiSoundPlayer Inherits NativeWindow Public Event SoundEnded(ByVal SndName As String, ByVal Msg As MCI_NOTIFY) Private Snds As New Dictionary(Of String, String) Private sndcnt As Integer = 0 Private Const MM_MCINOTIFY As Integer = &H3B9 Private Const WM_NCDESTROY As Integer = &H82 <DllImport("winmm.dll", EntryPoint:="mciSendStringW")> Private Shared Function mciSendStringW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpszCommand As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszReturnString As System.Text.StringBuilder, ByVal cchReturn As UInteger, ByVal hwndCallback As IntPtr) As Integer End Function Public Sub New(ByVal ParentForm As Form) If ParentForm Is Nothing Then Throw New Exception("The ParentForm can not be Nothing") Dim cp As New CreateParams With {.Parent = ParentForm.Handle} Me.CreateHandle(cp) End Sub Public Function AddSound(ByVal SoundName As String, ByVal SndFilePath As String) As Boolean If SoundName.Trim = "" Or Not IO.File.Exists(SndFilePath) Then Return False If mciSendStringW("open " & Chr(34) & SndFilePath & Chr(34) & " alias " & "Snd_" & sndcnt.ToString, Nothing, 0, IntPtr.Zero) <> 0 Then Return False Snds.Add(SoundName, "Snd_" & sndcnt.ToString) sndcnt += 1 Return True End Function Public Function Play(ByVal SoundName As String) As Boolean If Not Snds.ContainsKey(SoundName) Then Return False mciSendStringW("seek " & Snds.Item(SoundName) & " to start", Nothing, 0, IntPtr.Zero) If mciSendStringW("play " & Snds.Item(SoundName) & " notify", Nothing, 0, Me.Handle) <> 0 Then Return False Return True End Function Public Function [Stop](ByVal SoundName As String) As Boolean If Not Snds.ContainsKey(SoundName) Then Return False If mciSendStringW("stop " & Snds.Item(SoundName), Nothing, 0, IntPtr.Zero) <> 0 Then Return False Return True End Function Public Sub CloseAndClearSounds() For Each aliasname As String In Snds.Values mciSendStringW("close " & aliasname, Nothing, 0, IntPtr.Zero) Next sndcnt = 0 Snds.Clear() End Sub Protected Overrides Sub WndProc(ByRef m As Message) If m.Msg = WM_NCDESTROY Then Me.CloseAndClearSounds() Me.ReleaseHandle() End If MyBase.WndProc(m) If m.Msg = MM_MCINOTIFY Then Dim sn As String = Snds.ElementAt((m.LParam.ToInt32 - 1)).Key RaiseEvent SoundEnded(sn, CType(m.WParam.ToInt32, MCI_NOTIFY)) End If End Sub End Class
Then you can add 1 Button to the Form and use the code below for the Form. You will need to change the paths to some (.wav or .mp3) sound files on your computer. You can add as many sounds as you want, within reason that is.
Public Class Form1
Private WithEvents Player As MultiSoundPlayer 'declare a MultiSoundPlayer class using the WithEvents keyword so you can access the SoundEnded event
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Player = New MultiSoundPlayer(Me) 'create a new instance of the MultiSoundPlayer class and pass this form as the Parent
'add each sound you want to the Player by specifying a Unique Name for each sound and the full path to the sound file
Player.AddSound("Music", "C:\Test\Sounds\BackgroundMusic.mp3")
Player.AddSound("Machine Gun", "C:\Test\Sounds\MachineGun.wav")
Player.AddSound("Crazy Laugh", "C:\Test\Sounds\CrazyLaugh.wav")
Player.Play("Music") 'start playing the background music while the form loads
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Player.Play("Crazy Laugh") 'start laughing crazily....
Player.Play("Machine Gun") 'as you blast the enemy with the machine gun.
End Sub
Private Sub Player_SoundEnded(SndName As String, Msg As MCI_NOTIFY) Handles Player.SoundEnded
'if the name of the sound that is ending is the name of the background music and the Msg is SUCCESSFUL, then replay the music or start another.
If SndName = "Music" AndAlso Msg = MCI_NOTIFY.SUCCESSFUL Then
Player.Play("Music")
End If
End Sub
End Class
If you say it can`t be done then i`ll try it
- Marked as answer by Herro wongMicrosoft contingent staff Wednesday, June 15, 2016 2:01 AM
Friday, June 3, 2016 9:52 PM -
If you are looking to play sounds at the same time then see the below link:
Paul ~~~~ Microsoft MVP (Visual Basic)
- Proposed as answer by Reed KimbleMVP Friday, June 3, 2016 7:38 PM
- Marked as answer by Herro wongMicrosoft contingent staff Wednesday, June 15, 2016 2:00 AM
Friday, June 3, 2016 7:08 PM -
You can also take a look at the example used in this codeplex project. If you factor out the "game engine" you can reuse most of that code, or use it as a template for creating your own audio player class.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
- Marked as answer by Herro wongMicrosoft contingent staff Wednesday, June 15, 2016 2:00 AM
Friday, June 3, 2016 7:39 PM
All replies
-
If you are looking to play sounds at the same time then see the below link:
Paul ~~~~ Microsoft MVP (Visual Basic)
- Proposed as answer by Reed KimbleMVP Friday, June 3, 2016 7:38 PM
- Marked as answer by Herro wongMicrosoft contingent staff Wednesday, June 15, 2016 2:00 AM
Friday, June 3, 2016 7:08 PM -
You can also take a look at the example used in this codeplex project. If you factor out the "game engine" you can reuse most of that code, or use it as a template for creating your own audio player class.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
- Marked as answer by Herro wongMicrosoft contingent staff Wednesday, June 15, 2016 2:00 AM
Friday, June 3, 2016 7:39 PM -
As has been mentioned, the Media.MediaPlayer can be used to do this, however there are other methods that can be used but, they will require a bit more code to build a sound player class. Below is a stripped down version of a class i designed for Game Sounds which can play several sounds at one time. For example, some background music that will keep looping at the same time the user is blasting the enemy with a Machine Gun.
If you want to test it out, you can create a new Form project and add a Class to it named MultiSoundPlayer. Then use the code below for it.
Imports System.Runtime.InteropServices Public Enum MCI_NOTIFY As Integer SUCCESSFUL = &H1 'the sound ended by playing all the way to the end SUPERSEDED = &H2 'the sound ended because of another mciSendString command being executed on the sound ABORTED = &H4 'the sound ended because the Stop method was called FAILURE = &H8 'the sound failed End Enum Public Class MultiSoundPlayer Inherits NativeWindow Public Event SoundEnded(ByVal SndName As String, ByVal Msg As MCI_NOTIFY) Private Snds As New Dictionary(Of String, String) Private sndcnt As Integer = 0 Private Const MM_MCINOTIFY As Integer = &H3B9 Private Const WM_NCDESTROY As Integer = &H82 <DllImport("winmm.dll", EntryPoint:="mciSendStringW")> Private Shared Function mciSendStringW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpszCommand As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszReturnString As System.Text.StringBuilder, ByVal cchReturn As UInteger, ByVal hwndCallback As IntPtr) As Integer End Function Public Sub New(ByVal ParentForm As Form) If ParentForm Is Nothing Then Throw New Exception("The ParentForm can not be Nothing") Dim cp As New CreateParams With {.Parent = ParentForm.Handle} Me.CreateHandle(cp) End Sub Public Function AddSound(ByVal SoundName As String, ByVal SndFilePath As String) As Boolean If SoundName.Trim = "" Or Not IO.File.Exists(SndFilePath) Then Return False If mciSendStringW("open " & Chr(34) & SndFilePath & Chr(34) & " alias " & "Snd_" & sndcnt.ToString, Nothing, 0, IntPtr.Zero) <> 0 Then Return False Snds.Add(SoundName, "Snd_" & sndcnt.ToString) sndcnt += 1 Return True End Function Public Function Play(ByVal SoundName As String) As Boolean If Not Snds.ContainsKey(SoundName) Then Return False mciSendStringW("seek " & Snds.Item(SoundName) & " to start", Nothing, 0, IntPtr.Zero) If mciSendStringW("play " & Snds.Item(SoundName) & " notify", Nothing, 0, Me.Handle) <> 0 Then Return False Return True End Function Public Function [Stop](ByVal SoundName As String) As Boolean If Not Snds.ContainsKey(SoundName) Then Return False If mciSendStringW("stop " & Snds.Item(SoundName), Nothing, 0, IntPtr.Zero) <> 0 Then Return False Return True End Function Public Sub CloseAndClearSounds() For Each aliasname As String In Snds.Values mciSendStringW("close " & aliasname, Nothing, 0, IntPtr.Zero) Next sndcnt = 0 Snds.Clear() End Sub Protected Overrides Sub WndProc(ByRef m As Message) If m.Msg = WM_NCDESTROY Then Me.CloseAndClearSounds() Me.ReleaseHandle() End If MyBase.WndProc(m) If m.Msg = MM_MCINOTIFY Then Dim sn As String = Snds.ElementAt((m.LParam.ToInt32 - 1)).Key RaiseEvent SoundEnded(sn, CType(m.WParam.ToInt32, MCI_NOTIFY)) End If End Sub End Class
Then you can add 1 Button to the Form and use the code below for the Form. You will need to change the paths to some (.wav or .mp3) sound files on your computer. You can add as many sounds as you want, within reason that is.
Public Class Form1
Private WithEvents Player As MultiSoundPlayer 'declare a MultiSoundPlayer class using the WithEvents keyword so you can access the SoundEnded event
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Player = New MultiSoundPlayer(Me) 'create a new instance of the MultiSoundPlayer class and pass this form as the Parent
'add each sound you want to the Player by specifying a Unique Name for each sound and the full path to the sound file
Player.AddSound("Music", "C:\Test\Sounds\BackgroundMusic.mp3")
Player.AddSound("Machine Gun", "C:\Test\Sounds\MachineGun.wav")
Player.AddSound("Crazy Laugh", "C:\Test\Sounds\CrazyLaugh.wav")
Player.Play("Music") 'start playing the background music while the form loads
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Player.Play("Crazy Laugh") 'start laughing crazily....
Player.Play("Machine Gun") 'as you blast the enemy with the machine gun.
End Sub
Private Sub Player_SoundEnded(SndName As String, Msg As MCI_NOTIFY) Handles Player.SoundEnded
'if the name of the sound that is ending is the name of the background music and the Msg is SUCCESSFUL, then replay the music or start another.
If SndName = "Music" AndAlso Msg = MCI_NOTIFY.SUCCESSFUL Then
Player.Play("Music")
End If
End Sub
End Class
If you say it can`t be done then i`ll try it
- Marked as answer by Herro wongMicrosoft contingent staff Wednesday, June 15, 2016 2:01 AM
Friday, June 3, 2016 9:52 PM -
In
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click _Player1.Open(New Uri("c:\windows\media\Windows Logon Sound.wav")) _Player1.Play() End Sub
How do I refer to a resource file?
Greetings
Saturday, June 4, 2016 6:39 PM -
In
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click _Player1.Open(New Uri("c:\windows\media\Windows Logon Sound.wav")) _Player1.Play() End Sub
How do I refer to a resource file?
Greetings
You will have to save the resource to temporary file first if you use the MediaPlayer method.Paul ~~~~ Microsoft MVP (Visual Basic)
Saturday, June 4, 2016 7:28 PM