#include <windows.h>
#include <mmsystem.h>
#include <stdio.h>
/*
* Some good values for block size and count
*/
#define Block_size 8192
#define BLOCK_COUNT 20
/*
* Function prototypes
*/
static void CALLBACK Waveoutproc (hwaveout, UINT, DWORD, DWORD, DWORD);
static wavehdr* allocateblocks (int size, int count);
static void Freeblocks (wavehdr* blockarray);
static void Writeaudio (Hwaveout hwaveout, LPSTR data, int size);
/*
* Module level variables
*/
Static critical_section wavecriticalsection;
Static wavehdr* waveblocks;
static volatile int wavefreeblockcount;
static int wavecurrentblock;
static void CALLBACK Waveoutproc (
hwaveout hwaveout,
UINT umsg,
DWORD Dwinstance,
DWORD dwParam1 ,
DWORD dwParam2
)
{
/*
* Pointer to free block counter
*/
int* freeblockcounter = (int*) dwinstanc E
/*
* Ignore calls that occur due to openining and closing the
* device.
*/
if (umsg! = wom_done)
return;
EnterCriticalSection (&wavecriticalsection);
(*freeblockcounter) + +;
LeaveCriticalSection (&wavecriticalsection);
}
wavehdr* allocateblocks (int size, int count)
{
unsigned char* buffer;
int i;
wavehdr* blocks;
DWORD totalbuffersize = (size + sizeof (WAVEHDR)) * count;
/*
* Allocate memory for the entire set in one go
*/
if (buffer = (unsigned char*) HeapAlloc (
GetProcessHeap (),
Heap_zero_memory,
Totalbuffersize
)) = = NULL)
{
fprintf (stderr, "Memory allocation error\n");
ExitProcess (1);
}
/*
* and set up the pointers to each bit
*/
Blocks = (wavehdr*) buffer;
Buffer + = sizeof (WAVEHDR) * count;
for (i = 0; i < count; i++) {
Blocks[i].dwbufferlength = size;
Blocks[i].lpdata = (LPSTR) buffer;
Buffer + = size;
}
return blocks;
}
void Freeblocks (wavehdr* blockarray)
{
/*
* And this are why allocateblocks works the It does
*/
HeapFree (GetProcessHeap (), 0, Blockarray);
}
void Writeaudio (Hwaveout hwaveout, LPSTR data, int size)
{
wavehdr* current;
int remain;
Current = &waveBlocks[waveCurrentBlock];
while (Size > 0) {
/*
* First make sure the header we ' re going to use is unprepared
*/
if (Current->dwflags & whdr_prepared)
Waveoutunprepareheader (hwaveout, Current, sizeof (WAVEHDR));
if (size < (int) (Block_size-current->dwuser)) {
memcpy (Current->lpdata + current->dwuser, data, size);
Current->dwuser + = size;
Break
}
remain = block_size-current->dwuser;
memcpy (Current->lpdata + current->dwuser, data, remain);
Size-= remain;
Data + = remain;
Current->dwbufferlength = block_size;
Waveoutprepareheader (hwaveout, Current, sizeof (WAVEHDR));
Waveoutwrite (hwaveout, Current, sizeof (WAVEHDR));
EnterCriticalSection (&wavecriticalsection);
wavefreeblockcount--;
LeaveCriticalSection (&wavecriticalsection);
/*
* Wait for a block to become free
*/
while (!wavefreeblockcount)
Sleep (10);
/*
* Point to the next block
*/
wavecurrentblock++;
Wavecurrentblock%= Block_count;
Current = &waveBlocks[waveCurrentBlock];
Current->dwuser = 0;
}
}
int main (int argc, char* argv[])
{
Hwaveout hwaveout; /* Device handle */
HANDLE hfile;/* File HANDLE */
WaveFormatEx wfx; /* Look for this up in your documentation */
Char buffer[1024]; /* Intermediate buffer for reading */
int i;
/*
* Quick Argument Check
*/
/*if (argc! = 2) {
fprintf (stderr, "Usage:%s \ n", argv[0]);
ExitProcess (1);
}*/
/*
* Initialise the module variables
*/
Waveblocks = Allocateblocks (block_size, Block_count);
Wavefreeblockcount = Block_count;
wavecurrentblock= 0;
InitializeCriticalSection (&wavecriticalsection);
/*
* Try and open the file
*/
if (hfile = CreateFile (
"C:\\users\\public\\music\\sample music\\ Faye Wong-Miss 1.wav",//argv[1]
Generic_read,
File_share_read,
Null
Open_existing,
0,
Null
)) = = Invalid_handle_value)
{
fprintf (stderr, "%s:unable to open file '%s ' \ n", Argv[0], argv[1]);
ExitProcess (1);
}
/*
* Set up the WAVEFORMATEX structure.
*/
Wfx.nsamplespersec = 44100; /* Sample Rate */
Wfx.wbitspersample = 16; /* Sample Size */
Wfx.nchannels= 1; /* channels*/
wfx.cbsize = 0; /* Size of _extra_ info */
Wfx.wformattag = WAVE_FORMAT_PCM;
Wfx.nblockalign = (wfx.wbitspersample * wfx.nchannels) >> 3;
wfx.navgbytespersec = wfx.nblockalign * WFX.NSAMPLESPERSEC;
/*
* Try to open the default wave device. Wave_mapper is
* A constant defined in mmsystem.h, it always points to the
* Default wave device on the system (some people has 2 or
* More sound cards).
*/
if (Waveoutopen (
&hwaveout,
Wave_mapper,
&WFX,
(DWORD_PTR) Waveoutproc,
(DWORD_PTR) &wavefreeblockcount,
Callback_function
)! = Mmsyserr_noerror)
{
fprintf (stderr, "%s:unable to open Wave mapper device\n", argv[0]);
ExitProcess (1);
}
/*
* Playback loop
*/
while (1) {
DWORD readbytes;
if (! ReadFile (hfile, buffer, sizeof (buffer), &readbytes, NULL))
Break
if (readbytes = = 0)
Break
if (Readbytes < sizeof (buffer)) {
printf ("At end of buffer\n");
memset (buffer + readbytes, 0, sizeof (buffer)-readbytes);
printf ("After memcpy\n");
}
Writeaudio (hwaveout, buffer, sizeof (buffer));
}
/*
* Wait for all blocks
*/
while (Wavefreeblockcount < Block_count)
Sleep (10);
/*
* Unprepare any blocks that is still prepared
*/
for (i = 0; i < Wavefreeblockcount; i++)
if (Waveblocks[i].dwflags & whdr_prepared)
Waveoutunprepareheader (Hwaveout, &waveblocks[i], sizeof (WAVEHDR));
DeleteCriticalSection (&wavecriticalsection);
Freeblocks (waveblocks);
Waveoutclose (hwaveout);
CloseHandle (hfile);
return 0;
}
Windows inside waveout* Interface application