#include <windows.h>
#include "main.h"
#include <string.h>
#ifdef DX
const struct sounds sound_table[MAX_SOUND+1] =
{
{"audio/song1.wav", "Song1", 1368058},
{"audio/whoa-strange.wav", "Whoa-Strange", 34672},
{"Not Applicable!", "None", 0 }
};
int get_sound( char *name )
{
int i = 0;
for ( i = 0; i < MAX_SOUND; i++ )
if ( !stricmp(sound_table[i].name, name) )
return i;
return MAX_SOUND+1;
}
SOUND *get_sound_buf( LPDIRECTSOUNDBUFFER buf )
{
SOUND *s = NULL;
for ( s = first_sound; s != NULL; s = s->next )
if ( buf == s->sound )
return s;
return NULL;
}
void play_sound( int s )
{
if ( s < 0 || s > MAX_SOUND )
return;
LPDIRECTSOUNDBUFFER b = load_wave_from_file( sound_table[s].fname, sound_table[s].bytes, s );
b->lpVtbl->SetCurrentPosition(b,60);
play_wave( b, FALSE );
}
HMMIO wave;
int volume;
bool stopped;
int current_song;
SOUND *first_sound = NULL;
SOUND *last_sound = NULL;
LPDIRECTSOUND ds = NULL;
LPDIRECTSOUNDBUFFER song = NULL;
void close_dx( void )
{
SOUND *s = NULL;
SOUND *snext = NULL;
glog( "In close_dx..." );
for ( s = first_sound; s != NULL; s = snext )
{
snext = s->next;
delete_wave(s->sound);
}
ds->lpVtbl->Release(ds);
mmioClose( wave, 0 ); }
void delete_wave( LPDIRECTSOUNDBUFFER buf )
{
if ( buf == NULL )
return;
SOUND *s = get_sound_buf(buf);
if ( song == buf )
song = NULL;
if ( buf != NULL )
buf->lpVtbl->Release(buf);
if ( s != NULL )
{
glog( "Deleting wave... (Index: %d)", s->index );
s->sound = NULL;
UNLINK(s, first_sound, last_sound, next, prev );
DISPOSE(s);
}
}
LPDIRECTSOUNDBUFFER init_buffer( DWORD bytes, int index )
{
SOUND *s = NULL;
HRESULT hr;
WAVEFORMATEX wfx;
ZeroMemory( &wfx, sizeof(WAVEFORMATEX));
wfx.wFormatTag = (WORD) WAVE_FORMAT_PCM;
wfx.nChannels = 1;
wfx.nSamplesPerSec = 22050;
wfx.wBitsPerSample = 8;
wfx.nBlockAlign = (WORD) (wfx.wBitsPerSample / 8 * wfx.nChannels);
wfx.nAvgBytesPerSec = (DWORD) (wfx.nSamplesPerSec * wfx.nBlockAlign);
DSBUFFERDESC dsbd;
ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_CTRLVOLUME|DSBCAPS_GETCURRENTPOSITION2;
glog( "Init_buffer: bytes = %lu", bytes );
dsbd.dwBufferBytes = URANGE(DSBSIZE_MIN,bytes,DSBSIZE_MAX);
dsbd.lpwfxFormat = &wfx;
LPDIRECTSOUNDBUFFER buffer = NULL;
hr = ds->lpVtbl->CreateSoundBuffer(ds, &dsbd, &buffer, NULL );
buffer->lpVtbl->SetFormat(buffer, &wfx);
if FAILED(hr)
return NULL;
if ( buffer != NULL )
{
CREATE( s, SOUND, 1);
s->sound = buffer;
s->index = index;
LINK( s, first_sound, last_sound, next, prev );
}
return buffer;
}
LPDIRECTSOUNDBUFFER load_wave_from_file( LPSTR file, DWORD bytes, int index )
{
if ( !file || file[0] == '\0' )
return NULL;
HMMIO wve = NULL;
wve = mmioOpen( file, NULL, MMIO_READ );
if ( wve == NULL )
{
mmioClose( wve, 0 );
return NULL;
}
VOID* locked = NULL; DWORD lsize = 0; LPDIRECTSOUNDBUFFER buf = init_buffer(bytes, index);
if ( buf == NULL )
{
mmioClose( wve, 0);
return NULL;
}
HRESULT hr;
hr = buf->lpVtbl->Lock(buf, 0, bytes, &locked, &lsize, NULL, NULL, DSBLOCK_ENTIREBUFFER);
if FAILED(hr)
{
delete_wave(buf);
mmioClose( wve, 0 );
return NULL;
}
mmioSeek( wve, 0, SEEK_SET);
int rt;
rt = mmioRead( wve, (HPSTR)locked, (LONG)bytes );
if ( rt == 0 )
lsize = bytes;
else if ( rt == -1 )
{
delete_wave(buf);
mmioClose( wve, 0 );
return NULL;
}
buf->lpVtbl->Unlock(buf, locked, lsize, NULL, 0 );
mmioClose( wve, 0 );
return buf;
}
void play_wave( LPDIRECTSOUNDBUFFER buf, bool loop )
{
if ( buf == NULL )
return;
if ( loop == TRUE )
buf->lpVtbl->Play(buf,0,0,DSBPLAY_LOOPING);
else
buf->lpVtbl->Play(buf,0,0,0);
stopped = FALSE;
}
void stop_wave( LPDIRECTSOUNDBUFFER buf )
{
if ( buf == NULL )
return;
buf->lpVtbl->Stop(buf);
stopped = TRUE;
}
void set_volume( LPDIRECTSOUNDBUFFER buf, LONG amount )
{
if ( buf == NULL )
return;
volume = URANGE(DSBVOLUME_MIN,amount,DSBVOLUME_MAX);
buf->lpVtbl->SetVolume(buf,volume);
}
bool init_dx( int song )
{
bool ok = FALSE;
current_song = song;
if ( DirectSoundCreate( 0, &ds, 0 ) == DS_OK )
if ( ds->lpVtbl->SetCooperativeLevel(ds,game->hWindow,DSSCL_PRIORITY) == DS_OK )
ok = TRUE;
if ( ok == TRUE )
{
stopped = FALSE;
volume = -200;
if ( current_song != MAX_SOUND )
{
wave = mmioOpen( sound_table[current_song].fname, NULL, MMIO_READ ); handle_dx(TRUE); }
return TRUE;
}
return FALSE;
}
LPDIRECTSOUNDBUFFER load_wave_from_resource( HGLOBAL mem, DWORD bytes, int index )
{
if ( mem == NULL )
return NULL;
VOID* locked = NULL; DWORD lsize = 0; LPDIRECTSOUNDBUFFER buf = init_buffer(bytes, index);
if ( buf == NULL )
return NULL;
HRESULT hr;
hr = buf->lpVtbl->Lock(buf, 0, bytes, &locked, &lsize, NULL, NULL, DSBLOCK_ENTIREBUFFER);
if FAILED(hr)
{
delete_wave(buf);
return NULL;
}
BYTE *ptr;
ptr = mem;
memcpy(locked,&ptr[44],lsize);
buf->lpVtbl->Unlock(buf, locked, lsize, NULL, 0 );
return buf;
}
void handle_dx( bool restart )
{
if ( stopped == TRUE )
return;
if ( current_song == MAX_SOUND )
return;
static unsigned int seek_spot = 0;
LPDIRECTSOUNDBUFFER old = song; DWORD bytes = BUFFER_SIZE;
DWORD song_bytes = sound_table[current_song].bytes;
if ( restart == TRUE )
seek_spot = 0;
if ( (song_bytes-seek_spot) < bytes )
bytes = song_bytes-seek_spot; LPDIRECTSOUNDBUFFER d = init_buffer(bytes,current_song); if ( wave == NULL )
{
mmioClose( wave, 0 );
return;
}
VOID* locked = NULL; DWORD lsize = 0; if ( d == NULL )
{
mmioClose( wave, 0);
return;
}
HRESULT hr;
hr = d->lpVtbl->Lock(d, 0, bytes, &locked, &lsize, NULL, NULL, DSBLOCK_ENTIREBUFFER);
if FAILED(hr)
{
delete_wave(d);
mmioClose( wave, 0 );
return;
}
mmioSeek( wave, seek_spot, SEEK_SET);
int rt = mmioRead( wave, (HPSTR)locked, (LONG)bytes );
if ( rt == 0 )
lsize = bytes;
else if ( rt == -1 )
{
delete_wave(d);
mmioClose( wave, 0 );
return;
}
d->lpVtbl->Unlock(d, locked, lsize, NULL, 0 );
seek_spot += bytes;
song = d; set_volume( song, volume );
play_wave(song,FALSE);
delete_wave(old);
if ( bytes != BUFFER_SIZE) seek_spot = 0;
evaluate_waves();
}
void evaluate_waves( void )
{
SOUND *s, *snext;
DWORD play, write;
LPDIRECTSOUNDBUFFER d;
for ( s = first_sound; s != NULL; s = snext )
{
snext = s->next;
if ( s->sound == song || s->index == current_song )
continue;
d = s->sound;
d->lpVtbl->GetCurrentPosition(d, &play, &write);
if ( (play >= sound_table[s->index].bytes) || (play <= 0) ) delete_wave(d);
}
}
#endif