directsound driver test for freeaudio

BlitzMax Forums/BlitzMax Programming/directsound driver test for freeaudio

Could windows users please test the following and report any hiccups in audio, it's the tempest sample with a new freeaudio dsound device driver set to a rather low latency:

http://www.gameartnow.com/nitrologic/dsoundtest1.zip

single file exe so seems to run from inside the zip...

Fine here.

XP Home, 1GB, P4 3.2Gz HT, Radeon 9800XT, SB Audigy 2.

Not sure how good the test is as the sound effects are pretty primative.

Could this possibly improve BMax sound in Win98?

Works here.

Toshiba Satellite 1800-814 laptop
P3 1.1GHz
512mb RAM
Trident Cyberblade XP Ai1 (16mb)
ALi onboard sound
WinXP Home/SP2

Yep that fixes the sound delay on my Vista Ultimate PC. Thanks Skid!

No sound delays.

I tested it on (from my head):

1) XP Home sp2, 2.4Ghz P4, with a onboard realtek chip
2) Vista Ultimate, 3.8Ghz AMD2, with a onboard SoundMax chip.

Subjectively, the XP machine the sounded better than the Vista machine. The soundeffects used in the game are not the best to test crackling, so i can not say clearly if Vista is distorting the sound.

Great work! Works on my Vista set-up without the horrible delay I reported in the bugs section.

Cool. If people want to test with their own apps replace your pub.mod/freeaudio.mod with this beta:

http://gamecodenow.com/nitrologic/freeaudio.zip

Mmmm, slight problem. It doesn't work in my own apps! It seems to be playing a lot slower and is very crackly/echoey as well.

Don't know if this helps, but the way I play sounds is controlled by the following Type (or very similar).
Type TFX
	Field channel:TChannel
	Field sound:TSound
	
	Global fxList:TList
	
	Function Play(fx:TSound,volume:Float=1,pan:Float=0,kill:Int=False)
		If fxList=Null Then fxList=CreateList()
		' check if same sound needs to be killed if playing already
		If fxVolume>0 Then
			If kill Then
				For Local s:TFX=EachIn fxList
					If s.sound=fx Then
						s.channel.Stop
						fxList.Remove(s)
						s=Null
					EndIf
				Next
			EndIf
			' play sound
			Local sfx:TFX=New TFX
			fxList.AddLast(sfx)
			sfx.sound=fx
			sfx.channel=CueSound(fx)
			sfx.channel.SetVolume(fxVolume*volume)
			sfx.channel.SetPan(pan)
			sfx.channel.SetPaused(False)
		EndIf
	EndFunction
	
	Function Check()
		If fxList Then
			For Local sfx:TFX=EachIn fxList
				If Not(sfx.channel.Playing()) Then
					sfx.channel.Stop
					fxList.Remove(sfx)
					sfx=Null
				EndIf
			Next
		EndIf
	EndFunction
EndType

The Check() method gets called every logic loop (which is 200 times a second), however, I got the same result when I took it out, just to see if this could be causing the problem.

Fairly simple, but maybe you can see if there is a better way for me to do what I am currently doing. I notice that you pre-allocate sound channels in the Tempest program, whereas I do it on the fly.

Hope we manage to sort this soon.

the exe seems fine here too...

Skidracer: any ideas if this will help with previously reported win98 issues like sound drop out, stuttering etc. (particularly with ogg playback)?

Just been playing around a bit to see if I can get a sound playing without any problems, and even the following produces crackling and slow playback.
' quick sound test

Graphics 640,480

Global sound:TSound=LoadSound("sfx/fire.wav")
Global channel:TChannel=Null

While Not KeyHit(key_escape)
	Cls
	DrawText "Press space to fire, or Esc to quit",10,10
	Flip
	
	If KeyHit(key_space) Then
		PlaySound(sound,channel)
	EndIf
Wend
End

Not really sure what the Tempest program is doing any differently.

Try changing dsounddevice.cpp[12] to:

#define DSOUNDFRAG 2048

and build modules, you did build modules ya?

Well, that's much better. Still a little bit of crackle, but absolutely nowhere near as much as before.

Increasing it to 3072 yielded better results, although I thought I could see a very slight delay at this setting - could just be me seeing something that's not there!

Is your game DX or GL?

The lag becomes unacceptable at 8192, so I was hoping 2048 would be fine as the tempest fire button certainly feels nice and responsive at this setting.

<edit>
ok, this version of dsounddevice.cpp shouldn't overrun the buffer, if you still have problems please try uncommenting the logging on lines 178-179 and post the results

// dsounddevice.cpp

#include "freeaudio.h"

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <objbase.h>
#include <mmsystem.h>
#include <stdio.h>
#include "dsound.h"

#define DSOUNDFRAG 2048

struct dsounddevice:audiodevice{

	int	running,playing;	//threadsafe state machine

	int reset(){
		int res;
		
		running=1;
		playing=0;
		mix=new mixer(DSOUNDFRAG*6);
		mix->freq=44100;
		mix->channels=2;
		res=initdevice(DSOUNDFRAG);
		if (res) {
			running=0;
		}
		return res;
	}
	
	int close(){	
		int		timeout;
		if (running){
//stop
			running=0;
			timeout=20;	//100ms timeout
			while (timeout-- && playing) {
				Sleep(5);
			}
			freedevice();
		}
		return 0;
	}

// private

	HINSTANCE dsoundlib;
	HRESULT WINAPI (*DirectSoundCreate)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
	
	IDirectSound *directsound;
	IDirectSoundBuffer *primarybuffer;
	IDirectSoundBuffer *soundbuffer;
	IDirectSoundNotify *soundnotify;
	
	HANDLE soundevent;
	HANDLE soundthread;
	DWORD soundthreadid;

	int fragsize;	//in bytes
	int buffersize;	//3*fragsize

	int initdevice(int fragsamples){

		PCMWAVEFORMAT pcmwf; 
		DSBUFFERDESC dsbdesc; 
		DSCAPS dscaps;
		int res;
// init device
		directsound=0;
		primarybuffer=0;
		soundbuffer=0;
		soundnotify=0;		
		dsoundlib=LoadLibraryA("dsound");	
		DirectSoundCreate=(HRESULT WINAPI (*)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN))GetProcAddress(dsoundlib,"DirectSoundCreate");
		res=DirectSoundCreate(0,&directsound,0);
		if (res) return res;		
		res=directsound->SetCooperativeLevel(GetDesktopWindow(),DSSCL_PRIORITY);
		if (res) return res;	
//		printf("dsoundlib=%d soundcreate=%d res=%d\n",dsoundlib,(int)DirectSoundCreate,res);	
//		fflush(stdout);
		dscaps.dwSize=sizeof(DSCAPS);
		res=directsound->GetCaps(&dscaps);	
		if (res) return res;	
// set primary buffer format
		memset(&dsbdesc,0,sizeof(DSBUFFERDESC)); 	// Zero it out. 
		dsbdesc.dwSize=sizeof(DSBUFFERDESC); 
		dsbdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
		res=directsound->CreateSoundBuffer(&dsbdesc,&primarybuffer,0); 
		if (res) return res;
		memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT)); 
		pcmwf.wf.wFormatTag=WAVE_FORMAT_PCM; 
		pcmwf.wf.nChannels=2;
		pcmwf.wf.nSamplesPerSec=44100;
		pcmwf.wBitsPerSample=16; 
		pcmwf.wf.nBlockAlign=4;
		pcmwf.wf.nAvgBytesPerSec=pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign; 
		res=primarybuffer->SetFormat((LPWAVEFORMATEX)&pcmwf);
		if (res) return res;
// fragment size
		fragsize=fragsamples*4; //stereo 16bit=4 bytes per sample
		buffersize=fragsize*3;	//triple buffered
// format
		memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT)); 
		pcmwf.wf.wFormatTag=WAVE_FORMAT_PCM; 
		pcmwf.wf.nChannels=2;
		pcmwf.wf.nSamplesPerSec=44100;
		pcmwf.wf.nBlockAlign=4;
		pcmwf.wf.nAvgBytesPerSec=pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign; 
		pcmwf.wBitsPerSample=16; 
// description	
		memset(&dsbdesc,0,sizeof(DSBUFFERDESC)); 	// Zero it out. 
		dsbdesc.dwSize=sizeof(DSBUFFERDESC); 
		dsbdesc.dwBufferBytes=buffersize;			//1 * pcmwf.wf.nAvgBytesPerSec; 
		dsbdesc.lpwfxFormat=(LPWAVEFORMATEX)&pcmwf; 
		dsbdesc.dwFlags=DSBCAPS_CTRLPOSITIONNOTIFY|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_GLOBALFOCUS;
// createbuffer
		res=directsound->CreateSoundBuffer(&dsbdesc,&soundbuffer,0); 
		if (res) return res;
// notifications
		soundevent=CreateEvent(0,0,0,"SOUNDEVENT");
		if (soundevent==0) return res;
		res=soundbuffer->QueryInterface(IID_IDirectSoundNotify,(void**)&soundnotify); 
		if (res) return res;	
		DSBPOSITIONNOTIFY notif[3];
		int n; 
		for (n=0;n<3;n++){
			notif[n].dwOffset=n*fragsize;
			notif[n].hEventNotify=soundevent;
		}
	 	res=soundnotify->SetNotificationPositions(3,notif);
		if (res) return res;
// thread
		soundthread=CreateThread(NULL,0,soundproc,this,REALTIME_PRIORITY_CLASS,&soundthreadid);
		return 0;
	}
	
	void freedevice(){
		int res;
		if (primarybuffer){
			res=primarybuffer->Release();
			primarybuffer=0;
		}		
		if (soundbuffer){
			res=soundbuffer->Release();
			soundbuffer=0;
		}		
		if(directsound) {
			res=directsound->Release();
			directsound=0;
		}	
	}

//thread entry point

	DWORD run(){	
		DWORD read,write;
		int lastread,loopcount;
		void *mem1,*mem2;
		DWORD size1,size2;
		int readpos,writepos;
		int res;
		writepos=0;
		lastread=0;
		loopcount=0;
// playsound
		soundbuffer->Play(0,0,DSBPLAY_LOOPING);
		playing=1;
//		printf("running=%d\n",running);
//		fflush(stdout);
		while (running){
			res=soundbuffer->GetCurrentPosition(&read,&write);
			if (read<lastread) loopcount++;
			lastread=read;
			readpos=loopcount*buffersize+read;
			int count=((readpos+fragsize*2-writepos)/fragsize);
//			printf("read=%d write=%d  %d,%d  count=%d\n",read,write,readpos,writepos,count);
//			fflush(stdout);
			if (count>0){		
				if (count>2) count=2;	//avoid overrun
				res=soundbuffer->Lock(writepos%buffersize,count*fragsize,&mem1,&size1,&mem2,&size2,0);
				if (res) break;
//				printf("mem1=%d size1=%d mem2=%d size2=%d total=%d\n",mem1,size1,mem2,size2,size1+size2);
//				fflush(stdout);
				if (size1) mix->mix16((short*)mem1,size1/2);
				if (size2) mix->mix16((short*)mem2,size2/2);
				res=soundbuffer->Unlock(mem1,size1,mem2,size2);
				if (res) break;
				writepos+=size1+size2;
			}
			res=WaitForSingleObject(soundevent,1000);
			if (res!=WAIT_OBJECT_0) break;				
		}
		playing=0;
		soundbuffer->Stop();
//		printf("done...\n");
//		fflush(stdout);
	}
	
	static DWORD WINAPI soundproc(LPVOID lpParam){
		dsounddevice *dsd;
		dsd=(dsounddevice*)lpParam;
		return dsd->run();
	}
};

audiodevice *OpenSystemAudio(){
	return new dsounddevice();
}


Both! Although, I've been doing all this testing under DX.

EDIT - Same result with OpenGL.

Hi,

Under Vista, I'm getting the 1 second audio delay with standard FreeAudio.

With the Tempest test above, I get minimal delay, but a wacky 'echoey' effect.

OpenAL also appears to be semi-hosed under Vista - the default driver does not work (no audio) but forcing OpenAL to use DirectSound driver does.

Audio under Vista is *munted*! Nice GUI but...

Munted?

Is that good or bad?

Munted

Munted
"completely tw*tted of your face & gurning like a water buffalo."

Oh. Er.... I see.... :/

[edit] Ah! You meant "Broken, not workable for its origanal purpose."

:)

wow so does this mean that any Bmax games will sound awful on Vista?

Most games sound *shite* under Vista.

wow so does this mean that any Bmax games will sound awful on Vista?

For the most part, yes. But it's mostly down to the state of the drivers for your soundcard. Mine, for example, are still in beta, but I get the impression that they're simply waiting for certification from MicroSoft.

The new driver from Skidracer goes a long way towards fixing the current issues. There's no longer a delay, but we do now get the crackle. Increasing the DSOUNDFRAG value of the driver does improve on this, but at the expense of greater latency, but nowhere near the second we are currently getting.

Most games sound *shite* under Vista

Actually, the games I tested sounded just fine, although a little flat when EAX options were not available.


I'm actually taking another look at FMOD and going to convert one of my freeware games to use it to see how it works. If all goes fine then I'll consider it for my shareware games, but then there's a licence fee to consider as well. Ideally, I'd like the sound driver with BMax to be fixed to a usable state.

wow that's horrible news.

I need a change of career. This programming lark is one headache after another. :/

Things are lookig up. Check here.. http://www.blitzbasic.com/Community/posts.php?topic=67463

This whole issue seems pretty high up on the list of priorities at the moment, and it's come a long way in just a week.

To be fair, it's hardly unexpected when you consider when XP was released on to a 98 using public.

Thanks for the link. This is one I'm gonna have to sit out on for a bit as I'm battling with the Mac. Anyway, seems there's plenty of Cooks ...

The sound sounds very cracking after today's syncmods, you can test on Digesteroids...

It requires a fix definitely... :|

SPEC: XP SP2, OnBoard AC97, Geforce FX5200

Check the link in my post above. You can now choose an audio driver, including the original FreeAudio and some OpenAL ones (provided you have OpenAL installed).

I have reported in that post.. the problem i actually the new freeaudio, I'm waiting for fix.