Hey all.

Im working on a project that manipulates Wav files such as being able to add an echo to it and so on. So far ive managed to read in the Wav, split it up into the header file and data and manipulate the data by adding an echo to it and flange type effect. However, I am struggling with volume. Id like to know how I can increase and decrease the volume of a Wav file. Ive googled around and found nothing that can help me so any help on where to start would be appreciated.

Thanks, Ian

Recommended Answers

All 11 Replies

I'm pretty sure you need to take the individual sample values and scale them up (or down).

Definitely consider using a compression technique. Otherwise, scaling up can cause distortion. Its gross.

Thank you for your responses,

How would i compress the files after scaling as I did find scaling them up to cause distortion.

Compress the sound beforehand, then apply the gain. Try here for some info on dynamic range compression.

commented: couple of nice pointers to stuff. +4

Thanks for your replies, am looking into it as we speak.

One last question (for now!)

Im currently playing the loaded wav file using :

sndPlaySound(Filepath, SND_ASYNC);

Im aware that to add effects and change the volume on the fly that I need to play the wav file from the data loaded into the program. I have googled and have yet to find any way to do this. Is there anyone that can point me in the right direction?

Wave files follow the IFF standard which makes it easier to read. This page describes the inner structure of wave files. I trust you can do low-level file operations?

Hi!
You can make this very simple. Just you should multiply each sample by some value. If you work with signed samples. For example, suppose you have an array of signed short (16 bit audio PCM). a[5] = {10000, 9500, 3200, -2700, -3100}; Multiply each sample by 1.5 for an increase of volume. {15000, 14250, 4800, -4050, -4650}.
Or multiply by 0.7 for a decrease it. if value will be more (less) of maximum(minimum) -- just set this sample to maximum(min) of signed short: 32767(-32768). But this method works with signed samples only. For unsigned PCM audio methods are some different, but quite similar.

Im aware that to add effects and change the volume on the fly that I need to play the wav file from the data loaded into the program. I have googled and have yet to find any way to do this. Is there anyone that can point me in the right direction?

iaaan, use the waveOut* functions.
This way is little more complex, but much better.
first you should init sound device, wave-headers etc. and then only use waveOutWrite. Use MSDN :)
if needs -- look at this pieces of my code. it use two buffers, but i think, will be better for you to use one buffer. it will be so easier.

int CSoundPlayer::InitSndDevice()
{
	memset(&m_Format, 0, sizeof(m_Format));
	m_Format.nSamplesPerSec = m_MAX_FREQUENCY;
	m_Format.nChannels = STEREO;
	m_Format.wBitsPerSample = 16;
	m_Format.nBlockAlign = (m_Format.nChannels * m_Format.wBitsPerSample + 7) / 8;
	m_Format.nAvgBytesPerSec = m_Format.nBlockAlign * m_Format.nSamplesPerSec;
	m_Format.wFormatTag = WAVE_FORMAT_PCM;
	UINT res = waveOutOpen(&m_hWaveOut, m_DeviceID, &m_Format, (DWORD_PTR) waveOutProc,(DWORD_PTR) this, CALLBACK_FUNCTION);
	if (MMSYSERR_NOERROR != res)
	{
		ShowError((int)res, "Error waveOutOpen");
		return -1;
	}
	memset(&m_MainSndBuffer, 0, sizeof(m_MainSndBuffer));
	memset(&m_ExtSndBuffer, 0, sizeof(m_ExtSndBuffer));

	m_hMainWaveHdr.dwFlags = 0;
	m_hExtWaveHdr.dwFlags = 0;
	m_hMainWaveHdr.dwLoops = m_hExtWaveHdr.dwLoops = 0;
	m_hMainWaveHdr.lpData	= m_MainSndBuffer;
	m_hExtWaveHdr.lpData	= m_ExtSndBuffer;
	m_hMainWaveHdr.dwBufferLength = m_hExtWaveHdr.dwBufferLength = PLAYING_SOUND_BUFF_SIZE;

	res = waveOutPrepareHeader(m_hWaveOut, &m_hMainWaveHdr, sizeof(m_hMainWaveHdr));
	if (MMSYSERR_NOERROR != res)
	{	
		ShowError((int)res, "Error with waveOutPrepareHeader N1");
		return -1;
	};
	res = waveOutPrepareHeader(m_hWaveOut, &m_hExtWaveHdr, sizeof(m_hExtWaveHdr));
	if (MMSYSERR_NOERROR != res)
	{	
		ShowError((int)res, "Error with waveOutPrepareHeader N2");
		return -1;
	};
	return 0;
}
//-----------------------------------------------------------------------------

void CSoundPlayer::StartPlay()
{
	MMRESULT res = waveOutWrite(m_hWaveOut, &m_hMainWaveHdr, sizeof(m_hMainWaveHdr));
	if (MMSYSERR_NOERROR != res)	{	ShowError(res, "Error with waveOutWrite"); };
	m_LoopNumIsPlaying = 0;
	res = waveOutWrite(m_hWaveOut, &m_hExtWaveHdr, sizeof(m_hExtWaveHdr));
	if (MMSYSERR_NOERROR != res)	{	ShowError(res, "Error with waveOutWrite"); };
	return;
}
//-----------------------------------------------------------------------------

void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD dwParam1, DWORD dwParam2)
{
	dwParam1; // compiler warning :[]
	dwParam2;
	WAVEHDR *main_header = &((CSoundPlayer*)dwInstance)->m_hMainWaveHdr;
	WAVEHDR *ext_header = &((CSoundPlayer*)dwInstance)->m_hExtWaveHdr;
	char *main_buff = ((CSoundPlayer*)dwInstance)->m_MainSndBuffer;
	char *ext_buff = ((CSoundPlayer*)dwInstance)->m_ExtSndBuffer;
	if ((WOM_DONE == uMsg) && ((CSoundPlayer*)dwInstance)->m_DoWriteBuffer)
	{
		if (!(((CSoundPlayer*)dwInstance)->m_LoopNumIsPlaying % 2)) // even
		{
			memset(main_buff, 0, PLAYING_SOUND_BUFF_SIZE);
			MMRESULT res = waveOutWrite(hwo, main_header, sizeof(*main_header));
			if (MMSYSERR_NOERROR != res)	{	
				ShowError(res, "Error waveOutWrite"); 
			};
		} 
		else 
		{
			memset(ext_buff, 0, PLAYING_SOUND_BUFF_SIZE);
			MMRESULT res = waveOutWrite(hwo, ext_header, sizeof(*ext_header));
			if (MMSYSERR_NOERROR != res)	{	
				ShowError(res, "Error waveOutWrite"); 
			};
		}
		((CSoundPlayer*)dwInstance)->m_LoopNumIsPlaying++;
		((CSoundPlayer*)dwInstance)->m_PacketsCounter++;
		if (((CSoundPlayer*)dwInstance)->m_PacketsCounter == 0)
			((CSoundPlayer*)dwInstance)->GetNextPosition();
	}
	else 
	{
		((CSoundPlayer*)dwInstance)->m_LoopNumIsPlaying += 0;
	}
};
//-------------------------------------------------------------------------------------

upd.

and some member-variables declarations :)

void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD dwParam1, DWORD dwParam2);

..............
	HWAVEOUT    m_hWaveOut;
	WAVEFORMATEX  m_Format;
	HANDLE m_PlayedEvent;
	LPDWORD m_PlayingThreadId;
	MMTIME m_CurrTime;

	DWORD m_LastPos;
	DWORD m_PositionShift;
	DWORD m_LoopNumIsPlaying;
	WAVEHDR	m_hMainWaveHdr;
	WAVEHDR	m_hExtWaveHdr;
	char m_MainSndBuffer[PLAYING_SOUND_BUFF_SIZE];	
char m_ExtSndBuffer[PLAYING_SOUND_BUFF_SIZE];	
	DWORD m_MAX_FREQUENCY;
	bool m_DoWriteBuffer;
	DWORD m_DeviceID;

good luck!

commented: Good job +14

Thank you MHC for your help. Ive managed to get it to Play/Pause and currently working on volume using the waveOut functions.

Cheers mate

glad to help you :)

removed...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.