![]() |
Tipp 0142
|
SecondaryBuffer Read/Write
|
 |
|
Autor/Einsender: Datum: |
|
Alexander Csadek 16.10.2006 |
|
Entwicklungsumgebung: |
|
VB.Net 2003 |
DirectX-Version: |
|
DirectX 9 |
|
|
Ein sinnvoller Einsatz bei Spielen ist mir nicht eingefallen. Nur wenn man ein "Sound"-Programm erstellt, könnten die DirectSound-Funktionen
Read und Write interessant werden.
|
Zu Beginn des Tipps werden 10 verschiedene Sounds geladen, die auch durch Anklicken der Buttons einzeln abgespielt werden. Die
Ziffern der Buttons entsprechen den 10 verschiedenen Sounds.
|
Um die durch das Anklicken entstandene Ziffernfolge nach einander abspielen zu können, muss man nicht eine Routine schreiben, die prüft, ob nun
einer der Sounds aus der Ziffernfolge schon abgespielt wurde oder nicht, und darauf wartet bis der nächste abgespielt werden kann.
Natürlich könnte man auch gleich direkt die entsprechenden Sounds abspielen lassen, aber das hätte zur Folge das alle Sounds gleichzeitig
abgespielt werden - sie sollen aber nacheinander abgespielt werden.
|
Es geht auch anders. Man liest die Audio-Daten der entsprechenden Sounds aus und schreibt sie nacheinander in einen neuen SecondaryBuffer.
Hierfür wird ein neuer SecondaryBuffer erstellt, mit der Grösse aller abzuspielender Sounds. Beim Erzeugen des SecondaryBuffer wird
auch das WaveFormat eingestellt. Wenn dies fehlt, bekommt man nicht das gewünschte Ergebnis. Danach werden die Audio-Daten mit der
Funktion Read ausgelesen und nacheinander mit der Funktion Write in den anderen SecondaryBuffer geschrieben.
Wichtig ist das Nacheinander, denn sonst würde der folgende Sound den vorhergehenden überschreiben.
|
Anstatt mit einem Byte-Array können die Wav-Daten auch mit einem System.IO.MemoryStream ausgelesen werden. Hierbei ist zu beachten, dass
nach dem Read der Cursor vom MemoryStream wieder an den Anfang (BeginOrigin) gesetzt wird.
|
Der neue Sound kann in diesem Beispiel auch gleich als WAV-Datei abgespeichert werden. Da bei DirectX 9 die Funktion SaveToFile (wie
bei DirectX 7 und DirectX 8) nicht mehr zur Verfügung steht, muss dies "manuell" geschehen. Ich habe für dieses Beispiel aus dem
Microsoft DirectX 9 SDK Beispiel 'CaptureSound' die Methode CreateRIFF genommen. Mit dieser Methode wird ein entsprechender WAV-Header
erzeugt.
|
Im folgenden Code-Ausschnitt wird nur die Routine für das Abspielen der Ziffernfolge dargestellt.
|
|
|
Private Sub cmd_Play_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmd_Play.Click
Dim myDSoundBufferDesc As New BufferDescription
Dim myBufferCaps As BufferCaps
Dim intGesamtBytes As Integer
Dim intLastAdress As Integer
Dim i As Integer
'den eingegebenen Ziffern entsprechend werden die Sounds
'eingelesen und in einen neuen SoundBuffer geschrieben.
'Natürlich könnte man auch direkt die entsprechenden Sounds
'abspielen, aber dies hätte zur Folge das alle Sounds zur
'gleichen Zeit abgespielt werden.
'-> die Sounds sollen nach einander abgespielt werden.
If Trim(txt_Zahl.Text).Length > 0 Then
If Not IsNumeric(txt_Zahl.Text) Then Exit Sub
'feststellen der Länge alles Sounds in Byte
For i = 1 To txt_Zahl.Text.Length
myBufferCaps = _
DSSounds(CInt(Mid(txt_Zahl.Text, i, 1))).Caps()
intGesamtBytes += myBufferCaps.BufferBytes
Next
'auslesen des WaveFormat von einem der Sounds
'und in den neuen SoundBuffer setzen
myDSoundBufferDesc.Format = DSSounds(0).Format
myDSoundBufferDesc.StaticBuffer = True
'festlegen der Grösse des SoundBuffer's
myDSoundBufferDesc.BufferBytes = intGesamtBytes
'erstellen des neuen SoundBuffer's
If Not DSAll Is Nothing Then DSAll = Nothing
DSAll = New SecondaryBuffer(myDSoundBufferDesc, DSoundDevice)
'In dieser Schleife werden die Daten aller Sounds
'ausgelesen und nacheinander in den neuen SecondaryBuffer
'geschrieben. Es würde auch mit einem MemoryStream gehen,
'aber da der neue Sound auch gespeichert werden soll,
'ist es besser die Daten als Byte-Array zu haben.
Dim BufferData As Byte() = Nothing
'Der neue Sound soll gespeichert werden, daher wird eine
'WAV Datei mit einem entsprechendem Header erzeugt.
If chk_Save.Checked Then
CreateRIFF(Application.StartupPath & "\DTMFTon.wav", _
DSSounds(0).Format, intGesamtBytes)
End If
For i = 1 To txt_Zahl.Text.Length
myBufferCaps = _
DSSounds(CInt(Mid(txt_Zahl.Text, i, 1))).Caps()
'Auslesen der Bytes
BufferData = _
CType(DSSounds(CInt(Mid(txt_Zahl.Text, i, 1))).Read(0, _
GetType(Byte), LockFlag.None, myBufferCaps.BufferBytes), _
Byte())
'Schreiben des Byte-Arrays in den neuen Buffer
DSAll.Write(intLastAdress, BufferData, LockFlag.None)
intLastAdress += myBufferCaps.BufferBytes
'und wenn gewünscht auch in das WAV File
If chk_Save.Checked Then
Writer.Write(BufferData, 0, BufferData.Length)
End If
Next
'Falls der neue Sound gespeichert werden soll,
'muss der Writer noch geschlossen werden
If chk_Save.Checked Then
Writer.Close()
Writer = Nothing
WaveFile = Nothing
End If
DSAll.SetCurrentPosition(0)
DSAll.Play(0, BufferPlayFlags.Default)
End If
End Sub
|
|
|
|
Um diesen Tipp ausführen zu können, wird die DirectX 9 for Managed Code Runtime benötigt.
|
Dieses Beispiel funktioniert mit allen DirectX 9.0 SDK Versionen. Erstellt wurde es mit der folgenden Version:
|
Update DirectX 9.0 SDK (October 2005)
|
Pfad: C:\WINDOWS\Microsoft.NET\DirectX for Managed Code\1.0.2902.0\Microsoft.DirectX.dll
Laufzeitversion: v1.1.4322
Assemblyversion: 1.0.2902.0
|
Pfad: C:\WINDOWS\Microsoft.NET\DirectX for Managed Code\1.0.2902.0\Microsoft.DirectX.Direct3D.dll
Laufzeitversion: v1.1.4322
Assemblyversion: 1.0.2902.0
|
|
Windows-Version |
98/SE |
 |
|
ME |
 |
|
NT |
 |
|
2000 |
 |
|
XP |
 |
|
Vista |
 |
|
Win
7 |
 |
|
|
|
Download (83
kB)
|
Downloads bisher: [ 237 ]
|
|
|