Sound Replay in Visual Basic

Visual Basic is a widespread and easy to use programming environment that could be useful for experimental work in speech. However documentation about how to generate and replay sounds within VB programs is not readily available. This page provides some simple code for sound generation and replay of waveforms in both Visual Basic 6 and Visual Basic .NET.


DirectX

DirectX is the name Microsoft gives to a group of technologies to support audio, video and graphics applications on Windows PCs. The DirectX SDK (software development kit) can be downloaded free from the MSDN web site. The lastest version of DirectX is version 9, but for compatibility we will be using version 8 which is more widespread and is still supported. In these demonstrations we will be using the DirectSound component. End-users of DirectX applications will need the DirectX run-time components, also available from the MSDN web site.

Visual Basic 6

We present a very simple application that plays a one second tone. Set up the form to look like this with a single button called "Play":

Ensure your application references the DirectX8 Type library. Under Project|References, select this as follows:

If the DirectX8 Type library is not listed, you will need to download and install the DirectX SDK.

The code you need is then just:

    Option Explicit
    '
    ' DirectSound access
    Dim DX As DirectX8
    Dim DS As DirectSound8
    Dim dsToneBuffer As DirectSoundSecondaryBuffer8
    Dim desc As DSBUFFERDESC
    '
    ' Global variables
    Const PI = 3.14159265358979
    Const SRATE = 44100             ' Sampling Rate
    Const DUR = 1                   ' Tone duration
    Const FREQ = 500                ' Tone frequency
    Dim sbuf(0 To DUR * SRATE) As Integer
    
    Private Sub Form_Load()
    '
    ' initialise DirectSound
    Set DX = New DirectX8
    Set DS = DX.DirectSoundCreate("")
    DS.SetCooperativeLevel Me.hWnd, DSSCL_NORMAL
    '
    ' create a buffer
    desc.fxFormat.nFormatTag = WAVE_FORMAT_PCM
    desc.fxFormat.nSize = 0
    desc.fxFormat.lExtra = 0
    desc.fxFormat.nChannels = 1
    desc.fxFormat.lSamplesPerSec = SRATE
    desc.fxFormat.nBitsPerSample = 16
    desc.fxFormat.nBlockAlign = 2
    desc.fxFormat.lAvgBytesPerSec = 2 * SRATE
    desc.lFlags = 0
    desc.lBufferBytes = 2 * DUR * SRATE
    Set dsToneBuffer = DS.CreateSoundBuffer(desc)
    '
    ' create a tone
    Dim i
    For i = 0 To DUR * SRATE
        sbuf(i) = 10000 * Sin(2 * PI * FREQ * i / SRATE)
    Next i
    '
    ' copy tone to buffer
    dsToneBuffer.WriteBuffer 0, 2 * DUR * SRATE, sbuf(0), DSBLOCK_DEFAULT
    '
    End Sub
    
    Private Sub Play_Click()
    '
    ' play the tone
    dsToneBuffer.Play DSBPLAY_DEFAULT
    '
    End Sub

If you want to fill the sound buffer from a WAV file, rather than build it from scratch, use:

    Dim idesc As DSBUFFERDESC
    idesc.lFlags = 0
    Set dsToneBuffer = DS.CreateSoundBufferFromFile(App.Path & "\six.wav", idesc)

Visual Basic .NET

An excellent free version of Visual Basic .NET called Visual Basic 2005 Express Edition can be downloaded from the MSDN web site.

We present a very simple application that plays a one second tone. Set up the form to look as above with a single button called "Play". Ensure your application references the DirectX8 Type library. Under Project|Properties|References, add the reference as follows:

If the DirectX8 Type library is not listed, you will need to download and install the DirectX SDK.

The code you need is then just:

    Option Strict Off
    Option Explicit On
    Imports System.Runtime.InteropServices
    Friend Class Form1
    Inherits System.Windows.Forms.Form
    '
    ' Direct Sound access
    Dim DX As DxVBLibA.DirectX8
    Dim DS As DxVBLibA.DirectSound8
    Dim dsToneBuffer As DxVBLibA.DirectSoundSecondaryBuffer8
    Dim desc As DxVBLibA.DSBUFFERDESC
    '
    ' Global variables
    Const PI As Double = 3.14159265358979
    Const SRATE As Integer = 44100            ' Sampling Rate
    Const DUR As Double = 1                   ' Tone duration
    Const FREQ As Double = 500                ' Tone frequency
    Dim sbuf(0 To DUR * SRATE) As Short
    
    Private Sub Form1_Load(ByVal eventSender As System.Object, _
        ByVal eventArgs As System.EventArgs) Handles MyBase.Load
    '
    ' initialise DirectSound
    DX = New DxVBLibA.DirectX8
    DS = DX.DirectSoundCreate("")
    DS.SetCooperativeLevel(Me.Handle.ToInt32, _
        DxVBLibA.CONST_DSSCLFLAGS.DSSCL_NORMAL)
    '
    ' create a buffer
    desc.fxFormat.nFormatTag = DxVBLibA.CONST_DSOUND.WAVE_FORMAT_PCM
    desc.fxFormat.nSize = 0
    desc.fxFormat.lExtra = 0
    desc.fxFormat.nChannels = 1
    desc.fxFormat.lSamplesPerSec = SRATE
    desc.fxFormat.nBitsPerSample = 16
    desc.fxFormat.nBlockAlign = 2
    desc.fxFormat.lAvgBytesPerSec = 2 * SRATE
    desc.lFlags = 0
    desc.lBufferBytes = 2 * DUR * SRATE
    dsToneBuffer = DS.CreateSoundBuffer(desc)
    '
    ' create a tone
    Dim i As Integer
    For i = 0 To DUR * SRATE
        sbuf(i) = 10000 * System.Math.Sin(2 * PI * FREQ * i / SRATE)
    Next i
    '
    ' copy tone to buffer
    Dim hmem As GCHandle = GCHandle.Alloc(sbuf, GCHandleType.Pinned)
    dsToneBuffer.WriteBuffer(0, 2 * DUR * SRATE, hmem.AddrOfPinnedObject(), _
        DxVBLibA.CONST_DSBLOCKFLAGS.DSBLOCK_DEFAULT)
    hmem.Free()
    '
    End Sub
    
    Private Sub Play_Click(ByVal eventSender As System.Object, _
        ByVal eventArgs As System.EventArgs) Handles Play.Click
    '
    ' play the tone
    dsToneBuffer.Play(DxVBLibA.CONST_DSBPLAYFLAGS.DSBPLAY_DEFAULT)
    '
    End Sub
    End Class

If you want to fill the sound buffer from a WAV file, rather than build it from scratch, use:

    Public Function App_Path() As String
        Return System.AppDomain.CurrentDomain.BaseDirectory()
    End Function
    
    Dim idesc As DxVBLibA.DSBUFFERDESC idesc.lFlags = 0 dsToneBuffer = DS.CreateSoundBufferFromFile(App_Path() & "six.wav", idesc)


© 2006