WaveOutWrite: Unterschied zwischen den Versionen

Aus API-Wiki
Wechseln zu: Navigation, Suche
K
(Beispielcode überarbeitet: Kommentar in der Callback und Loop bis Buffer fertig gespielt wurden ergänzt.)
Zeile 43: Zeile 43:
 
   
 
   
 
Private Declare Function waveOutClose Lib "winmm.dll" (ByVal hWaveOut 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, _
 
Private Declare Function waveOutWrite Lib "winmm.dll" (ByVal hWaveOut As Long, _
 
         ByRef lpWaveOutHdr As WAVEHDR, ByVal uSize As Long) As Long
 
         ByRef lpWaveOutHdr As WAVEHDR, ByVal uSize As Long) As Long
               
+
 
Private Type WAVEFORMATEX
 
Private Type WAVEFORMATEX
 
     wFormatTag          As Integer
 
     wFormatTag          As Integer
Zeile 82: Zeile 82:
 
   
 
   
 
Private lBufferFinished As Long
 
Private lBufferFinished As Long
 
+
 
Public Sub TestAudioOutput()
 
Public Sub TestAudioOutput()
 
     If OpenOutputDevice(0) Then
 
     If OpenOutputDevice(0) Then
Zeile 92: Zeile 92:
 
         End If
 
         End If
 
          
 
          
 +
        Do While lBufferFinished <> 0
 +
            'warten bis beide Buffer abgespielt wurden
 +
        Loop
 
         CloseOutputDevice
 
         CloseOutputDevice
 
     Else
 
     Else
Zeile 97: Zeile 100:
 
     End If
 
     End If
 
End Sub
 
End Sub
 
+
 
Private Sub CreateTestData()
 
Private Sub CreateTestData()
 
     'Diese Funktion erstellt zwei verschiedene Wellenformen in den beiden Buffern
 
     'Diese Funktion erstellt zwei verschiedene Wellenformen in den beiden Buffern
Zeile 103: Zeile 106:
 
     Dim x As Long
 
     Dim x As Long
 
     Dim lSample As Long
 
     Dim lSample As Long
 
+
 
     'Sägezahn Schwingung in Buffer 1:
 
     'Sägezahn Schwingung in Buffer 1:
 
     lSample = 0
 
     lSample = 0
Zeile 125: Zeile 128:
 
     Next
 
     Next
 
End Sub
 
End Sub
 
+
 
+
 
Public Function OpenOutputDevice(DevID As Long) As Boolean
 
Public Function OpenOutputDevice(DevID As Long) As Boolean
 
     Dim udtWaveFormat As WAVEFORMATEX
 
     Dim udtWaveFormat As WAVEFORMATEX
Zeile 163: Zeile 166:
 
             CloseOutputDevice
 
             CloseOutputDevice
 
         Else
 
         Else
 +
            lBufferFinished = 3
 
             OpenOutputDevice = True
 
             OpenOutputDevice = True
 
         End If
 
         End If
 
     End If
 
     End If
 
End Function
 
End Function
 
+
 
Public Function CloseOutputDevice()
 
Public Function CloseOutputDevice()
 
     If hDevice <> INVALID_HANDLE_VALUE Then
 
     If hDevice <> INVALID_HANDLE_VALUE Then
Zeile 176: Zeile 180:
 
     End If
 
     End If
 
End Function
 
End Function
 
+
 
Private Sub CallBack(ByVal hDev As Long, ByVal uMsg As Long, dwInstance As Long, _
 
Private Sub CallBack(ByVal hDev As Long, ByVal uMsg As Long, dwInstance As Long, _
 
         dwParam1 As WAVEHDR, dwParam2 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
 
     If uMsg = WOM_DONE Then
 
         lBufferFinished = lBufferFinished And (Not dwParam1.dwUser)
 
         lBufferFinished = lBufferFinished And (Not dwParam1.dwUser)
Zeile 184: Zeile 199:
 
End Sub
 
End Sub
 
</code>
 
</code>
 
  
 
==Quelle(n)==
 
==Quelle(n)==

Version vom 12. Januar 2011, 18:07 Uhr

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