www.pudn.com > 3DÓÎÏ·Source.rar > demo10_3.cpp


// DEMO10_3.CPP - Loading and playing a wav file 
// with real-time manipulation 
 
// INCLUDES /////////////////////////////////////////////// 
#define WIN32_LEAN_AND_MEAN   
 
#include    // include important windows stuff 
#include   
#include  
#include  // include important C/C++ stuff 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
 
#include   // directX includes 
#include  
 
// directx 7.0 compatibility 
 
#ifndef DSBCAPS_CTRLDEFAULT 
#define DSBCAPS_CTRLDEFAULT (DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME ) 
#endif 
 
// DEFINES //////////////////////////////////////////////// 
 
// defines for windows  
#define WINDOW_CLASS_NAME "WINCLASS1"  // class name 
 
#define WINDOW_WIDTH  400              // size of window 
#define WINDOW_HEIGHT 300 
#define SCREEN_WIDTH  640              // size of screen 
#define SCREEN_HEIGHT 480 
#define SCREEN_BPP    8                // bits per pixel 
 
#define MAX_SOUNDS     256 // max number of sounds in system at once  
 
// digital sound object state defines 
#define SOUND_NULL     0 // " " 
#define SOUND_LOADED   1 
#define SOUND_PLAYING  2 
#define SOUND_STOPPED  3 
 
 
// MACROS ///////////////////////////////////////////////// 
 
// these read the keyboard asynchronously 
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) 
#define KEY_UP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) 
 
// TYPES ////////////////////////////////////////////////// 
 
typedef unsigned short USHORT; 
typedef unsigned short WORD; 
typedef unsigned char  UCHAR; 
typedef unsigned char  BYTE; 
 
// this holds a single sound 
typedef struct pcm_sound_typ 
	{ 
	LPDIRECTSOUNDBUFFER dsbuffer;   // the ds buffer containing the sound 
	int state;                      // state of the sound 
	int rate;                       // playback rate 
	int size;                       // size of sound 
	int id;                         // id number of the sound 
	} pcm_sound, *pcm_sound_ptr; 
 
// PROTOTYPES ///////////////////////////////////////////// 
 
int Game_Init(void *parms=NULL); 
int Game_Shutdown(void *parms=NULL); 
int Game_Main(void *parms=NULL); 
int DSound_Load_WAV(char *filename, int control_flags = DSBCAPS_CTRLDEFAULT); 
 
// GLOBALS //////////////////////////////////////////////// 
 
HWND main_window_handle = NULL; // save the window handle 
HINSTANCE main_instance = NULL; // save the instance 
char buffer[80];                // used to print text 
 
LPDIRECTSOUND		lpds;           // directsound interface pointer 
DSBUFFERDESC		dsbd;           // directsound description 
DSCAPS				dscaps;         // directsound caps 
HRESULT				dsresult;       // general directsound result 
DSBCAPS             dsbcaps;        // directsound buffer caps 
 
LPDIRECTSOUNDBUFFER	lpdsbprimary,    // you won't need this normally 
                    lpdsbsecondary;  // the sound buffers 
 
WAVEFORMATEX        pcmwf;          // generic waveformat structure 
 
pcm_sound			sound_fx[MAX_SOUNDS];    // the array of secondary sound buffers 
 
 
HWND                freq_hwnd,      // window handles for controls 
                    volume_hwnd, 
                    pan_hwnd; 
 
 
int                 sound_id = -1;  // id of sound we load for demo 
 
// FUNCTIONS ////////////////////////////////////////////// 
 
LRESULT CALLBACK WindowProc(HWND hwnd,  
						    UINT msg,  
                            WPARAM wparam,  
                            LPARAM lparam) 
{ 
// this is the main message handler of the system 
PAINTSTRUCT	ps;		   // used in WM_PAINT 
HDC			hdc;	   // handle to a device context 
 
// what is the message  
switch(msg) 
	{	 
	case WM_CREATE:  
        { 
		// do initialization stuff here 
		return(0); 
		} break; 
 
    case WM_PAINT: 
         { 
         // start painting 
         hdc = BeginPaint(hwnd,&ps); 
         
         // first the static text 
         // set the color 
         SetTextColor(hdc,RGB(0,255,0)); 
         SetBkColor(hdc,RGB(0,0,0)); 
         SetBkMode(hdc,OPAQUE); 
 
         TextOut(hdc,160-5*7,40-20,"VOLUME        ",         strlen("VOLUME        ")); 
         TextOut(hdc,160-5*13,100-20,"PLAYBACK RATE        ",strlen("PLAYBACK RATE        ")); 
         TextOut(hdc,160-5*14,160-20,"STEREO PANNING        ",strlen("STEREO PANNING        ")); 
          
         // end painting 
         EndPaint(hwnd,&ps); 
         return(0); 
        } break; 
 
/////////////////////////////////////////////////////////// 
 
    case WM_HSCROLL: 
    case WM_VSCROLL: 
        { 
        int nscrollcode    = (int)LOWORD(wparam); // scroll bar value  
        int npos           = (int)HIWORD(wparam); // scroll box position  
        HWND hwndscrollbar = (HWND)lparam;        // handle of scroll bar  
 
        // get teh dc for printing 
        hdc = GetDC(hwnd); 
         
        // set the color 
        SetTextColor(hdc,RGB(0,255,0)); 
        SetBkColor(hdc,RGB(0,0,0)); 
        SetBkMode(hdc,OPAQUE); 
                 
        // make sure that the scroll bar is being tracked 
        if (nscrollcode==SB_THUMBPOSITION ||  
            nscrollcode==SB_THUMBTRACK)  
        { 
        // what scroll bar sent message 
        if (hwndscrollbar==volume_hwnd) 
           { 
           // re-position scroll bar 
           SetScrollPos(volume_hwnd, SB_CTL,npos,TRUE); 
           sprintf(buffer,"VOLUME=%d       ",-npos); 
            
           // output text 
           TextOut(hdc,160-5*7,40-20,buffer,strlen(buffer));  
 
           // set the volume 
           sound_fx[sound_id].dsbuffer->SetVolume(-npos); 
 
           } // end if 
        else 
        if (hwndscrollbar==freq_hwnd) 
           { 
           // re-position scroll bar 
           SetScrollPos(freq_hwnd, SB_CTL,npos,TRUE); 
           sprintf(buffer,"PLAYBACK RATE=%d      ",npos); 
      
           // output text 
           TextOut(hdc,160-5*13,100-20,buffer,strlen(buffer)); 
 
           // set the frequency 
           sound_fx[sound_id].dsbuffer->SetFrequency(npos); 
           } // end if 
        // what scroll bar sent message 
        else 
        if (hwndscrollbar==pan_hwnd) 
           { 
           // re-position scroll bar 
           SetScrollPos(pan_hwnd, SB_CTL,npos,TRUE); 
           sprintf(buffer,"STEREO PANNING=%d      ",-(npos-10000)); 
            
           // output text 
           TextOut(hdc,160-5*14,160-20,buffer,strlen(buffer)); 
  
           // set the stereo panning 
           sound_fx[sound_id].dsbuffer->SetPan(-(npos-10000)); 
           } // end if 
         
        } // end if 
 
        // release the dc 
        ReleaseDC(hwnd,hdc); 
 
        // message has been processed 
        return(0); 
 
        } break; 
 
/////////////////////////////////////////////////////////// 
 
	case WM_DESTROY:  
		{ 
		// kill the application			 
		PostQuitMessage(0); 
		return(0); 
		} break; 
 
	default:break; 
 
    } // end switch 
 
// process any messages that we didn't take care of  
return (DefWindowProc(hwnd, msg, wparam, lparam)); 
 
} // end WinProc 
 
// WINMAIN //////////////////////////////////////////////// 
 
int WINAPI WinMain(	HINSTANCE hinstance, 
					HINSTANCE hprevinstance, 
					LPSTR lpcmdline, 
					int ncmdshow) 
{ 
 
WNDCLASS winclass;	// this will hold the class we create 
HWND	 hwnd;		// generic window handle 
MSG		 msg;		// generic message 
HDC      hdc;       // generic dc 
PAINTSTRUCT ps;     // generic paintstruct 
 
// first fill in the window class stucture 
winclass.style			= CS_DBLCLKS | CS_OWNDC |  
                          CS_HREDRAW | CS_VREDRAW; 
winclass.lpfnWndProc	= WindowProc; 
winclass.cbClsExtra		= 0; 
winclass.cbWndExtra		= 0; 
winclass.hInstance		= hinstance; 
winclass.hIcon			= LoadIcon(NULL, IDI_APPLICATION); 
winclass.hCursor		= LoadCursor(NULL, IDC_ARROW); 
winclass.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH); 
winclass.lpszMenuName	= NULL;  
winclass.lpszClassName	= WINDOW_CLASS_NAME; 
 
// register the window class 
if (!RegisterClass(&winclass)) 
	return(0); 
 
// create the window, note the use of WS_POPUP 
if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class 
						  "DirectSound WAV File Loading DEMO",	 // title 
						  WS_OVERLAPPEDWINDOW | WS_VISIBLE, 
					 	  0,0,	   // x,y 
						  WINDOW_WIDTH,  // width 
                          WINDOW_HEIGHT, // height 
						  NULL,	   // handle to parent  
						  NULL,	   // handle to menu 
						  hinstance,// instance 
						  NULL)))	// creation parms 
return(0); 
 
// save the window handle and instance in a global 
main_window_handle = hwnd; 
main_instance      = hinstance; 
 
// create some scroll controls to change volume, frequency 
// and panning 
 
// create the volume control scroller 
volume_hwnd = CreateWindow("SCROLLBAR", // class 
						  "",	    // title 
						  WS_CHILD | WS_VISIBLE, 
					 	  80,40,	    // x,y 
						  160,       // width 
                          16,      // height 
						  hwnd,	    // handle to parent  
						  NULL,	    // handle to menu 
						  hinstance,// instance 
						  NULL);    // creation parms 
 
// create the frequency control scroller 
freq_hwnd = CreateWindow("SCROLLBAR", // class 
						  "",	    // title 
						  WS_CHILD | WS_VISIBLE, 
					 	  80,100,	    // x,y 
						  160,       // width 
                          16,      // height 
						  hwnd,	    // handle to parent  
						  NULL,	    // handle to menu 
						  hinstance,// instance 
						  NULL);    // creation parms 
 
// create the stereo panning control scroller 
pan_hwnd = CreateWindow("SCROLLBAR", // class 
						  "",	    // title 
						  WS_CHILD | WS_VISIBLE, 
					 	  80,160,	// x,y 
						  160,      // width 
                          16,       // height 
						  hwnd,	    // handle to parent  
						  NULL,	    // handle to menu 
						  hinstance,// instance 
						  NULL);    // creation parms 
 
 
// set range and value of each scroll bar 
SetScrollRange(volume_hwnd, SB_CTL, 0, 4000,TRUE); 
SetScrollPos(volume_hwnd, SB_CTL,0,TRUE); 
 
SetScrollRange(freq_hwnd, SB_CTL, 0, 50000,TRUE); 
SetScrollPos(freq_hwnd, SB_CTL,11000,TRUE); 
 
SetScrollRange(pan_hwnd, SB_CTL, 0, 20000,TRUE); 
SetScrollPos(pan_hwnd, SB_CTL,10000,TRUE); 
 
// perform all game console specific initialization 
// start up the directsound sound 
Game_Init(); 
 
// enter main event loop 
while(1) 
	{ 
	if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) 
		{  
		// test if this is a quit 
        if (msg.message == WM_QUIT) 
           break; 
	 
		// translate any accelerator keys 
		TranslateMessage(&msg); 
 
		// send the message to the window proc 
		DispatchMessage(&msg); 
		} // end if 
     
    // main game processing goes here 
    Game_Main(); 
 
	} // end while 
 
// shutdown game and release all resources 
Game_Shutdown(); 
 
// return to Windows like this 
return(msg.wParam); 
 
} // end WinMain 
 
// WINX GAME PROGRAMMING CONSOLE FUNCTIONS //////////////// 
 
int Game_Init(void *parms) 
{ 
// this function is where you do all the initialization  
// for your game 
 
// create a directsound object 
if (DirectSoundCreate(NULL, &lpds, NULL)!=DS_OK ) 
	return(0); 
 
// set cooperation level 
if (lpds->SetCooperativeLevel(main_window_handle,DSSCL_NORMAL)!=DS_OK) 
	return(0); 
 
// clear array out 
memset(sound_fx,0,sizeof(pcm_sound)*MAX_SOUNDS); 
	 
// initialize the sound fx array 
for (int index=0; indexStop(); 
 
		// release the buffer 
		sound_fx[index].dsbuffer->Release(); 
	 
		} // end if 
 
	// clear the record out 
	memset(&sound_fx[index],0,sizeof(pcm_sound)); 
 
	// now set up the fields 
	sound_fx[index].state = SOUND_NULL; 
	sound_fx[index].id    = index; 
 
	} // end for index 
 
// load a wav file in 
if ((sound_id = DSound_Load_WAV("FLIGHT.WAV"))!=-1) 
   { 
   // start the voc playing in looping mode 
   sound_fx[sound_id].dsbuffer->Play(0,0,DSBPLAY_LOOPING); 
   } // end if 
 
// return success 
return(1); 
 
} // end Game_Init 
 
/////////////////////////////////////////////////////////// 
 
int Game_Shutdown(void *parms) 
{ 
// this function is where you shutdown your game and 
// release all resources that you allocated 
 
// release the sound buffer 
if (sound_fx[sound_id].dsbuffer) 
   sound_fx[sound_id].dsbuffer->Release(); 
 
// release the directsoundobject 
if (lpds!=NULL) 
   lpds->Release(); 
 
// return success 
return(1); 
} // end Game_Shutdown 
 
/////////////////////////////////////////////////////////// 
 
int Game_Main(void *parms) 
{ 
// this is the workhorse of your game it will be called 
// continuously in real-time this is like main() in C 
// all the calls for you game go here! 
 
// check of user is trying to exit 
if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE)) 
    PostMessage(main_window_handle, WM_DESTROY,0,0); 
 
// return success 
return(1); 
} // end Game_Main 
 
/////////////////////////////////////////////////////////// 
 
int DSound_Load_WAV(char *filename, int control_flags) 
{ 
// this function loads a .wav file, sets up the directsound  
// buffer and loads the data into memory, the function returns  
// the id number of the sound 
 
 
HMMIO 			hwav;    // handle to wave file 
MMCKINFO		parent,  // parent chunk 
                child;   // child chunk 
WAVEFORMATEX    wfmtx;   // wave format structure 
 
int	sound_id = -1,       // id of sound to be loaded 
	index;               // looping variable 
 
UCHAR *snd_buffer,       // temporary sound buffer to hold voc data 
      *audio_ptr_1=NULL, // data ptr to first write buffer  
	  *audio_ptr_2=NULL; // data ptr to second write buffer 
 
DWORD audio_length_1=0,  // length of first write buffer 
	  audio_length_2=0;  // length of second write buffer 
			 
// step one: are there any open id's ? 
for (index=0; index < MAX_SOUNDS; index++) 
	{	 
    // make sure this sound is unused 
	if (sound_fx[index].state==SOUND_NULL) 
	   { 
	   sound_id = index; 
	   break; 
	   } // end if 
 
	} // end for index 
 
// did we get a free id? 
if (sound_id==-1) 
	return(-1); 
 
// set up chunk info structure 
parent.ckid 	    = (FOURCC)0; 
parent.cksize 	    = 0; 
parent.fccType	    = (FOURCC)0; 
parent.dwDataOffset = 0; 
parent.dwFlags		= 0; 
 
// copy data 
child = parent; 
 
// open the WAV file 
if ((hwav = mmioOpen(filename, NULL, MMIO_READ | MMIO_ALLOCBUF))==NULL) 
    return(-1); 
 
// descend into the RIFF  
parent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); 
 
if (mmioDescend(hwav, &parent, NULL, MMIO_FINDRIFF)) 
    { 
    // close the file 
    mmioClose(hwav, 0); 
 
    // return error, no wave section 
    return(-1); 	 
    } // end if 
 
// descend to the WAVEfmt  
child.ckid = mmioFOURCC('f', 'm', 't', ' '); 
 
if (mmioDescend(hwav, &child, &parent, 0)) 
    { 
    // close the file 
    mmioClose(hwav, 0); 
 
    // return error, no format section 
    return(-1); 	 
    } // end if 
 
// now read the wave format information from file 
if (mmioRead(hwav, (char *)&wfmtx, sizeof(wfmtx)) != sizeof(wfmtx)) 
    { 
    // close file 
    mmioClose(hwav, 0); 
 
    // return error, no wave format data 
    return(-1); 
    } // end if 
 
// make sure that the data format is PCM 
if (wfmtx.wFormatTag != WAVE_FORMAT_PCM) 
    { 
    // close the file 
    mmioClose(hwav, 0); 
 
    // return error, not the right data format 
    return(-1);  
    } // end if 
 
// now ascend up one level, so we can access data chunk 
if (mmioAscend(hwav, &child, 0)) 
   { 
   // close file 
   mmioClose(hwav, 0); 
 
   // return error, couldn't ascend 
   return(-1); 	 
   } // end if 
 
// descend to the data chunk  
child.ckid = mmioFOURCC('d', 'a', 't', 'a'); 
 
if (mmioDescend(hwav, &child, &parent, MMIO_FINDCHUNK)) 
    { 
    // close file 
    mmioClose(hwav, 0); 
 
    // return error, no data 
    return(-1); 	 
    } // end if 
 
// finally!!!! now all we have to do is read the data in and 
// set up the directsound buffer 
 
// allocate the memory to load sound data 
snd_buffer = (UCHAR *)malloc(child.cksize); 
 
// read the wave data  
mmioRead(hwav, (char *)snd_buffer, child.cksize); 
 
// close the file 
mmioClose(hwav, 0); 
 
// set rate and size in data structure 
sound_fx[sound_id].rate  = wfmtx.nSamplesPerSec; 
sound_fx[sound_id].size  = child.cksize; 
sound_fx[sound_id].state = SOUND_LOADED; 
 
// set up the format data structure 
memset(&pcmwf, 0, sizeof(WAVEFORMATEX)); 
 
pcmwf.wFormatTag	  = WAVE_FORMAT_PCM;  // pulse code modulation 
pcmwf.nChannels		  = 1;                // mono  
pcmwf.nSamplesPerSec  = 11025;            // always this rate 
pcmwf.nBlockAlign	  = 1;                 
pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign; 
pcmwf.wBitsPerSample  = 8; 
pcmwf.cbSize		  = 0; 
 
// prepare to create sounds buffer 
dsbd.dwSize			= sizeof(DSBUFFERDESC); 
dsbd.dwFlags		= control_flags | DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE; 
dsbd.dwBufferBytes	= child.cksize; 
dsbd.lpwfxFormat	= &pcmwf; 
 
// create the sound buffer 
if (FAILED(lpds->CreateSoundBuffer(&dsbd,&sound_fx[sound_id].dsbuffer,NULL))) 
   { 
   // release memory 
   free(snd_buffer); 
 
   // return error 
   return(-1); 
   } // end if 
 
// copy data into sound buffer 
if (FAILED(sound_fx[sound_id].dsbuffer->Lock(0,					  
								      child.cksize,			 
								      (void **) &audio_ptr_1,  
								      &audio_length_1, 
								      (void **)&audio_ptr_2,  
								      &audio_length_2, 
								      DSBLOCK_FROMWRITECURSOR))) 
								 return(0); 
 
// copy first section of circular buffer 
memcpy(audio_ptr_1, snd_buffer, audio_length_1); 
 
// copy last section of circular buffer 
memcpy(audio_ptr_2, (snd_buffer+audio_length_1),audio_length_2); 
 
// unlock the buffer 
if (FAILED(sound_fx[sound_id].dsbuffer->Unlock(audio_ptr_1,  
									    audio_length_1,  
									    audio_ptr_2,  
									    audio_length_2))) 
 							     return(0); 
 
// release the temp buffer 
free(snd_buffer); 
 
// return id 
return(sound_id); 
 
} // end DSound_Load_WAV