WaveOutWrite

Aus API-Wiki
Wechseln zu: Navigation, Suche

Die API-Funktion waveOutWrite weißt das Ausgabegerät an, den übergebenen Audiobuffer abzuspielen.

Declare Function waveOutWrite lib "winmm.dll" _
                 Alias "waveOutWrite" ( _
                 ByVal hWaveOut As Long, _
                 ByRef lpWaveOutHdr As WAVEHDR, _
                 ByVal uSize As Long) As Long


Parameter

hWaveOut

Handle des Devices zu dem der Buffer hinzugefügt werden soll. Siehe waveOutOpen.

lpWaveOutHdr

Zeiger auf die WAVEHDR Struktur des Buffers. Die Struktur muss mittels waveOutPrepareHeader vorbereitet worden sein.

uSize

Grösse der übergebenen WAVEHDR Struktur.

Rückgabe(n)

0 bei Erfolg, ansonsten Fehlercode.

Beispiel

In diesem Beispiel wird ein Gerät zur Ausgabe von 16 Bit 44.1kHz Mono Audiodaten geöffnet, zwei Buffer werden reserviert und in diesen werden Testdaten generiert. Schlussendlich werden die beiden Buffer ausgegeben und das Device wieder geschlossen.

'Module1
Option Explicit
 
Private Declare Function waveOutOpen Lib "winmm.dll" (hWaveOut As Long, _
        ByVal uDeviceID As Long, Format As Any, ByVal dwCallback As Long, _
        ByVal dwInstance As Long, ByVal dwFlags As Long) As Long
 
Private Declare Function waveOutPrepareHeader Lib "winmm.dll" ( _
        ByVal hWaveOut As Long, lpWaveInHdr As Any, ByVal uSize As Long) As Long
 
Private Declare Function waveOutUnprepareHeader Lib "winmm.dll" ( _
        ByVal hWaveOut As Long, lpWaveInHdr As Any, ByVal uSize As Long) As Long
 
Private Declare Function waveOutClose Lib "winmm.dll" (ByVal hWaveOut As Long) As Long
 
Private Declare Function waveOutWrite Lib "winmm.dll" (ByVal hWaveOut As Long, _
        ByRef lpWaveOutHdr As WAVEHDR, ByVal uSize As Long) As Long
 
Private Type WAVEFORMATEX
    wFormatTag          As Integer
    nChannels           As Integer
    nSamplesPerSec      As Long
    nAvgBytesPerSec     As Long
    nBlockAlign         As Integer
    wBitsPerSample      As Integer
    cbSize              As Integer
End Type
 
Private Type WAVEHDR
    lpData              As Long
    dwBufferLength      As Long
    dwBytesRecorded     As Long
    dwUser              As Long
    dwFlags             As Long
    dwLoops             As Long
    lpNext              As Long
    Reserved            As Long
End Type
 
Private Const WAVE_FORMAT_PCM As Long = 1
Private Const CALLBACK_FUNCTION As Long = &H30000
Private Const INVALID_HANDLE_VALUE As Long = -1
Private Const WOM_DONE As Long = &H3BD
 
Private hDevice As Long
 
Private udtBuffer1Hdr As WAVEHDR
Private btWaveOutBuffer1() As Byte
 
Private udtBuffer2Hdr As WAVEHDR
Private btWaveOutBuffer2() As Byte
 
Private lBufferFinished As Long
 
Public Sub TestAudioOutput()
    If OpenOutputDevice(0) Then
        CreateTestData
        If Not waveOutWrite(hDevice, udtBuffer1Hdr, LenB(udtBuffer1Hdr)) = 0 Then
            'error
        ElseIf Not waveOutWrite(hDevice, udtBuffer2Hdr, LenB(udtBuffer2Hdr)) = 0 Then
            'error
        End If
        
        Do While lBufferFinished <> 0
            'warten bis beide Buffer abgespielt wurden
        Loop
        CloseOutputDevice
    Else
        Debug.Print "Kann Gerät 0 nicht öffnen!"
    End If
End Sub
 
Private Sub CreateTestData()
    'Diese Funktion erstellt zwei verschiedene Wellenformen in den beiden Buffern
    'damit ein Unterschied hörbar ist.
    Dim x As Long
    Dim lSample As Long
 
    'Sägezahn Schwingung in Buffer 1:
    lSample = 0
    For x = 0 To UBound(btWaveOutBuffer1) Step 2
        lSample = lSample + 5
        If lSample > 32767 Then
            lSample = 0
        End If
        btWaveOutBuffer1(x) = (lSample And &HFF00&) \ &H100
        btWaveOutBuffer1(x + 1) = lSample And &HFF&
    Next
    'Sägezahn Schwingung in Buffer 2:
    lSample = 0
    For x = 0 To UBound(btWaveOutBuffer2) Step 2
        lSample = lSample + 8
        If lSample > 32767 Then
            lSample = 0
        End If
        btWaveOutBuffer2(x) = (lSample And &HFF00&) \ &H100
        btWaveOutBuffer2(x + 1) = lSample And &HFF&
    Next
End Sub
 
 
Public Function OpenOutputDevice(DevID As Long) As Boolean
    Dim udtWaveFormat As WAVEFORMATEX
 
    'Definition des abzuspielenden Formats:
    With udtWaveFormat
        .cbSize = 0
        .wFormatTag = WAVE_FORMAT_PCM   'wave format
        .nChannels = 1                  'mono
        .nSamplesPerSec = 44100         '44.1 kHz
        .wBitsPerSample = 16            '16 Bits pro Sample
        .nBlockAlign = .nChannels * .wBitsPerSample / 8
        .nAvgBytesPerSec = .nSamplesPerSec * .nBlockAlign
    End With
 
    If waveOutOpen(hDevice, DevID, udtWaveFormat, AddressOf CallBack, 0, CALLBACK_FUNCTION) <> 0 Then
        'Failed
        hDevice = INVALID_HANDLE_VALUE
    Else
        'Device erfolgreich geöffnet, jetzt zwei buffer, jeweils 1/4 sekunde
        '16 bit audio reservieren:
        ReDim btWaveOutBuffer1(udtWaveFormat.nSamplesPerSec * udtWaveFormat.nBlockAlign * 0.25 - 1)
        ReDim btWaveOutBuffer2(udtWaveFormat.nSamplesPerSec * udtWaveFormat.nBlockAlign * 0.25 - 1)
        With udtBuffer1Hdr
            .lpData = VarPtr(btWaveOutBuffer1(0))
            .dwBufferLength = UBound(btWaveOutBuffer1) + 1
            .dwUser = 1
        End With
        With udtBuffer2Hdr
            .lpData = VarPtr(btWaveOutBuffer2(0))
            .dwBufferLength = UBound(btWaveOutBuffer2) + 1
            .dwUser = 2
        End With
        If waveOutPrepareHeader(hDevice, udtBuffer1Hdr, LenB(udtBuffer1Hdr)) Or _
                waveOutPrepareHeader(hDevice, udtBuffer2Hdr, LenB(udtBuffer2Hdr)) <> 0 Then
            CloseOutputDevice
        Else
            lBufferFinished = 3
            OpenOutputDevice = True
        End If
    End If
End Function
 
Public Function CloseOutputDevice()
    If hDevice <> INVALID_HANDLE_VALUE Then
        waveOutUnprepareHeader hDevice, udtBuffer1Hdr, LenB(udtBuffer1Hdr)
        waveOutUnprepareHeader hDevice, udtBuffer2Hdr, LenB(udtBuffer2Hdr)
        waveOutClose hDevice
        hDevice = INVALID_HANDLE_VALUE
    End If
End Function
 
Private Sub CallBack(ByVal hDev As Long, ByVal uMsg As Long, dwInstance As Long, _
        dwParam1 As WAVEHDR, dwParam2 As Long)
    'Achtung: innerhalb der Callback Funktion dürfen nur wenige Funktionen und API Calls erfolgen!
    'MSDN:
    'Applications should not call any system-defined functions from inside a callback function,
    'except for EnterCriticalSection, LeaveCriticalSection, midiOutLongMsg, midiOutShortMsg,
    'OutputDebugString, PostMessage, PostThreadMessage, SetEvent, timeGetSystemTime, timeGetTime,
    'timeKillEvent, and timeSetEvent. Calling other wave functions will cause deadlock.
    '
    'Zu bedenken ist auch, dass viele VB Funktionen ihrerseits im Hintergrund APIs aufrufen und dies
    'die Limitierungen verletzen könnte. Ein Zuwiederhandeln zeigt sich meist erst in der kompilierten
    'EXE (Absturz) wohingegen der Code in der IDE fehlerfrei läuft!

    If uMsg = WOM_DONE Then
        lBufferFinished = lBufferFinished And (Not dwParam1.dwUser)
    End If
End Sub

Quelle(n)

  • MSDN US-Libary