Day 007 - Problem with WaveFormat.wFormatTag

Hello everyone!

I'm a bit late to the Handmade Hero GameDev but I made my way up to Day 7 in one go. But now I ran into a problem with the Win32InitSound function which it seems I can't figure out myself. More specific it's the WaveFormat.wFormatTag which i cannot set without getting the [E_INVALIDARG One or more arguments are invalid - unrecognized token] error. If it is not set the PrimaryBuffer->SetFormat(&WaveFormat) returns S_OK. Is there a way to find out why it is not working? My code for the DirectSound Implementation:


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
#include <dsound.h>

#define DIRECT_SOUND_CREATE(name) HRESULT WINAPI name(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter)
typedef DIRECT_SOUND_CREATE(direct_sound_create);

internal void Win32InitDirectSound(HWND Window, int32 SamplesPerSecond, int32 BufferSize)
{

	// note: load the library
	HMODULE DirectSoundLibrary = LoadLibrary("dsound.dll");

	if (DirectSoundLibrary) {

		// note: Get a DirectSound Object - cooperative
		direct_sound_create *DirectSoundCreate = (direct_sound_create *) GetProcAddress(DirectSoundLibrary, "DirectSoundCreate");

		// todo: doublecheck that this works on windows xp - directsound8 or 7?
		LPDIRECTSOUND DirectSound;
		if (DirectSoundCreate && SUCCEEDED(DirectSoundCreate(0, &DirectSound, 0))) {

			// note: waveformat für die buffer vorbereiten

			// typedef struct {
			// 	WORD  wFormatTag;
			// 	WORD  nChannels;
			// 	DWORD nSamplesPerSec;
			// 	DWORD nAvgBytesPerSec;
			// 	WORD  nBlockAlign;
			// 	WORD  wBitsPerSample;
			// 	WORD  cbSize;
			// } WAVEFORMATEX;
			WAVEFORMATEX WaveFormat 	= {};
			WaveFormat.cbSize 			= 0;
			WaveFormat.wFormatTag 		= WAVE_FORMAT_PCM; // -> E_INVALIDARG One or more arguments are invalid.
			WaveFormat.nChannels 		= 2;
			WaveFormat.wBitsPerSample  	= 16;
			WaveFormat.nSamplesPerSec 	= SamplesPerSecond;
			WaveFormat.nBlockAlign 		= (WaveFormat.nChannels * WaveFormat.wBitsPerSample) / 8;
			WaveFormat.nAvgBytesPerSec  = WaveFormat.nChannels * WaveFormat.nBlockAlign;

			if (SUCCEEDED(DirectSound->SetCooperativeLevel(Window, DSSCL_PRIORITY))) {

				// note: primären buffer anlegen
				// todo: DSBCAPS_GLOBALFOCUS?

				// typedef struct DSBUFFERDESC {
				// 	DWORD dwSize;
				// 	DWORD dwFlags;
				// 	DWORD dwBufferBytes;
				// 	DWORD dwReserved;
				// 	LPWAVEFORMATEX lpwfxFormat;
				// 	GUID guid3DAlgorithm;
				// } DSBUFFERDESC;
				DSBUFFERDESC BufferDescription  = {};
				BufferDescription.dwSize 		= sizeof(BufferDescription);
				BufferDescription.dwFlags 		= DSBCAPS_PRIMARYBUFFER;

				LPDIRECTSOUNDBUFFER PrimaryBuffer;
				if (SUCCEEDED(DirectSound->CreateSoundBuffer(&BufferDescription, &PrimaryBuffer, 0))) {

					// HRESULT error = PrimaryBuffer->SetFormat(&WaveFormat);
					// if (SUCCEEDED(error)) {
					if (SUCCEEDED(PrimaryBuffer->SetFormat(&WaveFormat))) {
						OutputDebugStringA("PrimaryBuffer format was set\n");
					} else {
						// todo: error log
					}

				} else {
					// todo: error log
				}

			} else {
				// todo: error log
			}

			// note: sekundären buffer anlegen
			// todo: DSBCAPS_GETCURRENTPOSITION2?
			DSBUFFERDESC BufferDescription  = {};
			BufferDescription.dwSize 		= sizeof(BufferDescription);
			BufferDescription.dwFlags 		= 0;
			BufferDescription.dwBufferBytes = BufferSize;
			BufferDescription.lpwfxFormat 	= &WaveFormat;

			LPDIRECTSOUNDBUFFER SecondaryBuffer;
			// HRESULT error = DirectSound->CreateSoundBuffer(&BufferDescription, &SecondaryBuffer, 0);
			// if (SUCCEEDED(error)) {
			if (SUCCEEDED(DirectSound->CreateSoundBuffer(&BufferDescription, &SecondaryBuffer, 0))) {

				OutputDebugStringA("SecondaryBuffer created successfully\n");

			} else {
				// todo: error log
			}

		} else {
			// todo: error log
		}

	}

}



PS: I'm developing on Windows 10 with VS2017 if that has anything to do with it
nAvgBytesPerSec needs to be bytes per second, not bytes per all channels per all channels (you are multiplying channels two times into it).

1
nAvgBytesPerSec = WaveFormat.nSamplesPerSec * WaveFormat.nBlockAlign;

Read the documentation more carefully: https://msdn.microsoft.com/en-us/...ary/windows/desktop/dd390970.aspx
nAvgBytesPerSec

Required average data-transfer rate, in bytes per second, for the format tag. If wFormatTag is WAVE_FORMAT_PCM, nAvgBytesPerSec must equal nSamplesPerSec × nBlockAlign.

Edited by Mārtiņš Možeiko on
mmozeiko
nAvgBytesPerSec needs to be bytes per second, not bytes per all channels per all channels (you are multiplying channels two times into it).

1
nAvgBytesPerSec = WaveFormat.nSamplesPerSec * WaveFormat.nBlockAlign;

Read the documentation more carefully: https://msdn.microsoft.com/en-us/...ary/windows/desktop/dd390970.aspx
nAvgBytesPerSec

Required average data-transfer rate, in bytes per second, for the format tag. If wFormatTag is WAVE_FORMAT_PCM, nAvgBytesPerSec must equal nSamplesPerSec × nBlockAlign.


Whoops, that error must have slipped in as I was reordering the struct. Thanks for your fast response and good catch, would have taken ages to find that myself. Cheers!
7 days in one go?
I wish I had your stamina! :D
DanZaidan
7 days in one go?
I wish I had your stamina! :D


I have to admit that I skipped the Q&A's at the end of every video, but I'm so glad i stumbled upon this series. It really is invaluable from an educational perspective and the way Casey teaches makes it quite addictive one might say xD