Jump to content
  • Advertisement
Sign in to follow this  
flounder

sound playing problems

This topic is 4749 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

i found some source code on playing sounds. (i would just use playsound but i want to be able control the volume and pitch of the sound) i pretty much just copy and pasted the example code and add a struct to it. the example program works but this doesn't.
//your going to need winmm.lib as well
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <mmsystem.h>
#include <malloc.h>


struct sound
{
	// Name of the WAVE file
	TCHAR* WaveName;
	// WAVEFORMATEX structure for reading in the WAVE fmt chunk
	WAVEFORMATEX WaveFormat;
	// file handle for open file 
	HMMIO HMmio;
	// subchunk information structure for reading WAVE file
	MMCKINFO MmckinfoSubchunk;
	// Count of waveform data still to play
	DWORD WaveDataPlayed;
	// Handle of opened WAVE Out device
	HWAVEOUT HWaveOut;
	// The size of each WAVEHDR's wave buffer
	DWORD WaveBufSize;
	// 2 WAVEHDR structures (for double-buffered playback of WAVE)
	WAVEHDR WaveHeader[2];
	// Ptr to last WAVEHDR played
	WAVEHDR* LastHdr;
	// Event used by callback to signal main thread
	HANDLE Event;
};

sound* sound_hold;
int sound_num,current_sound,playing_sound;

void num_sound(int num)
{
	sound_hold=new sound[num];
	current_sound=0;
	sound_num=num;
}

/* ************************** QueueWaveData() *****************************
 * Queues a buffer worth of data for the passed WAVEHDR. This is called
 * by my callback WaveOutProc().
 *
 * Returns a 0 for playback to continue. A -1 if an error. A 1 if the
 * wave has finished playing back and no more buffers need to be queued.
 */

long QueueWaveData(int num,WAVEHDR * waveHeader)
{ 
/* More WAVE data to be queued? */
	if (sound_hold[num].WaveDataPlayed)
	{
		/* Only a partial block left? */
		if (sound_hold[num].WaveDataPlayed < sound_hold[num].WaveBufSize)
		{
			/* Tell Windows to read the remaining waveform data into our allocated memory */
			if(mmioRead(sound_hold[num].HMmio, (HPSTR)waveHeader->lpData, sound_hold[num].WaveDataPlayed) != (long)sound_hold[num].WaveDataPlayed) goto bad;

			/* Set the length field to remaining amount */
			waveHeader->dwBufferLength = sound_hold[num].WaveDataPlayed;

			/* Store last WAVEHDR */
			sound_hold[num].LastHdr = waveHeader;

			/* Indicate done */
			sound_hold[num].WaveDataPlayed = 0;

			goto good;
		}

		/* Tell Windows to read another full block of waveform data into our allocated memory */
		if(mmioRead(sound_hold[num].HMmio, (HPSTR)waveHeader->lpData, sound_hold[num].WaveBufSize) != (long)sound_hold[num].WaveBufSize)
		{
bad:		/* Stop playback */
			waveOutPause(sound_hold[num].HWaveOut);

			/* Oops! */
			printf("ERROR: reading WAVE data!\n");

			return(-1);
		}

		/* Decrease # of bytes yet to play */
		sound_hold[num].WaveDataPlayed -= sound_hold[num].WaveBufSize;

good:	/* Clear the WHDR_DONE bit (which the driver set last time that
		   this WAVEHDR was sent via waveOutWrite and was played). Some
		   drivers need this to be cleared */
		waveHeader->dwFlags &= ~WHDR_DONE;
		
		/* Queue the WAVEHDR */
		waveOutWrite(sound_hold[num].HWaveOut, waveHeader, sizeof(WAVEHDR));

		/* Allow playback to continue */
		return(0);
	}

	/* Did the last WAVEHDR get a chance to play? */
	if (waveHeader == sound_hold[num].LastHdr)
	{
		/* Finished playing all WAVE data */
		return(1);
	}

	/* Allow playback to continue */
	return(0);
}

int load_sound(char* name)
{
	sound_hold[current_sound].WaveName=new char[strlen(name)];
	strncpy(sound_hold[current_sound].WaveName,name,strlen(name));
	//sound_hold[current_sound].WaveName=new TCHAR[12];
		
	MMCKINFO	mmckinfoParent;		/* parent chunk information structure */
	/* Allocate an Event signal */
	/* Allocate an Event signal */
	if ((sound_hold[current_sound].Event = CreateEvent(0, FALSE, FALSE, 0)))
	{
		/* Open the file for reading */
		if ((sound_hold[current_sound].HMmio = mmioOpen(&sound_hold[current_sound].WaveName[0], 0, MMIO_READ)))
		{
			/*	Tell Windows to locate a WAVE FileType chunk header somewhere in the file.
				This marks the start of any embedded WAVE format within the file */
			mmckinfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E'); 
			if (mmioDescend(sound_hold[current_sound].HMmio, (LPMMCKINFO)&mmckinfoParent, 0, MMIO_FINDRIFF)) 
			{
				/* Oops! No embedded WAVE format within this file */
				printf("ERROR: This file doesn't contain a WAVE!\n");

				/* Close the file and exit with error */
out:			mmioClose(sound_hold[current_sound].HMmio, 0);

				//goto out2;
			} 
 
			/* Tell Windows to locate the WAVE's "fmt " chunk, and read in its size field */
			sound_hold[current_sound].MmckinfoSubchunk.ckid = mmioFOURCC('f', 'm', 't', ' '); 
			if (mmioDescend(sound_hold[current_sound].HMmio, &sound_hold[current_sound].MmckinfoSubchunk, &mmckinfoParent, MMIO_FINDCHUNK)) 
			{
				/* Oops! The required fmt chunk was not found! */
				printf("ERROR: Required fmt chunk was not found!\n");
				goto out;
			}
 
			/* Tell Windows to read in the "fmt " chunk into our WAVEFORMATEX structure */
			if (mmioRead(sound_hold[current_sound].HMmio, (HPSTR)&sound_hold[current_sound].WaveFormat, sound_hold[current_sound].MmckinfoSubchunk.cksize) != (LRESULT)sound_hold[current_sound].MmckinfoSubchunk.cksize)
			{
				/* Oops! */
				printf("ERROR: reading the fmt chunk!\n");
				goto out;
			}
 
			/*	Ascend out of the "fmt " subchunk. If you plan to parse any other chunks in the file, you need to
				"ascend" out of any chunk that you've mmioDescend()'ed into */
			mmioAscend(sound_hold[current_sound].HMmio, &sound_hold[current_sound].MmckinfoSubchunk, 0); 

			/*	Tell Windows to locate the data chunk. Upon return, the file
				pointer will be ready to read in the actual waveform data within
				the data chunk */
			sound_hold[current_sound].MmckinfoSubchunk.ckid = mmioFOURCC('d', 'a', 't', 'a'); 
			if (mmioDescend(sound_hold[current_sound].HMmio, &sound_hold[current_sound].MmckinfoSubchunk, &mmckinfoParent, MMIO_FINDCHUNK)) 
			{
				/* Oops! */
				printf("ERROR: reading the data chunk!\n");
				goto out;
			}
 
			/* Set how many total bytes to play */
			sound_hold[current_sound].WaveDataPlayed = sound_hold[current_sound].MmckinfoSubchunk.cksize;
		}
	}
	current_sound++;
	return current_sound-1;
}

/* ************************** WaveOutProc() *****************************
 * My WAVE callback. This is called by Windows every time that some event
 * needs to be handled by my program.
 */

void CALLBACK WaveOutProc(HWAVEOUT waveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
	/* Has a buffer finished playing? */
	if (uMsg == MM_WOM_DONE)
	{
		/* NOTE: This works upon Windows 95/98/ME, but Windows NT/2000/XP do
		 * not seem to like certain operating system functions called
		 * from within a callback. One such function is waveOutWrite().
		 * If designing your app for Win NT/2000 then you should either
		 * use a different method than a callback handler (such as the
		 * Window Message method), or have your callback signal another
		 * thread to do the below queuing of the next buffer. I recommend
		 * the Windows Message method.
		 */

		/* Queue another buffer */
		if (QueueWaveData(playing_sound,(WAVEHDR *)dwParam1))
		{
			/* If no more buffers, notify PlayWave() that the WAVE is done playing */

			SetEvent(sound_hold[playing_sound].Event);
		}
	}
}

void play_sound(int num)
{
	DWORD	err;
	playing_sound=num;
	/* Open the default WAVE Out Device, specifying my callback */
	if ((err = waveOutOpen(&sound_hold[num].HWaveOut, WAVE_MAPPER, &sound_hold[num].WaveFormat, (DWORD)WaveOutProc, 0, CALLBACK_FUNCTION)))
	{
		printf("ERROR: Can't open WAVE Out Device! -- %08X\n", err);
		return;
	}

	/* I'll allocate 2 buffers large enough to hold 2 seconds worth of waveform data. NOTE: Just to make it
	   easy, I'll use 1 call to VirtualAlloc to allocate both buffers, but you can use 2 separate calls since
	   the buffers do NOT need to be contiguous */
	sound_hold[num].WaveBufSize = sound_hold[num].WaveFormat.nAvgBytesPerSec << 1;

	if (!(sound_hold[num].WaveHeader[0].lpData = (char *)VirtualAlloc(0, sound_hold[num].WaveBufSize<<1, MEM_COMMIT, PAGE_READWRITE)))
	{
		printf("ERROR: Can't allocate memory for WAVE buffer!\n");
		goto bad1;

	}

	/* Fill in WAVEHDR fields for buffer starting address and size */
	sound_hold[num].WaveHeader[1].lpData = sound_hold[num].WaveHeader[0].lpData + sound_hold[num].WaveBufSize;
	sound_hold[num].WaveHeader[1].dwBufferLength = sound_hold[num].WaveHeader[0].dwBufferLength = sound_hold[num].WaveBufSize;

	/* Leave other WAVEHDR fields at 0 */

	/* Prepare the 2 WAVEHDR's */
	if ((err = waveOutPrepareHeader(sound_hold[num].HWaveOut, &sound_hold[num].WaveHeader[0], sizeof(WAVEHDR))))
	{
		goto bad2;
	}

	if ((err = waveOutPrepareHeader(sound_hold[num].HWaveOut, &sound_hold[num].WaveHeader[1], sizeof(WAVEHDR))))
	{		
		goto bad3;
	}

	/* Queue first buffer (it starts playing because device isn't paused) */
	if (!QueueWaveData(num,&sound_hold[num].WaveHeader[0]))
	{
		/* Queue second buffer */
		if (QueueWaveData(num,&sound_hold[num].WaveHeader[1]) >= 0)
		{
			/* Wait for playback to finish. My callback notifies me when all wave data has been played */
			WaitForSingleObject(sound_hold[num].Event, INFINITE);
		}
	}

	/* Stop Windows queuing of buffers (and calling of my callback) */
	waveOutReset(sound_hold[num].HWaveOut);

	/* Unprepare WAVE buffers */
	waveOutUnprepareHeader(sound_hold[num].HWaveOut, &sound_hold[num].WaveHeader[1], sizeof(WAVEHDR));
bad3:
	waveOutUnprepareHeader(sound_hold[num].HWaveOut, &sound_hold[num].WaveHeader[0], sizeof(WAVEHDR));

bad2:
	/* Free WAVE buffers */
	VirtualFree(sound_hold[num].WaveHeader[0].lpData, sound_hold[num].WaveBufSize<<1, MEM_FREE);

bad1:
	/* Close WAVE Out device */
	waveOutClose(sound_hold[num].HWaveOut);
}

here's an example prog num_sound(2); int test_sound=load_sound("powerup.wav"); play_sound(test_sound);

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!