Results 1 to 2 of 2

Thread: Here's how to play an Integer array as sound.

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Here's how to play an Integer array as sound.

    This code should be added to a module, and then called from wherever you need it. It plays 16bit audio from any one-dimensional Integer array with an LBound of 0.

    Code:
    Private Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" (ByRef lpszName As Any, ByVal hModule As Long, ByVal dwFlags As Long) As Long
    Private Declare Sub vbaCopyBytes Lib "msvbvm60.dll" Alias "__vbaCopyBytes" (ByVal ByteCount As Long, ByRef Dest As Any, ByRef Src As Any)
    
    Private Const SND_ASYNC As Long = &H1
    Private Const SND_MEMORY As Long = &H4
    Private Const SND_LOOP As Long = &H8
    
    Private Type RiffHeader
        ID As Long
        Size As Long
        FileFormat As Long
    End Type
    Private Type FormatHeader
        ID As Long
        Size As Long
        AudioFormat As Integer
        NumChannels As Integer
        SR As Long
        ByteRate As Long
        BytesPerSample As Integer
        BitsPerChannel As Integer
    End Type
    Private Type DataHeader
        ID As Long
        Size As Long
    End Type
    
    Public Sub PlayWave(ByRef Wave() As Integer, Optional ByVal SR As Long = 48000, Optional ByVal LoopSound As Boolean, Optional ByVal WaitTillPlayFinished As Boolean)
        Dim Flags As Long
        Dim WavFile() As Byte
        Dim RH As RiffHeader
        Dim FH As FormatHeader
        Dim DH As DataHeader
        
        Flags = SND_MEMORY
        If WaitTillPlayFinished = False Then Flags = Flags Or SND_ASYNC
        If LoopSound Then Flags = Flags Or SND_LOOP
        
        
        DH.ID = &H61746164
        DH.Size = (UBound(Wave) + 1) * 2
        
        With FH
            .ID = &H20746D66
            .Size = LenB(FH) - 8
            .AudioFormat = 1
            .NumChannels = 1
            .SR = SR
            .BitsPerChannel = 16
            .BytesPerSample = (.BitsPerChannel \ 8) * .NumChannels
            .ByteRate = .SR * .BytesPerSample
        End With
        RH.ID = &H46464952
        RH.Size = DH.Size + 8 + FH.Size + 8 + 4
        RH.FileFormat = &H45564157
    
        ReDim WavFile(RH.Size + 8 - 1)
        vbaCopyBytes LenB(RH), WavFile(0), RH
        vbaCopyBytes LenB(FH), WavFile(LenB(RH)), FH
        vbaCopyBytes LenB(DH), WavFile(LenB(RH) + LenB(FH)), DH
        vbaCopyBytes DH.Size, WavFile(LenB(RH) + LenB(FH) + LenB(DH)), Wave(0)
        
        PlaySound WavFile(0), 0, Flags
    End Sub
    
    Public Sub StopWave()
        PlaySound ByVal 0&, 0, 0
    End Sub
    The only public elements are the PlayWave and StopWave subs, so all the functionality you need are in those.
    PlayWave parameters are:
    Wave() which is an Integer array that contains the sound waveform that you want to play. It's the only required field.
    SR which is the sample rate, and it defaults to 48000 if you don't set it.
    LoopSound which is a boolean value. If true, the sound repeats indefinitely. You will need to call the StopWave sub to get it to stop playing. Otherwise it just plays through once. Default = False
    WaitTillPlayFinished is a boolean value. If true, the sound playing will be a blocking operation. That is, the rest of your code won't execute until the sound has finished playing. Otherwise it will keep playing while the rest of your code executes. Default = false.

    Note that LoopSound and WaitTillPlayFinished are mutually exclusive. You can't use them simultaneously. If you could, your program would lock up and keep playing the sound forever. To prevent this, the Windows API function that my sub calls is designed to not let this combination be used. However, instead of refusing to play at all, it seems that synchronous play flag simply overrides the looping flag, meaning that it will behave as if the synchronous play flag were set, and the looping flag is not set. Thus it will play the sound, instead of not playing, but the sound playing will be a blocking operation.

    The PlayWave sub has no parameters. You need to call it to stop the sound playing if you are playing on a loop. Also it will stop a really long sound playing early (even if looping isn't enabled), if it is called before the sound has finished playing.

  2. #2
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    5,647

    Re: Here's how to play an Integer array as sound.

    Just as a fun related project, you can also play an MP3 through PlaySound using a byte array.
    Last edited by fafalone; Oct 31st, 2020 at 03:18 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width