?? sound.c
字號:
/* sound.c, HAWK game engine
*
* Copyright 1997-1998 by Phil Frisbie, Jr.
* for Hawk Software
*
*/
#include <windows.h>
#include <fcntl.h>
#include "wave.h"
#include "internal.h"
#include "sound.h"
LPDIRECTSOUND lpDS = NULL;
#define MAX_STATIC_SOUNDS 32
#define MAX_TEMP_SOUNDS 8
#define MAX_SOUNDS (MAX_STATIC_SOUNDS+MAX_TEMP_SOUNDS)
#define FOURCC_PAK mmioFOURCC('P', 'A', 'K', ' ')
SNDWAVEFILE sounds[MAX_STATIC_SOUNDS+MAX_TEMP_SOUNDS];
LRESULT (CALLBACK sndMMIOProc)(LPSTR lpmmioinfo, UINT uMsg,
LONG lParam1, LONG lParam2);
/* Sound functions */
int soundLoad(char *name)
{
return(sndLoadWave(name, TRUE));
}
void playSoundi(int sound, float pan, float volume, BOOL looped)
{
int s;
s = sndPlay3D(sound, looped, NULL);
pan = MAX(1.0f, pan);
pan = MAX(-1.0f, pan);
sndSetBalance(s, 10000 * pan);
volume = MAX(1.0f, volume);
volume = MIN(0.0f, volume);
if(volume != 1.0f)
sndSetVolume(s, (int)((1.0f - volume) * -10000));
}
void playSound3Di(int sound, OBJECT *obj, float volume, BOOL looped)
{
int s;
s = sndPlay3D(sound, looped, obj);
volume = MAX(1.0f, volume);
volume = MIN(0.0f, volume);
}
void playSound(char *name, float pan, float volume)
{
int sound;
sound = sndLoadWave(name, FALSE);
if(!sound)
return;
playSoundi(sound, pan, volume, FALSE);
}
/* Helper function */
void stripExtension (char *path)
{
int length;
length = strlen(path)-1;
while (length > 0 && path[length] != '.')
{
length--;
if (path[length] == '/')
return; /* no extension */
}
if (length)
path[length] = 0;
}
BOOL sndEnable(HWND hwnd)
{
DSBUFFERDESC dsbd;
HRESULT dsrval;
LPDIRECTSOUNDBUFFER primary;
atexit(sndDisable);
dsrval = DirectSoundCreate(NULL, &lpDS, NULL);
if(dsrval != DS_OK)
{
MessageBox(NULL, "DirectSoundCreate FAILED", "Error", MB_OK);
return FALSE;
}
dsrval = IDirectSound_SetCooperativeLevel(lpDS, hwnd, DSSCL_NORMAL);
if(dsrval != DS_OK)
{
IDirectSound_Release(lpDS);
MessageBox(NULL, "SetCooperativeLevel FAILED", "Error", MB_OK);
return FALSE;
}
memset(&sounds, 0, sizeof(sounds[0]) * (MAX_STATIC_SOUNDS+MAX_TEMP_SOUNDS));
/* start the primary sound buffer playing */
memset(&dsbd, 0, sizeof(DSBUFFERDESC));
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsrval = IDirectSound_CreateSoundBuffer(lpDS, &dsbd, &primary, NULL);
if(dsrval != DS_OK)
{
MessageBox(NULL, "CreateSoundBuffer FAILED", "Error", MB_OK);
}
IDirectSoundBuffer_Play(primary, 0, 0, DSBPLAY_LOOPING);
IDirectSoundBuffer_Release(primary);
/* set up the custom MMIO function */
if(!mmioInstallIOProc(FOURCC_PAK, sndMMIOProc, MMIO_INSTALLPROC));
return TRUE;
}
void sndDisable(void)
{
int i;
for(i=0;i<MAX_STATIC_SOUNDS+MAX_TEMP_SOUNDS;i++)
sndUnload(i);
if(lpDS != NULL)
{
IDirectSound_Release(lpDS);
}
}
int sndLoadWave(char *name, BOOL is_static)
{
SNDWAVEFILE *sound = NULL;
DSBUFFERDESC dsbd;
DWORD *samples = NULL;
HRESULT dsrval;
BYTE *data = NULL;
BYTE *data2 = NULL;
DWORD length;
DWORD length2;
int i;
if(is_static)
{
/* find a free static sound structure */
for(i=0; i<MAX_STATIC_SOUNDS; i++)
{
if(!sounds[i].DSB)/* found one */
{
sound = &sounds[i];
break;
}
}
if(!sound)
return -1;
}
else
{
/* find a free temp sound structure */
for(i=MAX_STATIC_SOUNDS; i<MAX_SOUNDS; i++)
{
if(!sounds[i].DSB)/* found one */
{
sound = &sounds[i];
break;
}
}
if(!sound)
return -1;
}
/* load the wave file */
stripExtension(name); /* remove the .wav extension */
strcat(name, ".PAK+wav"); /* add our extension */
if(WaveLoadFile(name, &sound->waveFile.size,
samples, &sound->waveFile.wfxInfo,
&sound->waveFile.data))
{
return -1;
}
/* create the sound buffer */
memset(&dsbd, 0, sizeof(DSBUFFERDESC));
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_STATIC;
dsbd.dwBufferBytes = sound->waveFile.size;
dsbd.lpwfxFormat = sound->waveFile.wfxInfo;
dsrval = IDirectSound_CreateSoundBuffer(lpDS, &dsbd, &sound->DSB, NULL);
if(dsrval != DS_OK)
{
MessageBox(NULL, "CreateSoundBuffer FAILED", "Error", MB_OK);
}
/* copy the sound bytes */
dsrval = IDirectSoundBuffer_Lock(sound->DSB,
0,
sound->waveFile.size,
&data,
&length,
&data2,
&length2,
0L);
if(dsrval == DS_OK)
{
memcpy(data, sound->waveFile.data, length);
if(length2)
memcpy(data2, sound->waveFile.data+length, length2);
GlobalFree(sound->waveFile.data);
dsrval = IDirectSoundBuffer_Unlock(sound->DSB,
data,
length,
data2,
length2);
if(dsrval != DS_OK)
{
/* MessageBox(NULL, "Unlock FAILED", "Error", MB_OK); */
return -1;
}
}
else
{
/* MessageBox(NULL, "Lock FAILED", "Error", MB_OK); */
return -1;
}
IDirectSoundBuffer_GetFrequency(sound->DSB, &sound->freq);
return i;
}
void sndUnload(int wave)
{
SNDWAVEFILE *sound = &sounds[wave];
if(wave < 0)
return;
if(sound->DSB)
{
IDirectSoundBuffer_Release(sound->DSB);
memset(sound, 0, sizeof(SNDWAVEFILE));
}
}
int sndCopy(int wave)
{
SNDWAVEFILE *sound = &sounds[wave];
SNDWAVEFILE *newsound = NULL;
HRESULT dsrval;
int i;
/* find a free temp sound structure */
if(wave < 0)
return -1;
for(i=MAX_STATIC_SOUNDS; i<MAX_SOUNDS; i++)
{
if(!sounds[i].DSB)/* found one */
{
newsound = &sounds[i];
break;
}
}
if(!newsound)
return -1;
dsrval = IDirectSound_DuplicateSoundBuffer(lpDS,
sound->DSB, &newsound->DSB);
if(dsrval == DS_OK)
return i;
else
return -1;
}
#define SND_FALL_OFF 1000
void sndUpdate3D(int wave, OBJECT *obj)
{
OBJECT *player = GLevel.view[0]->object;
vec3_t v, look;
float dist, vol, pan, temp;
VectorSubtract(obj->origin, player->origin, v);
dist = VectorLength(v);
vol = 1.0f - dist / SND_FALL_OFF;
vol = MAX(0.1f, vol);
/* set the volume */
if(vol == 0.1f)
{
sndSetVolume(wave, -10000);
return;
}
else
sndSetVolume(wave, (int)((1.0f - vol) * -10000));
/* set the panning */
/* find the amount left/right */
v[Z] = 0.0f;
VectorNormalize(v, v);
VectorCopy(GLevel.view[0]->look, look);
pan = 1.0f - DotProduct(v, look);
/* find if left or right */
temp = v[X]; v[X] = v[Y]; v[Y] = (-1.0f) * temp;
if(DotProduct(v, look) > 0.0f)
{
sndSetBalance(wave, (int)(-10000 * pan));
}
else
{
sndSetBalance(wave, (int)(10000 * pan));
}
}
int sndPlay3D(int wave, BOOL looped, OBJECT *obj)
{
SNDWAVEFILE *sound = &sounds[wave];
int nwave;
if(wave < 0)
return wave;
if(sndIsPlaying(wave))
{
if(sound->looped)
return wave; /* don't duplicate a looped sound */
nwave = sndCopy(wave);
if(nwave >=0)
{
sound = &sounds[nwave];
IDirectSoundBuffer_Play(sound->DSB, 0, 0, 0);
sound->looped = FALSE; /* don't loop a temp sound buffer */
sound->obj = obj;
}
}
else
{
nwave = wave;
if(looped)
{
IDirectSoundBuffer_Play(sound->DSB, 0, 0, DSBPLAY_LOOPING);
sound->looped = TRUE;
}
else
{
IDirectSoundBuffer_Play(sound->DSB, 0, 0, 0);
sound->looped = FALSE;
}
sound->obj = obj;
}
if(obj)
sndUpdate3D(nwave, obj);
return nwave;
}
void sndStop(int wave)
{
SNDWAVEFILE *sound = &sounds[wave];
if(wave < 0)
return;
IDirectSoundBuffer_Stop(sound->DSB);
}
BOOL sndIsPlaying(int wave)
{
SNDWAVEFILE *sound = &sounds[wave];
DWORD status;
if(wave < 0)
return FALSE;
IDirectSoundBuffer_GetStatus(sound->DSB, &status);
return (status & DSBSTATUS_PLAYING);
}
int sndGetFrequency(int wave)
{
SNDWAVEFILE *sound = &sounds[wave];
if(wave < 0)
return -1;
return sound->freq;
}
int sndGetBalance(int wave)
{
SNDWAVEFILE *sound = &sounds[wave];
if(wave < 0)
return 0;
return sound->pan;
}
int sndGetVolume(int wave)
{
SNDWAVEFILE *sound = &sounds[wave];
if(wave < 0)
return 0;
return sound->vol;
}
BOOL sndGetLooping(int wave)
{
SNDWAVEFILE *sound = &sounds[wave];
if(wave < 0)
return FALSE;
return sound->looped;
}
void sndSetFrequency(int wave, int frequency)
{
SNDWAVEFILE *sound = &sounds[wave];
HRESULT dsrval;
if(wave < 0)
return;
dsrval = IDirectSoundBuffer_SetFrequency(sound->DSB, frequency);
if(dsrval == DS_OK)
sound->freq = frequency;
}
void sndSetBalance(int wave, int balance)
{
SNDWAVEFILE *sound = &sounds[wave];
HRESULT dsrval;
if(wave < 0)
return;
dsrval = IDirectSoundBuffer_SetPan(sound->DSB, balance);
if(dsrval == DS_OK)
sound->pan = balance;
}
void sndSetVolume(int wave, int volume)
{
SNDWAVEFILE *sound = &sounds[wave];
HRESULT dsrval;
if(wave < 0)
return;
dsrval = IDirectSoundBuffer_SetVolume(sound->DSB, volume);
if(dsrval == DS_OK)
sound->vol = volume;
}
void sndSetLooping(int wave, BOOL looping)
{
SNDWAVEFILE *sound = &sounds[wave];
if(wave < 0)
return;
if(looping == sound->looped)
return;
if(looping)
{
IDirectSoundBuffer_Play(sound->DSB, 0, 0, DSBPLAY_LOOPING);
sound->looped = TRUE;
}
else
{
IDirectSoundBuffer_Play(sound->DSB, 0, 0, 0);
sound->looped = FALSE;
}
}
void sndUpdate(void)
{
/* delete temp sounds that are done playing */
int i;
SNDWAVEFILE *sound;
for(i=MAX_STATIC_SOUNDS; i<MAX_SOUNDS; i++)
{
sound = &sounds[i];
if(sound->DSB)
if(!sndIsPlaying(i))
sndUnload(i);
}
/* update 3D sounds */
for(i=0; i<MAX_SOUNDS; i++)
{
sound = &sounds[i];
if(sound->DSB && sndIsPlaying(i) && sound->obj)
sndUpdate3D(i, sound->obj);
}
}
/*
* Custom IO procedure for MMIO calls.
*
* Used to allow wave files to be accessed in PAK files.
*/
LRESULT (CALLBACK sndMMIOProc)(LPSTR lpmmioinfo, UINT uMsg,
LONG lParam1, LONG lParam2)
{
char *filename;
int f, count;
MMIOINFO *mmioinfo = (MMIOINFO *)lpmmioinfo;
switch (uMsg)
{
case MMIOM_OPEN:
filename = (char*)lParam1;
stripExtension(filename); /* remove the .wav extension */
strcat(filename, ".wav"); /* add our extension */
f = openFile(filename,O_RDONLY|O_BINARY);
if(f >0)
{
mmioinfo->adwInfo[0] = f;
seekFile(f, 0, SEEK_SET);
return MMSYSERR_NOERROR;
}
else
{
return MMIOERR_CANNOTOPEN;
}
break;
case MMIOM_CLOSE:
f = mmioinfo->adwInfo[0];
closeFile(f);
return MMSYSERR_NOERROR;
break;
case MMIOM_READ:
f = mmioinfo->adwInfo[0];
count = readFile(f, (char *)lParam1, lParam2);
if(count > 0)
mmioinfo->lDiskOffset += count;
return count;
break;
case MMIOM_SEEK:
f = mmioinfo->adwInfo[0];
count = seekFile(f, lParam1, lParam2);
if(count > 0)
mmioinfo->lDiskOffset += count;
return count;
break;
default:
return 0;
break;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -