Freefall63 Posted April 24, 2014 Posted April 24, 2014 Hello guys, I tried to work the low level winmm.dll functionality out in VB .NET, but encountered several problems. My goal is to play a wave file from stream using WaveOutOpen, WaveOutPrepareHeader und WaveOutWrite, using it only once to play the whole file: Imports System.GlobalizationImports System.Runtime.InteropServicesImports System.TextImports System.IOImports System.ThreadingPublic Class Form1 <StructLayout(LayoutKind.Sequential)> _ Private Structure WAVEHDR Public lpData As Integer Public dwBufferLength As Integer Public dwBytesRecorded As Integer Public dwUser As Integer Public dwFlags As Integer Public dwLoops As Integer Public lpNext As Integer Public Reserved As Integer End Structure <StructLayout(LayoutKind.Sequential)> _ Private Structure WAVEFORMATEX Public wFormatTag As Int16 Public nChannels As Int16 Public nSamplesPerSec As Int32 Public nAvgBytesPerSec As Int32 Public nBlockAlign As Int16 Public wBitsPerSample As Int16 Public cbSize As Int16 End Structure Public Const CALLBACK_WINDOW As UInteger = &H10000 Private Declare Function waveOutGetNumDevs Lib "winmm.dll" () As UInteger Private Declare Function waveOutOpen Lib "winmm.dll" (ByRef lphWaveOut As Int32, ByVal uDeviceID As Int32, ByRef lpFormat As WAVEFORMATEX, ByVal dwCallback As waveOutProc, ByVal dwInstance As Int32, ByVal dwFlags As Int32) As Int32 Private Declare Function waveOutClose Lib "winmm.dll" (ByVal hWaveOut As Int32) As Int32 Private Declare Function waveOutPrepareHeader Lib "winmm.dll" (ByVal hWaveOut As Int32, ByRef lpWaveOutHdr As IntPtr, ByVal uSize As Int32) As Int32 Private Declare Function waveOutUnprepareHeader Lib "winmm.dll" (ByVal hWaveOut As Int32, ByRef lpWaveOutHdr As IntPtr, ByVal uSize As Int32) As Int32 Private Declare Function waveOutWrite Lib "winmm.dll" (ByVal hWaveOut As Int32, ByRef lpWaveOutHdr As IntPtr, ByVal uSize As Int32) As Int32 Private Delegate Sub waveOutProc(ByVal hwo As IntPtr, ByVal uMsg As Integer, ByVal dwInstance As IntPtr, ByVal dwParam1 As IntPtr, ByVal dwParam2 As IntPtr) Dim hWaveOut As IntPtr = 0 Private callback As waveOutProc Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim Song As Stream = My.Resources.AiR___Waves_Complete_VST_RTAS_TDM_7_1_1_6_installer 'FormatDataLength lesen. Song.Seek(16, SeekOrigin.Begin) Dim FormatDataLength As Integer = Song.ReadByte '16 or 17 or 18 Bytes Sized FormatDataBlock. => Benötigt für Bytes Luft. FormatDataLength += Song.ReadByte * 256 FormatDataLength += Song.ReadByte * 256 * 256 FormatDataLength += Song.ReadByte * 256 * 256 * 256 'FormatType lesen. Song.Seek(20, SeekOrigin.Begin) Dim FormatType As Short = Song.ReadByte '1 = PCM. FormatType += Song.ReadByte * 256 'Channels lesen. Song.Seek(22, SeekOrigin.Begin) Dim Channels As Short = Song.ReadByte '2 Channels. Channels += Song.ReadByte * 256 'SampleRate lesen. Song.Seek(24, SeekOrigin.Begin) Dim SampleRate As Integer = Song.ReadByte '44100 Hz. SampleRate += Song.ReadByte * 256 SampleRate += Song.ReadByte * 256 * 256 SampleRate += Song.ReadByte * 256 * 256 * 256 'Bytes / Second lesen. Song.Seek(28, SeekOrigin.Begin) Dim BytesPerSecond As Integer = Song.ReadByte '176400 Bytes/s. BytesPerSecond += Song.ReadByte * 256 BytesPerSecond += Song.ReadByte * 256 * 256 BytesPerSecond += Song.ReadByte * 256 * 256 * 256 'Bytes / Sample lesen. Song.Seek(32, SeekOrigin.Begin) Dim BytesPerSample As Short = Song.ReadByte '4 Bytes/Sample. BytesPerSample += Song.ReadByte * 256 'Bits / Sample lesen. Song.Seek(34, SeekOrigin.Begin) Dim BitsPerSample As Short = Song.ReadByte '16 Bits/Sample. BitsPerSample += Song.ReadByte * 256 'DataSize und DataBeginOffset lesen. Dim DataSize As Integer = 0 Dim DataOffset As Byte = 0 If 18 - FormatDataLength = 2 Then '0 Bytes Luft. 'DataSize auslesen. Song.Seek(40, SeekOrigin.Begin) 'Ab Offset 44 ist alles Data innerhalb der Datasize. DataOffset = 44 ElseIf 18 - FormatDataLength = 1 Then '1 Byte Luft. 'DataSize auslesen. Song.Seek(41, SeekOrigin.Begin) 'Ab Offset 45 ist alles Data innerhalb der Datasize. DataOffset = 45 ElseIf 18 - FormatDataLength = 0 Then '2 Byte Luft. 'DataSize auslesen. Song.Seek(42, SeekOrigin.Begin) 'Ab Offset 46 ist alles Data innerhalb der Datasize. DataOffset = 46 End If DataSize += Song.ReadByte DataSize += Song.ReadByte * 256 DataSize += Song.ReadByte * 256 * 256 DataSize += Song.ReadByte * 256 * 256 * 256 Dim wfx As New WAVEFORMATEX With wfx .wFormatTag = FormatType .nChannels = Channels .nSamplesPerSec = SampleRate .nAvgBytesPerSec = BytesPerSecond .nBlockAlign = BytesPerSample .wBitsPerSample = BitsPerSample .cbSize = 0 End With waveOutOpen(hWaveOut, -1, wfx, callback, CType(0, IntPtr), 196608 Or 8) Dim bufferData(DataSize - 1) As Byte For i = 0 To DataSize - 1 bufferData(i) = Song.ReadByte Next Dim dataHandle As GCHandle = GCHandle.Alloc(bufferData, GCHandleType.Pinned) Dim wavHeader As New WAVEHDR With wavHeader .dwBufferLength = 44100 * Channels * ((BitsPerSample + 7) / 8) .dwFlags = 0 .lpData = dataHandle.AddrOfPinnedObject .dwBytesRecorded = 0 .dwUser = IntPtr.Zero .dwLoops = 0 .lpNext = IntPtr.Zero .Reserved = 0 End With Dim headerHandle As GCHandle = GCHandle.Alloc(wavHeader, GCHandleType.Pinned) MsgBox(waveOutPrepareHeader(hWaveOut, headerHandle.AddrOfPinnedObject(), bufferData.Length)) MsgBox(waveOutWrite(hWaveOut, headerHandle.AddrOfPinnedObject, bufferData.Length)) End SubEnd ClassUnfortunately, the last messagebox (WaveOutWrite) returns the code "UNPREPARED = 34". I don´t understand this, I´ve prepared the header before... Can you help me to fix this? Best regardsVB .NET Wave Player.rar
Kurapica Posted April 24, 2014 Posted April 24, 2014 I advise you to check the Source code of this Project http://www.afterdawn.com/software/source_codes/darkwave_studio.cfm Full C++ code is included. Check this file : "WaveOutDriver.cpp" the "waveOutWrite" API is used in that file.
Freefall63 Posted April 24, 2014 Author Posted April 24, 2014 Hello Kurapica Thanks for your reply. I looked at that project, source seems to be offline C++ is not the best way to learn from since memory usage in .NET differs a lot. I had this problem before: http://stackoverflow.com/questions/9217856/waveoutprepareheader-returns-invalparams and solved it using Gchandle. Now I get the problem described above...
kao Posted April 24, 2014 Posted April 24, 2014 (edited) I don't speak VB much, but... MsgBox(waveOutPrepareHeader(hWaveOut, headerHandle.AddrOfPinnedObject(), bufferData.Length))you're passing the wrong size, that's for sure. EDIT: I suggest that you google for examples using winmm from .NET. Or you can start here: http://www.pinvoke.net/default.aspx/winmm.waveoutprepareheader Edited April 24, 2014 by kao
Freefall63 Posted April 24, 2014 Author Posted April 24, 2014 Thanks Kao this sounds interesting. I could need a full source to understand the bridges between these snippets... And I ask myself, why this MsgBox(waveOutPrepareHeader(hWaveOut, headerHandle.AddrOfPinnedObject(), bufferData.Length))is valid and returns no error, even with a incorrect size?!
Kurapica Posted April 24, 2014 Posted April 24, 2014 Weird, the link was fine few hours ago ! I attached the file here anyway.DarkWave-Studio-4.2.0-Source.zip
Freefall63 Posted April 24, 2014 Author Posted April 24, 2014 Thanks, but I am not that familiar with C++ and it´s hard to understand for me It would be easier if anybody could tell me what in my source is wrong and how it should be done at this point...
kao Posted April 24, 2014 Posted April 24, 2014 So... because it's hard for you to understand other people's code, someone else has to go to greath lengths understanding your VB code and finding your mistake in it? Sorry, nope.
Freefall63 Posted April 24, 2014 Author Posted April 24, 2014 (edited) I only want to find my mistake, I don´t want to blow the full thing up...Ofc you are free to help or not xD Somebody who has experience with the waveout apican just download the attachment and open in visual studio and tell me what´s wrong. That should not be too much work I think. I don´t need somebody who googles for me, I can do that myself. I need somebody who is willing to explain me the waveout thing in .NET to get my project working. Edited April 24, 2014 by Freefall63
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now