PDA

View Full Version : Anyone?



Bobby
07-11-2002, 08:38 PM
Anyone know what they are doing with directSound? I could use some help on my OmegaSound component. I'm having trouble knowing how big to make the sound buffer, I need to know how long the wave file is, but I have no clue on how to find this out. Anyone know? Thanks.

jdsgames
07-11-2002, 09:39 PM
Hi,

Maybe this can help. Here is some code that I am using in our GameVision engine. We are currently working on GV 2.0 and this will be the new wave file loading code. GV is currently in development so the code is not 100% tested yet. So, anything you fix/enhance, please send to me, thanks. It will prob crash if you try and load a compressed wave file:

function TGVAudio.WriteDataToBuffer(lpdsb: IDirectSoundBuffer; OffSet: DWord;
var SoundData; SoundBytes: DWord): Boolean;
var
AudioPtr1 : Pointer;
AudioPtr2 : Pointer;
AudioBytes1: DWord;
AudioBytes2: DWord;
h : HResult;
Temp : Pointer;
begin
Result:=True;
H:=lpdsb.Lock(OffSet, SoundBytes, AudioPtr1, AudioBytes1,
AudioPtr2, AudioBytes2, 0);
if H = DSERR_BUFFERLOST then
begin
lpdsb.Restore;
if lpdsb.Lock(OffSet, SoundBytes, AudioPtr1, AudioBytes1,
AudioPtr2, AudioBytes2, 0) <> DS_OK then Result:=False;
end else if H <> DS_OK then Result:=False;
Temp:=@SoundData;
Move(Temp^, AudioPtr1^, AudioBytes1);
if AudioPtr2 <> nil then
begin
Temp:=@SoundData;
Inc(Integer(Temp), AudioBytes1);
Move(Temp^, AudioPtr2^, AudioBytes2);
end;
if lpdsb.UnLock(AudioPtr1, AudioBytes1, AudioPtr2, AudioBytes2) <> DS_OK
then Result:=False;
end;

function TGVAudio.CreateSecondaryBufferFromWav(var lpdsb : IDirectSoundBuffer;
Name: string) : Boolean;
var Data : PChar;
FName : TFileStream;
dsbdesc : TDSBUFFERDESC;
PCM : TWaveFormatEx;
FWord : Word;
FDWord : DWord;
Chunk : String[4];
Pos : Integer;
DataSize : DWord;
begin
Result:=True;
FName:=TFileStream.Create(Name, fmOpenRead);
FillChar(dsbdesc, SizeOf(TDSBUFFERDESC), 0);
FillChar(PCM, SizeOf(TWaveFormatEx), 0);

with PCM do
begin
wFormatTag:=WAVE_FORMAT_PCM;
FName.Seek($16, soFromBeginning);
FName.Read(FWord, SizeOf(Word));
nChannels:=FWord;
FName.Read(FDWord, SizeOf(DWord));
nSamplesPerSec:=FDWord;
FName.Read(FDWord, SizeOf(DWord));
nAvgBytesPerSec:=FDWord;
FName.Read(FWord, SizeOf(Word));
nBlockAlign:=FWord;
FName.Read(FWord, SizeOf(Word));
wBitsPerSample:=FWord;
cbSize:=0;
end;

Pos:=$22;
SetLength(Chunk, 4);
repeat
FName.Seek(Pos, soFromBeginning);
FName.Read(Chunk[1], 4);
Inc(Pos);
until Chunk = 'data';
FName.Seek(Pos + 3, soFromBeginning);
FName.Read(DataSize, SizeOf(DWord));
GetMem(Data, DataSize);
FName.Read(Data^, DataSize);

dsbdesc.dwSize:=SizeOf(TDSBUFFERDESC);
dsbdesc.dwFlags:=DSBCAPS_GETCURRENTPOSITION2 or
//DSBCAPS_GLOBALFOCUS or
DSBCAPS_CTRLPAN or
DSBCAPS_CTRLVOLUME or
DSBCAPS_LOCSOFTWARE or
DSBCAPS_CTRLPOSITIONNOTIFY;

dsbdesc.dwBufferBytes:=DataSize;
dsbdesc.lpwfxFormat:=@PCM;

FName.Free;

if FDS.CreateSoundBuffer(dsbdesc, lpdsb, nil) <> DS_OK
then Result:=False;

if not WriteDataToBuffer(lpdsb, 0, Data^, DataSize) then Result:=False;
FreeMem(Data, DataSize);
end;


Best Regards

Jarrod Davis
JDS Games
http://www.jdsgames.com
jdsgames@jdsgames.com

Bobby
08-11-2002, 04:55 AM
Hi! Thanks man, your a life saver. It works perfectly now. I really appreciate it, I can finally release the working sound component now :D

jdsgames
08-11-2002, 05:16 AM
Coolness! Glad to hear its working.

JanBacke
18-11-2002, 06:44 PM
If you're working with the wav format then try to work with the wav API. (MMIO just easier, faster and better 8) ).

function LoadWaveFromFile(FFile:string):Boolean;
var HIO :HMMIO;
parent,
child1,
child2 :MMCKINFO;
wavefmt:TWAVEFORMATEX;
bufdesc:TDSBUFFERDESC;
length1,
length2:Cardinal;
write1,
write2 :Pointer;
dummy :IDirectSoundBuffer;
begin
result:=false;
HIO:=mmioopen(@FFile[1],nil,MMIO_READ or MMIO_ALLOCBUF);
if HIO>0 then
begin
parent.fccType:=mmioStringToFourCC('wave',MMIO_TOU PPER);
child1.ckid:=mmioStringToFourCC('fmt ',0);
child2.ckid:=mmioStringToFourCC('data',0);
if mmioDescend(HIO,@parent,nil,MMIO_FINDRIFF)=0 then
if mmioDescend(HIO,@child1,@parent,MMIO_FINDCHUNK)=0 then
if mmioread(HIO,@wavefmt,child1.cksize)=child1.cksize then
if mmioDescend(HIO,@child2,@parent,MMIO_FINDCHUNK)=0 then
begin
FillChar(bufdesc,sizeof(TDSBUFFERDESC),0);
bufdesc.dwSize:=sizeof(TDSBUFFERDESC);
bufdesc.dwFlags:=DSBCAPS_CTRLDEFAULT;
bufdesc.dwBufferBytes:=child2.cksize;
bufdesc.lpwfxFormat:=@wavefmt;
if dsound.CreateSoundBuffer(bufdesc,dummy,nil)=DS_OK then
begin
DSBuffer:=dummy as IDirectSoundBuffer8;
dummy:=nil;
if DSBuffer.Lock(0,child2.cksize,write1,length1,write 2,length2,DSBLOCK_FROMWRITECURSOR)=DS_OK then
begin
if (write1<>nil) then
mmioRead(HIO,PChar(write1),length1);
DSBuffer.Unlock(write1,length1,write2,length2);
end;
end;
end;
MMIOClose(HIO,MMIO_FHOPEN);
result:=true;
end;




Tutorial, source & exe on my site

jdsgames
18-11-2002, 08:57 PM
But.. can you also use the winmm routine to assist in loading that wav from a resource file. My engine uses standard zip files. All game assests can be loaded from a zip archive. It would be nice to let winmm do the loading as it would be able to handle the compressed WAVs for me.

Bobby
18-11-2002, 09:03 PM
Hi, jdsgames, do you know why setting the volume wouldnt work for me? I set the volume to -10000 just to test (Should be silent) but it doesnt change it at all. I did set the control volume flag when creating it, I dont know what I could be doing wrong, any ideas? Thanks.

jdsgames
18-11-2002, 09:13 PM
Hi Bobby,

Check your email, I'm sending you my whole GVAudio.pas unit. It has sample and mp3 playback code. You can control the volume, master volume and many other audio related tasks. I had problems with this at first too, but for me it turned out to be a flag that was not set (control vol flag). Check out that code and let me know. If you manage to improve on it at all, but sure to send me the updates. Thanks.

JanBacke
18-11-2002, 10:18 PM
But.. can you also use the winmm routine to assist in loading that wav from a resource file. My engine uses standard zip files. All game assests can be loaded from a zip archive. I would be nice to let winmm do the loading as it would be able to handle the compressed WAVs for me.

No. If you want to load your wave from a resource file via Win32 MMApi you must first buffer the resource via TResourceStream.
http://www.bridgespublishing.com/articles/issues/9808/Playing_wave_resources.htm
You must decompress your wav resource by yourself :). Sorry but it is only a low level wav interface.
sincerely Jan

JanBacke
18-11-2002, 10:27 PM
Can i have the GVAudio.pas too. I'll also take a look on it :D

jdsgames
18-11-2002, 10:52 PM
I see. Yea, I needed to be able to load textures, WAVs and other game assets from my resource file (not a windows resource thats compiled into the exe, but a standard zip archive file). GV has a class called TGVRezFile that does this. I had to use my own code to load the wavs in order for it to be able to come in from the rez file. If you open FreeStrike.rez with winzip you will notice its just a zip file.

Send me an email to: jdsgames@jdsgames.com and I will send you GVAudio.pas.

Bobby
03-12-2002, 07:54 PM
Hi, the volume works now, but it seems to only work on one of my buffers. When I have more than one sound playing, it seems to skip the first one, and works on the next one.. its wierd. I was adjusting the volume right before I play it, so it should affect every single buffer that tries to play a sound but for some reason it skips some. Any ideas? Thanks.

jdsgames
03-12-2002, 09:08 PM
This is the code that I am currently using. I just call SetChannelVol aftwards. Email me the code in question and I will take a look at it if you like.


function TGVAudio.PlaySample(Num, Chan: Integer; Vol: Single; Loop: Boolean): Integer;
var
I : Integer;
Flags: Cardinal;
begin
// check if init
if not FEnabled then
begin
Result := -1;
Exit;
end;

//FSampleBuffer[Id].Play(0, 0, 0)
if (Chan < 0) or (Chan > GV_MAX_CHANNELS-1) then
begin
I := FindFreeMixBuffer;
if I < 0 then
begin
Result := I;
Exit;
end;
end
else
begin
I := Chan;
StopChannel(I);
end;

// copy to mix buffer
FDS.DuplicateSoundBuffer(FSampleBuffer[Num], FMixBuffer[I]);

// play buffer
SetChannelVolume(I, Vol);

Flags := 0;
if Loop then
Flags := Flags or DSBPLAY_LOOPING;
FMixBuffer[I].Play(0, 0, Flags);

// return mix buffer id
Result := I;
end;

procedure TGVAudio.SetChannelVolume(Chan: Integer; Vol: Single);
begin
// check if init
if not FEnabled then
begin
Exit;
end;

if (Chan < 0) or (Chan > GV_MAX_CHANNELS-1) then Exit;
if Assigned(FMixBuffer[Chan]) then
begin
FMixBufferVol[Chan] := Vol;
FMixBuffer[Chan].SetVolume(CalcVolume(Vol, True));
end;
end;