Here's an example on how to read a wav file and playing the uncompressed PCM audio data inside it.
I did some heavy commenting so it should be easy to understand it.
#include <WINAPI.au3> ; Just a dummy variable I need for WINAPI_ReadFile Global $NULL ; Path to file that is going to be read Global $path = "C:\alive.wav" ; Just the three constants I'm using Global Const $WAVE_MAPPER = 4294967295 Global Const $WAVE_FORMAT_PCM = 0x01 Global Const $WHDR_BEGINLOOP = 0x04 Global $winmm = DllOpen("winmm.dll") Global $WaveDevice Global $Data; A struct that will contain all the raw audio data ; WAVEFORMATEX ; Used to open a wavedevice ; http://msdn.microsoft.com/en-us/library/ms713497(VS.85).aspx Global $WAVEFORMATEX = DllStructCreate("ushort wFormatTag;ushort nChannels;dword nSamplesPerSec;" & _ "dword nAvgBytesPerSec;ushort nBlockAlign;ushort wBitsPerSample;" & _ "ushort cbSize") ; WAVE_HEADER ; The header data that is read from the wav file ; Info found here: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ Global $WAVE_HEADER = DllStructCreate("char ChunkID[4];int ChunkSize;char Format[4];char Subchunk1ID[4];" & _ "int Subchunk1Size;short AudioFormat;short NumChannels;int SampleRate;" & _ "int ByteRate;short BlockAlign;short BitsPerSample;char Subchunk2ID[4];" & _ "int Subchunk2Size") ; WAVE_HDR ; Struct that contains the pointer to the raw audio data, which is sent to waveOutWrite ; http://msdn.microsoft.com/en-us/library/ms713724(VS.85).aspx Global $WAVE_HDR = DllStructCreate("ptr lpData;dword dwBufferLength;dword dwBytesRecorded;uint dwUser;" & _ "dword dwFlags;dword dwLoops;ptr lpNext;uint reserved") ; Open the file in read mode $fhandle = _WinAPI_CreateFile($path, 2, 2, 2) _WinAPI_ReadFile($fhandle, DllStructGetPtr($WAVE_HEADER, "ChunkID"), 4, $NULL) _WinAPI_ReadFile($fhandle, DllStructGetPtr($WAVE_HEADER, "ChunkSize"), 4, $NULL) _WinAPI_ReadFile($fhandle, DllStructGetPtr($WAVE_HEADER, "Format"), 4, $NULL) _WinAPI_ReadFile($fhandle, DllStructGetPtr($WAVE_HEADER, "Subchunk1ID"), 4, $NULL) _WinAPI_ReadFile($fhandle, DllStructGetPtr($WAVE_HEADER, "Subchunk1Size"), 4, $NULL) _WinAPI_ReadFile($fhandle, DllStructGetPtr($WAVE_HEADER, "AudioFormat"), 2, $NULL) _WinAPI_ReadFile($fhandle, DllStructGetPtr($WAVE_HEADER, "NumChannels"), 2, $NULL) _WinAPI_ReadFile($fhandle, DllStructGetPtr($WAVE_HEADER, "SampleRate"), 4, $NULL) _WinAPI_ReadFile($fhandle, DllStructGetPtr($WAVE_HEADER, "ByteRate"), 4, $NULL) _WinAPI_ReadFile($fhandle, DllStructGetPtr($WAVE_HEADER, "BlockAlign"), 2, $NULL) _WinAPI_ReadFile($fhandle, DllStructGetPtr($WAVE_HEADER, "BitsPerSample"), 2, $NULL) _WinAPI_ReadFile($fhandle, DllStructGetPtr($WAVE_HEADER, "Subchunk2ID"), 4, $NULL) _WinAPI_ReadFile($fhandle, DllStructGetPtr($WAVE_HEADER, "Subchunk2Size"), 4, $NULL) ; Before we read the heavy stuff, lets check if the data is what we expect If Not (DllStructGetData($WAVE_HEADER, "Format") == "WAVE") Then; All wav files should have the Format set to WAVE MsgBox(16, "Error", "This is not a valid wav file!" & @CRLF & "Script will terminate") Exit ElseIf DllStructGetData($WAVE_HEADER, "AudioFormat") <> 1 Then; 1 means PCM (raw audio data) which is the only thing supported MsgBox(16, "Error", "This is wav file is compressed, only uncompressed files are supported" & @CRLF & "Script will terminate") Exit ElseIf DllStructGetData($WAVE_HEADER, "BitsPerSample") <> 16 Then; THis script only deals with 16 bits, not difficult to fix though MsgBox(16, "Error", "This is wav file is has not a sample size of 16 bits, only 16 bits files are supported" & @CRLF & "Script will terminate") Exit EndIf ; Create the buffer for the raw audio data ; Since this implemenetion is made for 16 bit wav files each sample is 16 bit (2 bytes) thus each element is a short. ; Amount of samples is calculated with the total size of the raw audio data divided by the size of each sample $Data = DllStructCreate("ushort [" & DllStructGetData($WAVE_HEADER, "Subchunk2Size") / 2 & "]") _WinAPI_ReadFile($fhandle, DllStructGetPtr($Data), DllStructGetData($WAVE_HEADER, "Subchunk2Size"), $NULL) ; No more reading, the entire file is in memory! _WinAPI_CloseHandle($fhandle) ; Fill the WAVEFORMATEX structure, fortunetly the members are just like the ones we just read into memory ; Sometimes microsoft do make things easy;) DllStructSetData($WAVEFORMATEX, "wFormatTag", $WAVE_FORMAT_PCM) DllStructSetData($WAVEFORMATEX, "nChannels", DllStructGetData($WAVE_HEADER, "NumChannels")) DllStructSetData($WAVEFORMATEX, "nSamplesPerSec", DllStructGetData($WAVE_HEADER, "SampleRate")) DllStructSetData($WAVEFORMATEX, "nAvgBytesperSec", DllStructGetData($WAVE_HEADER, "ByteRate")) DllStructSetData($WAVEFORMATEX, "nBlockAlign", DllStructGetData($WAVE_HEADER, "BlockAlign")) DllStructSetData($WAVEFORMATEX, "wBitsPerSample", DllStructGetData($WAVE_HEADER, "BitsPerSample")) DllStructSetData($WAVEFORMATEX, "cbSize", 0) ; Opens the default wave out device ; The ingored parameters are for callbacks ; http://msdn.microsoft.com/en-us/library/ms713754(VS.85).aspx $call = DllCall($winmm, "int", "waveOutOpen", "ptr*", "", "uint", $WAVE_MAPPER, "ptr", DllStructGetPtr($WAVEFORMATEX), "ulong", 0, "ulong", 0, "dword", 0) $WaveDevice = $call[1] ; Fill the WAVE_HDR structure with the pointer to the raw audio and some playback info DllStructSetData($WAVE_HDR, "lpData", DllStructGetPtr($Data)) DllStructSetData($WAVE_HDR, "dwBufferLength", DllStructGetData($WAVE_HEADER, "Subchunk2Size")) DllStructSetData($WAVE_HDR, "dwFlags", $WHDR_BEGINLOOP) DllStructSetData($WAVE_HDR, "dwLoops", 1) ; Prepare the header for playback ; http://msdn.microsoft.com/en-us/library/ms713756(VS.85).aspx $call = DllCall($winmm, "int", "waveOutPrepareHeader", "ptr", $WaveDevice, "ptr", DllStructGetPtr($WAVE_HDR), "uint", DllStructGetSize($WAVE_HDR)) ; The moment has arrived, tme for p(l)ayback! ; This function is asynchronous so it returns as soon as playback has started ; http://msdn.microsoft.com/en-us/library/ms713764(VS.85).aspx DllCall($winmm, "int", "waveOutWrite", "ptr", $WaveDevice, "ptr", DllStructGetPtr($WAVE_HDR), "uint", DllStructGetSize($WAVE_HDR)) MsgBox(64, "Info", "Wav file is playing!" & @CRLF & "Press OK when you wish to stop playback")
To get the playback position you need to use the waveOutGetPosition function, but it involves using a struct in a union which is in another struct and I didn't feel like going into that tonight.
However said autoit was easier than c++ was wrong
Edited by monoceres, 07 September 2008 - 05:36 PM.













