2

Been doing VB2010 for about a year now, have recently started to push the boundary's for what kind of media i can incorporate into my forms. I haven't been able to play .wav or .mp3 files though. I have tried to follow tutorials on microsoft and other coding websites without success. Any help would be appreciated.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
Nathan Hogan
  • 23
  • 1
  • 1
  • 3
  • Hard to give advice without knowing what you have tried. A good list is at: http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/44f84924-636b-4f6a-a551-64e5ad1eef13 – John Arlen Apr 20 '12 at 15:18

1 Answers1

16

To play a wave file you can simply use this:

        My.Computer.Audio.Play("c:\temp\temp.wav")

If you want to play a mp3, wav, midi you can make some WIN32 API calls. Here's a class I created a few years ago that will allow you to play them easily. Create a class called AudioFile.vb in your project and paste this in. I haven't looked at this code in years though, hehe, it can probably stand to be cleaned up.

''' <summary>
''' This class is a wrapper for the Windows API calls to play wave, midi or mp3 files.
''' </summary>
''' <remarks>
''' </remarks>
Public Class AudioFile
'***********************************************************************************************************
'        Class:  PlayFile
'   Written By:  Blake Pell (bpell@indiana.edu)
' Initial Date:  03/31/2007
' Last Updated:  02/04/2009
'***********************************************************************************************************

' Windows API Declarations
Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Int32, ByVal hwndCallback As Int32) As Int32

''' <summary>
''' Constructor:  Location is the filename of the media to play.  Wave files and Mp3 files are the supported formats.
''' </summary>
''' <param name="Location"></param>
''' <remarks></remarks>
Public Sub New(ByVal location As String)
    Me.Filename = location
End Sub

''' <summary>
''' Plays the file that is specified as the filename.
''' </summary>
''' <remarks></remarks>
Public Sub Play()

    If _filename = "" Or Filename.Length <= 4 Then Exit Sub

    Select Case Right(Filename, 3).ToLower
        Case "mp3"
            mciSendString("open """ & _filename & """ type mpegvideo alias audiofile", Nothing, 0, IntPtr.Zero)

            Dim playCommand As String = "play audiofile from 0"

            If _wait = True Then playCommand += " wait"

            mciSendString(playCommand, Nothing, 0, IntPtr.Zero)
        Case "wav"
            mciSendString("open """ & _filename & """ type waveaudio alias audiofile", Nothing, 0, IntPtr.Zero)
            mciSendString("play audiofile from 0", Nothing, 0, IntPtr.Zero)
        Case "mid", "idi"
            mciSendString("stop midi", "", 0, 0)
            mciSendString("close midi", "", 0, 0)
            mciSendString("open sequencer!" & _filename & " alias midi", "", 0, 0)
            mciSendString("play midi", "", 0, 0)
        Case Else
            Throw New Exception("File type not supported.")
            Call Close()
    End Select

    IsPaused = False

End Sub

''' <summary>
''' Pause the current play back.
''' </summary>
''' <remarks></remarks>
Public Sub Pause()
    mciSendString("pause audiofile", Nothing, 0, IntPtr.Zero)
    IsPaused = True
End Sub

''' <summary>
''' Resume the current play back if it is currently paused.
''' </summary>
''' <remarks></remarks>
Public Sub [Resume]()
    mciSendString("resume audiofile", Nothing, 0, IntPtr.Zero)
    IsPaused = False
End Sub

''' <summary>
''' Stop the current file if it's playing.
''' </summary>
''' <remarks></remarks>
Public Sub [Stop]()
    mciSendString("stop audiofile", Nothing, 0, IntPtr.Zero)
End Sub

''' <summary>
''' Close the file.
''' </summary>
''' <remarks></remarks>
Public Sub Close()
    mciSendString("close audiofile", Nothing, 0, IntPtr.Zero)
End Sub

Private _wait As Boolean = False
''' <summary>
''' Halt the program until the .wav file is done playing.  Be careful, this will lock the entire program up until the
''' file is done playing.  It behaves as if the Windows Sleep API is called while the file is playing (and maybe it is, I don't
''' actually know, I'm just theorizing).  :P
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property Wait() As Boolean
    Get
        Return _wait
    End Get
    Set(ByVal value As Boolean)
        _wait = value
    End Set
End Property

''' <summary>
''' Sets the audio file's time format via the mciSendString API.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
ReadOnly Property Milleseconds() As Integer
    Get
        Dim buf As String = Space(255)
        mciSendString("set audiofile time format milliseconds", Nothing, 0, IntPtr.Zero)
        mciSendString("status audiofile length", buf, 255, IntPtr.Zero)

        buf = Replace(buf, Chr(0), "") ' Get rid of the nulls, they muck things up

        If buf = "" Then
            Return 0
        Else
            Return CInt(buf)
        End If
    End Get
End Property

''' <summary>
''' Gets the status of the current playback file via the mciSendString API.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
ReadOnly Property Status() As String
    Get
        Dim buf As String = Space(255)
        mciSendString("status audiofile mode", buf, 255, IntPtr.Zero)
        buf = Replace(buf, Chr(0), "")  ' Get rid of the nulls, they muck things up
        Return buf
    End Get
End Property

''' <summary>
''' Gets the file size of the current audio file.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
ReadOnly Property FileSize() As Integer
    Get
        Try
            Return My.Computer.FileSystem.GetFileInfo(_filename).Length
        Catch ex As Exception
            Return 0
        End Try
    End Get
End Property

''' <summary>
''' Gets the channels of the file via the mciSendString API.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
ReadOnly Property Channels() As Integer
    Get
        Dim buf As String = Space(255)
        mciSendString("status audiofile channels", buf, 255, IntPtr.Zero)

        If IsNumeric(buf) = True Then
            Return CInt(buf)
        Else
            Return -1
        End If
    End Get
End Property

''' <summary>
''' Used for debugging purposes.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
ReadOnly Property Debug() As String
    Get
        Dim buf As String = Space(255)
        mciSendString("status audiofile channels", buf, 255, IntPtr.Zero)

        Return Str(buf)
    End Get
End Property

Private _isPaused As Boolean = False
''' <summary>
''' Whether or not the current playback is paused.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property IsPaused() As Boolean
    Get
        Return _isPaused
    End Get
    Set(ByVal value As Boolean)
        _isPaused = value
    End Set
End Property

Private _filename As String
''' <summary>
''' The current filename of the file that is to be played back.
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property Filename() As String
    Get
        Return _filename
    End Get
    Set(ByVal value As String)

        If My.Computer.FileSystem.FileExists(value) = False Then
            Throw New System.IO.FileNotFoundException
            Exit Property
        End If

        _filename = value
    End Set
End Property

End Class

Here is some example usage of the above class:

    Dim audio As New AudioFile("C:\Temp\YourMP3File.mp3")
    audio.Play()
b.pell
  • 3,873
  • 2
  • 28
  • 39
  • 1
    I can't believe this answer has no points, +1 very good class for using MCI – ElektroStudios May 18 '13 at 10:15
  • Thank you for the compliment. :) – b.pell Aug 05 '13 at 17:57
  • 1
    Great elegant little class. Still handy in 2016! – stigzler Mar 16 '16 at 17:52
  • @stigzler Thanks. ;-) Glad it helped. – b.pell Mar 16 '16 at 19:58
  • 1
    Still handy in 2020! Just mising current playing time ;) – nelek Jun 22 '20 at 18:13
  • @nelek I have GitHub repo with some of this stuff called BasicAudio. There's both a C# and a VB.Net version. The classes there track milliseconds elapsed (they're not using the proper API's to get the exact position but it's works well enough). I'll provide the repo link (there's a NuGet package also for it 'BasicAudio' build off the C# version): https://github.com/blakepell/BasicAudio and the NuGet package is at: https://www.nuget.org/packages/BasicAudio/ The solutions in the GitHub repo support both the full framework and .Net Core although Core is Win only (e.g. the WinApi calls). – b.pell Jun 22 '20 at 21:07
  • I notice that general problem with all libraries I tried so far is duration of mp3, esspecially in some of combinations like channels = 1 (mono) or bitrate lower than 128kbps or samplerate lower than 24kHz. And that so liked VBR ;) btw. I make some nasty solution using `Timer`. It work nice but still problem with mp3 duration stay :( – nelek Jun 23 '20 at 16:40
  • It's interesting that the Timer didn't work in all cases. The channels being different or the bitrate being different shouldn't affect it since it's just counting time between when Play and Stop have been called. If you haven't already, check out NAudio. It's the most robust .NET audio software I've used. In fact, I use it for recording, it's been impeccable for me so far: https://github.com/naudio/NAudio – b.pell Jun 23 '20 at 19:10
  • @nelek Here are a few NAudio threads also show you how to play an MP3 and get the info you'd need to know the ellapsed time: https://stackoverflow.com/questions/2488426/how-to-play-a-mp3-file-using-naudio https://stackoverflow.com/questions/20982914/how-do-i-create-a-seekbar-in-c-naudio-music-player – b.pell Jun 23 '20 at 19:15