From 60c48066517a6786d57026fbc0ff1b6b9fd12220 Mon Sep 17 00:00:00 2001 From: Taylor Richards Date: Sat, 8 Feb 2014 03:03:49 -0500 Subject: [PATCH] first pass at updated sound code --- include/acm.h | 5 +- include/audiostr.h | 6 +- include/channel.h | 81 - include/ds.h | 374 --- include/ds3d.h | 67 - include/dscap.h | 60 - include/oal.h | 121 + include/oal_capture.h | 26 + include/oal_efx.h | 31 + include/sound.h | 25 +- src/CMakeLists.txt | 8 +- src/freespace2/freespace.cpp | 11 +- src/gamesnd/gamesnd.cpp | 2 +- src/hud/hud.cpp | 8 +- src/hud/hudlock.cpp | 2 +- src/menuui/optionsmenumulti.cpp | 29 +- src/movie/mveplayer.cpp | 43 +- src/network/multi_voice.cpp | 18 +- src/object/objectsnd.cpp | 80 +- src/ship/afterburner.cpp | 2 +- src/ship/shipfx.cpp | 2 +- src/sound/acm.cpp | 284 ++- src/sound/audiostr.cpp | 1381 +++++------ src/sound/ds.cpp | 3993 ------------------------------- src/sound/ds3d.cpp | 350 --- src/sound/dscap.cpp | 379 --- src/sound/oal.cpp | 1275 ++++++++++ src/sound/oal_capture.cpp | 188 ++ src/sound/oal_efx.cpp | 352 +++ src/sound/rtvoice.cpp | 97 +- src/sound/sound.cpp | 543 +++-- src/vcodec/codec1.cpp | 133 +- 32 files changed, 3381 insertions(+), 6595 deletions(-) delete mode 100644 include/channel.h delete mode 100644 include/ds.h delete mode 100644 include/ds3d.h delete mode 100644 include/dscap.h create mode 100644 include/oal.h create mode 100644 include/oal_capture.h create mode 100644 include/oal_efx.h delete mode 100644 src/sound/ds.cpp delete mode 100644 src/sound/ds3d.cpp delete mode 100644 src/sound/dscap.cpp create mode 100644 src/sound/oal.cpp create mode 100644 src/sound/oal_capture.cpp create mode 100644 src/sound/oal_efx.cpp diff --git a/include/acm.h b/include/acm.h index 3ae8b89..370a0c9 100644 --- a/include/acm.h +++ b/include/acm.h @@ -51,10 +51,11 @@ #define __FREESPACE_ACM_H__ #include "pstypes.h" +#include "oal.h" -int ACM_convert_ADPCM_to_PCM(WAVEFORMATEX *pwfxSrc, ubyte *src, int src_len, ubyte **dest, int max_dest_bytes, int *dest_len, unsigned int *src_bytes_used, unsigned short dest_bps=16); +int ACM_convert_ADPCM_to_PCM(WAVE_chunk *pwfxSrc, ubyte *src, int src_len, ubyte **dest, int max_dest_bytes, int *dest_len, unsigned int *src_bytes_used, unsigned short dest_bps=16); -int ACM_stream_open(WAVEFORMATEX *pwfxSrc, WAVEFORMATEX *pwfxDest, void **stream, int dest_bps=16); +int ACM_stream_open(WAVE_chunk *pwfxSrc, WAVE_chunk *pwfxDest, void **stream, int dest_bps=16); int ACM_stream_close(void *stream); int ACM_query_source_size(void *stream, int dest_len); int ACM_query_dest_size(void *stream, int src_len); diff --git a/include/audiostr.h b/include/audiostr.h index 324a0f7..d8ccd1d 100644 --- a/include/audiostr.h +++ b/include/audiostr.h @@ -115,7 +115,7 @@ void audiostream_close_all(int fade); void audiostream_play(int i, float volume = -1.0f, int looping = 1); // See if a particular stream is playing -int audiostream_is_playing(int i); +bool audiostream_is_playing(int i); // Stops the currently opened wave file void audiostream_stop(int i, int rewind = 1, int paused = 0); @@ -127,7 +127,7 @@ void audiostream_set_volume_all(float volume, int type); void audiostream_set_volume(int i, float volume); // see if a particular stream is paused -int audiostream_is_paused(int i); +bool audiostream_is_paused(int i); // set the number of bytes that the sound should cutoff after void audiostream_set_byte_cutoff(int i, unsigned int cutoff); @@ -136,7 +136,7 @@ void audiostream_set_byte_cutoff(int i, unsigned int cutoff); unsigned int audiostream_get_bytes_committed(int i); // check if the streaming has read all the bytes from disk yet -int audiostream_done_reading(int i); +bool audiostream_done_reading(int i); // return if audiostream has initialized ok int audiostream_is_inited(); diff --git a/include/channel.h b/include/channel.h deleted file mode 100644 index ed867df..0000000 --- a/include/channel.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) Volition, Inc. 1999. All rights reserved. - * - * All source code herein is the property of Volition, Inc. You may not sell - * or otherwise commercially exploit the source or things you created based on - * the source. - */ - -/* - * $Logfile: /Freespace2/code/Sound/channel.h $ - * $Revision$ - * $Date$ - * $Author$ - * - * Common types for the sound channels shared by the DirectSound modules - * - * $Log$ - * Revision 1.2 2002/06/09 04:41:12 relnev - * added copyright header - * - * Revision 1.1.1.1 2002/05/03 03:28:12 root - * Initial import. - * - * - * 4 10/25/99 5:56p Jefff - * increase num software channels to the number the users hardware can - * handle. not less than 16, tho. - * - * 3 8/27/99 6:38p Alanl - * crush the blasted repeating messages bug - * - * 2 10/07/98 10:54a Dave - * Initial checkin. - * - * 1 10/07/98 10:51a Dave - * - * 6 12/05/97 5:19p Lawrance - * re-do sound priorities to make more general and extensible - * - * 5 7/17/97 9:32a John - * made all directX header files name start with a v - * - * 4 7/15/97 11:15a Lawrance - * limit the max instances of simultaneous sound effects, implement - * priorities to force critical sounds - * - * 3 6/09/97 8:53a Lawrance - * add #ifndef ... #endif to avoid multiple inclusion - * - * 2 6/08/97 6:00p Lawrance - * created to share channel defs between ds.cpp and ds3d.cpp - * - * $NoKeywords: $ - */ - - -#include -#include "vdsound.h" - -#ifndef __CHANNEL_H__ -#define __CHANNEL_H__ - -typedef struct channel -{ - int sig; // uniquely identifies the sound playing on the channel - int snd_id; // identifies which kind of sound is playing - LPDIRECTSOUNDBUFFER pdsb; // pointer to the secondary buffer that was duplicated - LPDIRECTSOUND3DBUFFER pds3db; // 3D interface, only used if sound buffer created with CTRL3D flag - int looping; // flag to indicate that the sound is looping - int vol; // in DirectSound units - int priority; // implementation dependant priority - bool is_voice_msg; - DWORD last_position; -} channel; - - -// #define MAX_CHANNELS 16 -extern channel* Channels; //[MAX_CHANNELS]; - -#endif /* __CHANNEL_H__ */ - diff --git a/include/ds.h b/include/ds.h deleted file mode 100644 index 80b403e..0000000 --- a/include/ds.h +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (C) Volition, Inc. 1999. All rights reserved. - * - * All source code herein is the property of Volition, Inc. You may not sell - * or otherwise commercially exploit the source or things you created based on - * the source. - */ - -/* - * $Logfile: /Freespace2/code/Sound/ds.h $ - * $Revision$ - * $Date$ - * $Author$ - * - * Header file for interface to DirectSound - * - * $Log$ - * Revision 1.7 2006/04/26 19:36:12 taylor - * remove ALUT headers, since we don't use it anyway and there is no reason to make it a build requirement - * - * Revision 1.6 2005/10/01 21:38:32 taylor - * some reorg of includes to not requires the same headers in many different files - * handle FS1 specific language changes - * some OS X changes for paths and to handle socklen_t better - * - * Revision 1.5 2005/08/13 17:01:34 taylor - * gah, fix stupid commit message - * - * Revision 1.4 2005/08/12 08:47:24 taylor - * use new audiostr code rather than old windows and *nix version - * update all OpenAL commands with new error checking macros - * fix play_position to properly account for real position, fixes the talking heads and message text cutting out early - * movies will now use better filtering when scaled - * - * Revision 1.3 2002/06/09 04:41:12 relnev - * added copyright header - * - * Revision 1.2 2002/05/27 01:06:01 theoddone33 - * sound.cpp works - * - * Revision 1.1.1.1 2002/05/03 03:28:12 root - * Initial import. - * - * - * 5 8/27/99 6:38p Alanl - * crush the blasted repeating messages bug - * - * 4 8/01/99 2:06p Alanl - * increase the rolloff for A3D - * - * 3 5/23/99 8:11p Alanl - * Added support for EAX - * - * 2 10/07/98 10:54a Dave - * Initial checkin. - * - * 1 10/07/98 10:51a Dave - * - * 21 5/05/98 4:49p Lawrance - * Put in code to authenticate A3D, improve A3D support - * - * 20 4/20/98 12:03a Lawrance - * Allow prioritizing of CTRL3D buffers - * - * 19 4/18/98 9:12p Lawrance - * Added Aureal support. - * - * 18 4/13/98 5:04p Lawrance - * Write functions to determine how many milliseconds are left in a sound - * - * 17 3/23/98 10:32a Lawrance - * Add functions for extracting raw sound data - * - * 16 2/15/98 11:10p Lawrance - * more work on real-time voice system - * - * 15 2/15/98 4:43p Lawrance - * work on real-time voice - * - * 14 2/06/98 7:30p John - * Added code to monitor the number of channels of sound actually playing. - * - * 13 2/06/98 8:56a Allender - * fixed calling convention problem with DLL handles - * - * 12 2/04/98 6:08p Lawrance - * Read function pointers from dsound.dll, further work on - * DirectSoundCapture. - * - * 11 1/31/98 5:48p Lawrance - * Start on real-time voice recording - * - * 10 12/05/97 5:19p Lawrance - * re-do sound priorities to make more general and extensible - * - * 9 11/20/97 5:36p Dave - * Hooked in a bunch of main hall changes (including sound). Made it - * possible to reposition (rewind/ffwd) - * sound buffer pointers. Fixed animation direction change framerate - * problem. - * - * 8 10/13/97 7:41p Lawrance - * store duration of sound - * - * 7 7/28/97 11:39a Lawrance - * allow individual volume scaling on 3D buffers - * - * 6 7/17/97 9:32a John - * made all directX header files name start with a v - * - * 5 7/15/97 11:15a Lawrance - * limit the max instances of simultaneous sound effects, implement - * priorities to force critical sounds - * - * 4 6/09/97 11:50p Lawrance - * integrating DirectSound3D - * - * 3 6/02/97 1:45p Lawrance - * implementing hardware mixing - * - * 2 5/29/97 12:04p Lawrance - * creation of file to hold DirectSound specific portions - * - * $NoKeywords: $ - */ - -#ifndef __DS_H__ -#define __DS_H__ - -#ifndef PLAT_UNIX -#include -#include -#include "vdsound.h" -#endif -#include "pstypes.h" - -#define DS_HARDWARE (1<<0) -#define DS_3D (1<<1) -#define DS_USE_DS3D (1<<2) - -// Constants that DirectSound should assign, but doesn't -#define MAX_PAN 1500.0f -#define MIN_PITCH 100 -#define MAX_PITCH 100000 - - -// limits placed on how many concurrent sounds of the same type can play simultaneously -#define DS_MUST_PLAY 0 -#define DS_LIMIT_ONE 1 -#define DS_LIMIT_TWO 2 -#define DS_LIMIT_THREE 3 - -#define DS_DUP_FAILED -99 - -typedef struct sound_info { - int format; // WAVE_FORMAT_* defines from mmreg.h - uint size; - int sample_rate; - int avg_bytes_per_sec; - int n_block_align; - int bits; - int n_channels; - int duration; // time in ms for duration of sound - ubyte *data; -} sound_info; - -extern int ds_initialized; - - -#ifdef PLAT_UNIX - -#ifdef __APPLE__ - #include - #include -#else - #include - #include -#endif - -extern const char* openal_error_string(); - -// if an error occurs after executing 'x' then do 'y' -#define OpenAL_ErrorCheck( x, y ) do { \ - x; \ - const char *error_text = openal_error_string(); \ - if ( error_text != NULL ) { \ - while ( error_text != NULL ) { \ - nprintf(("Warning", "SOUND: %s:%d - OpenAL error = '%s'\n", __FILE__, __LINE__, error_text)); \ - error_text = openal_error_string(); \ - } \ - y; \ - } \ -} while (0); - -// like OpenAL_ErrorCheck() except that it gives the error message from x but does nothing about it -#define OpenAL_ErrorPrint( x ) do { \ - x; \ - const char *error_text = openal_error_string(); \ - if ( error_text != NULL ) { \ - while ( error_text != NULL ) { \ - nprintf(("Sound", "OpenAL ERROR: \"%s\" in %s, line %i\n", error_text, __FILE__, __LINE__)); \ - error_text = openal_error_string(); \ - } \ - } \ -} while (0); - -#else - -extern LPDIRECTSOUNDBUFFER pPrimaryBuffer; -extern LPDIRECTSOUND pDirectSound; - -extern HRESULT (__stdcall *pfn_DirectSoundCaptureCreate)(LPGUID lpGUID, LPDIRECTSOUNDCAPTURE *lplpDSC, LPUNKNOWN pUnkOuter); -#endif - -int ds_init(int use_a3d, int use_eax); -void ds_close(); -void ds_get_primary_format(WAVEFORMATEX *wfx); -int ds_parse_wave(char *filename, ubyte **dest, uint *dest_size, WAVEFORMATEX **header); -int ds_load_buffer(int *sid, int *hid, int *final_size, void *header, sound_info *si, int flags); -void ds_unload_buffer(int sid, int hid); -int ds_play(int sid, int hid, int snd_id, int priority, int volume, int pan, int looping, bool is_voice_msg = false); -int ds_convert_volume(float volume); // Convert a volume from 0.0f->1.0f to -10000 -> 0 -float ds_get_percentage_vol(int ds_vol); // Convert a volume from -10000 -> 0 to 0.0f->1.0f -int ds_get_channel(int sig); -int ds_is_channel_playing(int channel); -void ds_stop_channel(int channel); -void ds_stop_channel_all(); -void ds_set_volume( int channel, int vol ); -void ds_set_pan( int channel, int pan ); -int ds_get_pitch(int channel); -void ds_set_pitch(int channel, int pitch); -void ds_chg_loop_status(int channel, int loop); -void ds_set_position(int channel, DWORD offset); -DWORD ds_get_play_position(int channel); -DWORD ds_get_write_position(int channel); -int ds_get_data(int sid, char *data); -int ds_get_size(int sid, int *size); - -int ds_create_buffer(int frequency, int bits_per_sample, int nchannels, int nseconds); -int ds_lock_data(int sid, unsigned char *data, int size); -int ds_play_easy(int sid, int volume); -void ds_stop_easy(int sid); -int ds_get_channel_size(int channel); -int ds_is_3d_buffer(int sid); -int ds_using_ds3d(); -bool ds_using_a3d(); - -unsigned int ds_get_primary_buffer_interface(); -unsigned int ds_get_dsound_interface(); -unsigned int ds_get_property_set_interface(); - -// Returns the number of channels that are actually playing -int ds_get_number_channels(); - -int ds3d_play( int sid, int hid, int snd_id, vector *pos, vector *vel, int min, int max, int looping, int max_volume, int estimated_vol, int priority=DS_MUST_PLAY ); - -// Get a character string for the error code -char *get_DSERR_text(int DSResult); - -void ds_do_frame(); - -// -------------------- -// -// Creative eax.h -// -// -------------------- - -// EAX (listener) reverb property set {4a4e6fc1-c341-11d1-b73a-444553540000} -#ifndef PLAT_UNIX -DEFINE_GUID(DSPROPSETID_EAX_ReverbProperties, - 0x4a4e6fc1, - 0xc341, - 0x11d1, - 0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00); -#endif - -typedef enum -{ - DSPROPERTY_EAX_ALL, // all reverb properties - DSPROPERTY_EAX_ENVIRONMENT, // standard environment no. - DSPROPERTY_EAX_VOLUME, // loudness of the reverb - DSPROPERTY_EAX_DECAYTIME, // how long the reverb lasts - DSPROPERTY_EAX_DAMPING // the high frequencies decay faster -} DSPROPERTY_EAX_REVERBPROPERTY; - -#define EAX_NUM_STANDARD_PROPERTIES (DSPROPERTY_EAX_DAMPING + 1) - -// use this structure for get/set all properties... -typedef struct -{ - unsigned long environment; // 0 to EAX_ENVIRONMENT_COUNT-1 - float fVolume; // 0 to 1 - float fDecayTime_sec; // seconds, 0.1 to 100 - float fDamping; // 0 to 1 -} EAX_REVERBPROPERTIES; - - -enum -{ - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_COUNT // total number of environments -}; - -#define EAX_MAX_ENVIRONMENT (EAX_ENVIRONMENT_COUNT - 1) - -// EAX buffer reverb property set {4a4e6fc0-c341-11d1-b73a-444553540000} -#ifndef PLAT_UNIX -DEFINE_GUID(DSPROPSETID_EAXBUFFER_ReverbProperties, - 0x4a4e6fc0, - 0xc341, - 0x11d1, - 0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00); -#endif - -typedef enum -{ - DSPROPERTY_EAXBUFFER_ALL, // all reverb buffer properties - DSPROPERTY_EAXBUFFER_REVERBMIX // the wet source amount -} DSPROPERTY_EAXBUFFER_REVERBPROPERTY; - -// use this structure for get/set all properties... -typedef struct -{ - float fMix; // linear factor, 0.0F to 1.0F -} EAXBUFFER_REVERBPROPERTIES; - -#define EAX_REVERBMIX_USEDISTANCE -1.0F // out of normal range - // signifies the reverb engine should - // calculate it's own reverb mix value - // based on distance - -// prototypes - -int ds_eax_init(); -void ds_eax_close(); - -int ds_eax_set_preset(unsigned long envid); - -int ds_eax_set_volume(float volume); -int ds_eax_set_decay_time(float seconds); -int ds_eax_set_damping(float damp); -int ds_eax_set_environment(unsigned long envid); -int ds_eax_set_all(unsigned long id, float volume, float damping, float decay); -int ds_eax_get_all(EAX_REVERBPROPERTIES *er); -int ds_eax_is_inited(); - -#endif /* __DS_H__ */ - diff --git a/include/ds3d.h b/include/ds3d.h deleted file mode 100644 index 22335fa..0000000 --- a/include/ds3d.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) Volition, Inc. 1999. All rights reserved. - * - * All source code herein is the property of Volition, Inc. You may not sell - * or otherwise commercially exploit the source or things you created based on - * the source. - */ - -/* - * $Logfile: /Freespace2/code/Sound/ds3d.h $ - * $Revision$ - * $Date$ - * $Author$ - * - * Header file for interface to DirectSound3D - * - * $Log$ - * Revision 1.2 2002/06/09 04:41:12 relnev - * added copyright header - * - * Revision 1.1.1.1 2002/05/03 03:28:12 root - * Initial import. - * - * - * 3 5/23/99 8:11p Alanl - * Added support for EAX - * - * 2 10/07/98 10:54a Dave - * Initial checkin. - * - * 1 10/07/98 10:51a Dave - * - * 8 4/19/98 9:31p Lawrance - * Use Aureal_enabled flag - * - * 7 7/28/97 11:39a Lawrance - * allow individual volume scaling on 3D buffers - * - * 6 6/09/97 11:50p Lawrance - * integrating DirectSound3D - * - * 5 6/08/97 5:59p Lawrance - * integrate DirectSound3D into sound system - * - * 4 6/02/97 1:45p Lawrance - * implementing hardware mixing - * - * 3 5/29/97 4:02p Lawrance - * listener interface in place - * - * 2 5/29/97 12:03p Lawrance - * creation of file to hold DirectSound3D specific code - * - * $NoKeywords: $ - */ - -#ifndef __DS3D_H__ -#define __DS3D_H__ - -int ds3d_init(int voice_manager_required); -void ds3d_close(); -int ds3d_update_listener(vector *pos, vector *vel, matrix *orient); -int ds3d_update_buffer(int channel, float min, float max, vector *pos, vector *vel); -int ds3d_set_sound_cone(int channel, int inner_angle, int outer_angle, int vol); - -#endif /* __DS3D_H__ */ - diff --git a/include/dscap.h b/include/dscap.h deleted file mode 100644 index 80f0b7f..0000000 --- a/include/dscap.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) Volition, Inc. 1999. All rights reserved. - * - * All source code herein is the property of Volition, Inc. You may not sell - * or otherwise commercially exploit the source or things you created based on - * the source. - */ - -/* - * $Logfile: /Freespace2/code/Sound/dscap.h $ - * $Revision$ - * $Date$ - * $Author$ - * - * Header file for DirectSoundCapture code - * - * $Log$ - * Revision 1.2 2002/06/09 04:41:12 relnev - * added copyright header - * - * Revision 1.1.1.1 2002/05/03 03:28:12 root - * Initial import. - * - * - * 2 10/07/98 10:54a Dave - * Initial checkin. - * - * 1 10/07/98 10:51a Dave - * - * 4 2/15/98 11:10p Lawrance - * more work on real-time voice system - * - * 3 2/15/98 4:43p Lawrance - * work on real-time voice - * - * 2 2/03/98 11:53p Lawrance - * Adding support for DirectSoundCapture - * - * 1 2/03/98 4:48p Lawrance - * - * $NoKeywords: $ - */ - -#ifndef __DSCAP_H__ -#define __DSCAP_H__ - -int dscap_init(); -void dscap_close(); -int dscap_supported(); -int dscap_create_buffer(int freq, int bits_per_sample, int nchannels, int nseconds); -void dscap_release_buffer(); - -int dscap_start_record(); -int dscap_stop_record(); -int dscap_max_buffersize(); -int dscap_get_raw_data(unsigned char *outbuf, unsigned int max_size); - - -#endif // __DSCAP_H__ - diff --git a/include/oal.h b/include/oal.h new file mode 100644 index 0000000..b050942 --- /dev/null +++ b/include/oal.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) Volition, Inc. 1999. All rights reserved. + * + * All source code herein is the property of Volition, Inc. You may not sell + * or otherwise commercially exploit the source or things you created based on + * the source. + */ + +#ifndef __OAL_H__ +#define __OAL_H__ + +#include "al.h" +#include "alc.h" + +#include "pstypes.h" + + +#ifndef WAVE_FORMAT_PCM +#define WAVE_FORMAT_PCM 1 +#endif + +#ifndef WAVE_FORMAT_ADPCM +#define WAVE_FORMAT_ADPCM 2 +#endif + +typedef struct WAVE_chunk { + short code; + ushort num_channels; + uint sample_rate; + uint bytes_per_second; + ushort block_align; + ushort bits_per_sample; + + ushort extra_size; + ubyte *extra_data; + + WAVE_chunk() : code(0), num_channels(0), sample_rate(0), bytes_per_second(0), + block_align(0), bits_per_sample(0), extra_size(0), extra_data(NULL) + { + } +} WAVE_chunk; + +typedef struct sound_channel { + int sig; // uniquely identifies the sound playing on the channel + int snd_id; // identifies which kind of sound is playing + ALuint source_id; // OpenAL source id + int buf_idx; // currently bound buffer index (-1 if none) + int flags; // looping, voice_msg, 3d, ... + float vol; + int priority; // implementation dependant priority + ALint last_position; + + sound_channel() : sig(0), snd_id(0), source_id(0), buf_idx(-1), flags(0), + vol(1.0f), priority(0), last_position(0) + { + } +} sound_channel; + +typedef struct sound_info { + int format; // WAVE_FORMAT_* defines + uint size; + int sample_rate; + int avg_bytes_per_sec; + int n_block_align; + int bits; + int n_channels; + int duration; // time in ms for duration of sound + ubyte *data; +} sound_info; + + +int oal_init(int use_eax); +void oal_close(); + +int oal_is_initted(); + +int oal_get_channel(int sig); +int oal_get_number_channels(); + +int oal_get_buffer_size(int sid, int *size); +int oal_get_channel_size(int channel); + +void oal_stop_buffer(int sid); +void oal_stop_channel(int channel); +void oal_stop_channel_all(); + +void oal_set_volume(int channel, float volume); +void oal_set_pan(int channel, float pan); +void oal_set_pitch(int channel, float pitch); +void oal_set_play_position(int channel, int position); + +float oal_get_pitch(int channel); +int oal_get_play_position(int channel); + +int oal_is_channel_playing(int channel); + +void oal_chg_loop_status(int channel, int loop); + +int oal_parse_wave(const char *filename, ubyte **dest, uint *dest_size, WAVE_chunk **header); + +int oal_load_buffer(int *sid, int *final_size, WAVE_chunk *header, sound_info *si, int flags); +void oal_unload_buffer(int sid); + +int oal_create_buffer(int frequency, int bits_per_sample, int nchannels, int nseconds); +int oal_lock_data(int sid, ubyte *data, int size); + +sound_channel *oal_get_free_channel(float volume, int snd_id, int priority); + +void oal_do_frame(); + +int oal_update_source(int channel, int min, int max, vector *pos, vector *vel); +int oal_update_listener(vector *pos, vector *vel, matrix *orient); + +int oal_play(int sid, int snd_id, int priority, float volume, float pan, int flags); +int oal_play_3d( int sid, int snd_id, vector *pos, vector *vel, int min, int max, int looping, float max_volume, float estimated_vol, int priority); + +bool oal_check_for_errors(const char *location); + +void oal_set_source_properties_all(ALenum param, ALint *props); + +#endif // __OAL_H__ diff --git a/include/oal_capture.h b/include/oal_capture.h new file mode 100644 index 0000000..cefb165 --- /dev/null +++ b/include/oal_capture.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) Volition, Inc. 1999. All rights reserved. + * + * All source code herein is the property of Volition, Inc. You may not sell + * or otherwise commercially exploit the source or things you created based on the + * source. + * +*/ + +#ifndef _OAL_CAPTURE_H +#define _OAL_CAPTURE_H + +int oal_capture_create_buffer(int freq, int bits_per_sample, int nchannels, int nseconds); +void oal_capture_release_buffer(); + +int oal_capture_supported(); + +int oal_capture_start_record(); +int oal_capture_stop_record(); + +void oal_capture_close(); + +int oal_capture_max_buffersize(); +int oal_capture_get_raw_data(ubyte *outbuf, uint max_size); + +#endif // _OAL_CAPTURE_H diff --git a/include/oal_efx.h b/include/oal_efx.h new file mode 100644 index 0000000..eb6a86b --- /dev/null +++ b/include/oal_efx.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) Volition, Inc. 1999. All rights reserved. + * + * All source code herein is the property of Volition, Inc. You may not sell + * or otherwise commercially exploit the source or things you created based on the + * source. + * +*/ + +#ifndef OAL_EFX_H_ +#define OAL_EFX_H_ + + +typedef struct +{ + uint environment; // 0 to EAX_ENVIRONMENT_COUNT-1 + float fVolume; // 0 to 1 + float fDecayTime_sec; // seconds, 0.1 to 100 + float fDamping; // 0 to 1 +} EAX_REVERBPROPERTIES; + + +int oal_efx_init(); +void oal_efx_close(); + +int oal_efx_is_inited(); + +int oal_efx_get_all(EAX_REVERBPROPERTIES *er, int id); +int oal_efx_set_all(uint id, float vol, float damping, float decay); + +#endif // OAL_EFX_H_ diff --git a/include/sound.h b/include/sound.h index ae6320e..7d9835c 100644 --- a/include/sound.h +++ b/include/sound.h @@ -211,12 +211,12 @@ #define MAX_SOUNDS 256 -// Used for keeping track which low-level sound library is being used -#define SOUND_LIB_DIRECTSOUND 0 -#define SOUND_LIB_RSX 1 +#define GAME_SND_USE_3D (1<<1) +#define GAME_SND_VOICE (1<<2) -#define GAME_SND_USE_DS3D (1<<1) -#define GAME_SND_VOICE (1<<2) +#define SND_FLAG_3D (1<<1) +#define SND_FLAG_VOICE (1<<2) +#define SND_FLAG_LOOPING (1<<3) // Priorities that can be passed to snd_play() functions to limit how many concurrent sounds of a // given type are played. @@ -249,10 +249,9 @@ extern int Sound_enabled; extern float Master_sound_volume; // 0 -> 1.0 extern float Master_voice_volume; // 0 -> 1.0 extern int Snd_sram; // System memory consumed by sound data -extern int Snd_hram; // Soundcard memory consumed by sound data //int snd_load( char *filename, int hardware=0, int three_d=0, int *sig=NULL ); -int snd_load( game_snd *gs, int allow_hardware_load = 0); +int snd_load( game_snd *gs); int snd_unload( int sndnum ); void snd_unload_all(); @@ -277,7 +276,7 @@ void snd_update_3d_pos(int soudnnum, game_snd *gs, vector *new_pos); // Use these for looping sounds. // Returns the handle of the sound. -1 if failed. // If startloop or stoploop are not -1, then then are used. -int snd_play_looping( game_snd *gs, float pan=0.0f, int start_loop=-1, int stop_loop=-1, float vol_scale=1.0f, int priority = SND_PRIORITY_MUST_PLAY, int force = 0 ); +int snd_play_looping( game_snd *gs, float pan=0.0f, float vol_scale=1.0f, int priority = SND_PRIORITY_MUST_PLAY, int force = 0 ); void snd_stop( int snd_handle ); @@ -291,9 +290,9 @@ void snd_set_volume( int snd_handle, float volume ); void snd_set_pan( int snd_handle, float pan ); // Sets the pitch (frequency) of a sound that is already playing -// Valid values for pitch are between 100 and 100000 -void snd_set_pitch( int snd_handle, int pitch ); -int snd_get_pitch( int snd_handle ); +// Valid values for pitch are > 0 +void snd_set_pitch( int snd_handle, float pitch ); +float snd_get_pitch( int snd_handle ); // Stops all sounds from playing, even looping ones. void snd_stop_all(); @@ -310,7 +309,7 @@ int snd_get_duration(int snd_id); // get a 3D vol and pan for a particular sound int snd_get_3d_vol_and_pan(game_snd *gs, vector *pos, float* vol, float *pan, float radius=0.0f); -int snd_init(int use_a3d, int use_eax); +int snd_init(int use_eax); void snd_close(); // Return 1 or 0 to show that sound system is inited ok @@ -321,6 +320,8 @@ uint sound_get_ds(); void snd_update_listener(vector *pos, vector *vel, matrix *orient); +void snd_update_source(int snd_handle, int min, int max, vector *pos, vector *vel); + void snd_use_lib(int lib_id); int snd_num_playing(); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba6f105..9b6d45d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -186,9 +186,11 @@ set(code_SOURCE ship/shipcontrails.cpp ship/shipfx.cpp ship/shiphit.cpp - sound/acm-unix.cpp - sound/audiostr-openal.cpp - sound/ds.cpp + sound/acm.cpp + sound/audiostr.cpp + sound/oal.cpp + sound/oal_capture.cpp + sound/oal_efx.cpp sound/rtvoice.cpp sound/sound.cpp starfield/nebula.cpp diff --git a/src/freespace2/freespace.cpp b/src/freespace2/freespace.cpp index 8e793c1..5f4dfaa 100644 --- a/src/freespace2/freespace.cpp +++ b/src/freespace2/freespace.cpp @@ -652,7 +652,6 @@ #include "sexp.h" #include "medals.h" #include "multiteamselect.h" -#include "ds3d.h" #include "shipfx.h" #include "readyroom.h" #include "mainhallmenu.h" @@ -2432,7 +2431,6 @@ void game_init() // SOUND INIT START ///////////////////////////// - int use_a3d = 0; int use_eax = 0; ptr = os_config_read_string(NULL, NOX("Soundcard"), NULL); @@ -2440,16 +2438,13 @@ void game_init() if (ptr) { if (!stricmp(ptr, NOX("no sound"))) { Cmdline_freespace_no_sound = 1; - - } else if (!stricmp(ptr, NOX("Aureal A3D"))) { - use_a3d = 1; - } else if (!stricmp(ptr, NOX("EAX"))) { + } else if ( !stricmp(ptr, NOX("EAX")) || !stricmp(ptr, NOX("Aureal A3D")) ) { use_eax = 1; } } if (!Is_standalone) { - snd_init(use_a3d, use_eax); + snd_init(use_eax); } ///////////////////////////// // SOUND INIT END @@ -3389,7 +3384,7 @@ void do_timing_test(float flFrametime) // start looping digital sounds for ( i = 0; i < NUM_MIXED_SOUNDS; i++ ) - snds[i] = snd_play_looping( &Snds[i], 0.0f, -1, -1); + snds[i] = snd_play_looping( &Snds[i], 0.0f); } diff --git a/src/gamesnd/gamesnd.cpp b/src/gamesnd/gamesnd.cpp index b30f054..e9147b1 100644 --- a/src/gamesnd/gamesnd.cpp +++ b/src/gamesnd/gamesnd.cpp @@ -318,7 +318,7 @@ void gamesnd_parse_line(game_snd *gs, const char *tag) stuff_float(&gs->default_volume); stuff_int(&is_3d); if ( is_3d ) { - gs->flags |= GAME_SND_USE_DS3D; + gs->flags |= GAME_SND_USE_3D; stuff_int(&gs->min); stuff_int(&gs->max); } diff --git a/src/hud/hud.cpp b/src/hud/hud.cpp index 3e9f060..8189c06 100644 --- a/src/hud/hud.cpp +++ b/src/hud/hud.cpp @@ -1693,7 +1693,7 @@ void update_throttle_sound() { // determine what engine sound to play float percent_throttle; -// int throttle_pitch; +// float throttle_pitch; // if we're a multiplayer observer, stop any engine sounds from playing and return if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){ @@ -1728,7 +1728,7 @@ void update_throttle_sound() } else { if ( Player_engine_snd_loop == -1 ){ - Player_engine_snd_loop = snd_play_looping( &Snds[SND_ENGINE], 0.0f , -1, -1, percent_throttle * ENGINE_MAX_VOL ); + Player_engine_snd_loop = snd_play_looping( &Snds[SND_ENGINE], 0.0f, percent_throttle * ENGINE_MAX_VOL ); } else { // The sound may have been trashed at the low-level if sound channel overflow. // TODO: implement system where certain sounds cannot be interrupted (priority?) @@ -1742,8 +1742,8 @@ void update_throttle_sound() } // throttle_pitch = snd_get_pitch(Player_engine_snd_loop); -// if ( percent_throttle > 0.5 ) { -// snd_set_pitch(Player_engine_snd_loop, fl2i(22050 + (percent_throttle-0.5f)*1000)); +// if ( percent_throttle > 0.5f ) { +// snd_set_pitch(Player_engine_snd_loop, 1.0f + (percent_throttle-0.5f)*1.0f)); // } } // end if (percent_throttle != last_percent_throttle) diff --git a/src/hud/hudlock.cpp b/src/hud/hudlock.cpp index 8ad5fdb..559e8d3 100644 --- a/src/hud/hudlock.cpp +++ b/src/hud/hudlock.cpp @@ -1017,7 +1017,7 @@ void hud_calculate_lock_position(float frametime) } if ( Missile_track_loop == -1 ) { - Missile_track_loop = snd_play_looping( &Snds[SND_MISSILE_TRACKING], 0.0f , -1, -1); + Missile_track_loop = snd_play_looping( &Snds[SND_MISSILE_TRACKING], 0.0f); } if (!Players[Player_num].lock_time_to_target) { diff --git a/src/menuui/optionsmenumulti.cpp b/src/menuui/optionsmenumulti.cpp index a97f8e0..c81653b 100644 --- a/src/menuui/optionsmenumulti.cpp +++ b/src/menuui/optionsmenumulti.cpp @@ -224,7 +224,7 @@ #include "bmpman.h" #include "cfile.h" #include "key.h" -#include "ds.h" +#include "oal.h" #include "font.h" #include "gamesnd.h" #include "freespace.h" @@ -2237,19 +2237,24 @@ void options_multi_vox_do() case OM_VOX_TEST_PLAYBACK: // if we were playing a sound back, but now the sound is done - if((Om_vox_playback_handle != -1) && (ds_get_play_position(ds_get_channel(Om_vox_playback_handle)) >= (DWORD)Om_vox_voice_comp_size)){ - // flush all playing sounds safely - rtvoice_stop_playback_all(); + if (Om_vox_playback_handle != -1) { + int channel = oal_get_channel(Om_vox_playback_handle); - // null the sound handle - Om_vox_playback_handle = -1; + // channel will be -1 if sound has already stopped playing + if ( (channel == -1) || (oal_get_play_position(channel) >= Om_vox_voice_comp_size) ) { + // flush all playing sounds safely + rtvoice_stop_playback_all(); + + // null the sound handle + Om_vox_playback_handle = -1; - // set this so we know not to display any more waveforms - Om_vox_voice_buffer_size = -1; - Om_vox_voice_comp_size = -1; + // set this so we know not to display any more waveforms + Om_vox_voice_buffer_size = -1; + Om_vox_voice_comp_size = -1; - // free the status up - Om_vox_test_status = OM_VOX_TEST_NONE; + // free the status up + Om_vox_test_status = OM_VOX_TEST_NONE; + } } break; } @@ -2402,7 +2407,7 @@ void options_multi_vox_process_waveform() case OM_VOX_TEST_PLAYBACK: // get the offset into the playing direct sound buffer - buf_offset = ds_get_play_position(ds_get_channel(Om_vox_playback_handle)); + buf_offset = oal_get_play_position(oal_get_channel(Om_vox_playback_handle)); // get the # of samples we'll average for one line avg_len = (int)((float)OM_VOX_RECORD_INT * ((1024.0f * 11.0f) / 1000.0f)) / c_width; diff --git a/src/movie/mveplayer.cpp b/src/movie/mveplayer.cpp index 6c47ce4..015c0a0 100644 --- a/src/movie/mveplayer.cpp +++ b/src/movie/mveplayer.cpp @@ -43,7 +43,7 @@ #include "sound.h" #include "bmpman.h" #include "osregistry.h" -#include "ds.h" +#include "oal.h" #include "gropengl.h" #include @@ -73,12 +73,12 @@ static int audiobuf_created; // struct for the audio stream information struct mve_audio_t { + sound_channel *chan; ALenum format; int sample_rate; int bytes_per_sec; int channels; int bitsize; - ALuint source_id; ALuint buffers[MVE_AUDIO_BUFFERS]; }; @@ -206,7 +206,7 @@ void mve_audio_createbuf(ubyte minor, ubyte *data) return; // if game sound disabled don't try and play movie audio - if (!Sound_enabled) { + if ( !Sound_enabled ) { mve_audio_canplay = 0; audiobuf_created = 1; return; @@ -279,20 +279,20 @@ void mve_audio_createbuf(ubyte minor, ubyte *data) return; } - alGenSources(1, &mas->source_id); + mas->chan = oal_get_free_channel(1.0f, -1, SND_PRIORITY_MUST_PLAY); - if (mas->source_id == 0) { + if (mas->chan == NULL) { mve_audio_canplay = 0; audiobuf_created = 1; return; } - alSourcef(mas->source_id, AL_GAIN, 1.0f); - alSource3f(mas->source_id, AL_POSITION, 0.0f, 0.0f, 0.0f); - alSource3f(mas->source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f); - alSource3f(mas->source_id, AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSourcef(mas->source_id, AL_ROLLOFF_FACTOR, 0.0f); - alSourcei(mas->source_id, AL_SOURCE_RELATIVE, AL_TRUE); + alSourcef(mas->chan->source_id, AL_GAIN, 1.0f); + alSource3f(mas->chan->source_id, AL_POSITION, 0.0f, 0.0f, 0.0f); + alSource3f(mas->chan->source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + alSource3f(mas->chan->source_id, AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSourcef(mas->chan->source_id, AL_ROLLOFF_FACTOR, 0.0f); + alSourcei(mas->chan->source_id, AL_SOURCE_RELATIVE, AL_TRUE); for (int i = 0; i < MVE_AUDIO_BUFFERS; i++) { alGenBuffers(1, &mas->buffers[i]); @@ -311,11 +311,11 @@ void mve_audio_play() ALint queued = 0; ALint status = AL_INVALID; - alGetSourcei(mas->source_id, AL_BUFFERS_QUEUED, &queued); - alGetSourcei(mas->source_id, AL_SOURCE_STATE, &status); + alGetSourcei(mas->chan->source_id, AL_BUFFERS_QUEUED, &queued); + alGetSourcei(mas->chan->source_id, AL_SOURCE_STATE, &status); if ( (status != AL_PLAYING) && (queued > 0) ) { - alSourcePlay(mas->source_id); + alSourcePlay(mas->chan->source_id); mve_audio_playing = 1; } } @@ -335,18 +335,17 @@ static void mve_audio_stop() mve_audio_bufl_free.clear(); - if (mas && mas->source_id) { - alSourceStop(mas->source_id); + if (mas && mas->chan->source_id) { + alSourceStop(mas->chan->source_id); - alGetSourcei(mas->source_id, AL_BUFFERS_PROCESSED, &processed); + alGetSourcei(mas->chan->source_id, AL_BUFFERS_PROCESSED, &processed); while (processed > 0) { - alSourceUnqueueBuffers(mas->source_id, 1, &bid); + alSourceUnqueueBuffers(mas->chan->source_id, 1, &bid); --processed; } alDeleteBuffers(MVE_AUDIO_BUFFERS, mas->buffers); - alDeleteSources(1, &mas->source_id); } if (mas != NULL) { @@ -399,10 +398,10 @@ int mve_audio_data(ubyte major, ubyte *data) mprintf(("MVE audio_buf overrun!!\n")); } - alGetSourcei(mas->source_id, AL_BUFFERS_PROCESSED, &processed); + alGetSourcei(mas->chan->source_id, AL_BUFFERS_PROCESSED, &processed); while (processed) { - alSourceUnqueueBuffers(mas->source_id, 1, &bid); + alSourceUnqueueBuffers(mas->chan->source_id, 1, &bid); mve_audio_bufl_free.push_back(bid); --processed; } @@ -411,7 +410,7 @@ int mve_audio_data(ubyte major, ubyte *data) bid = mve_audio_bufl_free.back(); alBufferData(bid, mas->format, mve_audio_buf, mve_audio_buf_offset, mas->sample_rate); - alSourceQueueBuffers(mas->source_id, 1, &bid); + alSourceQueueBuffers(mas->chan->source_id, 1, &bid); mve_audio_buf_offset = 0; mve_audio_bufl_free.pop_back(); diff --git a/src/network/multi_voice.cpp b/src/network/multi_voice.cpp index 7e2a502..0e341e7 100644 --- a/src/network/multi_voice.cpp +++ b/src/network/multi_voice.cpp @@ -532,16 +532,14 @@ void multi_voice_init() // attempt to copy in the "pre" voice sound pre_sound = snd_load(&Snds[MULTI_VOICE_PRE_SOUND]); + Multi_voice_pre_sound_size = 0; if(pre_sound != -1){ // get the pre-sound size if((snd_size(pre_sound,&pre_size) != -1) && (pre_size < MULTI_VOICE_MAX_BUFFER_SIZE)){ - snd_get_data(pre_sound,Multi_voice_playback_buffer); - Multi_voice_pre_sound_size = pre_size; - } else { - Multi_voice_pre_sound_size = 0; + if ( !snd_get_data(pre_sound,Multi_voice_playback_buffer) ) { + Multi_voice_pre_sound_size = pre_size; + } } - } else { - Multi_voice_pre_sound_size = 0; } } @@ -1641,10 +1639,10 @@ int multi_voice_mix(int post_sound,char *data,int cur_size,int max_size) if(post_size > 0){ if((max_size - cur_size) > post_size){ // copy in the sound - snd_get_data(post_sound,data + cur_size); - - // increment the cur_size - cur_size += post_size; + if ( !snd_get_data(post_sound,data + cur_size) ) { + // increment the cur_size + cur_size += post_size; + } } } diff --git a/src/object/objectsnd.cpp b/src/object/objectsnd.cpp index 9a2e2ec..3854059 100644 --- a/src/object/objectsnd.cpp +++ b/src/object/objectsnd.cpp @@ -258,8 +258,7 @@ #include "linklist.h" #include "ship.h" #include "gamesnd.h" -#include "ds.h" -#include "ds3d.h" +#include "oal.h" #include "timer.h" #include "3d.h" #include "joy_ff.h" @@ -689,7 +688,7 @@ void obj_snd_do_frame() object *objp, *closest_objp; game_snd *gs; ship *sp; - int channel, go_ahead_flag; + int go_ahead_flag; vector source_pos; float add_distance; @@ -787,19 +786,9 @@ void obj_snd_do_frame() } // end switch if ( go_ahead_flag ) { - if ( ds_using_ds3d() ) { - osp->instance = snd_play_3d(gs, &source_pos, &View_position, add_distance, &objp->phys_info.vel, 1, 1.0f, SND_PRIORITY_TRIPLE_INSTANCE); - if ( osp->instance != -1 ) { - Num_obj_sounds_playing++; - } - } - else { - snd_get_3d_vol_and_pan(gs, &source_pos, &osp->vol, &osp->pan, add_distance); - osp->instance = snd_play_looping( gs, osp->pan, 0, 0, (osp->vol*speed_vol_multiplier)/gs->default_volume, SND_PRIORITY_TRIPLE_INSTANCE ); - if ( osp->instance != -1 ) { - osp->freq = snd_get_pitch(osp->instance); - Num_obj_sounds_playing++; - } + osp->instance = snd_play_3d(gs, &source_pos, &View_position, add_distance, &objp->phys_info.vel, 1, 1.0f, SND_PRIORITY_TRIPLE_INSTANCE); + if ( osp->instance != -1 ) { + Num_obj_sounds_playing++; } } Assert(Num_obj_sounds_playing <= MAX_OBJ_SOUNDS_PLAYING); @@ -831,51 +820,28 @@ void obj_snd_do_frame() if ( objp->type == OBJ_SHIP ) sp = &Ships[objp->instance]; - if (ds_using_ds3d()) { - channel = ds_get_channel(osp->instance); - // for DirectSound3D sounds, re-establish the maximum speed based on the - // speed_vol_multiplier - if ( sp == NULL || ( (sp != NULL) && (sp->flags & SF_ENGINES_ON) ) ) { - snd_set_volume( osp->instance, gs->default_volume*speed_vol_multiplier ); - } - else { - // engine sound is disabled - snd_set_volume( osp->instance, 0.0f ); - } - - vector *vel=NULL; - vel = &objp->phys_info.vel; - - // Don't play doppler effect for cruisers or captials - if ( sp ) { - if ( ship_get_SIF(sp) & (SIF_BIG_SHIP | SIF_HUGE_SHIP) ) { - vel=NULL; - } - } - - ds3d_update_buffer(channel, i2fl(gs->min), i2fl(gs->max), &source_pos, vel); - snd_get_3d_vol_and_pan(gs, &source_pos, &osp->vol, &osp->pan, add_distance); + // for 3D sounds, re-establish the maximum speed based on the + // speed_vol_multiplier + if ( sp == NULL || ( (sp != NULL) && (sp->flags & SF_ENGINES_ON) ) ) { + snd_set_volume( osp->instance, gs->default_volume*speed_vol_multiplier ); } else { - if ( sp == NULL || (sp != NULL && (sp->flags & SF_ENGINES_ON) ) ) { - snd_get_3d_vol_and_pan(gs, &source_pos, &osp->vol, &osp->pan, add_distance); - snd_set_volume( osp->instance, osp->vol*speed_vol_multiplier ); - snd_set_pan( osp->instance, osp->pan ); - // Don't play doppler effect for cruisers or captials - if ( objp->type == OBJ_SHIP && Doppler_enabled == TRUE ) { - if ( !(ship_get_SIF(sp) & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) ) { - int new_freq; - // calc doppler effect - new_freq = obj_snd_get_freq(osp->freq, objp, Player_obj, &source_pos); - if ( abs(new_freq - osp->freq) > OBJSND_CHANGE_FREQUENCY_THRESHOLD ) { - snd_set_pitch( osp->instance, new_freq); - } - } - } + // engine sound is disabled + snd_set_volume( osp->instance, 0.0f ); + } + + vector *vel=NULL; + vel = &objp->phys_info.vel; + + // Don't play doppler effect for cruisers or captials + if ( sp ) { + if ( ship_get_SIF(sp) & (SIF_BIG_SHIP | SIF_HUGE_SHIP) ) { + vel=NULL; } - else - snd_set_volume( osp->instance, 0.0f ); } + + snd_update_source(osp->instance, gs->min, gs->max, &source_pos, vel); + snd_get_3d_vol_and_pan(gs, &source_pos, &osp->vol, &osp->pan, add_distance); } // end for // see if we want to play a flyby sound diff --git a/src/ship/afterburner.cpp b/src/ship/afterburner.cpp index be81b07..a2a71df 100644 --- a/src/ship/afterburner.cpp +++ b/src/ship/afterburner.cpp @@ -371,7 +371,7 @@ void afterburners_update(object *objp, float fl_frametime) Player_afterburner_vol = AFTERBURNER_DEFAULT_VOL; Player_afterburner_loop_delay = 0; if ( Player_afterburner_loop_id == -1 ) { - Player_afterburner_loop_id = snd_play_looping( &Snds[SND_ABURN_LOOP], 0.0f , -1, -1); + Player_afterburner_loop_id = snd_play_looping(&Snds[SND_ABURN_LOOP], 0.0f); snd_set_volume(Player_afterburner_loop_id, Player_afterburner_vol); // nprintf(("Alan","PLAY LOOPING SOUND\n")); } diff --git a/src/ship/shipfx.cpp b/src/ship/shipfx.cpp index 713621d..2aa0446 100644 --- a/src/ship/shipfx.cpp +++ b/src/ship/shipfx.cpp @@ -2963,7 +2963,7 @@ void engine_wash_ship_process(ship *shipp) if(shipp != Player_ship){ obj_snd_assign(shipp->objnum, SND_ENGINE_WASH, &vmd_zero_vector, 1); } else { - Player_engine_wash_loop = snd_play_looping( &Snds[SND_ENGINE_WASH], 0.0f , -1, -1, 1.0f); + Player_engine_wash_loop = snd_play_looping( &Snds[SND_ENGINE_WASH], 0.0f, 1.0f); } } } diff --git a/src/sound/acm.cpp b/src/sound/acm.cpp index dfa59c8..2bbaced 100644 --- a/src/sound/acm.cpp +++ b/src/sound/acm.cpp @@ -25,6 +25,7 @@ #include "pstypes.h" #include "acm.h" +#include "oal.h" typedef struct adpcmcoef_tag{ @@ -40,9 +41,9 @@ typedef struct adpcmblockheader_tag { } ADPCMBLOCKHEADER; typedef struct adpcmwaveformat_tag { - WAVEFORMATEX wav; - WORD wSamplesPerBlock; - WORD wNumCoef; + WAVE_chunk wav; + ushort wSamplesPerBlock; + ushort wNumCoef; ADPCMCOEFSET *aCoef; } ADPCMWAVEFORMAT; @@ -91,22 +92,6 @@ static int read_ushort(SDL_RWops *rw, ushort *i) return 1; } -static int read_word(SDL_RWops *rw, WORD *i) -{ - int rc = SDL_RWread(rw, i, sizeof(WORD), 1); - IF_ERR(rc != 1, 0); - return 1; -} - -// same as read_word() but swapped -static int read_word_s(SDL_RWops *rw, WORD *i) -{ - int rc = SDL_RWread(rw, i, sizeof(WORD), 1); - IF_ERR(rc != 1, 0); - *i = INTEL_SHORT(*i); - return 1; -} - static int read_short(SDL_RWops *rw, short *i) { int rc = SDL_RWread(rw, i, sizeof(short), 1); @@ -115,13 +100,6 @@ static int read_short(SDL_RWops *rw, short *i) return 1; } -static int read_dword(SDL_RWops *rw, DWORD *i) -{ - int rc = SDL_RWread(rw, i, sizeof(DWORD), 1); - IF_ERR(rc != 1, 0); - return 1; -} - static int read_ubyte(SDL_RWops *rw, ubyte *i) { int rc = SDL_RWread(rw, i, sizeof(ubyte), 1); @@ -133,14 +111,14 @@ static int read_ubyte(SDL_RWops *rw, ubyte *i) static int read_adpcm_block_headers(SDL_RWops *rw, adpcm_fmt_t *fmt) { int i; - int max = fmt->adpcm.wav.nChannels; + int max = fmt->adpcm.wav.num_channels; - if (fmt->bytes_remaining < fmt->adpcm.wav.nBlockAlign) { + if (fmt->bytes_remaining < fmt->adpcm.wav.block_align) { return 0; } - fmt->bytes_remaining -= fmt->adpcm.wav.nBlockAlign; - fmt->bytes_processed += fmt->adpcm.wav.nBlockAlign; + fmt->bytes_remaining -= fmt->adpcm.wav.block_align; + fmt->bytes_processed += fmt->adpcm.wav.block_align; for (i = 0; i < max; i++) IF_ERR(!read_ubyte(rw, &fmt->header[i].bPredictor), 0); @@ -198,7 +176,7 @@ static void do_adpcm_nibble(ubyte nib, ADPCMBLOCKHEADER *header, int lPredSamp) static int decode_adpcm_sample_frame(SDL_RWops *rw, adpcm_fmt_t *fmt) { int i; - int max = fmt->adpcm.wav.nChannels; + int max = fmt->adpcm.wav.num_channels; ubyte nib = fmt->nibble; short iCoef1, iCoef2; int lPredSamp; @@ -228,7 +206,7 @@ static void put_adpcm_sample_frame1(ubyte *_buf, adpcm_fmt_t *fmt) short *buf = (short *)_buf; int i; - for (i = 0; i < fmt->adpcm.wav.nChannels; i++) + for (i = 0; i < fmt->adpcm.wav.num_channels; i++) *buf++ = fmt->header[i].iSamp1; } @@ -237,7 +215,7 @@ static void put_adpcm_sample_frame2(ubyte *_buf, adpcm_fmt_t *fmt) short *buf = (short *)_buf; int i; - for (i = 0; i < fmt->adpcm.wav.nChannels; i++) + for (i = 0; i < fmt->adpcm.wav.num_channels; i++) *buf++ = fmt->header[i].iSamp2; } @@ -282,6 +260,8 @@ static uint read_sample_fmt_adpcm(ubyte *data, SDL_RWops *rw, adpcm_fmt_t *fmt) static void adpcm_memory_free(adpcm_fmt_t *fmt) { + SDL_assert( fmt != NULL ); + if (fmt->adpcm.aCoef != NULL) { free(fmt->adpcm.aCoef); fmt->adpcm.aCoef = NULL; @@ -291,11 +271,8 @@ static void adpcm_memory_free(adpcm_fmt_t *fmt) free(fmt->header); fmt->header = NULL; } - - if (fmt != NULL) { - free(fmt); - fmt = NULL; - } + + free(fmt); } // ============================================================================= @@ -303,7 +280,7 @@ static void adpcm_memory_free(adpcm_fmt_t *fmt) // // Convert an ADPCM wave file to a PCM wave file using the Audio Compression Manager // -// parameters: *pwfxSrc => address of WAVEFORMATEX structure describing the source wave +// parameters: *pwfxSrc => address of WAVE_chunk structure describing the source wave // *src => pointer to raw source wave data // src_len => num bytes of source wave data // **dest => pointer to pointer to dest buffer for wave data @@ -321,78 +298,101 @@ static void adpcm_memory_free(adpcm_fmt_t *fmt) // 1. Storage for the decompressed audio will be allocated in this function if *dest in NULL. // The caller is responsible for freeing this memory later. // -int ACM_convert_ADPCM_to_PCM(WAVEFORMATEX *pwfxSrc, ubyte *src, int src_len, ubyte **dest, int max_dest_bytes, int *dest_len, unsigned int *src_bytes_used, unsigned short dest_bps) +int ACM_convert_ADPCM_to_PCM(WAVE_chunk *pwfxSrc, ubyte *src, int src_len, ubyte **dest, int max_dest_bytes, int *dest_len, unsigned int *src_bytes_used, unsigned short dest_bps) { - Assert( pwfxSrc != NULL ); - Assert( pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM ); - Assert( src != NULL ); - Assert( src_len > 0 ); - Assert( dest_len != NULL ); + SDL_assert( pwfxSrc != NULL ); + SDL_assert( pwfxSrc->code == WAVE_FORMAT_ADPCM ); + SDL_assert( pwfxSrc->extra_data != NULL ); + SDL_assert( src != NULL ); + SDL_assert( src_len > 0 ); + SDL_assert( dest_len != NULL ); - SDL_RWops *hdr = SDL_RWFromMem(pwfxSrc, sizeof(WAVEFORMATEX) + pwfxSrc->cbSize); - SDL_RWops *rw = SDL_RWFromMem(src, src_len); uint rc; uint new_size = 0; + SDL_RWops *hdr = SDL_RWFromMem(pwfxSrc->extra_data, pwfxSrc->extra_size); + SDL_RWops *rw = SDL_RWFromMem(src, src_len); + + adpcm_fmt_t *fmt = NULL; + // estimate size of uncompressed data // uncompressed data has: channels=pfwxScr->nChannels, bitPerSample=destbits // compressed data has: channels=pfwxScr->nChannels, bitPerSample=pwfxSrc->wBitsPerSample - new_size = ( src_len * dest_bps ) / pwfxSrc->wBitsPerSample; + new_size = ( src_len * dest_bps ) / pwfxSrc->bits_per_sample; new_size *= 2;//buffer must be large enough for all data // DO NOT free() here, *estimated size* if ( *dest == NULL ) { *dest = (ubyte *)malloc(new_size); - - IF_ERR(*dest == NULL, -1); - + + if ( (*dest == NULL) ) { + goto Fail; + } + // memset(*dest, 0x80, new_size); // silence (for 8 bits/sample) memset(*dest, 0x00, new_size); // silence (for 16 bits/sample) } - adpcm_fmt_t *fmt = (adpcm_fmt_t *)malloc(sizeof(adpcm_fmt_t)); - IF_ERR(fmt == NULL, -1); + fmt = (adpcm_fmt_t *)malloc(sizeof(adpcm_fmt_t)); + + if (fmt == NULL) { + goto Fail; + } + memset(fmt, '\0', sizeof(adpcm_fmt_t)); - // wav header info (WAVEFORMATEX) - IF_ERR(!read_word(hdr, &fmt->adpcm.wav.wFormatTag), -1); - IF_ERR(!read_word(hdr, &fmt->adpcm.wav.nChannels), -1); - IF_ERR(!read_dword(hdr, &fmt->adpcm.wav.nSamplesPerSec), -1); - IF_ERR(!read_dword(hdr, &fmt->adpcm.wav.nAvgBytesPerSec), -1); - IF_ERR(!read_word(hdr, &fmt->adpcm.wav.nBlockAlign), -1); - IF_ERR(!read_word(hdr, &fmt->adpcm.wav.wBitsPerSample), -1); - IF_ERR(!read_word(hdr, &fmt->adpcm.wav.cbSize), -1); + // wav header info (WAVE_chunk) + fmt->adpcm.wav.code = pwfxSrc->code; + fmt->adpcm.wav.num_channels = pwfxSrc->num_channels; + fmt->adpcm.wav.sample_rate = pwfxSrc->sample_rate; + fmt->adpcm.wav.bytes_per_second = pwfxSrc->bytes_per_second; + fmt->adpcm.wav.block_align = pwfxSrc->block_align; + fmt->adpcm.wav.bits_per_sample = pwfxSrc->bits_per_sample; + + // sanity check, should always be 4 + if (fmt->adpcm.wav.bits_per_sample != 4) { + goto Fail; + } + // adpcm specific header info - IF_ERR(!read_word_s(hdr, &fmt->adpcm.wSamplesPerBlock), -1); - IF_ERR(!read_word_s(hdr, &fmt->adpcm.wNumCoef), -1); + if ( !read_ushort(hdr, &fmt->adpcm.wSamplesPerBlock) ) { + goto Fail; + } + + if ( !read_ushort(hdr, &fmt->adpcm.wNumCoef) ) { + goto Fail; + } // allocate memory for COEF struct and fill it fmt->adpcm.aCoef = (ADPCMCOEFSET *)malloc(sizeof(ADPCMCOEFSET) * fmt->adpcm.wNumCoef); - IF_ERR(fmt->adpcm.aCoef == NULL, -1); + + if (fmt->adpcm.aCoef == NULL) { + goto Fail; + } for (int i=0; iadpcm.wNumCoef; i++) { - IF_ERR(!read_short(hdr, &fmt->adpcm.aCoef[i].iCoef1), -1); - IF_ERR(!read_short(hdr, &fmt->adpcm.aCoef[i].iCoef2), -1); + if ( !read_short(hdr, &fmt->adpcm.aCoef[i].iCoef1) ) { + goto Fail; + } + + if ( !read_short(hdr, &fmt->adpcm.aCoef[i].iCoef2) ) { + goto Fail; + } } // allocate memory for the ADPCM block header that's to be filled later - fmt->header = (ADPCMBLOCKHEADER *)malloc(sizeof(ADPCMBLOCKHEADER) * fmt->adpcm.wav.nChannels); - IF_ERR(fmt->header == NULL, -1); + fmt->header = (ADPCMBLOCKHEADER *)malloc(sizeof(ADPCMBLOCKHEADER) * fmt->adpcm.wav.num_channels); + + if (fmt->header == NULL) { + goto Fail; + } // buffer to estimated size since we have to process the whole thing at once fmt->buffer_size = new_size; fmt->bytes_remaining = src_len; fmt->bytes_processed = 0; - // sanity check, should always be 4 - if (fmt->adpcm.wav.wBitsPerSample != 4) { - adpcm_memory_free(fmt); - SDL_RWclose(hdr); - SDL_RWclose(rw); - return -1; - } - - fmt->sample_frame_size = dest_bps/8*pwfxSrc->nChannels; + fmt->sample_frame_size = dest_bps/8*pwfxSrc->num_channels; if ( !max_dest_bytes ) { max_dest_bytes = new_size; @@ -401,6 +401,10 @@ int ACM_convert_ADPCM_to_PCM(WAVEFORMATEX *pwfxSrc, ubyte *src, int src_len, uby // convert to PCM rc = read_sample_fmt_adpcm(*dest, rw, fmt); + if (rc == 0) { + goto Fail; + } + // send back actual sizes *dest_len = rc; *src_bytes_used = fmt->bytes_processed; @@ -411,73 +415,118 @@ int ACM_convert_ADPCM_to_PCM(WAVEFORMATEX *pwfxSrc, ubyte *src, int src_len, uby SDL_RWclose(rw); return 0; + +Fail: + if (fmt) { + adpcm_memory_free(fmt); + } + + SDL_RWclose(hdr); + SDL_RWclose(rw); + + return -1; } -int ACM_stream_open(WAVEFORMATEX *pwfxSrc, WAVEFORMATEX *pwfxDest, void **stream, int dest_bps) +int ACM_stream_open(WAVE_chunk *pwfxSrc, WAVE_chunk *pwfxDest, void **stream, int dest_bps) { - Assert( pwfxSrc != NULL ); - Assert( pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM ); - Assert( stream != NULL ); + SDL_assert( pwfxSrc != NULL ); + SDL_assert( pwfxSrc->code == WAVE_FORMAT_ADPCM ); + SDL_assert( pwfxSrc->extra_data != NULL ); + SDL_assert( stream != NULL ); - SDL_RWops *hdr = SDL_RWFromMem(pwfxSrc, sizeof(WAVEFORMATEX) + pwfxSrc->cbSize); - uint rc; + SDL_RWops *hdr = SDL_RWFromMem(pwfxSrc->extra_data, pwfxSrc->extra_size); + acm_stream_t *str = NULL; adpcm_fmt_t *fmt = (adpcm_fmt_t *)malloc(sizeof(adpcm_fmt_t)); - IF_ERR(fmt == NULL, -1); + + if (fmt == NULL) { + goto Fail; + } + memset(fmt, '\0', sizeof(adpcm_fmt_t)); - // wav header info (WAVEFORMATEX) - IF_ERR(!read_word(hdr, &fmt->adpcm.wav.wFormatTag), -1); - IF_ERR(!read_word(hdr, &fmt->adpcm.wav.nChannels), -1); - IF_ERR(!read_dword(hdr, &fmt->adpcm.wav.nSamplesPerSec), -1); - IF_ERR(!read_dword(hdr, &fmt->adpcm.wav.nAvgBytesPerSec), -1); - IF_ERR(!read_word(hdr, &fmt->adpcm.wav.nBlockAlign), -1); - IF_ERR(!read_word(hdr, &fmt->adpcm.wav.wBitsPerSample), -1); - IF_ERR(!read_word(hdr, &fmt->adpcm.wav.cbSize), -1); + // wav header info (WAVE_chunk) + fmt->adpcm.wav.code = pwfxSrc->code; + fmt->adpcm.wav.num_channels = pwfxSrc->num_channels; + fmt->adpcm.wav.sample_rate = pwfxSrc->sample_rate; + fmt->adpcm.wav.bytes_per_second = pwfxSrc->bytes_per_second; + fmt->adpcm.wav.block_align = pwfxSrc->block_align; + fmt->adpcm.wav.bits_per_sample = pwfxSrc->bits_per_sample; + + // sanity check, should always be 4 + if (fmt->adpcm.wav.bits_per_sample != 4) { + goto Fail; + } + // adpcm specific header info - IF_ERR(!read_word_s(hdr, &fmt->adpcm.wSamplesPerBlock), -1); - IF_ERR(!read_word_s(hdr, &fmt->adpcm.wNumCoef), -1); + if ( !read_ushort(hdr, &fmt->adpcm.wSamplesPerBlock) ) { + goto Fail; + } + + if ( !read_ushort(hdr, &fmt->adpcm.wNumCoef) ) { + goto Fail; + } // allocate memory for COEF struct and fill it fmt->adpcm.aCoef = (ADPCMCOEFSET *)malloc(sizeof(ADPCMCOEFSET) * fmt->adpcm.wNumCoef); - IF_ERR(fmt->adpcm.aCoef == NULL, -1); + + if (fmt->adpcm.aCoef == NULL) { + goto Fail; + } for (int i=0; iadpcm.wNumCoef; i++) { - IF_ERR(!read_short(hdr, &fmt->adpcm.aCoef[i].iCoef1), -1); - IF_ERR(!read_short(hdr, &fmt->adpcm.aCoef[i].iCoef2), -1); + if ( !read_short(hdr, &fmt->adpcm.aCoef[i].iCoef1) ) { + goto Fail; + } + + if ( !read_short(hdr, &fmt->adpcm.aCoef[i].iCoef2) ) { + goto Fail; + } } // allocate memory for the ADPCM block header that's to be filled later - fmt->header = (ADPCMBLOCKHEADER *)malloc(sizeof(ADPCMBLOCKHEADER) * fmt->adpcm.wav.nChannels); - IF_ERR(fmt->header == NULL, -1); + fmt->header = (ADPCMBLOCKHEADER *)malloc(sizeof(ADPCMBLOCKHEADER) * fmt->adpcm.wav.num_channels); - // sanity check, should always be 4 - if (fmt->adpcm.wav.wBitsPerSample != 4) { - adpcm_memory_free(fmt); - SDL_RWclose(hdr); - return -1; + if (fmt->header == NULL) { + goto Fail; } - fmt->sample_frame_size = dest_bps/8*pwfxSrc->nChannels; + fmt->sample_frame_size = dest_bps/8*pwfxSrc->num_channels; - acm_stream_t *str = (acm_stream_t *)malloc(sizeof(acm_stream_t)); - IF_ERR(str == NULL, -1); + str = (acm_stream_t *)malloc(sizeof(acm_stream_t)); + + if (str == NULL) { + goto Fail; + } + str->fmt = fmt; str->dest_bps = dest_bps; - str->src_bps = pwfxSrc->wBitsPerSample; + str->src_bps = pwfxSrc->bits_per_sample; *stream = str; SDL_RWclose(hdr); return 0; + +Fail: + if (fmt) { + adpcm_memory_free(fmt); + } + + SDL_RWclose(hdr); + + return -1; } int ACM_stream_close(void *stream) { - Assert(stream != NULL); + SDL_assert(stream != NULL); + acm_stream_t *str = (acm_stream_t *)stream; + adpcm_memory_free(str->fmt); free(str); + return 0; } @@ -486,8 +535,10 @@ int ACM_stream_close(void *stream) */ int ACM_query_source_size(void *stream, int dest_len) { - Assert(stream != NULL); + SDL_assert(stream != NULL); + acm_stream_t *str = (acm_stream_t *)stream; + // estimate size of compressed data // uncompressed data has: channels=pfwxScr->nChannels, bitPerSample=destbits // compressed data has: channels=pfwxScr->nChannels, bitPerSample=pwfxSrc->wBitsPerSample @@ -499,8 +550,10 @@ int ACM_query_source_size(void *stream, int dest_len) */ int ACM_query_dest_size(void *stream, int src_len) { - Assert(stream != NULL); + SDL_assert(stream != NULL); + acm_stream_t *str = (acm_stream_t *)stream; + // estimate size of uncompressed data // uncompressed data has: channels=pfwxScr->nChannels, bitPerSample=destbits // compressed data has: channels=pfwxScr->nChannels, bitPerSample=pwfxSrc->wBitsPerSample @@ -512,10 +565,11 @@ int ACM_query_dest_size(void *stream, int src_len) */ int ACM_convert(void *stream, ubyte *src, int src_len, ubyte *dest, int max_dest_bytes, unsigned int *dest_len, unsigned int *src_bytes_used) { - Assert(stream != NULL); - Assert( src != NULL ); - Assert( src_len > 0 ); - Assert( dest_len != NULL ); + SDL_assert(stream != NULL); + SDL_assert( src != NULL ); + SDL_assert( src_len > 0 ); + SDL_assert( dest_len != NULL ); + acm_stream_t *str = (acm_stream_t *)stream; uint rc; diff --git a/src/sound/audiostr.cpp b/src/sound/audiostr.cpp index 04f66d3..75691ca 100644 --- a/src/sound/audiostr.cpp +++ b/src/sound/audiostr.cpp @@ -77,11 +77,12 @@ * $NoKeywords: $ */ -#ifdef PLAT_UNIX // to end of file... + +#include #include "pstypes.h" #include "audiostr.h" -#include "ds.h" +#include "oal.h" #include "acm.h" #include "cfile.h" #include "sound.h" @@ -90,91 +91,80 @@ #define MAX_STREAM_BUFFERS 4 -// status -#define ASF_FREE 0 -#define ASF_USED 1 - -#define MAX_AUDIO_STREAMS 30 - // Constants -#ifndef SUCCESS -#define SUCCESS TRUE // Error returns for all member functions -#define FAILURE FALSE -#endif // SUCCESS - #define BIGBUF_SIZE 180000 // This can be reduced to 88200 once we don't use any stereo //#define BIGBUF_SIZE 88300 // This can be reduced to 88200 once we don't use any stereo -ubyte *Wavedata_load_buffer = NULL; // buffer used for cueing audiostreams -ubyte *Wavedata_service_buffer = NULL; // buffer used for servicing audiostreams +static ubyte *Wavedata_load_buffer = NULL; // buffer used for cueing audiostreams +static ubyte *Wavedata_service_buffer = NULL; // buffer used for servicing audiostreams CRITICAL_SECTION Global_service_lock; -typedef BOOL (*TIMERCALLBACK)(ptr_u); +typedef bool (*TIMERCALLBACK)(ptr_u); #define COMPRESSED_BUFFER_SIZE 88300 -ubyte *Compressed_buffer = NULL; // Used to load in compressed data during a cueing interval -ubyte *Compressed_service_buffer = NULL; // Used to read in compressed data during a service interval +static ubyte *Compressed_buffer = NULL; // Used to load in compressed data during a cueing interval +static ubyte *Compressed_service_buffer = NULL; // Used to read in compressed data during a service interval #define AS_HIGHEST_MAX 999999999 // max uncompressed filesize supported is 999 meg -int Audiostream_inited = 0; +static int Audiostream_inited = 0; -static int audiostr_read_word(SDL_RWops *rw, WORD *i) +class Timer { - int rc = SDL_RWread( rw, i, 1, sizeof(WORD) ); +public: + void constructor(); + void destructor(); - if (rc != sizeof(WORD)) - return 0; + bool Create(uint nPeriod, ptr_u dwUser, TIMERCALLBACK pfnCallback); - *i = INTEL_SHORT(*i); +protected: + static Uint32 TimeProc(Uint32 interval, void *dwUser); - return 1; -} + TIMERCALLBACK m_pfnCallback; + ptr_u m_dwUser; + uint m_nPeriod; + SDL_TimerID m_nIDTimer; +}; -static int audiostr_read_dword(SDL_RWops *rw, DWORD *i) +class WaveFile { - int rc = SDL_RWread( rw, i, 1, sizeof(DWORD) ); +public: + void Init(); + void Close(); + bool Open(const char *pszFilename); + bool Cue(); + int Read(ubyte *pbDest, uint cbSize, int service = 1); + ubyte GetSilenceData(); + + uint GetNumBytesRemaining() + { + return (m_nDataSize - m_nBytesPlayed); + } - if (rc != sizeof(DWORD)) - return 0; + uint GetUncompressedAvgDataRate() + { + return m_nUncompressedAvgDataRate; + } - *i = INTEL_INT(*i); + uint GetDataSize() + { + return m_nDataSize; + } - return 1; -} + uint GetNumBytesPlayed() + { + return m_nBytesPlayed; + } -class Timer -{ -public: - void constructor(void); - void destructor(void); - BOOL Create (UINT nPeriod, UINT nRes, DWORD dwUser, TIMERCALLBACK pfnCallback); -protected: - static Uint32 CALLBACK TimeProc(Uint32 interval, void *dwUser); - TIMERCALLBACK m_pfnCallback; - DWORD m_dwUser; - UINT m_nPeriod; - UINT m_nRes; - SDL_TimerID m_nIDTimer; -}; + ALenum GetOALFormat() + { + return m_oal_format; + } -class WaveFile -{ -public: - void Init(void); - void Close(void); - BOOL Open (const char *pszFilename); - BOOL Cue (void); - int Read (ubyte *pbDest, uint cbSize, int service=1); - uint GetNumBytesRemaining (void) { return (m_nDataSize - m_nBytesPlayed); } - uint GetUncompressedAvgDataRate (void) { return (m_nUncompressedAvgDataRate); } - uint GetDataSize (void) { return (m_nDataSize); } - uint GetNumBytesPlayed (void) { return (m_nBytesPlayed); } - ubyte GetSilenceData (void); - WAVEFORMATEX m_wfmt; // format of wave file used by Direct Sound - WAVEFORMATEX *m_pwfmt_original; // foramt of wave file from actual wave source + WAVE_chunk m_wfmt; // format of wave file + WAVE_chunk *m_pwfmt_original; // foramt of wave file from actual wave source uint m_total_uncompressed_bytes_read; uint m_max_uncompressed_bytes_to_read; uint m_bits_per_sample_uncompressed; @@ -182,63 +172,87 @@ public: protected: uint m_data_offset; // number of bytes to actual wave data int m_data_bytes_left; - SDL_RWops *cfp; + CFILE *cfp; + ALenum m_oal_format; uint m_wave_format; // format of wave source (ie WAVE_FORMAT_PCM, WAVE_FORMAT_ADPCM) uint m_nBlockAlign; // wave data block alignment spec uint m_nUncompressedAvgDataRate; // average wave data rate uint m_nDataSize; // size of data chunk uint m_nBytesPlayed; // offset into data chunk - BOOL m_abort_next_read; + bool m_abort_next_read; - void *m_hStream; - int m_hStream_open; - WAVEFORMATEX m_wfxDest; + void *m_hStream; + int m_hStream_open; + WAVE_chunk m_wfxDest; }; class AudioStream { public: - AudioStream (void); - ~AudioStream (void); - BOOL Create (const char *pszFilename); - BOOL Destroy (void); - void Play (long volume, int looping); - int Is_Playing(){ return(m_fPlaying); } - int Is_Paused(){ return(m_bIsPaused); } - int Is_Past_Limit() { return m_bPastLimit; } - void Stop (int paused=0); - void Stop_and_Rewind (void); - void Fade_and_Destroy (void); - void Fade_and_Stop(void); - void Set_Volume(long vol); - long Get_Volume(); - void Init_Data(); - void Set_Byte_Cutoff(unsigned int num_bytes_cutoff); - void Set_Default_Volume(long converted_volume) { m_lDefaultVolume = converted_volume; } - long Get_Default_Volume() { return m_lDefaultVolume; } - uint Get_Bytes_Committed(void); - int Is_looping() { return m_bLooping; } - int status; + AudioStream(); + ~AudioStream(); + + bool Create(const char *pszFilename); + bool Destroy(); + void Play(float volume, int looping); + void Stop(int paused = 0); + void Stop_and_Rewind(); + void Fade_and_Destroy(); + void Fade_and_Stop(); + void Set_Volume(float vol); + float Get_Volume(); + void Set_Byte_Cutoff(uint num_bytes_cutoff); + uint Get_Bytes_Committed(); + + int Is_Playing() + { + return m_fPlaying; + } + + int Is_Paused() + { + return m_bIsPaused; + } + + int Is_Past_Limit() + { + return m_bPastLimit; + } + + void Set_Default_Volume(float _volume) + { + m_lDefaultVolume = _volume; + } + + float Get_Default_Volume() + { + return m_lDefaultVolume; + } + + int Is_looping() + { + return m_bLooping; + } + int type; ushort m_bits_per_sample_uncompressed; protected: - void Cue (void); - BOOL WriteWaveData (uint cbSize, uint* num_bytes_written,int service=1); - BOOL WriteSilence (uint cbSize); - DWORD GetMaxWriteSize (void); - BOOL ServiceBuffer (void); - static BOOL TimerCallback (ptr_u dwUser); + void Cue(); + bool WriteWaveData(uint cbSize, uint* num_bytes_written,int service=1); + uint GetMaxWriteSize(); + bool ServiceBuffer(); + static bool TimerCallback(ptr_u dwUser); ALuint m_source_id; // name of openAL source ALuint m_buffer_ids[MAX_STREAM_BUFFERS]; //names of buffers int m_play_buffer_id; Timer m_timer; // ptr to Timer object - WaveFile * m_pwavefile; // ptr to WaveFile object - BOOL m_fCued; // semaphore (stream cued) - BOOL m_fPlaying; // semaphore (stream playing) + WaveFile *m_pwavefile; // ptr to WaveFile object + bool m_fCued; // semaphore (stream cued) + bool m_fPlaying; // semaphore (stream playing) long m_lInService; // reentrancy semaphore uint m_cbBufOffset; // last write position uint m_nBufLength; // length of sound buffer in msec @@ -246,21 +260,18 @@ protected: uint m_nBufService; // service interval in msec uint m_nTimeStarted; // time (in system time) playback started - BOOL m_bLooping; // whether or not to loop playback - BOOL m_bFade; // fade out music - BOOL m_bDestroy_when_faded; - long m_lVolume; // volume of stream ( 0 -> -10 000 ) - long m_lCutoffVolume; - BOOL m_bIsPaused; // stream is stopped, but not rewinded + bool m_bLooping; // whether or not to loop playback + bool m_bFade; // fade out music + bool m_bDestroy_when_faded; + float m_lVolume; // volume of stream ( 0 -> -10 000 ) + float m_lCutoffVolume; + bool m_bIsPaused; // stream is stopped, but not rewinded ushort m_silence_written; // number of bytes of silence written to buffer ushort m_bReadingDone; // no more bytes to be read from disk, still have remaining buffer to play - DWORD m_fade_timer_id; // timestamp so we know when to start fade - DWORD m_finished_id; // timestamp so we know when we've played #bytes required - BOOL m_bPastLimit; // flag to show we've played past the number of bytes requred - long m_lDefaultVolume; - int h_result; - - CRITICAL_SECTION write_lock; + uint m_fade_timer_id; // timestamp so we know when to start fade + uint m_finished_id; // timestamp so we know when we've played #bytes required + bool m_bPastLimit; // flag to show we've played past the number of bytes requred + float m_lDefaultVolume; }; @@ -268,63 +279,55 @@ protected: // //////////////////////////////////////////////////////////// -// constructor -void Timer::constructor(void) +void Timer::constructor() { - m_nIDTimer = NULL; + m_nIDTimer = 0; } - -// Destructor -void Timer::destructor(void) +void Timer::destructor() { if (m_nIDTimer) { SDL_RemoveTimer(m_nIDTimer); - m_nIDTimer = NULL; + m_nIDTimer = 0; } } -// Create -BOOL Timer::Create (UINT nPeriod, UINT nRes, DWORD dwUser, TIMERCALLBACK pfnCallback) +bool Timer::Create(uint nPeriod, ptr_u dwUser, TIMERCALLBACK pfnCallback) { - BOOL bRtn = SUCCESS; // assume success - - Assert(pfnCallback); - Assert(nPeriod > 10); - Assert(nPeriod >= nRes); + SDL_assert( pfnCallback != NULL ); + SDL_assert( nPeriod > 10 ); m_nPeriod = nPeriod; - m_nRes = nRes; m_dwUser = dwUser; m_pfnCallback = pfnCallback; - if ((m_nIDTimer = SDL_AddTimer (m_nPeriod, TimeProc, (void*) this)) == NULL) { + m_nIDTimer = SDL_AddTimer(m_nPeriod, TimeProc, (void*)this); + + if ( !m_nIDTimer ) { nprintf(("SOUND", "SOUND ==> Error, unable to create timer\n")); - bRtn = FAILURE; + return false; } - return (bRtn); + return true; } - -// Timer proc for multimedia timer callback set with timeSetTime(). -// // Calls procedure specified when Timer object was created. The // dwUser parameter contains "this" pointer for associated Timer object. // -Uint32 CALLBACK Timer::TimeProc(Uint32 interval, void *dwUser) +Uint32 Timer::TimeProc(Uint32 interval, void *dwUser) { // dwUser contains ptr to Timer object - Timer * ptimer = (Timer *) dwUser; + Timer *ptimer = (Timer *)dwUser; // Call user-specified callback and pass back user specified data - (ptimer->m_pfnCallback) (ptimer->m_dwUser); + (ptimer->m_pfnCallback)(ptimer->m_dwUser); if (ptimer->m_nPeriod) { return interval; } else { SDL_RemoveTimer(ptimer->m_nIDTimer); - ptimer->m_nIDTimer = NULL; + ptimer->m_nIDTimer = 0; + return 0; } } @@ -334,8 +337,7 @@ Uint32 CALLBACK Timer::TimeProc(Uint32 interval, void *dwUser) // //////////////////////////////////////////////////////////// -// Constructor -void WaveFile::Init(void) +void WaveFile::Init() { // Init data members m_data_offset = 0; @@ -349,11 +351,10 @@ void WaveFile::Init(void) m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX; m_hStream_open = 0; - m_abort_next_read = FALSE; + m_abort_next_read = false; } -// Destructor -void WaveFile::Close(void) +void WaveFile::Close() { // Free memory if (m_pwfmt_original) { @@ -361,162 +362,182 @@ void WaveFile::Close(void) m_pwfmt_original = NULL; } - if ( m_hStream_open ) { + if (m_hStream_open) { ACM_stream_close((void*)m_hStream); m_hStream_open = 0; } // Close file if (cfp) { - SDL_RWclose( cfp ); + cfclose(cfp); cfp = NULL; } } - -// Open -BOOL WaveFile::Open (const char *pszFilename) +bool WaveFile::Open(const char *pszFilename) { - int done = FALSE; - WORD cbExtra = 0; - BOOL fRtn = SUCCESS; // assume success - PCMWAVEFORMAT pcmwf; - char fullpath[_MAX_PATH]; + int done = false; + bool fRtn = true; // assume success + int id = 0; + uint tag = 0, size = 0, next_chunk; m_total_uncompressed_bytes_read = 0; m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX; - int FileSize, FileOffset; + m_pwfmt_original = (WAVE_chunk*) malloc (sizeof(WAVE_chunk)); - if ( !cf_find_file_location(pszFilename, CF_TYPE_ANY, fullpath, &FileSize, &FileOffset )) { + if (m_pwfmt_original == NULL) { goto OPEN_ERROR; } - cfp = SDL_RWFromFile(fullpath, "rb"); + cfp = cfopen(pszFilename, "rb"); - if ( cfp == NULL ) { + if (cfp == NULL) { goto OPEN_ERROR; } - // Skip the "RIFF" tag and file size (8 bytes) - // Skip the "WAVE" tag (4 bytes) - SDL_RWseek( cfp, 12+FileOffset, SEEK_SET ); + // check for valid file type + id = cfread_int(cfp); - // Now read RIFF tags until the end of file - DWORD tag, size, next_chunk; + // 'RIFF' + if (id != 0x46464952) { + nprintf(("Error", "Not a WAVE file '%s'\n", pszFilename)); + goto OPEN_ERROR; + } - while(done == FALSE) { - if ( !audiostr_read_dword(cfp, &tag) ) - break; + // skip RIFF size + cfread_int(cfp); - if ( !audiostr_read_dword(cfp, &size) ) - break; + // check for valid RIFF type + id = cfread_int(cfp); - next_chunk = SDL_RWtell( cfp ); - next_chunk += size; + // 'WAVE' + if (id != 0x45564157) { + nprintf(("Error", "Not a WAVE file '%s'\n", pszFilename)); + goto OPEN_ERROR; + } - switch( tag ) { - case 0x20746d66: // The 'fmt ' tag - audiostr_read_word(cfp, &pcmwf.wf.wFormatTag); - audiostr_read_word(cfp, &pcmwf.wf.nChannels); - audiostr_read_dword(cfp, &pcmwf.wf.nSamplesPerSec); - audiostr_read_dword(cfp, &pcmwf.wf.nAvgBytesPerSec); - audiostr_read_word(cfp, &pcmwf.wf.nBlockAlign); - audiostr_read_word(cfp, &pcmwf.wBitsPerSample); + while ( !done ) { + tag = cfread_uint(cfp); + size = cfread_uint(cfp); - if ( pcmwf.wf.wFormatTag != WAVE_FORMAT_PCM ) { - audiostr_read_word(cfp, &cbExtra); - } + next_chunk = cftell(cfp) + size; - // Allocate memory for WAVEFORMATEX structure + extra bytes - if ( (m_pwfmt_original = (WAVEFORMATEX *) malloc ( sizeof(WAVEFORMATEX)+cbExtra )) != NULL ){ - Assert(m_pwfmt_original != NULL); - // Copy bytes from temporary format structure - memcpy (m_pwfmt_original, &pcmwf, sizeof(pcmwf)); - m_pwfmt_original->cbSize = cbExtra; + switch (tag) { + // 'fmt ' + case 0x20746d66: { + m_pwfmt_original->code = cfread_short(cfp); + m_pwfmt_original->num_channels = cfread_ushort(cfp); + m_pwfmt_original->sample_rate = cfread_uint(cfp); + m_pwfmt_original->bytes_per_second = cfread_uint(cfp); + m_pwfmt_original->block_align = cfread_ushort(cfp); + m_pwfmt_original->bits_per_sample = cfread_ushort(cfp); - // Read those extra bytes, append to WAVEFORMATEX structure - if (cbExtra != 0) { - SDL_RWread( cfp, ((ubyte *)(m_pwfmt_original) + sizeof(WAVEFORMATEX)), 1, cbExtra ); + if (m_pwfmt_original->code != 1) { + m_pwfmt_original->extra_size = cfread_ushort(cfp); } + + if (m_pwfmt_original->extra_size) { + m_pwfmt_original->extra_data = (ubyte*) malloc (m_pwfmt_original->extra_size); + SDL_assert( m_pwfmt_original->extra_data != NULL ); + + if (m_pwfmt_original->extra_data == NULL) { + goto OPEN_ERROR; + } + + cfread(m_pwfmt_original->extra_data, m_pwfmt_original->extra_size, 1, cfp); + } + + break; } - else { - Int3(); // malloc failed - goto OPEN_ERROR; - } - break; - case 0x61746164: // the 'data' tag - m_nDataSize = size; // This is size of data chunk. Compressed if ADPCM. - m_data_bytes_left = size; - m_data_offset = SDL_RWtell( cfp ); - done = TRUE; - break; + // 'data' + case 0x61746164: { + m_nDataSize = size; // size of data, compressed size if ADPCM + m_data_bytes_left = size; + m_data_offset = cftell(cfp); - default: // unknown, skip it - break; - } // end switch + done = true; + + break; + } + + // drop everything else + default: + break; + } - SDL_RWseek( cfp, next_chunk, SEEK_SET ); + cfseek(cfp, next_chunk, CF_SEEK_SET); } - // At this stage, examine source format, and set up WAVEFORATEX structure for DirectSound. - // Since DirectSound only supports PCM, force this structure to be PCM compliant. We will - // need to convert data on the fly later if our souce is not PCM - switch ( m_pwfmt_original->wFormatTag ) { + // we force PCM format, so keep track of original format for later + switch (m_pwfmt_original->code) { case WAVE_FORMAT_PCM: m_wave_format = WAVE_FORMAT_PCM; - m_wfmt.wBitsPerSample = m_pwfmt_original->wBitsPerSample; + m_wfmt.bits_per_sample = m_pwfmt_original->bits_per_sample; break; case WAVE_FORMAT_ADPCM: m_wave_format = WAVE_FORMAT_ADPCM; - m_wfmt.wBitsPerSample = 16; + m_wfmt.bits_per_sample = 16; m_bits_per_sample_uncompressed = 16; break; default: - nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n", m_pwfmt_original->wFormatTag)); + nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n", m_pwfmt_original->code)); //Int3(); goto OPEN_ERROR; break; - } // end switch + } - // Set up the WAVEFORMATEX structure to have the right PCM characteristics - m_wfmt.wFormatTag = WAVE_FORMAT_PCM; - m_wfmt.nChannels = m_pwfmt_original->nChannels; - m_wfmt.nSamplesPerSec = m_pwfmt_original->nSamplesPerSec; - m_wfmt.cbSize = 0; - m_wfmt.nBlockAlign = (ushort)(( m_wfmt.nChannels * m_wfmt.wBitsPerSample ) / 8); - m_wfmt.nAvgBytesPerSec = m_wfmt.nBlockAlign * m_wfmt.nSamplesPerSec; + m_wfmt.code = WAVE_FORMAT_PCM; + m_wfmt.num_channels = m_pwfmt_original->num_channels; + m_wfmt.sample_rate = m_pwfmt_original->sample_rate; + m_wfmt.extra_size = 0; + m_wfmt.block_align = (ushort)(( m_wfmt.num_channels * m_wfmt.bits_per_sample ) / 8); + m_wfmt.bytes_per_second = m_wfmt.block_align * m_wfmt.sample_rate; + + // set OpenAL format + m_oal_format = AL_FORMAT_MONO8; + + if (m_wfmt.num_channels == 1) { + if (m_wfmt.bits_per_sample == 8) { + m_oal_format = AL_FORMAT_MONO8; + } else if (m_wfmt.bits_per_sample == 16) { + m_oal_format = AL_FORMAT_MONO16; + } + } else if (m_wfmt.num_channels == 2) { + if (m_wfmt.bits_per_sample == 8) { + m_oal_format = AL_FORMAT_STEREO8; + } else if (m_wfmt.bits_per_sample == 16) { + m_oal_format = AL_FORMAT_STEREO16; + } + } // Init some member data from format chunk - m_nBlockAlign = m_pwfmt_original->nBlockAlign; - m_nUncompressedAvgDataRate = m_wfmt.nAvgBytesPerSec; - - // Cue for streaming - Cue (); + m_nBlockAlign = m_pwfmt_original->block_align; + m_nUncompressedAvgDataRate = m_wfmt.bytes_per_second; // Successful open goto OPEN_DONE; - + OPEN_ERROR: // Handle all errors here - nprintf(("SOUND","SOUND ==> Could not open wave file %s for streaming\n",pszFilename)); + nprintf(("SOUND","SOUND ==> Could not open wave file %s for streaming\n", pszFilename)); - fRtn = FAILURE; - if (cfp != NULL) { - // Close file - SDL_RWclose( cfp ); - cfp = NULL; - } - if (m_pwfmt_original) - { + fRtn = false; + + if (m_pwfmt_original) { free(m_pwfmt_original); m_pwfmt_original = NULL; } + if (cfp != NULL) { + cfclose(cfp); + cfp = NULL; + } + OPEN_DONE: return (fRtn); } @@ -525,27 +546,26 @@ OPEN_DONE: // // Set the file pointer to the start of wave data // -BOOL WaveFile::Cue (void) +bool WaveFile::Cue() { - BOOL fRtn = SUCCESS; // assume success + bool fRtn = true; // assume success int rval = -1; m_total_uncompressed_bytes_read = 0; m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX; - rval = SDL_RWseek( cfp, m_data_offset, SEEK_SET ); + rval = cfseek(cfp, m_data_offset, CF_SEEK_SET); - if ( rval == -1 ) { - fRtn = FAILURE; + if (rval) { + fRtn = false; } m_data_bytes_left = m_nDataSize; - m_abort_next_read = FALSE; + m_abort_next_read = false; return fRtn; } - // Read // // Returns number of bytes actually read. @@ -555,9 +575,9 @@ BOOL WaveFile::Cue (void) // locate a suitable block int WaveFile::Read(ubyte *pbDest, uint cbSize, int service) { - void *dest_buf=NULL, *uncompressed_wave_data; - int rc, uncompressed_bytes_written; - uint src_bytes_used, convert_len, num_bytes_desired=0, num_bytes_read; + void *dest_buf = NULL, *uncompressed_wave_data; + int rc, uncompressed_bytes_written; + uint src_bytes_used, convert_len, num_bytes_desired=0, num_bytes_read; // nprintf(("Alan","Reqeusted: %d\n", cbSize)); @@ -567,15 +587,17 @@ int WaveFile::Read(ubyte *pbDest, uint cbSize, int service) uncompressed_wave_data = Wavedata_load_buffer; } - switch ( m_wave_format ) { - case WAVE_FORMAT_PCM: + switch (m_wave_format) { + case WAVE_FORMAT_PCM: { num_bytes_desired = cbSize; dest_buf = pbDest; + break; + } - case WAVE_FORMAT_ADPCM: + case WAVE_FORMAT_ADPCM: { if ( !m_hStream_open ) { - if ( !ACM_stream_open(m_pwfmt_original, &m_wfxDest, (void**)&m_hStream, m_bits_per_sample_uncompressed) ) { + if ( !ACM_stream_open(m_pwfmt_original, &m_wfxDest, (void**)&m_hStream, m_bits_per_sample_uncompressed) ) { m_hStream_open = 1; } else { Int3(); @@ -584,20 +606,22 @@ int WaveFile::Read(ubyte *pbDest, uint cbSize, int service) num_bytes_desired = cbSize; - if ( service ) { + if (service) { dest_buf = Compressed_service_buffer; } else { dest_buf = Compressed_buffer; } - if ( num_bytes_desired <= 0 ) { + if (num_bytes_desired <= 0) { num_bytes_desired = 0; // nprintf(("Alan","No bytes required for ADPCM time interval\n")); } else { num_bytes_desired = ACM_query_source_size((void*)m_hStream, cbSize); // nprintf(("Alan","Num bytes desired: %d\n", num_bytes_desired)); } + break; + } default: nprintf(("SOUND", "SOUND => Not supporting %d format for playing wave files\n")); @@ -611,31 +635,32 @@ int WaveFile::Read(ubyte *pbDest, uint cbSize, int service) src_bytes_used = 0; // read data from disk - if ( m_data_bytes_left <= 0 ) { + if (m_data_bytes_left <= 0) { num_bytes_read = 0; uncompressed_bytes_written = 0; + return -1; } if ( (m_data_bytes_left > 0) && (num_bytes_desired > 0) ) { int actual_read = 0; - if ( num_bytes_desired <= (uint)m_data_bytes_left ) { + if (num_bytes_desired <= (uint)m_data_bytes_left) { num_bytes_read = num_bytes_desired; - } - else { + } else { num_bytes_read = m_data_bytes_left; } - actual_read = SDL_RWread( cfp, dest_buf, 1, num_bytes_read ); + actual_read = cfread(dest_buf, 1, num_bytes_read, cfp); if ( (actual_read <= 0) || (m_abort_next_read) ) { num_bytes_read = 0; uncompressed_bytes_written = 0; + return -1; } - if ( num_bytes_desired >= (uint)m_data_bytes_left ) { + if (num_bytes_desired >= (uint)m_data_bytes_left) { m_abort_next_read = 1; } @@ -643,22 +668,24 @@ int WaveFile::Read(ubyte *pbDest, uint cbSize, int service) } // convert data if necessary, to PCM - if ( m_wave_format == WAVE_FORMAT_ADPCM ) { + if (m_wave_format == WAVE_FORMAT_ADPCM) { if ( num_bytes_read > 0 ) { rc = ACM_convert((void*)m_hStream, (ubyte*)dest_buf, num_bytes_read, (ubyte*)uncompressed_wave_data, BIGBUF_SIZE, &convert_len, &src_bytes_used); - if ( rc == -1 ) { + if (rc == -1) { goto READ_ERROR; } - if ( convert_len == 0 ) { + + if (convert_len == 0) { Int3(); } } - Assert(src_bytes_used <= num_bytes_read); - if ( src_bytes_used < num_bytes_read ) { + SDL_assert( src_bytes_used <= num_bytes_read ); + + if (src_bytes_used < num_bytes_read) { // seek back file pointer to reposition before unused source data - SDL_RWseek( cfp, src_bytes_used - num_bytes_read, SEEK_CUR ); + cfseek(cfp, src_bytes_used - num_bytes_read, CF_SEEK_CUR); } // Adjust number of bytes left @@ -668,26 +695,27 @@ int WaveFile::Read(ubyte *pbDest, uint cbSize, int service) // Successful read, keep running total of number of data bytes read goto READ_DONE; - } - else { + } else { // Successful read, keep running total of number of data bytes read // Adjust number of bytes left m_data_bytes_left -= num_bytes_read; m_nBytesPlayed += num_bytes_read; uncompressed_bytes_written = num_bytes_read; + #if BYTE_ORDER == BIG_ENDIAN - if ( m_wave_format == WAVE_FORMAT_PCM ) { + if (m_wave_format == WAVE_FORMAT_PCM) { // swap 16-bit sound data - if (m_wfmt.wBitsPerSample == 16) { + if (m_wfmt.bits_per_sample == 16) { ushort *swap_tmp; - for (int i=0; i Failed to create WaveFile object %s\n\r", pszFilename)); + return false; + } - // Create a new WaveFile object - m_pwavefile = (WaveFile *)malloc(sizeof(WaveFile)); - Assert(m_pwavefile); + // Call constructor + m_pwavefile->Init(); - if (m_pwavefile) { - // Call constructor - m_pwavefile->Init(); - // Open given file - m_pwavefile->m_bits_per_sample_uncompressed = m_bits_per_sample_uncompressed; - if (m_pwavefile->Open (pszFilename)) { - // Calculate sound buffer size in bytes - // Buffer size is average data rate times length of buffer - // No need for buffer to be larger than wave data though - m_cbBufSize = (m_nBufLength/1000) * (m_pwavefile->m_wfmt.wBitsPerSample/8) * m_pwavefile->m_wfmt.nChannels * m_pwavefile->m_wfmt.nSamplesPerSec; - m_cbBufSize /= MAX_STREAM_BUFFERS; - // if the requested buffer size is too big then cap it - m_cbBufSize = (m_cbBufSize > BIGBUF_SIZE) ? BIGBUF_SIZE : m_cbBufSize; + m_pwavefile->m_bits_per_sample_uncompressed = m_bits_per_sample_uncompressed; -// nprintf(("SOUND", "SOUND => Stream buffer created using %d bytes\n", m_cbBufSize)); + // Open given file + if ( m_pwavefile->Open(pszFilename) ) { + // Calculate sound buffer size in bytes + // Buffer size is average data rate times length of buffer + // No need for buffer to be larger than wave data though + m_cbBufSize = (m_nBufLength/1000) * (m_pwavefile->m_wfmt.bits_per_sample/8) * m_pwavefile->m_wfmt.num_channels * m_pwavefile->m_wfmt.sample_rate; + m_cbBufSize /= MAX_STREAM_BUFFERS; + // if the requested buffer size is too big then cap it + m_cbBufSize = (m_cbBufSize > BIGBUF_SIZE) ? BIGBUF_SIZE : m_cbBufSize; - // Create sound buffer - OpenAL_ErrorCheck( alGenBuffers(MAX_STREAM_BUFFERS, m_buffer_ids), return FAILURE ); - - OpenAL_ErrorCheck( alGenSources(1, &m_source_id), return FAILURE ); - - OpenAL_ErrorPrint( alSourcef(m_source_id, AL_ROLLOFF_FACTOR, 0) ); +// nprintf(("SOUND", "SOUND => Stream buffer created using %d bytes\n", m_cbBufSize)); - OpenAL_ErrorPrint( alSourcei(m_source_id, AL_SOURCE_RELATIVE, AL_TRUE) ); + // Create sound buffer + alGenBuffers(MAX_STREAM_BUFFERS, m_buffer_ids); - ALfloat posv[] = { 0, 0, 0 }; - OpenAL_ErrorPrint( alSourcefv(m_source_id, AL_POSITION, posv) ); + Snd_sram += m_cbBufSize * MAX_STREAM_BUFFERS; + } else { + // Error opening file + nprintf(("SOUND", "SOUND => Failed to open wave file: %s\n\r", pszFilename)); - OpenAL_ErrorPrint( alSourcef(m_source_id, AL_GAIN, 1) ); + m_pwavefile->Close(); - // Cue for playback - Cue(); - Snd_sram += m_cbBufSize; - } - else { - // Error opening file - nprintf(("SOUND", "SOUND => Failed to open wave file: %s\n\r", pszFilename)); - m_pwavefile->Close(); - free(m_pwavefile); - m_pwavefile = NULL; - fRtn = FAILURE; - } - } - else { - // Error, unable to create WaveFile object - nprintf(("Sound", "SOUND => Failed to create WaveFile object %s\n\r", pszFilename)); - fRtn = FAILURE; - } - } - else { - // Error, passed invalid parms - fRtn = FAILURE; + free(m_pwavefile); + m_pwavefile = NULL; + + return false; } - return (fRtn); + return true; } // Destroy -BOOL AudioStream::Destroy (void) +bool AudioStream::Destroy() { - BOOL fRtn = SUCCESS; - - SDL_LockMutex(write_lock); - // Stop playback - Stop (); + Stop(); // Release sound buffer - OpenAL_ErrorPrint( alDeleteBuffers(MAX_STREAM_BUFFERS, m_buffer_ids) ); - OpenAL_ErrorPrint( alDeleteSources(1, &m_source_id) ); + alDeleteBuffers(MAX_STREAM_BUFFERS, m_buffer_ids); + Snd_sram -= m_cbBufSize; // Delete WaveFile object if (m_pwavefile) { m_pwavefile->Close(); + free(m_pwavefile); m_pwavefile = NULL; } - status = ASF_FREE; - - SDL_UnlockMutex(write_lock); + type = ASF_NONE; - return fRtn; + return true; } // WriteWaveData // // Writes wave data to sound buffer. This is a helper method used by Create and // ServiceBuffer; it's not exposed to users of the AudioStream class. -BOOL AudioStream::WriteWaveData (uint size, uint *num_bytes_written, int service) +bool AudioStream::WriteWaveData(uint size, uint *num_bytes_written, int service) { - BOOL fRtn = SUCCESS; ubyte *uncompressed_wave_data; *num_bytes_written = 0; - if ( size == 0 || m_bReadingDone ) { - return fRtn; + if ( (size == 0) || m_bReadingDone ) { + return false; } if ( (m_buffer_ids[0] == 0) || !m_pwavefile ) { - return fRtn; + return false; } if ( service ) { @@ -927,253 +930,219 @@ BOOL AudioStream::WriteWaveData (uint size, uint *num_bytes_written, int service int num_bytes_read = 0; - // Lock the sound buffer - num_bytes_read = m_pwavefile->Read(uncompressed_wave_data, m_cbBufSize, service); - - if ( num_bytes_read == -1 ) { - // means nothing left to read! - num_bytes_read = 0; - m_bReadingDone = 1; - } - - if ( num_bytes_read > 0 ) { - // nprintf(("SOUND", "SOUND ==> Queueing %d bytes of Data\n", num_bytes_read)); + if ( !service ) { + for (int ib = 0; ib < MAX_STREAM_BUFFERS; ib++) { + num_bytes_read = m_pwavefile->Read(uncompressed_wave_data, m_cbBufSize, service); - // Lock the sound buffer - ALenum format = AL_FORMAT_MONO8; + if (num_bytes_read < 0) { + m_bReadingDone = 1; + } else if (num_bytes_read > 0) { + alBufferData(m_buffer_ids[ib], m_pwavefile->GetOALFormat(), uncompressed_wave_data, num_bytes_read, m_pwavefile->m_wfmt.sample_rate); + alSourceQueueBuffers(m_source_id, 1, &m_buffer_ids[ib]); - if (m_pwavefile->m_wfmt.nChannels == 1) { - if (m_pwavefile->m_wfmt.wBitsPerSample == 8) - format = AL_FORMAT_MONO8; - else if (m_pwavefile->m_wfmt.wBitsPerSample == 16) - format = AL_FORMAT_MONO16; - } else if (m_pwavefile->m_wfmt.nChannels == 2) { - if (m_pwavefile->m_wfmt.wBitsPerSample == 8) - format = AL_FORMAT_STEREO8; - else if (m_pwavefile->m_wfmt.wBitsPerSample == 16) - format = AL_FORMAT_STEREO16; + *num_bytes_written += num_bytes_read; + } } + } else { + ALint buffers_processed = 0; + ALuint buffer_id = 0; - // unqueue and recycle a processed buffer - ALint p = 0; - ALuint bid; + alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &buffers_processed); - OpenAL_ErrorPrint( alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &p) ); + while (buffers_processed) { + alSourceUnqueueBuffers(m_source_id, 1, &buffer_id); - if ( p > 0 ) { - OpenAL_ErrorPrint( alSourceUnqueueBuffers(m_source_id, 1, &bid) ); - } + num_bytes_read = m_pwavefile->Read(uncompressed_wave_data, m_cbBufSize, service); - OpenAL_ErrorCheck( alBufferData(m_buffer_ids[m_play_buffer_id], format, uncompressed_wave_data, num_bytes_read, m_pwavefile->m_wfmt.nSamplesPerSec), return FAILURE ); + if (num_bytes_read < 0) { + m_bReadingDone = 1; + } else if (num_bytes_read > 0) { + alBufferData(buffer_id, m_pwavefile->GetOALFormat(), uncompressed_wave_data, num_bytes_read, m_pwavefile->m_wfmt.sample_rate); + alSourceQueueBuffers(m_source_id, 1, &buffer_id); - OpenAL_ErrorCheck( alSourceQueueBuffers(m_source_id, 1, &m_buffer_ids[m_play_buffer_id]), return FAILURE ); - - m_play_buffer_id++; + *num_bytes_written += num_bytes_read; + } - if (m_play_buffer_id >= MAX_STREAM_BUFFERS) - m_play_buffer_id = 0; + buffers_processed--; + } } if ( service ) { SDL_UnlockMutex(Global_service_lock); } - return (fRtn); + return true; } - -// WriteSilence -// -// Writes silence to sound buffer. This is a helper method used by -// ServiceBuffer; it's not exposed to users of the AudioStream class. -BOOL AudioStream::WriteSilence (uint size) -{ - BOOL fRtn = SUCCESS; - - // not used currently with the OpenAL code - - return (fRtn); -} - - // GetMaxWriteSize // // Helper function to calculate max size of sound buffer write operation, i.e. how much // free space there is in buffer. -DWORD AudioStream::GetMaxWriteSize (void) +uint AudioStream::GetMaxWriteSize() { - DWORD dwMaxSize = m_cbBufSize; - ALint n, q; + uint dwMaxSize = m_cbBufSize; + ALint n = 0, q = 0; - OpenAL_ErrorCheck( alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &n), return 0 ); + alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &n); - OpenAL_ErrorCheck( alGetSourcei(m_source_id, AL_BUFFERS_QUEUED, &q), return 0 ); + alGetSourcei(m_source_id, AL_BUFFERS_QUEUED, &q); - if (!n && (q >= MAX_STREAM_BUFFERS)) //all buffers queued + if ( !n && (q >= MAX_STREAM_BUFFERS) ) { + //all buffers queued dwMaxSize = 0; + } // nprintf(("Alan","Max write size: %d\n", dwMaxSize)); - return (dwMaxSize); + return dwMaxSize; } -#define FADE_VOLUME_INTERVAL 400 // 100 == 1db -#define VOLUME_ATTENUATION_BEFORE_CUTOFF 3000 // 12db -BOOL AudioStream::ServiceBuffer (void) -{ - long vol; - int fRtn = TRUE; - - if ( status != ASF_USED ) - return FALSE; - - SDL_LockMutex(write_lock); +#define VOLUME_ATTENUATION_BEFORE_CUTOFF 0.03f // 12db +#define VOLUME_ATTENUATION 0.65f - // status may have changed, so lets check once again - if ( status != ASF_USED ){ - SDL_UnlockMutex(write_lock); +bool AudioStream::ServiceBuffer() +{ + float vol; + int fRtn = true; - return FALSE; + if (type == ASF_NONE) { + return false; } - if ( m_bFade == TRUE ) { - if ( m_lCutoffVolume == -10000 ) { + if (m_bFade) { + if (m_lCutoffVolume == 0.0f) { vol = Get_Volume(); // nprintf(("Alan","Volume is: %d\n",vol)); - m_lCutoffVolume = max(vol - VOLUME_ATTENUATION_BEFORE_CUTOFF, -10000); + m_lCutoffVolume = vol * VOLUME_ATTENUATION_BEFORE_CUTOFF; } - vol = Get_Volume(); - vol = vol - FADE_VOLUME_INTERVAL; // decrease by 1db + vol = Get_Volume() * VOLUME_ATTENUATION; // nprintf(("Alan","Volume is now: %d\n",vol)); Set_Volume(vol); // nprintf(("Sound","SOUND => Volume for stream sound is %d\n",vol)); // nprintf(("Alan","Cuttoff Volume is: %d\n",m_lCutoffVolume)); - if ( vol < m_lCutoffVolume ) { - m_bFade = 0; - m_lCutoffVolume = -10000; - if ( m_bDestroy_when_faded == TRUE ) { - SDL_UnlockMutex(write_lock); + if (vol < m_lCutoffVolume) { + m_bFade = false; + m_lCutoffVolume = 0.0f; + if (m_bDestroy_when_faded) { Destroy(); - // Reset reentrancy semaphore - return FALSE; + return false; } else { Stop_and_Rewind(); - // Reset reentrancy semaphore - SDL_UnlockMutex(write_lock); - return TRUE; + return true; } } } // All of sound not played yet, send more data to buffer - DWORD dwFreeSpace = GetMaxWriteSize (); + uint dwFreeSpace = GetMaxWriteSize(); // Determine free space in sound buffer if (dwFreeSpace) { - // Some wave data remains, but not enough to fill free space // Send wave data to buffer, fill remainder of free space with silence uint num_bytes_written; - if (WriteWaveData (dwFreeSpace, &num_bytes_written) == SUCCESS) { + if ( WriteWaveData(dwFreeSpace, &num_bytes_written) ) { // nprintf(("Alan","Num bytes written: %d\n", num_bytes_written)); - if ( m_pwavefile->m_total_uncompressed_bytes_read >= m_pwavefile->m_max_uncompressed_bytes_to_read ) { + if (m_pwavefile->m_total_uncompressed_bytes_read >= m_pwavefile->m_max_uncompressed_bytes_to_read) { m_fade_timer_id = timer_get_milliseconds() + 1700; // start fading 1.7 seconds from now m_finished_id = timer_get_milliseconds() + 2000; // 2 seconds left to play out buffer m_pwavefile->m_max_uncompressed_bytes_to_read = AS_HIGHEST_MAX; } - if ( (m_fade_timer_id>0) && ((uint)timer_get_milliseconds() > m_fade_timer_id) ) { + if ( (m_fade_timer_id > 0) && ((uint)timer_get_milliseconds() > m_fade_timer_id) ) { m_fade_timer_id = 0; Fade_and_Stop(); } - if ( (m_finished_id>0) && ((uint)timer_get_milliseconds() > m_finished_id) ) { + if ( (m_finished_id > 0) && ((uint)timer_get_milliseconds() > m_finished_id) ) { m_finished_id = 0; - m_bPastLimit = TRUE; + m_bPastLimit = true; } - ALint n = 0; - // get the number of buffers processed to see if we're done - OpenAL_ErrorCheck( alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &n), return FALSE ); + // see if we're done + ALint state = 0; - if ( m_bReadingDone && (n == MAX_STREAM_BUFFERS) ) { - if ( m_bDestroy_when_faded == TRUE ) { - SDL_UnlockMutex(write_lock); + alGetSourcei(m_source_id, AL_SOURCE_STATE, &state); + if ( m_bReadingDone && (state != AL_PLAYING) ) { + if ( m_bDestroy_when_faded == true ) { Destroy(); // Reset reentrancy semaphore - return FALSE; + return false; } + // All of sound has played, stop playback or loop again if ( m_bLooping && !m_bFade) { Play(m_lVolume, m_bLooping); - } - else { + } else { Stop_and_Rewind(); } } - } - else { + } else { // Error writing wave data - fRtn = FALSE; + fRtn = false; Int3(); } } - - SDL_UnlockMutex(write_lock); - return (fRtn); } // Cue -void AudioStream::Cue (void) +void AudioStream::Cue() { uint num_bytes_written; - if (!m_fCued) { - m_bFade = FALSE; + if ( !m_fCued ) { + m_bFade = false; m_fade_timer_id = 0; m_finished_id = 0; - m_bPastLimit = FALSE; - m_lVolume = 0; - m_lCutoffVolume = -10000; + m_bPastLimit = false; + m_lVolume = 1.0f; + m_lCutoffVolume = 0.0f; - m_bDestroy_when_faded = FALSE; + m_bDestroy_when_faded = false; // Reset buffer ptr m_cbBufOffset = 0; // Reset file ptr, etc - m_pwavefile->Cue (); + m_pwavefile->Cue(); // Unqueue all buffers - ALint p = 0; - OpenAL_ErrorPrint( alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &p) ); - OpenAL_ErrorPrint( alSourceUnqueueBuffers(m_source_id, p, m_buffer_ids) ); + ALint buffers_processed = 0; + ALuint buffer_id = 0; + + alGetSourcei(m_source_id, AL_BUFFERS_PROCESSED, &buffers_processed); + + while (buffers_processed) { + alSourceUnqueueBuffers(m_source_id, 1, &buffer_id); + + buffers_processed--; + } // Fill buffer with wave data - WriteWaveData (m_cbBufSize, &num_bytes_written, 0); + WriteWaveData(m_cbBufSize, &num_bytes_written, 0); - m_fCued = TRUE; + m_fCued = true; } } // Play -void AudioStream::Play (long volume, int looping) +void AudioStream::Play(float volume, int looping) { if (m_buffer_ids[0] != 0) { // If playing, stop if (m_fPlaying) { - if ( m_bIsPaused == FALSE) + if ( m_bIsPaused == false) Stop_and_Rewind(); } @@ -1182,12 +1151,13 @@ void AudioStream::Play (long volume, int looping) Cue (); } - if ( looping ) - m_bLooping = 1; - else - m_bLooping = 0; + if (looping == 1) { + m_bLooping = true; + } else { + m_bLooping = false; + } - OpenAL_ErrorPrint( alSourcePlay(m_source_id) ); + alSourcePlay(m_source_id); m_nTimeStarted = timer_get_milliseconds(); Set_Volume(volume); @@ -1195,16 +1165,16 @@ void AudioStream::Play (long volume, int looping) // Kick off timer to service buffer m_timer.constructor(); - m_timer.Create (m_nBufService, m_nBufService, ptr_u (this), TimerCallback); + m_timer.Create(m_nBufService, (ptr_u)this, TimerCallback); // Playback begun, no longer cued - m_fPlaying = TRUE; - m_bIsPaused = FALSE; + m_fPlaying = true; + m_bIsPaused = false; } } // Timer callback for Timer object created by ::Play method. -BOOL AudioStream::TimerCallback (ptr_u dwUser) +bool AudioStream::TimerCallback(ptr_u dwUser) { // dwUser contains ptr to AudioStream object AudioStream * pas = (AudioStream *) dwUser; @@ -1220,27 +1190,28 @@ void AudioStream::Set_Byte_Cutoff(unsigned int byte_cutoff) m_pwavefile->m_max_uncompressed_bytes_to_read = byte_cutoff; } -unsigned int AudioStream::Get_Bytes_Committed(void) +uint AudioStream::Get_Bytes_Committed(void) { - if ( m_pwavefile == NULL ) + if (m_pwavefile == NULL) { return 0; + } return m_pwavefile->m_total_uncompressed_bytes_read; } // Fade_and_Destroy -void AudioStream::Fade_and_Destroy (void) +void AudioStream::Fade_and_Destroy() { - m_bFade = TRUE; - m_bDestroy_when_faded = TRUE; + m_bFade = true; + m_bDestroy_when_faded = true; } // Fade_and_Destroy -void AudioStream::Fade_and_Stop (void) +void AudioStream::Fade_and_Stop() { - m_bFade = TRUE; - m_bDestroy_when_faded = FALSE; + m_bFade = true; + m_bDestroy_when_faded = false; } @@ -1249,12 +1220,12 @@ void AudioStream::Stop(int paused) { if (m_fPlaying) { if (paused) { - OpenAL_ErrorPrint( alSourcePause(m_source_id) ); + alSourcePause(m_source_id); } else { - OpenAL_ErrorPrint( alSourceStop(m_source_id) ); + alSourceStop(m_source_id); } - m_fPlaying = FALSE; + m_fPlaying = false; m_bIsPaused = paused; // Delete Timer object @@ -1263,60 +1234,46 @@ void AudioStream::Stop(int paused) } // Stop_and_Rewind -void AudioStream::Stop_and_Rewind (void) +void AudioStream::Stop_and_Rewind() { if (m_fPlaying) { // Stop playback - OpenAL_ErrorPrint( alSourceStop(m_source_id) ); + alSourceStop(m_source_id); // Delete Timer object m_timer.destructor(); - m_fPlaying = FALSE; + m_fPlaying = false; } - m_fCued = FALSE; // this will cause wave file to start from beginning - m_bReadingDone = FALSE; + m_fCued = false; // this will cause wave file to start from beginning + m_bReadingDone = false; } // Set_Volume -void AudioStream::Set_Volume(long vol) +void AudioStream::Set_Volume(float vol) { - if ( vol < -10000 ) - vol = -10000; - - if ( vol > 0 ) - vol = 0; - - Assert( vol >= -10000 && vol <= 0 ); - - ALfloat alvol = (vol != -10000) ? powf(10.0f, (float)vol / (-600.0f / log10f(.5f))): 0.0f; - - OpenAL_ErrorPrint( alSourcef(m_source_id, AL_GAIN, alvol) ); + alSourcef(m_source_id, AL_GAIN, vol); m_lVolume = vol; - if ( h_result != 0 ) - nprintf(("Sound","SOUND => SetVolume() failed with code '%s'\n", get_DSERR_text(h_result) )); } // Set_Volume -long AudioStream::Get_Volume() +float AudioStream::Get_Volume() { return m_lVolume; } - -AudioStream Audio_streams[MAX_AUDIO_STREAMS]; +static std::vector Audio_streams; void audiostream_init() { - int i; - - if ( Audiostream_inited == 1 ) + if (Audiostream_inited) { return; + } // Allocate memory for the buffer which holds the uncompressed wave data that is streamed from the // disk during a load/cue @@ -1343,11 +1300,7 @@ void audiostream_init() Assert(Compressed_service_buffer != NULL); } - for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) { - Audio_streams[i].Init_Data(); - Audio_streams[i].status = ASF_FREE; - Audio_streams[i].type = ASF_NONE; - } + Audio_streams.clear(); SDL_InitSubSystem(SDL_INIT_TIMER); @@ -1360,18 +1313,24 @@ void audiostream_init() // be used. void audiostream_close() { - if ( Audiostream_inited == 0 ) + int i; + + if ( !Audiostream_inited ) { return; + } - int i; + int size = (int)Audio_streams.size(); - for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) { - if ( Audio_streams[i].status == ASF_USED ) { - Audio_streams[i].status = ASF_FREE; - Audio_streams[i].Destroy(); + for (i = 0; i < size; i++) { + if (Audio_streams[i].type == ASF_NONE) { + continue; } + + Audio_streams[i].Destroy(); } + Audio_streams.clear(); + // free global buffers if ( Wavedata_load_buffer ) { free(Wavedata_load_buffer); @@ -1411,73 +1370,87 @@ void audiostream_close() // failure => -1 int audiostream_open( const char *filename, int type ) { - int i, rc; + int i; - if (!Audiostream_inited || !snd_is_inited()) + if ( !Audiostream_inited ) { return -1; + } - for ( i=0; i No more audio streams available!\n")); - return -1; + if (i == size) { + AudioStream n_stream; + Audio_streams.push_back(n_stream); } - switch(type) { + switch (type) { case ASF_VOICE: case ASF_SOUNDFX: Audio_streams[i].m_bits_per_sample_uncompressed = 8; + break; + case ASF_EVENTMUSIC: Audio_streams[i].m_bits_per_sample_uncompressed = 16; break; + default: Int3(); return -1; } - rc = Audio_streams[i].Create(filename); - - if ( rc == 0 ) { - Audio_streams[i].status = ASF_FREE; + if ( !Audio_streams[i].Create(filename) ) { + Audio_streams[i].type = ASF_NONE; return -1; - } else { - return i; } + + return i; } void audiostream_close_file(int i, int fade) { - if (!Audiostream_inited) + if ( !Audiostream_inited ) { return; + } - if ( i == -1 ) - return; + SDL_assert( i >= 0 ); + SDL_assert( i < (int)Audio_streams.size() ); - Assert( i >= 0 && i < MAX_AUDIO_STREAMS ); + if (i < 0) { + return; + } - if ( Audio_streams[i].status == ASF_USED ) { - if ( fade == TRUE ) { - Audio_streams[i].Fade_and_Destroy(); - } else { - Audio_streams[i].Destroy(); - } + if (Audio_streams[i].type == ASF_NONE) { + return; } + if (fade) { + Audio_streams[i].Fade_and_Destroy(); + } else { + Audio_streams[i].Destroy(); + } } void audiostream_close_all(int fade) { int i; - for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) { - if ( Audio_streams[i].status == ASF_FREE ) + if ( !Audiostream_inited ) { + return; + } + + int size = (int)Audio_streams.size(); + + for (i = 0; i < size; i++) { + if (Audio_streams[i].type == ASF_NONE) { continue; + } audiostream_close_file(i, fade); } @@ -1485,151 +1458,193 @@ void audiostream_close_all(int fade) void audiostream_play(int i, float volume, int looping) { - if (!Audiostream_inited) + if ( !Audiostream_inited ) { return; + } - if ( i == -1 ) - return; + SDL_assert( i >= 0 ); + SDL_assert( i < (int)Audio_streams.size() ); - Assert(looping >= 0); - Assert( i >= 0 && i < MAX_AUDIO_STREAMS ); + if (i < 0) { + return; + } - // convert from 0->1 to -10000->0 for volume - int converted_volume; - if ( volume == -1 ) { - converted_volume = Audio_streams[i].Get_Default_Volume(); + if (Audio_streams[i].type == ASF_NONE) { + return; } - else { - Assert(volume >= 0.0f && volume <= 1.0f ); - converted_volume = ds_convert_volume(volume); + + if (volume < 0.0f) { + volume = Audio_streams[i].Get_Default_Volume(); } - Assert( Audio_streams[i].status == ASF_USED ); - Audio_streams[i].Set_Default_Volume(converted_volume); - Audio_streams[i].Play(converted_volume, looping); + Audio_streams[i].Set_Default_Volume(volume); + Audio_streams[i].Play(volume, looping); } // use as buffer service function -int audiostream_is_playing(int i) +bool audiostream_is_playing(int i) { - if ( i == -1 ) - return 0; + if ( !Audiostream_inited ) { + return false; + } - Assert( i >= 0 && i < MAX_AUDIO_STREAMS ); - if ( Audio_streams[i].status != ASF_USED ) - return 0; + SDL_assert( i >= 0 ); + SDL_assert( i < (int)Audio_streams.size() ); + + if (i < 0) { + return false; + } + + if (Audio_streams[i].type == ASF_NONE) { + return false; + } return Audio_streams[i].Is_Playing(); } void audiostream_stop(int i, int rewind, int paused) { - if (!Audiostream_inited) + if ( !Audiostream_inited ) { return; + } - if ( i == -1 ) + SDL_assert( i >= 0 ); + SDL_assert( i < (int)Audio_streams.size() ); + + if (i < 0) { return; + } - Assert( i >= 0 && i < MAX_AUDIO_STREAMS ); - Assert( Audio_streams[i].status == ASF_USED ); + if (Audio_streams[i].type == ASF_NONE) { + return; + } - if ( rewind ) + if (rewind) { Audio_streams[i].Stop_and_Rewind(); - else + } else { Audio_streams[i].Stop(paused); + } } void audiostream_set_volume_all(float volume, int type) { int i; - for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) { - if ( Audio_streams[i].status == ASF_FREE ) + if ( !Audiostream_inited ) { + return; + } + + int size = (int)Audio_streams.size(); + + for (i = 0; i < size; i++) { + if (Audio_streams[i].type == ASF_NONE) { continue; + } - if ( Audio_streams[i].type == type ) { - int converted_volume; - converted_volume = ds_convert_volume(volume); - Audio_streams[i].Set_Volume(converted_volume); + if (Audio_streams[i].type == type) { + Audio_streams[i].Set_Volume(volume); } } } void audiostream_set_volume(int i, float volume) { - if ( i == -1 ) + if ( !Audiostream_inited ) { return; + } + + SDL_assert( i >= 0 ); + SDL_assert( i < (int)Audio_streams.size() ); - Assert( i >= 0 && i < MAX_AUDIO_STREAMS ); - Assert( volume >= 0 && volume <= 1); + if (i < 0) { + return; + } - if ( Audio_streams[i].status == ASF_FREE ) + if (Audio_streams[i].type == ASF_NONE) { return; + } - int converted_volume; - converted_volume = ds_convert_volume(volume); - Audio_streams[i].Set_Volume(converted_volume); + Audio_streams[i].Set_Volume(volume); } -int audiostream_is_paused(int i) +bool audiostream_is_paused(int i) { - if ( i == -1 ) - return 0; + if ( !Audiostream_inited ) { + return false; + } - Assert( i >= 0 && i < MAX_AUDIO_STREAMS ); - if ( Audio_streams[i].status == ASF_FREE ) - return -1; + SDL_assert( i >= 0 ); + SDL_assert( i < (int)Audio_streams.size() ); + + if (i < 0) { + return false; + } - BOOL is_paused; - is_paused = Audio_streams[i].Is_Paused(); + if (Audio_streams[i].type == ASF_NONE) { + return false; + } - return is_paused; + return Audio_streams[i].Is_Paused(); } -void audiostream_set_byte_cutoff(int i, unsigned int cutoff) +void audiostream_set_byte_cutoff(int i, uint cutoff) { - if ( i == -1 ) + if ( !Audiostream_inited ) { return; + } - Assert( i >= 0 && i < MAX_AUDIO_STREAMS ); - Assert( cutoff > 0 ); + SDL_assert( i >= 0 ); + SDL_assert( i < (int)Audio_streams.size() ); + + if (i < 0) { + return; + } - if ( Audio_streams[i].status == ASF_FREE ) + if (Audio_streams[i].type == ASF_NONE) { return; + } Audio_streams[i].Set_Byte_Cutoff(cutoff); } uint audiostream_get_bytes_committed(int i) { - if ( i == -1 ) + if ( !Audiostream_inited ) { return 0; + } - Assert( i >= 0 && i < MAX_AUDIO_STREAMS ); + SDL_assert( i >= 0 ); + SDL_assert( i < (int)Audio_streams.size() ); - if ( Audio_streams[i].status == ASF_FREE ) + if (i < 0) { return 0; + } - uint num_bytes_committed; - num_bytes_committed = Audio_streams[i].Get_Bytes_Committed(); - - return num_bytes_committed; + if (Audio_streams[i].type == ASF_NONE) { + return 0; + } + + return Audio_streams[i].Get_Bytes_Committed(); } -int audiostream_done_reading(int i) +bool audiostream_done_reading(int i) { - if ( i == -1 ) - return 0; + if ( !Audiostream_inited ) { + return true; + } - Assert( i >= 0 && i < MAX_AUDIO_STREAMS ); + SDL_assert( i >= 0 ); + SDL_assert( i < (int)Audio_streams.size() ); - if ( Audio_streams[i].status == ASF_FREE ) - return 0; + if (i < 0) { + return true; + } - int done_reading; - done_reading = Audio_streams[i].Is_Past_Limit(); - - return done_reading; + if (Audio_streams[i].type == ASF_NONE) { + return true; + } + + return Audio_streams[i].Is_Past_Limit(); } int audiostream_is_inited() @@ -1639,14 +1654,22 @@ int audiostream_is_inited() void audiostream_pause(int i) { - if ( i == -1 ) + if ( !Audiostream_inited ) { return; + } + + SDL_assert( i >= 0 ); + SDL_assert( i < (int)Audio_streams.size() ); + + if (i < 0) { + return; + } - Assert( i >= 0 && i < MAX_AUDIO_STREAMS ); - if ( Audio_streams[i].status == ASF_FREE ) + if (Audio_streams[i].type == ASF_NONE) { return; + } - if ( audiostream_is_playing(i) == TRUE ) { + if ( audiostream_is_playing(i) ) { audiostream_stop(i, 0, 1); } } @@ -1655,9 +1678,16 @@ void audiostream_pause_all() { int i; - for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) { - if ( Audio_streams[i].status == ASF_FREE ) + if ( !Audiostream_inited ) { + return; + } + + int size = (int)Audio_streams.size(); + + for (i = 0; i < size; i++) { + if (Audio_streams[i].type == ASF_NONE) { continue; + } audiostream_pause(i); } @@ -1667,14 +1697,22 @@ void audiostream_unpause(int i) { int is_looping; - if ( i == -1 ) + if ( !Audiostream_inited ) { + return; + } + + SDL_assert( i >= 0 ); + SDL_assert( i < (int)Audio_streams.size() ); + + if (i < 0) { return; + } - Assert( i >= 0 && i < MAX_AUDIO_STREAMS ); - if ( Audio_streams[i].status == ASF_FREE ) + if (Audio_streams[i].type == ASF_NONE) { return; + } - if ( audiostream_is_paused(i) == TRUE ) { + if ( audiostream_is_paused(i) ) { is_looping = Audio_streams[i].Is_looping(); audiostream_play(i, -1.0f, is_looping); } @@ -1684,24 +1722,17 @@ void audiostream_unpause_all() { int i; - for ( i = 0; i < MAX_AUDIO_STREAMS; i++ ) { - if ( Audio_streams[i].status == ASF_FREE ) - continue; - - audiostream_unpause(i); + if ( !Audiostream_inited ) { + return; } -} -void audiostream_set_sample_cutoff(int i, uint cutoff) -{ -// STUB_FUNCTION; -} + int size = (int)Audio_streams.size(); -uint audiostream_get_samples_committed(int i) -{ -// STUB_FUNCTION; + for (i = 0; i < size; i++) { + if (Audio_streams[i].type == ASF_NONE) { + continue; + } - return 0; + audiostream_unpause(i); + } } - -#endif // PLAT_UNIX diff --git a/src/sound/ds.cpp b/src/sound/ds.cpp deleted file mode 100644 index ba81ff6..0000000 --- a/src/sound/ds.cpp +++ /dev/null @@ -1,3993 +0,0 @@ -/* - * Copyright (C) Volition, Inc. 1999. All rights reserved. - * - * All source code herein is the property of Volition, Inc. You may not sell - * or otherwise commercially exploit the source or things you created based on - * the source. - */ - -/* - * $Logfile: /Freespace2/code/Sound/ds.cpp $ - * $Revision$ - * $Date$ - * $Author$ - * - * C file for interface to DirectSound - * - * $Log$ - * Revision 1.27 2005/11/18 09:36:13 taylor - * gah, should have been paying more attention there - * - * Revision 1.26 2005/11/14 05:22:08 taylor - * patch from mailing list (courtesy of fatty) to allow compling with both OpenAL 1.0 and 1.1 - * - * Revision 1.25 2005/10/01 21:53:06 taylor - * include file cleanup - * byte-swap streaming PCM to avoid the endless, loud, static - * - * Revision 1.24 2005/08/13 17:01:34 taylor - * gah, fix stupid commit message - * - * Revision 1.23 2005/08/12 20:21:06 taylor - * woorps! - * - * Revision 1.22 2005/08/12 08:47:24 taylor - * use new audiostr code rather than old windows and *nix version - * update all OpenAL commands with new error checking macros - * fix play_position to properly account for real position, fixes the talking heads and message text cutting out early - * movies will now use better filtering when scaled - * - * Revision 1.21 2005/04/02 18:57:01 taylor - * little better error handling, debug output of OpenAL info - * - * Revision 1.20 2005/03/29 07:50:34 taylor - * Update to newest movie code with much better video support and audio support from - * Pierre Willenbrock. Movies are enabled always now (no longer a build option) - * and but can be skipped with the "--nomovies" or "-n" cmdline options. - * - * Revision 1.19 2004/07/04 11:39:06 taylor - * fix missing debrief text, crash on exit, path separator's, warning fixes, no GR_SOFT - * - * Revision 1.18 2004/06/11 02:07:01 tigital - * byte-swapping changes for bigendian systems - * - * Revision 1.17 2003/12/02 03:24:47 taylor - * MS-ADPCM support, fix file parser with OSX support - * - * Revision 1.16 2003/08/03 16:03:53 taylor - * working play position; 2D pan; pitch; cleanup - * - * Revision 1.15 2003/03/15 05:12:56 theoddone33 - * Fix OpenAL cleanup (Taylor) - * - * Revision 1.14 2002/08/01 04:55:45 relnev - * experimenting with texture state - * - * Revision 1.13 2002/07/30 05:24:38 relnev - * command line - * - * Revision 1.12 2002/07/28 05:19:44 relnev - * more housecleaning - * - * Revision 1.11 2002/06/16 01:43:23 relnev - * fixed demo dogfight multiplayer mission - * - * minor sound changes - * - * Revision 1.10 2002/06/09 04:41:26 relnev - * added copyright header - * - * Revision 1.9 2002/06/05 08:05:29 relnev - * stub/warning removal. - * - * reworked the sound code. - * - * Revision 1.8 2002/06/05 04:03:33 relnev - * finished cfilesystem. - * - * removed some old code. - * - * fixed mouse save off-by-one. - * - * sound cleanups. - * - * Revision 1.7 2002/06/02 22:31:37 cemason - * Changes - * - * Revision 1.6 2002/06/02 21:11:12 cemason - * Few changes - * - * Revision 1.5 2002/06/02 09:50:42 relnev - * check open status - * - * Revision 1.4 2002/06/02 07:17:44 cemason - * Added OpenAL support. - * - * Revision 1.3 2002/05/28 17:03:29 theoddone33 - * fs2 gets to the main game loop now - * - * Revision 1.2 2002/05/27 21:35:50 theoddone33 - * Stub out dsound backend - * - * Revision 1.1.1.1 2002/05/03 03:28:10 root - * Initial import. - * - * - * 18 10/25/99 5:56p Jefff - * increase num software channels to the number the users hardware can - * handle. not less than 16, tho. - * - * 17 9/08/99 3:22p Dave - * Updated builtin mission list. - * - * 16 8/27/99 6:38p Alanl - * crush the blasted repeating messages bug - * - * 15 8/23/99 11:16p Danw - * Allow stereo waves - * - * 14 8/22/99 11:06p Alanl - * fix small bug in ds_close_channel - * - * 13 8/19/99 11:25a Alanl - * change format of secondary buffer from 44100 to 22050 - * - * 12 8/17/99 4:11p Danw - * AL: temp fix for solving A3D crash - * - * 11 8/06/99 2:20p Jasonh - * AL: free 3D portion of buffer first - * - * 10 8/04/99 9:48p Alanl - * fix bug with setting 3D properties on a 2D sound buffer - * - * 9 8/04/99 11:42a Danw - * tone down EAX reverb - * - * 8 8/01/99 2:06p Alanl - * increase the rolloff for A3D - * - * 7 7/20/99 5:28p Dave - * Fixed debug build error. - * - * 6 7/20/99 1:49p Dave - * Peter Drake build. Fixed some release build warnings. - * - * 5 7/14/99 11:32a Danw - * AL: add some debug code to catch nefarious A3D problem - * - * 4 5/23/99 8:11p Alanl - * Added support for EAX - * - * 3 10/08/98 4:29p Dave - * Removed reference to osdefs.h - * - * 2 10/07/98 10:54a Dave - * Initial checkin. - * - * 1 10/07/98 10:51a Dave - * - * 72 6/28/98 6:34p Lawrance - * add sanity check in while() loop for releasing channels - * - * 71 6/13/98 1:45p Sandeep - * - * 70 6/10/98 2:29p Lawrance - * don't use COM for initializing DirectSound... appears some machines - * don't like it - * - * 69 5/26/98 2:10a Lawrance - * make sure DirectSound pointer gets freed if Aureal resource manager - * fails - * - * 68 5/21/98 9:14p Lawrance - * remove obsolete registry setting - * - * 67 5/20/98 4:28p Allender - * upped sound buffers as per alan's request - * - * 66 5/15/98 3:36p John - * Fixed bug with new graphics window code and standalone server. Made - * hwndApp not be a global anymore. - * - * 65 5/06/98 3:37p Lawrance - * allow panned sounds geesh - * - * 64 5/05/98 4:49p Lawrance - * Put in code to authenticate A3D, improve A3D support - * - * 63 4/20/98 11:17p Lawrance - * fix bug with releasing channels - * - * 62 4/20/98 7:34p Lawrance - * take out obsolete directsound3d debug command - * - * 61 4/20/98 11:10a Lawrance - * put correct flags when creating sound buffer - * - * 60 4/20/98 12:03a Lawrance - * Allow prioritizing of CTRL3D buffers - * - * 59 4/19/98 9:31p Lawrance - * Use Aureal_enabled flag - * - * 58 4/19/98 9:39a Lawrance - * use DYNAMIC_LOOPERS for Aureal resource manager - * - * 57 4/19/98 4:13a Lawrance - * Improve how dsound is initialized - * - * 56 4/18/98 9:13p Lawrance - * Added Aureal support. - * - * 55 4/13/98 5:04p Lawrance - * Write functions to determine how many milliseconds are left in a sound - * - * 54 4/09/98 5:53p Lawrance - * Make DirectSound init more robust - * - * 53 4/01/98 9:21p John - * Made NDEBUG, optimized build with no warnings or errors. - * - * 52 3/31/98 5:19p John - * Removed demo/save/restore. Made NDEBUG defined compile. Removed a - * bunch of debug stuff out of player file. Made model code be able to - * unload models and malloc out only however many models are needed. - * - * - * 51 3/29/98 12:56a Lawrance - * preload the warp in and explosions sounds before a mission. - * - * 50 3/25/98 6:10p Lawrance - * Work on DirectSound3D - * - * 49 3/24/98 4:28p Lawrance - * Make DirectSound3D support more robust - * - * 48 3/24/98 11:49a Dave - * AL: Change way buffer gets locked. - * - * 47 3/24/98 11:27a Lawrance - * Use buffer_size for memcpy when locking buffer - * - * 46 3/23/98 10:32a Lawrance - * Add functions for extracting raw sound data - * - * 45 3/19/98 5:36p Lawrance - * Add some sound debug functions to see how many sounds are playing, and - * to start/stop random looping sounds. - * - * 44 3/07/98 3:35p Dave - * AL: check for ds being initialized in ds_create_buffer() - * - * 43 2/18/98 5:49p Lawrance - * Even if the ADPCM codec is unavailable, allow game to continue. - * - * 42 2/16/98 7:31p Lawrance - * get compression/decompression of voice working - * - * 41 2/15/98 11:10p Lawrance - * more work on real-time voice system - * - * 40 2/15/98 4:43p Lawrance - * work on real-time voice - * - * 39 2/06/98 7:30p John - * Added code to monitor the number of channels of sound actually playing. - * - * 38 2/06/98 8:56a Allender - * fixed calling convention problem with DLL handles - * - * 37 2/04/98 6:08p Lawrance - * Read function pointers from dsound.dll, further work on - * DirectSoundCapture. - * - * 36 2/03/98 11:53p Lawrance - * Adding support for DirectSoundCapture - * - * 35 1/31/98 5:48p Lawrance - * Start on real-time voice recording - * - * 34 1/10/98 1:14p John - * Added explanation to debug console commands - * - * 33 12/21/97 4:33p John - * Made debug console functions a class that registers itself - * automatically, so you don't need to add the function to - * debugfunctions.cpp. - * - * 32 12/08/97 12:24a Lawrance - * Allow duplicate sounds to be stopped if less than OR equal to new sound - * volume. - * - * 31 12/05/97 5:19p Lawrance - * re-do sound priorities to make more general and extensible - * - * 30 11/28/97 2:09p Lawrance - * Overhaul how ADPCM conversion works... use much less memory... safer - * too. - * - * 29 11/22/97 11:32p Lawrance - * decompress ADPCM data into 8 bit (not 16bit) for regular sounds (ie not - * music) - * - * 28 11/20/97 5:36p Dave - * Hooked in a bunch of main hall changes (including sound). Made it - * possible to reposition (rewind/ffwd) - * sound buffer pointers. Fixed animation direction change framerate - * problem. - * - * 27 10/13/97 7:41p Lawrance - * store duration of sound - * - * 26 10/11/97 6:39p Lawrance - * start playing primary buffer, to reduce latency on sounds starting - * - * 25 10/08/97 5:09p Lawrance - * limit player impact sounds so only one plays at a time - * - * 24 9/26/97 5:43p Lawrance - * fix a bug that was freeing memory early when playing compressed sound - * data - * - * 23 9/09/97 3:39p Sandeep - * warning level 4 bugs - * - * 22 8/16/97 4:05p Lawrance - * don't load sounds into hardware if running Lean_and_mean - * - * 21 8/05/97 1:39p Lawrance - * support compressed stereo playback - * - * 20 7/31/97 10:38a Lawrance - * return old debug function for toggling DirectSound3D - * - * 19 7/29/97 3:27p Lawrance - * make console toggle for directsound3d work right - * - * 18 7/28/97 11:39a Lawrance - * allow individual volume scaling on 3D buffers - * - * 17 7/18/97 8:18p Lawrance - * fix bug in ds_get_free_channel() that caused sounds to not play when - * they should have - * - * 16 7/17/97 8:04p Lawrance - * allow priority sounds to play if free channel, otherwise stop lowest - * volume priority sound of same type - * - * 15 7/17/97 5:57p John - * made directsound3d config value work - * - * 14 7/17/97 5:43p John - * added new config stuff - * - * 13 7/17/97 4:25p John - * First, broken, stage of changing config stuff - * - * 12 7/15/97 12:13p Lawrance - * don't stop sounds that have highest priority - * - * 11 7/15/97 11:15a Lawrance - * limit the max instances of simultaneous sound effects, implement - * priorities to force critical sounds - * - * 10 6/09/97 11:50p Lawrance - * integrating DirectSound3D - * - * 9 6/08/97 5:59p Lawrance - * integrate DirectSound3D into sound system - * - * 8 6/04/97 1:19p Lawrance - * made hardware mixing robust - * - * 7 6/03/97 1:56p Hoffoss - * Return correct error code when direct sound init fails. - * - * 6 6/03/97 12:07p Lawrance - * don't enable 3D sounds in Primary buffer - * - * 5 6/02/97 3:45p Dan - * temp disable of hardware mixing until problem solved with - * CreateBuffer() failing - * - * 4 6/02/97 1:45p Lawrance - * implementing hardware mixing - * - * 3 5/29/97 4:01p Lawrance - * let snd_init() have final say on initialization - * - * 2 5/29/97 12:04p Lawrance - * creation of file to hold DirectSound specific portions - * - * $NoKeywords: $ - */ - -#include "pstypes.h" -#ifndef PLAT_UNIX -#include -#include "channel.h" -#endif -#include "cfile.h" -#include "ds.h" -#include "ds3d.h" -#include "acm.h" -#include "osapi.h" -#include "dscap.h" - -#ifndef PLAT_UNIX -#include -#include -#endif - -#ifndef PLAT_UNIX -// Pointers to functions contained in DSOUND.dll -HRESULT (__stdcall *pfn_DirectSoundCreate)(LPGUID lpGuid, LPDIRECTSOUND *ppDS, IUnknown FAR *pUnkOuter) = NULL; -HRESULT (__stdcall *pfn_DirectSoundCaptureCreate)(LPGUID lpGUID, LPDIRECTSOUNDCAPTURE *lplpDSC, LPUNKNOWN pUnkOuter) = NULL; -int Ds_dll_loaded=0; -HINSTANCE Ds_dll_handle=NULL; - -LPDIRECTSOUND pDirectSound = NULL; -LPDIRECTSOUNDBUFFER pPrimaryBuffer = NULL; -LPIA3D2 pIA3d2 = NULL; - -static LPKSPROPERTYSET pPropertySet; // pointer to sound card property set -static LPDIRECTSOUNDBUFFER Ds_property_set_pdsb = NULL; -static LPDIRECTSOUND3DBUFFER Ds_property_set_pds3db = NULL; - -static int Ds_must_call_couninitialize = 0; - -channel* Channels; //[MAX_CHANNELS]; -static int channel_next_sig = 1; - -#define MAX_DS_SOFTWARE_BUFFERS 256 -typedef struct ds_sound_buffer -{ - LPDIRECTSOUNDBUFFER pdsb; - DSBUFFERDESC desc; - WAVEFORMATEX wfx; - -} ds_sound_buffer; - -ds_sound_buffer ds_software_buffers[MAX_DS_SOFTWARE_BUFFERS]; - -#define MAX_DS_HARDWARE_BUFFERS 32 -ds_sound_buffer ds_hardware_buffers[MAX_DS_HARDWARE_BUFFERS]; - -static DSCAPS Soundcard_caps; // current soundcard capabilities - -extern int Snd_sram; // mem (in bytes) used up by storing sounds in system memory -extern int Snd_hram; // mem (in bytes) used up by storing sounds in soundcard memory - -static int Ds_use_ds3d = 0; -static int Ds_use_a3d = 0; -static int Ds_use_eax = 0; - -GUID IID_IA3d2_Def = {0xfb80d1e0, 0x98d3, 0x11d1, {0x90, 0xfb, 0x00, 0x60, 0x08, 0xa1, 0xf4, 0x41}}; -GUID CLSID_A3d_Def = {0xd8f1eee0, 0xf634, 0x11cf, {0x87, 0x0, 0x0, 0xa0, 0x24, 0x5d, 0x91, 0x8b}}; - -static bool Stop_logging_sounds = false; - - -/////////////////////////// -// -// EAX -// -/////////////////////////// - -// presets -//#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC,0.5F,1.493F,0.5F -#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC,0.2F,0.2F,1.0F -#define EAX_PRESET_PADDEDCELL EAX_ENVIRONMENT_PADDEDCELL,0.25F,0.1F,0.0F -#define EAX_PRESET_ROOM EAX_ENVIRONMENT_ROOM,0.417F,0.4F,0.666F -#define EAX_PRESET_BATHROOM EAX_ENVIRONMENT_BATHROOM,0.653F,1.499F,0.166F -#define EAX_PRESET_LIVINGROOM EAX_ENVIRONMENT_LIVINGROOM,0.208F,0.478F,0.0F -#define EAX_PRESET_STONEROOM EAX_ENVIRONMENT_STONEROOM,0.5F,2.309F,0.888F -#define EAX_PRESET_AUDITORIUM EAX_ENVIRONMENT_AUDITORIUM,0.403F,4.279F,0.5F -#define EAX_PRESET_CONCERTHALL EAX_ENVIRONMENT_CONCERTHALL,0.5F,3.961F,0.5F -#define EAX_PRESET_CAVE EAX_ENVIRONMENT_CAVE,0.5F,2.886F,1.304F -#define EAX_PRESET_ARENA EAX_ENVIRONMENT_ARENA,0.361F,7.284F,0.332F -#define EAX_PRESET_HANGAR EAX_ENVIRONMENT_HANGAR,0.5F,10.0F,0.3F -#define EAX_PRESET_CARPETEDHALLWAY EAX_ENVIRONMENT_CARPETEDHALLWAY,0.153F,0.259F,2.0F -#define EAX_PRESET_HALLWAY EAX_ENVIRONMENT_HALLWAY,0.361F,1.493F,0.0F -#define EAX_PRESET_STONECORRIDOR EAX_ENVIRONMENT_STONECORRIDOR,0.444F,2.697F,0.638F -#define EAX_PRESET_ALLEY EAX_ENVIRONMENT_ALLEY,0.25F,1.752F,0.776F -#define EAX_PRESET_FOREST EAX_ENVIRONMENT_FOREST,0.111F,3.145F,0.472F -#define EAX_PRESET_CITY EAX_ENVIRONMENT_CITY,0.111F,2.767F,0.224F -#define EAX_PRESET_MOUNTAINS EAX_ENVIRONMENT_MOUNTAINS,0.194F,7.841F,0.472F -#define EAX_PRESET_QUARRY EAX_ENVIRONMENT_QUARRY,1.0F,1.499F,0.5F -#define EAX_PRESET_PLAIN EAX_ENVIRONMENT_PLAIN,0.097F,2.767F,0.224F -#define EAX_PRESET_PARKINGLOT EAX_ENVIRONMENT_PARKINGLOT,0.208F,1.652F,1.5F -#define EAX_PRESET_SEWERPIPE EAX_ENVIRONMENT_SEWERPIPE,0.652F,2.886F,0.25F -#define EAX_PRESET_UNDERWATER EAX_ENVIRONMENT_UNDERWATER,1.0F,1.499F,0.0F -#define EAX_PRESET_DRUGGED EAX_ENVIRONMENT_DRUGGED,0.875F,8.392F,1.388F -#define EAX_PRESET_DIZZY EAX_ENVIRONMENT_DIZZY,0.139F,17.234F,0.666F -#define EAX_PRESET_PSYCHOTIC EAX_ENVIRONMENT_PSYCHOTIC,0.486F,7.563F,0.806F - -static LPKSPROPERTYSET Ds_eax_reverb = NULL; - -static int Ds_eax_inited = 0; - -EAX_REVERBPROPERTIES Ds_eax_presets[] = -{ - {EAX_PRESET_GENERIC}, - {EAX_PRESET_PADDEDCELL}, - {EAX_PRESET_ROOM}, - {EAX_PRESET_BATHROOM}, - {EAX_PRESET_LIVINGROOM}, - {EAX_PRESET_STONEROOM}, - {EAX_PRESET_AUDITORIUM}, - {EAX_PRESET_CONCERTHALL}, - {EAX_PRESET_CAVE}, - {EAX_PRESET_ARENA}, - {EAX_PRESET_HANGAR}, - {EAX_PRESET_CARPETEDHALLWAY}, - {EAX_PRESET_HALLWAY}, - {EAX_PRESET_STONECORRIDOR}, - {EAX_PRESET_ALLEY}, - {EAX_PRESET_FOREST}, - {EAX_PRESET_CITY}, - {EAX_PRESET_MOUNTAINS}, - {EAX_PRESET_QUARRY}, - {EAX_PRESET_PLAIN}, - {EAX_PRESET_PARKINGLOT}, - {EAX_PRESET_SEWERPIPE}, - {EAX_PRESET_UNDERWATER}, - {EAX_PRESET_DRUGGED}, - {EAX_PRESET_DIZZY}, - {EAX_PRESET_PSYCHOTIC}, -}; - -GUID DSPROPSETID_EAX_ReverbProperties_Def = {0x4a4e6fc1, 0xc341, 0x11d1, {0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}; -GUID DSPROPSETID_EAXBUFFER_ReverbProperties_Def = {0x4a4e6fc0, 0xc341, 0x11d1, {0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}; - -//---------------------------------------------------------------- -// prototypes -void ds_get_soundcard_caps(DSCAPS *dscaps); -#else // !PLAT_UNIX - -typedef struct channel -{ - int sig; // uniquely identifies the sound playing on the channel - int snd_id; // identifies which kind of sound is playing - ALuint source_id; // OpenAL source id - int buf_id; // currently bound buffer index (-1 if none) - int looping; // flag to indicate that the sound is looping - int vol; - int priority; // implementation dependant priority - bool is_voice_msg; - DWORD last_position; -} channel; - -typedef struct sound_buffer -{ - ALuint buf_id; // OpenAL buffer id - int source_id; // source index this buffer is currently bound to - - int frequency; - int bits_per_sample; - int nchannels; - int nseconds; - int nbytes; -} sound_buffer; - -#define MAX_DS_SOFTWARE_BUFFERS 256 - -static int MAX_CHANNELS = 1000; // initialized properly in ds_init_channels() -channel *Channels; -static int channel_next_sig = 1; - -sound_buffer sound_buffers[MAX_DS_SOFTWARE_BUFFERS]; - -extern int Snd_sram; // mem (in bytes) used up by storing sounds in system memory - -static int Ds_use_ds3d = 0; -static int Ds_use_a3d = 0; -static int Ds_use_eax = 0; - -static int AL_play_position = 0; - -#ifndef AL_BYTE_LOKI -// in case it's not defined by older/other drivers -#define AL_BYTE_LOKI 0x100C -#endif - -ALCdevice *ds_sound_device = NULL; -ALCcontext *ds_sound_context = NULL; - - -//-------------------------------------------------------------------------- -// openal_error_string() -// -// Returns the human readable error string if there is an error or NULL if not -// -const char* openal_error_string() -{ - int i; - - i = alGetError(); - - if ( i != AL_NO_ERROR ) - return (const char*)alGetString(i); - - return NULL; -} - -#endif // PLAT_UNIX - -int ds_vol_lookup[101]; // lookup table for direct sound volumes -int ds_initialized = FALSE; - - -//-------------------------------------------------------------------------- -// ds_is_3d_buffer() -// -// Determine if a secondary buffer is a 3d secondary buffer. -// -#ifndef PLAT_UNIX -int ds_is_3d_buffer(LPDIRECTSOUNDBUFFER pdsb) -{ - DSBCAPS dsbc; - HRESULT hr; - - dsbc.dwSize = sizeof(dsbc); - hr = pdsb->GetCaps(&dsbc); - if ( hr == DS_OK && dsbc.dwFlags & DSBCAPS_CTRL3D ) { - return TRUE; - } - else { - return FALSE; - } -} -#endif - -//-------------------------------------------------------------------------- -// ds_is_3d_buffer() -// -// Determine if a secondary buffer is a 3d secondary buffer. -// -int ds_is_3d_buffer(int sid) -{ -#ifndef PLAT_UNIX - if ( sid >= 0 ) { - return ds_is_3d_buffer(ds_software_buffers[sid].pdsb); - } -#else - // they are all 3d - if ( sid >= 0 ) { - return 1; - } - - return 0; -#endif -} - -//-------------------------------------------------------------------------- -// ds_build_vol_lookup() -// -// Fills up the ds_vol_lookup[] tables that converts from a volume in the form -// 0.0 -> 1.0 to -10000 -> 0 (this is the DirectSound method, where units are -// hundredths of decibls) -// -void ds_build_vol_lookup() -{ - int i; - float vol; - - ds_vol_lookup[0] = -10000; - for ( i = 1; i <= 100; i++ ) { - vol = i / 100.0f; - ds_vol_lookup[i] = fl2i( (log(vol) / log(2.0f)) * 1000.0f); - } -} - - -//-------------------------------------------------------------------------- -// ds_convert_volume() -// -// Takes volume between 0.0f and 1.0f and converts into -// DirectSound style volumes between -10000 and 0. -int ds_convert_volume(float volume) -{ - int index; - - index = fl2i(volume * 100.0f); - if ( index > 100 ) - index = 100; - if ( index < 0 ) - index = 0; - - return ds_vol_lookup[index]; -} - -//-------------------------------------------------------------------------- -// ds_get_percentage_vol() -// -// Converts -10000 -> 0 range volume to 0 -> 1 -float ds_get_percentage_vol(int ds_vol) -{ - double vol; - vol = pow(2.0, ds_vol/1000.0); - return (float)vol; -} - -// --------------------------------------------------------------------------------------- -// ds_parse_wave() -// -// Parse a wave file. -// -// parameters: filename => file of sound to parse -// dest => address of pointer of where to store raw sound data (output parm) -// dest_size => number of bytes of sound data stored (output parm) -// header => address of pointer to a WAVEFORMATEX struct (output parm) -// -// returns: 0 => wave file successfully parsed -// -1 => error -// -// NOTE: memory is malloced for the header and dest in this function. It is the responsibility -// of the caller to free this memory later. -// -int ds_parse_wave(char *filename, ubyte **dest, uint *dest_size, WAVEFORMATEX **header) -{ - CFILE *fp; - PCMWAVEFORMAT PCM_header; - ushort cbExtra = 0; - unsigned int tag, size, next_chunk; - - fp = cfopen( filename, "rb" ); - if ( fp == NULL ) { - nprintf(("Error", "Couldn't open '%s'\n", filename )); - return -1; - } - - // Skip the "RIFF" tag and file size (8 bytes) - // Skip the "WAVE" tag (4 bytes) - cfseek( fp, 12, CF_SEEK_SET ); - - // Now read RIFF tags until the end of file - - while(1) { - if ( cfread( &tag, sizeof(uint), 1, fp ) != 1 ) - break; - tag = INTEL_INT( tag ); - - if ( cfread( &size, sizeof(uint), 1, fp ) != 1 ) - break; - size = INTEL_INT( size ); - - next_chunk = cftell(fp) + size; - - switch( tag ) { - case 0x20746d66: // The 'fmt ' tag - //nprintf(("Sound", "SOUND => size of fmt block: %d\n", size)); - PCM_header.wf.wFormatTag = cfread_ushort(fp); - PCM_header.wf.nChannels = cfread_ushort(fp); - PCM_header.wf.nSamplesPerSec = cfread_uint(fp); - PCM_header.wf.nAvgBytesPerSec = cfread_uint(fp); - PCM_header.wf.nBlockAlign = cfread_ushort(fp); - PCM_header.wBitsPerSample = cfread_ushort(fp); - - if ( PCM_header.wf.wFormatTag != WAVE_FORMAT_PCM ) { - cbExtra = cfread_ushort(fp); - } - - // Allocate memory for WAVEFORMATEX structure + extra bytes - if ( (*header = (WAVEFORMATEX *) malloc ( sizeof(WAVEFORMATEX)+cbExtra )) != NULL ){ - // Copy bytes from temporary format structure - memcpy (*header, &PCM_header, sizeof(PCM_header)); - (*header)->cbSize = cbExtra; - - // Read those extra bytes, append to WAVEFORMATEX structure - if (cbExtra != 0) { - cfread( ((ubyte *)(*header) + sizeof(WAVEFORMATEX)), cbExtra, 1, fp); - } - } - else { - Assert(0); // malloc failed - } - - break; - case 0x61746164: // the 'data' tag - *dest_size = size; - (*dest) = (ubyte *)malloc(size); - Assert( *dest != NULL ); - cfread( *dest, size, 1, fp ); - break; - default: // unknown, skip it - break; - } - cfseek( fp, next_chunk, CF_SEEK_SET ); - } - cfclose(fp); - - return 0; -} - -// --------------------------------------------------------------------------------------- -// ds_get_sid() -// -// -int ds_get_sid() -{ -#ifdef PLAT_UNIX - int i; - - for ( i = 0; i < MAX_DS_SOFTWARE_BUFFERS; i++ ) { - if ( sound_buffers[i].buf_id == 0 ) - break; - } - - if ( i == MAX_DS_SOFTWARE_BUFFERS ) { - return -1; - } - - return i; -#else - int i; - - for ( i = 0; i < MAX_DS_SOFTWARE_BUFFERS; i++ ) { - if ( ds_software_buffers[i].pdsb == NULL ) - break; - } - - if ( i == MAX_DS_SOFTWARE_BUFFERS ) { - return -1; - } - - return i; -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_get_hid() -// -// not used -int ds_get_hid() -{ -#ifdef PLAT_UNIX - return -1; -#else - int i; - - for ( i = 0; i < MAX_DS_HARDWARE_BUFFERS; i++ ) { - if ( ds_hardware_buffers[i].pdsb == NULL ) - break; - } - - if ( i == MAX_DS_HARDWARE_BUFFERS ) { - return -1; - } - - return i; -#endif -} - -// --------------------------------------------------------------------------------------- -// Load a DirectSound secondary buffer with sound data. The sounds data for -// game sounds are stored in the DirectSound secondary buffers, and are -// duplicated as needed and placed in the Channels[] array to be played. -// -// -// parameters: -// sid => pointer to software id for sound ( output parm) -// hid => pointer to hardware id for sound ( output parm) -// final_size => pointer to storage to receive uncompressed sound size (output parm) -// header => pointer to a WAVEFORMATEX structure -// si => sound_info structure, contains details on the sound format -// flags => buffer properties ( DS_HARDWARE , DS_3D ) -// -// returns: -1 => sound effect could not loaded into a secondary buffer -// 0 => sound effect successfully loaded into a secondary buffer -// -// -// NOTE: this function is slow, especially when sounds are loaded into hardware. Don't call this -// function from within gameplay. -// - -int ds_load_buffer(int *sid, int *hid, int *final_size, void *header, sound_info *si, int flags) -{ -#ifdef PLAT_UNIX - Assert( final_size != NULL ); - Assert( header != NULL ); - Assert( si != NULL ); - - // All sounds are required to have a software buffer - - *sid = ds_get_sid(); - if ( *sid == -1 ) { - nprintf(("Sound","SOUND ==> No more sound buffers available\n")); - return -1; - } - - ALuint pi; - OpenAL_ErrorCheck( alGenBuffers (1, &pi), return -1 ); - - ALenum format; - ALsizei size; - ALint bits, bps; - ALuint frequency; - ALvoid *data = NULL; - - // the below two covnert_ variables are only used when the wav format is not - // PCM. DirectSound only takes PCM sound data, so we must convert to PCM if required - ubyte *convert_buffer = NULL; // storage for converted wav file - int convert_len; // num bytes of converted wav file - uint src_bytes_used; // number of source bytes actually converted (should always be equal to original size) - int rc; - WAVEFORMATEX *pwfx = (WAVEFORMATEX *)header; - - - switch (si->format) { - case WAVE_FORMAT_PCM: - Assert( si->data != NULL ); - bits = si->bits; - bps = si->avg_bytes_per_sec; - size = si->size; -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - // swap 16-bit sound data - if (bits == 16) { - ushort *swap_tmp; - - for (uint i=0; idata + i); - *swap_tmp = INTEL_SHORT(*swap_tmp); - } - } -#endif - data = si->data; - break; - - case WAVE_FORMAT_ADPCM: - Assert( si->data != NULL ); - // this ADPCM decoder decodes to 16-bit only so keep that in mind - nprintf(( "Sound", "SOUND ==> converting sound from ADPCM to PCM\n" )); - rc = ACM_convert_ADPCM_to_PCM(pwfx, si->data, si->size, &convert_buffer, 0, &convert_len, &src_bytes_used, 16); - - if ( rc == -1 ) { - return -1; - } - - if (src_bytes_used != si->size) { - return -1; // ACM conversion failed? - } - - bits = 16; - bps = (((si->n_channels * bits) / 8) * si->sample_rate); - size = convert_len; - data = convert_buffer; - - nprintf(( "Sound", "SOUND ==> Coverted sound from ADPCM to PCM successfully\n" )); - break; - - default: - STUB_FUNCTION; - return -1; - } - - /* format is now in pcm */ - frequency = si->sample_rate; - - if (bits == 16) { - if (si->n_channels == 2) { - format = AL_FORMAT_STEREO16; - } else if (si->n_channels == 1) { - format = AL_FORMAT_MONO16; - } else { - return -1; - } - } else if (bits == 8) { - if (si->n_channels == 2) { - format = AL_FORMAT_STEREO8; - } else if (si->n_channels == 1) { - format = AL_FORMAT_MONO8; - } else { - return -1; - } - } else { - return -1; - } - - Snd_sram += size; - *final_size = size; - - OpenAL_ErrorCheck( alBufferData (pi, format, data, size, frequency), return -1 ); - - sound_buffers[*sid].buf_id = pi; - sound_buffers[*sid].source_id = -1; - sound_buffers[*sid].frequency = frequency; - sound_buffers[*sid].bits_per_sample = bits; - sound_buffers[*sid].nchannels = si->n_channels; - sound_buffers[*sid].nseconds = size / bps; - sound_buffers[*sid].nbytes = size; - - if ( convert_buffer ) - free( convert_buffer ); - - return 0; - -#else // !PLAT_UNIX - Assert( final_size != NULL ); - Assert( header != NULL ); - Assert( si != NULL ); - Assert( si->data != NULL ); - Assert( si->size > 0 ); - Assert( si->sample_rate > 0); - Assert( si->bits > 0 ); - Assert( si->n_channels > 0 ); - Assert( si->n_block_align >= 0 ); - Assert( si->avg_bytes_per_sec > 0 ); - - WAVEFORMATEX *pwfx = (WAVEFORMATEX *)header; - DSBUFFERDESC BufferDesc; - WAVEFORMATEX WaveFormat; - HRESULT DSReturn; - int rc, final_sound_size, DSOUND_load_buffer_result = 0; - BYTE *pData, *pData2; - DWORD DataSize, DataSize2; - - // the below two covnert_ variables are only used when the wav format is not - // PCM. DirectSound only takes PCM sound data, so we must convert to PCM if required - ubyte *convert_buffer = NULL; // storage for converted wav file - int convert_len; // num bytes of converted wav file - uint src_bytes_used; // number of source bytes actually converted (should always be equal to original size) - - // Ensure DirectSound initialized - if (!ds_initialized) { - DSOUND_load_buffer_result = -1; - goto DSOUND_load_buffer_done; - } - - // Set up buffer information - WaveFormat.wFormatTag = (unsigned short)si->format; - WaveFormat.nChannels = (unsigned short)si->n_channels; - WaveFormat.nSamplesPerSec = si->sample_rate; - WaveFormat.wBitsPerSample = (unsigned short)si->bits; - WaveFormat.cbSize = 0; - WaveFormat.nBlockAlign = (unsigned short)si->n_block_align; - WaveFormat.nAvgBytesPerSec = si->avg_bytes_per_sec; - - final_sound_size = si->size; // assume this format will be used, may be over-ridded by convert_len - -// Assert(WaveFormat.nChannels == 1); - - switch ( si->format ) { - case WAVE_FORMAT_PCM: - break; - - case WAVE_FORMAT_ADPCM: - - nprintf(( "Sound", "SOUND ==> converting sound from ADPCM to PCM\n" )); - rc = ACM_convert_ADPCM_to_PCM(pwfx, si->data, si->size, &convert_buffer, 0, &convert_len, &src_bytes_used, 8); - if ( rc == -1 ) { - DSOUND_load_buffer_result = -1; - goto DSOUND_load_buffer_done; - } - - if (src_bytes_used != si->size) { - Int3(); // ACM conversion failed? - DSOUND_load_buffer_result = -1; - goto DSOUND_load_buffer_done; - } - - final_sound_size = convert_len; - - // Set up the WAVEFORMATEX structure to have the right PCM characteristics - WaveFormat.wFormatTag = WAVE_FORMAT_PCM; - WaveFormat.nChannels = (unsigned short)si->n_channels; - WaveFormat.nSamplesPerSec = si->sample_rate; - WaveFormat.wBitsPerSample = 8; - WaveFormat.cbSize = 0; - WaveFormat.nBlockAlign = (unsigned short)(( WaveFormat.nChannels * WaveFormat.wBitsPerSample ) / 8); - WaveFormat.nAvgBytesPerSec = WaveFormat.nBlockAlign * WaveFormat.nSamplesPerSec; - - nprintf(( "Sound", "SOUND ==> Coverted sound from ADPCM to PCM successfully\n" )); - break; - - default: - nprintf(( "Sound", "Unsupported sound encoding\n" )); - DSOUND_load_buffer_result = -1; - goto DSOUND_load_buffer_done; - break; - } - - WaveFormat.wFormatTag = WAVE_FORMAT_PCM; // DirectSound only used PCM wave files - - // Set up a DirectSound buffer - ZeroMemory(&BufferDesc, sizeof(BufferDesc)); - BufferDesc.dwSize = sizeof(BufferDesc); - BufferDesc.dwBufferBytes = final_sound_size; - BufferDesc.lpwfxFormat = &WaveFormat; - - // check if DirectSound3D is enabled and the sound is flagged for 3D - if ((ds_using_ds3d()) && (flags & DS_USE_DS3D)) { -// if (ds_using_ds3d()) { - BufferDesc.dwFlags = DSBCAPS_STATIC | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE; - } else { - BufferDesc.dwFlags = DSBCAPS_STATIC | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_LOCSOFTWARE; - } - - // Create a new software buffer using the settings for this wave - // All sounds are required to have a software buffer - *sid = ds_get_sid(); - if ( *sid == -1 ) { - nprintf(("Sound","SOUND ==> No more software secondary buffers available\n")); - return -1; - } - DSReturn = pDirectSound->CreateSoundBuffer(&BufferDesc, &ds_software_buffers[*sid].pdsb, NULL ); - - if ( DSReturn == DS_OK && ds_software_buffers[*sid].pdsb != NULL ) { - - ds_software_buffers[*sid].desc = BufferDesc; - ds_software_buffers[*sid].wfx = *BufferDesc.lpwfxFormat; - - // Lock the buffer and copy in the data - if ((ds_software_buffers[*sid].pdsb)->Lock(0, final_sound_size, (void**)(&pData), &DataSize, (void**)(&pData2), &DataSize2, 0) == DS_OK) { - - if ( convert_buffer ) - memcpy(pData, convert_buffer, final_sound_size); // use converted data (PCM format) - else - memcpy(pData, si->data, final_sound_size); - - (ds_software_buffers[*sid].pdsb)->Unlock(pData, DataSize, 0, 0); - } - DSOUND_load_buffer_result = 0; - - // update ram used for sound - Snd_sram += final_sound_size; - *final_size = final_sound_size; - } - else { - nprintf(("Sound","SOUND => fatal error in DSOUND_load_buffer\n")); - *sid = -1; - DSOUND_load_buffer_result = -1; - } - - DSOUND_load_buffer_done: - if ( convert_buffer ) - free( convert_buffer ); - return DSOUND_load_buffer_result; -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_init_channels() -// -// init the Channels[] array -// -void ds_init_channels() -{ -#ifdef PLAT_UNIX - int i; - - MAX_CHANNELS = 32; - - Channels = (channel*) malloc(sizeof(channel) * MAX_CHANNELS); - if (Channels == NULL) { - Error(LOCATION, "Unable to allocate %d bytes for %d audio channels.", sizeof(channel) * MAX_CHANNELS, MAX_CHANNELS); - } - - // init the channels - for ( i = 0; i < MAX_CHANNELS; i++ ) { - OpenAL_ErrorPrint( alGenSources(1, &Channels[i].source_id) ); - Channels[i].buf_id = -1; - Channels[i].vol = 0; - } -#else - int i; - - // detect how many channels we can support - DSCAPS caps; - ds_get_soundcard_caps(&caps); - -// caps.dwSize = sizeof(DSCAPS); -// pDirectSound->GetCaps(&caps); - - // minimum 16 channels - MAX_CHANNELS = caps.dwMaxHwMixingStaticBuffers; - int dbg_channels = MAX_CHANNELS; - if (MAX_CHANNELS < 16) { - MAX_CHANNELS = 16; - } - - // allocate the channels array - Channels = (channel*) malloc(sizeof(channel) * MAX_CHANNELS); - if (Channels == NULL) { - Error(LOCATION, "Unable to allocate %d bytes for %d audio channels.", sizeof(channel) * MAX_CHANNELS, MAX_CHANNELS); - } - - // init the channels - for ( i = 0; i < MAX_CHANNELS; i++ ) { - Channels[i].pdsb = NULL; - Channels[i].pds3db = NULL; - Channels[i].vol = 0; - } - - mprintf(("** MAX_CHANNELS set to %d. DS reported %d.\n", MAX_CHANNELS, dbg_channels)); -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_init_software_buffers() -// -// init the software buffers -// -void ds_init_software_buffers() -{ -#ifdef PLAT_UNIX - int i; - - for ( i = 0; i < MAX_DS_SOFTWARE_BUFFERS; i++ ) { - sound_buffers[i].buf_id = 0; - sound_buffers[i].source_id = -1; - } -#else - int i; - - for ( i = 0; i < MAX_DS_SOFTWARE_BUFFERS; i++ ) { - ds_software_buffers[i].pdsb = NULL; - } -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_init_hardware_buffers() -// -// init the hardware buffers -// -void ds_init_hardware_buffers() -{ -#ifdef PLAT_UNIX - // STUB_FUNCTION; // not needed with openal (CM) - return; -#else - int i; - - for ( i = 0; i < MAX_DS_HARDWARE_BUFFERS; i++ ) { - ds_hardware_buffers[i].pdsb = NULL; - } -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_init_buffers() -// -// init the both the software and hardware buffers -// -void ds_init_buffers() -{ - ds_init_software_buffers(); - ds_init_hardware_buffers(); -} - -// Get the current soundcard capabilities -#ifndef PLAT_UNIX -void ds_get_soundcard_caps(DSCAPS *dscaps) -{ - HRESULT hr; - int n_hbuffers, hram; - - dscaps->dwSize = sizeof(DSCAPS); - - hr = pDirectSound->GetCaps(dscaps); - if (hr != DS_OK ) { - nprintf(("Sound","SOUND ==> DirectSound GetCaps() failed with code %s\n.",get_DSERR_text(hr) )); - return; - } - - n_hbuffers = dscaps->dwMaxHwMixingStaticBuffers; - hram = dscaps->dwTotalHwMemBytes; - - if ( !(dscaps->dwFlags & DSCAPS_CERTIFIED) ) { - nprintf(("Sound","SOUND ==> Warning: audio driver is not Microsoft certified.\n")); - } -} - -// --------------------------------------------------------------------------------------- -// ds_show_caps() -// -// init the both the software and hardware buffers -// -void ds_show_caps(DSCAPS *dscaps) -{ - nprintf(("Sound", "SOUND => Soundcard Capabilities:\n")); - nprintf(("Sound", "================================\n")); - nprintf(("Sound", "Number of primary buffers: %d\n", dscaps->dwPrimaryBuffers )); - nprintf(("Sound", "Number of total hw mixing buffers: %d\n", dscaps->dwMaxHwMixingAllBuffers )); - nprintf(("Sound", "Number of total hw mixing static buffers: %d\n", dscaps->dwMaxHwMixingStaticBuffers )); - nprintf(("Sound", "Number of total hw mixing streaming buffers: %d\n", dscaps->dwMaxHwMixingStreamingBuffers )); - nprintf(("Sound", "Number of free hw mixing buffers: %d\n", dscaps->dwFreeHwMixingAllBuffers )); - nprintf(("Sound", "Number of free hw mixing static buffers: %d\n", dscaps->dwFreeHwMixingStaticBuffers )); - nprintf(("Sound", "Number of free hw mixing streaming buffers: %d\n", dscaps->dwFreeHwMixingStreamingBuffers )); - nprintf(("Sound", "Number of hw 3D buffers: %d\n", dscaps->dwMaxHw3DAllBuffers )); - nprintf(("Sound", "Number of hw 3D static buffers: %d\n", dscaps->dwMaxHw3DStaticBuffers )); - nprintf(("Sound", "Number of hw 3D streaming buffers: %d\n", dscaps->dwMaxHw3DStreamingBuffers )); - nprintf(("Sound", "Number of free hw 3D buffers: %d\n", dscaps->dwFreeHw3DAllBuffers )); - nprintf(("Sound", "Number of free hw static 3D buffers: %d\n", dscaps->dwFreeHw3DStaticBuffers )); - nprintf(("Sound", "Number of free hw streaming 3D buffers: %d\n", dscaps->dwFreeHw3DStreamingBuffers )); - nprintf(("Sound", "Number of total hw bytes: %d\n", dscaps->dwTotalHwMemBytes )); - nprintf(("Sound", "Number of free hw bytes: %d\n", dscaps->dwFreeHwMemBytes )); - nprintf(("Sound", "================================\n")); -} -#endif - -#ifndef PLAT_UNIX -// Fill in the waveformat struct with the primary buffer characteristics. -void ds_get_primary_format(WAVEFORMATEX *wfx) -{ - // Set 16 bit / 22KHz / mono - wfx->wFormatTag = WAVE_FORMAT_PCM; - wfx->nChannels = 2; - wfx->nSamplesPerSec = 22050; - wfx->wBitsPerSample = 16; - wfx->cbSize = 0; - wfx->nBlockAlign = (unsigned short)(wfx->nChannels * (wfx->wBitsPerSample / 8)); - wfx->nAvgBytesPerSec = wfx->nBlockAlign * wfx->nSamplesPerSec; - -} -//XSTR:OFF -// obtain the function pointers from the dsound.dll -void ds_dll_get_functions() -{ - pfn_DirectSoundCreate = (HRESULT(__stdcall *)(LPGUID lpGuid, LPDIRECTSOUND *ppDS, IUnknown FAR *pUnkOuter))GetProcAddress(Ds_dll_handle,"DirectSoundCreate"); - pfn_DirectSoundCaptureCreate = (HRESULT(__stdcall *)(LPGUID lpGuid, LPDIRECTSOUNDCAPTURE *lplpDSC, IUnknown FAR *pUnkOuter))GetProcAddress(Ds_dll_handle,"DirectSoundCaptureCreate"); -} -#endif - -// Load the dsound.dll, and get funtion pointers -// exit: 0 -> dll loaded successfully -// !0 -> dll could not be loaded -int ds_dll_load() -{ -#ifdef PLAT_UNIX - // unused -#else - if ( !Ds_dll_loaded ) { - Ds_dll_handle = LoadLibrary("dsound.dll"); - if ( !Ds_dll_handle ) { - return -1; - } - ds_dll_get_functions(); - Ds_dll_loaded=1; - } -#endif - return 0; -} - - -int ds_init_a3d() -{ -#ifdef PLAT_UNIX - //unused -#else - HINSTANCE a3d_handle; - HRESULT hr; - - a3d_handle = LoadLibrary("a3d.dll"); - if (!a3d_handle) { - return -1; - } else { - FreeLibrary(a3d_handle); - } - - CoInitialize(NULL); - Ds_must_call_couninitialize = 1; - - hr = CoCreateInstance(CLSID_A3d_Def, NULL, CLSCTX_INPROC_SERVER, IID_IDirectSound, (void**)&pDirectSound); - if (FAILED(hr)) { - return -1; - } - - Assert(pDirectSound != NULL); - hr = pDirectSound->QueryInterface(IID_IA3d2_Def, (void**)&pIA3d2); - if (FAILED(hr)) { - return -1; - } - - A3DCAPS_SOFTWARE swCaps; - - // Get Dll Software CAP to get DLL version number - ZeroMemory(&swCaps,sizeof(swCaps)); - - swCaps.dwSize = sizeof(swCaps); - pIA3d2->GetSoftwareCaps(&swCaps); - - // Compare version from a3d.dll to header version only return A3D_OK if dll version >= to header version - if (swCaps.dwVersion < A3D_CURRENT_VERSION) { - pDirectSound->Release(); - pDirectSound = NULL; - return -1; - } - - - // verify this is authentic A3D - int aureal_verified; - aureal_verified = VerifyAurealA3D(); - - if (aureal_verified == FALSE) { - // This is fake A3D!!! Ignore - pDirectSound->Release(); - pDirectSound = NULL; - return -1; - } - - // Register our version for backwards compatibility with newer A3d.dll - pIA3d2->RegisterVersion(A3D_CURRENT_VERSION); - - hr = pDirectSound->Initialize(NULL); - if (FAILED(hr)) { - pDirectSound->Release(); - pDirectSound = NULL; - return -1; - } - - pIA3d2->SetResourceManagerMode(A3D_RESOURCE_MODE_DYNAMIC_LOOPERS); -#endif - return 0; -} - - -// Initialize the property set interface. -// -// returns: 0 if successful, otherwise -1. If successful, the global pPropertySet will -// set to a non-NULL value. -// -int ds_init_property_set() -{ -#ifdef PLAT_UNIX - //unused -#else - HRESULT hr; - - // Create the secondary buffer required for EAX initialization - WAVEFORMATEX wf; - wf.wFormatTag = WAVE_FORMAT_PCM; - wf.nChannels = 1; - wf.nSamplesPerSec = 22050; - wf.wBitsPerSample = 16; - wf.cbSize = 0; - wf.nBlockAlign = (unsigned short)(wf.nChannels * (wf.wBitsPerSample / 8)); - wf.nAvgBytesPerSec = wf.nBlockAlign * wf.nSamplesPerSec; - - DSBUFFERDESC dsbd; - ZeroMemory(&dsbd, sizeof(dsbd)); - dsbd.dwSize = sizeof(dsbd); - dsbd.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STATIC | DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE; - dsbd.dwBufferBytes = 3 * wf.nAvgBytesPerSec; - dsbd.lpwfxFormat = &wf; - - // Create a new buffer using the settings for this wave - hr = pDirectSound->CreateSoundBuffer(&dsbd, &Ds_property_set_pdsb, NULL); - if (FAILED(hr)) { - pPropertySet = NULL; - return -1; - } - - // Get the 3D interface from the secondary buffer, which is used to query the EAX interface - hr = Ds_property_set_pdsb->QueryInterface(IID_IDirectSound3DBuffer, (void**)&Ds_property_set_pds3db); - if (FAILED(hr)) { - Ds_property_set_pds3db = NULL; - return -1; - } - - Assert(Ds_property_set_pds3db != NULL); - hr = Ds_property_set_pds3db->QueryInterface(IID_IKsPropertySet, (void**)&pPropertySet); - if ((FAILED(hr)) || (pPropertySet == NULL)) { - return -1; - } -#endif - - return 0; -} - -// --------------------------------------------------------------------------------------- -// ds_init() -// -// returns: -1 => init failed -// 0 => init success -int ds_init(int use_a3d, int use_eax) -{ -#ifdef PLAT_UNIX -// NOTE: A3D and EAX are unused in OpenAL - // changed from 22050 to 44100 so that movies don't sound like crap -#ifdef AL_VERSION_1_1 - const ALCchar *initStr = (ALCchar *)"\'( (sampling-rate 44100 ))"; -#else - ALCubyte *initStr = (ALCubyte *)"\'( (sampling-rate 44100 ))"; -#endif - int attr[] = { ALC_FREQUENCY, 44100, ALC_SYNC, AL_FALSE, 0 }; - - Ds_use_a3d = 0; - Ds_use_eax = 0; - Ds_use_ds3d = 0; - - nprintf(( "Sound", "SOUND ==> Initializing OpenAL...\n" )); - - // load OpenAL - ds_sound_device = alcOpenDevice( initStr ); - - if (ds_sound_device == NULL) { - nprintf(("Sound", "SOUND ==> Couldn't open OpenAL device\n")); - return -1; - } - - // Create Sound Device - ds_sound_context = alcCreateContext( ds_sound_device, attr ); - - if (ds_sound_context == NULL) { - nprintf(("Sound", "SOUND ==> Couldn't create OpenAL context\n")); - alcCloseDevice( ds_sound_device ); - return -1; - } - - alcMakeContextCurrent( ds_sound_context ); - - if (alcGetError( ds_sound_device ) != ALC_NO_ERROR) { - nprintf(("Sound", "SOUND ==> Couldn't initialize OpenAL\n")); - return -1; - } - -#ifndef NDEBUG - mprintf(( "\n" )); - mprintf(( "OpenAL INITED!\n" )); - mprintf(( "\n" )); - mprintf(( "Vendor : %s\n", alGetString( AL_VENDOR ) )); - mprintf(( "Renderer : %s\n", alGetString( AL_RENDERER ) )); - mprintf(( "Version : %s\n", alGetString( AL_VERSION ) )); - mprintf(( "Extensions : \n" )); - - // print out OpenAL extensions - static const char *OAL_extensions=(const char*)alGetString( AL_EXTENSIONS ); - - // we use the "+1" here to have an extra NULL char on the end (with the memset()) - // this is to fix memory errors when the last char in extlist is the same as the token - // we are looking for and ultra evil strtok() may still return non-NULL at EOS - char *extlist = (char*)malloc( strlen(OAL_extensions) + 1 ); - memset( extlist, 0, strlen(OAL_extensions) + 1); - - if (extlist != NULL) { - memcpy(extlist, OAL_extensions, strlen(OAL_extensions)); - - char *curext = strtok(extlist, " "); - - while (curext) { - mprintf(( " %s\n", curext )); - curext = strtok(NULL, " "); - } - - free(extlist); - extlist = NULL; - } - - mprintf(( "\n" )); -#endif - - // make sure we can actually use AL_BYTE_LOKI (Mac OpenAL doesn't have it) -#ifdef AL_VERSION_1_1 - AL_play_position = alIsExtensionPresent( (const ALchar*)"AL_LOKI_play_position" ); -#else - AL_play_position = alIsExtensionPresent( (ALubyte*)"AL_LOKI_play_position" ); -#endif - - // Initialize DirectSound3D. Since software performance of DirectSound3D is unacceptably - // slow, we require the voice manger (a DirectSound extension) to be present. The - // exception is when A3D is being used, since A3D has a resource manager built in. -// if (Ds_use_ds3d && ds3d_init(0) != 0) -// Ds_use_ds3d = 0; - - // setup default listener position/orientation - // this is needed for 2D pan - OpenAL_ErrorPrint( alListener3f(AL_POSITION, 0.0, 0.0, 0.0) ); - - ALfloat list_orien[] = { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f }; - OpenAL_ErrorPrint( alListenerfv(AL_ORIENTATION, list_orien) ); - - ds_build_vol_lookup(); - ds_init_channels(); - ds_init_buffers(); -#else - HRESULT hr; - HWND hwnd; - WAVEFORMATEX wave_format; - DSBUFFERDESC BufferDesc; - - nprintf(( "Sound", "SOUND ==> Initializing DirectSound...\n" )); - - hwnd = (HWND)os_get_window(); - if ( hwnd == NULL ) { - nprintf(( "Sound", "SOUND ==> No window handle, so no sound...\n" )); - return -1; - } - - if ( ds_dll_load() == -1 ) { - return -1; - } - - pDirectSound = NULL; - - Ds_use_a3d = use_a3d; - Ds_use_eax = use_eax; - - if (Ds_use_a3d || Ds_use_eax) { - Ds_use_ds3d = 1; - } - - if (Ds_use_a3d && Ds_use_eax) { - Ds_use_eax = 0; - } - - - // If we want A3D, ensure a3d.dll exists - if (Ds_use_a3d == 1) { - if (ds_init_a3d() != 0) { - Ds_use_a3d = 0; - Ds_use_ds3d = 0; - } - } - - - if (Ds_use_a3d == 0) { - if (!pfn_DirectSoundCreate) { - nprintf(( "Sound", "SOUND ==> Could not get DirectSoundCreate function pointer\n" )); - return -1; - } - - hr = pfn_DirectSoundCreate(NULL, &pDirectSound, NULL); - if (FAILED(hr)) { - return -1; - } - } - - // Set up DirectSound for exclusive mode, so we can change the primary buffer if we want to. - hr = pDirectSound->SetCooperativeLevel(hwnd, DSSCL_EXCLUSIVE); - if (hr != DS_OK) { - nprintf(("Sound","SOUND ==> DirectSound pDirectSound->SetCooperativeLevel failed with code %s\n.",get_DSERR_text(hr) )); - pDirectSound = NULL; - return -1; - } - - // Create the primary buffer - ZeroMemory(&BufferDesc, sizeof(BufferDesc)); - BufferDesc.dwSize = sizeof(BufferDesc); - - ds_get_soundcard_caps(&Soundcard_caps); - - if (Ds_use_ds3d) { - BufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D; - - hr = pDirectSound->CreateSoundBuffer(&BufferDesc, &pPrimaryBuffer, 0); - if (hr != DS_OK) { - nprintf(("Sound","SOUND ==> Primary Buffer create failed with DSBCAPS_CTRL3D property... disabling DirectSound3D\n")); - Ds_use_ds3d = 0; - Ds_use_eax = 0; - Ds_use_a3d = 0; - } else { - nprintf(("Sound","SOUND ==> Primary Buffer created with DirectSound3D enabled\n")); - } - } - - // If not using DirectSound3D, then create a normal primary buffer - if (Ds_use_ds3d == 0) { - BufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER; - hr = pDirectSound->CreateSoundBuffer(&BufferDesc, &pPrimaryBuffer, 0); - if (hr != DS_OK) { - nprintf(("Sound","SOUND ==> Primary Buffer create failed with error: %s\n",get_DSERR_text(hr) )); - pDirectSound = NULL; - return -1; - } - else { - nprintf(("Sound","SOUND ==> Primary Buffer created with without DirectSound3D enabled\n")); - } - } - - // Get the primary buffer format - ds_get_primary_format(&wave_format); - - hr = pPrimaryBuffer->SetFormat(&wave_format); - if (hr != DS_OK) { - nprintf(("Sound","SOUND ==> pPrimaryBuffer->SetFormat() failed with code %s\n",get_DSERR_text(hr) )); - } - - pPrimaryBuffer->GetFormat(&wave_format, sizeof(wave_format), NULL); - nprintf(("Sound","SOUND ==> Primary Buffer forced to: rate: %d Hz bits: %d n_channels: %d\n", - wave_format.nSamplesPerSec, wave_format.wBitsPerSample, wave_format.nChannels)); - - // start the primary buffer playing. This will reduce sound latency when playing a sound - // if no other sounds are playing. - hr = pPrimaryBuffer->Play(0, 0, DSBPLAY_LOOPING); - if (hr != DS_OK) { - nprintf(("Sound","SOUND ==> pPrimaryBuffer->Play() failed with code %s\n",get_DSERR_text(hr) )); - } - - // Initialize DirectSound3D. Since software performance of DirectSound3D is unacceptably - // slow, we require the voice manger (a DirectSound extension) to be present. The - // exception is when A3D is being used, since A3D has a resource manager built in. - if (Ds_use_ds3d) { - int vm_required = 1; // voice manager - if (Ds_use_a3d == 1) { - vm_required = 0; - } - - if (ds3d_init(vm_required) != 0) { - Ds_use_ds3d = 0; - //Ds_use_eax = 0; - } - } - - if (Ds_use_eax == 1) { - ds_init_property_set(); - if (ds_eax_init() != 0) { - Ds_use_eax = 0; - } - } - - ds_build_vol_lookup(); - ds_init_channels(); - ds_init_buffers(); - - ds_show_caps(&Soundcard_caps); -#endif - - return 0; -} - -// --------------------------------------------------------------------------------------- -// get_DSERR_text() -// -// returns the text equivalent for the a DirectSound DSERR_ code -// -char *get_DSERR_text(int DSResult) -{ -#ifdef PLAT_UNIX - STUB_FUNCTION; - - static char buf[20]; - snprintf(buf, 19, "unknown %d", DSResult); - return buf; -#else - switch( DSResult ) { - - case DS_OK: - return "DS_OK"; - break; - - case DSERR_ALLOCATED: - return "DSERR_ALLOCATED"; - break; - - case DSERR_ALREADYINITIALIZED: - return "DSERR_ALREADYINITIALIZED"; - break; - - case DSERR_BADFORMAT: - return "DSERR_BADFORMAT"; - break; - - case DSERR_BUFFERLOST: - return "DSERR_BUFFERLOST"; - break; - - case DSERR_CONTROLUNAVAIL: - return "DSERR_CONTROLUNAVAIL"; - break; - - case DSERR_GENERIC: - return "DSERR_GENERIC"; - break; - - case DSERR_INVALIDCALL: - return "DSERR_INVALIDCALL"; - break; - - case DSERR_INVALIDPARAM: - return "DSERR_INVALIDPARAM"; - break; - - case DSERR_NOAGGREGATION: - return "DSERR_NOAGGREGATION"; - break; - - case DSERR_NODRIVER: - return "DSERR_NODRIVER"; - break; - - case DSERR_OUTOFMEMORY: - return "DSERR_OUTOFMEMORY"; - break; - - case DSERR_OTHERAPPHASPRIO: - return "DSERR_OTHERAPPHASPRIO"; - break; - - case DSERR_PRIOLEVELNEEDED: - return "DSERR_PRIOLEVELNEEDED"; - break; - - case DSERR_UNINITIALIZED: - return "DSERR_UNINITIALIZED"; - break; - - case DSERR_UNSUPPORTED: - return "DSERR_UNSUPPORTED"; - break; - - default: - return "unknown"; - break; - } -#endif -} - - -// --------------------------------------------------------------------------------------- -// ds_close_channel() -// -// Free a single channel -// -void ds_close_channel(int i) -{ -#ifdef PLAT_UNIX - if(Channels[i].source_id != 0 && alIsSource (Channels[i].source_id)) { - OpenAL_ErrorPrint( alSourceStop (Channels[i].source_id) ); - - OpenAL_ErrorPrint( alDeleteSources(1, &Channels[i].source_id) ); - - Channels[i].source_id = 0; - } - - return; -#else - HRESULT hr; - - // If a 3D interface exists, free it - if ( Channels[i].pds3db != NULL ) { - - if (Ds_use_a3d) { - Channels[i].pds3db = NULL; - } else { - int attempts = 0; - while(++attempts < 10) { - hr = Channels[i].pds3db->Release(); - if ( hr == DS_OK ) { - break; - } else { - // nprintf(("Sound", "SOUND ==> Channels[channel].pds3db->Release() failed with return value %s\n", get_DSERR_text(second_hr) )); - } - } - - Channels[i].pds3db = NULL; - } - } - - if ( Channels[i].pdsb != NULL ) { - // If a 2D interface exists, free it - if ( Channels[i].pdsb != NULL ) { - int attempts = 0; - while(++attempts < 10) { - hr = Channels[i].pdsb->Release(); - if ( hr == DS_OK ) { - break; - } else { - nprintf(("Sound", "SOUND ==> Channels[channel].pdsb->Release() failed with return value %s\n", get_DSERR_text(hr) )); - } - } - } - - Channels[i].pdsb = NULL; - } -#endif -} - - - -// --------------------------------------------------------------------------------------- -// ds_close_all_channels() -// -// Free all the channel buffers -// -void ds_close_all_channels() -{ - int i; - - for (i = 0; i < MAX_CHANNELS; i++) { - ds_close_channel(i); - } -} - -// --------------------------------------------------------------------------------------- -// ds_unload_buffer() -// -// -void ds_unload_buffer(int sid, int hid) -{ -#ifdef PLAT_UNIX - if (sid != -1) { - ALuint buf_id = sound_buffers[sid].buf_id; - - if (buf_id != 0 && alIsBuffer(buf_id)) { - OpenAL_ErrorPrint( alDeleteBuffers(1, &buf_id) ); - } - - sound_buffers[sid].buf_id = 0; - } - - /* hid unused */ - - return; -#else - HRESULT hr; - - if ( sid != -1 ) { - if ( ds_software_buffers[sid].pdsb != NULL ) { - hr = ds_software_buffers[sid].pdsb->Release(); - if ( hr != DS_OK ) { - Int3(); - nprintf(("Sound", "SOUND ==> ds_software_buffers[sid]->Release() failed with return value %s\n", get_DSERR_text(hr) )); - } - ds_software_buffers[sid].pdsb = NULL; - } - } - - if ( hid != -1 ) { - if ( ds_hardware_buffers[hid].pdsb != NULL ) { - hr = ds_hardware_buffers[hid].pdsb->Release(); - if ( hr != DS_OK ) { - Int3(); - nprintf(("Sound", "SOUND ==> ds_hardware_buffers[hid]->Release() failed with return value %s\n", get_DSERR_text(hr) )); - } - ds_hardware_buffers[hid].pdsb = NULL; - } - } -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_close_software_buffers() -// -// -void ds_close_software_buffers() -{ -#ifdef PLAT_UNIX - int i; - - for (i = 0; i < MAX_DS_SOFTWARE_BUFFERS; i++) { - ALuint buf_id = sound_buffers[i].buf_id; - - if (buf_id != 0 && alIsBuffer(buf_id)) { - OpenAL_ErrorPrint( alDeleteBuffers(1, &buf_id) ); - } - - sound_buffers[i].buf_id = 0; - } -#else - int i; - HRESULT hr; - - for (i = 0; i < MAX_DS_SOFTWARE_BUFFERS; i++) { - if ( ds_software_buffers[i].pdsb != NULL ) { - hr = ds_software_buffers[i].pdsb->Release(); - if ( hr != DS_OK ) { - Int3(); - nprintf(("Sound", "SOUND ==> ds_software_buffers[i]->Release() failed with return value %s\n", get_DSERR_text(hr) )); - } - ds_software_buffers[i].pdsb = NULL; - } - } -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_close_hardware_buffers() -// -// -void ds_close_hardware_buffers() -{ -#ifdef PLAT_UNIX - // unused -#else - int i; - HRESULT hr; - - for (i = 0; i < MAX_DS_HARDWARE_BUFFERS; i++) { - if ( ds_hardware_buffers[i].pdsb != NULL ) { - hr = ds_hardware_buffers[i].pdsb->Release(); - if ( hr != DS_OK ) { - Int3(); - nprintf(("Sound", "SOUND ==> ds_hardware_buffers[i]->Release() failed with return value %s\n", get_DSERR_text(hr) )); - } - ds_hardware_buffers[i].pdsb = NULL; - } - } -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_close_buffers() -// -// Free the channel buffers -// -void ds_close_buffers() -{ - ds_close_software_buffers(); - ds_close_hardware_buffers(); -} - -// --------------------------------------------------------------------------------------- -// ds_close() -// -// Close the DirectSound system -// -void ds_close() -{ - ds_close_all_channels(); - ds_close_buffers(); - -#ifndef PLAT_UNIX - if (pPropertySet != NULL) { - pPropertySet->Release(); - pPropertySet = NULL; - } - - if (Ds_property_set_pdsb != NULL) { - Ds_property_set_pdsb->Release(); - Ds_property_set_pdsb = NULL; - } - - if (Ds_property_set_pds3db != NULL) { - Ds_property_set_pds3db->Release(); - Ds_property_set_pds3db = NULL; - } - - if (pPrimaryBuffer) { - pPrimaryBuffer->Release(); - pPrimaryBuffer = NULL; - } - - if ( pIA3d2 ) { - pIA3d2->Release(); - pIA3d2 = NULL; - } - - if (pDirectSound) { - pDirectSound->Release(); - pDirectSound = NULL; - } - - if ( Ds_dll_loaded ) { - FreeLibrary(Ds_dll_handle); - Ds_dll_loaded=0; - } - - if (Ds_must_call_couninitialize == 1) { - CoUninitialize(); - } -#endif - - // free the Channels[] array, since it was dynamically allocated - free(Channels); - Channels = NULL; - -#ifdef PLAT_UNIX - if (ds_sound_context != NULL) - alcDestroyContext(ds_sound_context); - - if (ds_sound_device != NULL) - alcCloseDevice(ds_sound_device); -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_get_3d_interface() -// -// Get the 3d interface for a secondary buffer. -// -// If the secondary buffer wasn't created with a DSBCAPS_CTRL3D flag, then no 3d interface -// exists -// -#ifndef PLAT_UNIX -void ds_get_3d_interface(LPDIRECTSOUNDBUFFER pdsb, LPDIRECTSOUND3DBUFFER *ppds3db) -{ - DSBCAPS dsbc; - HRESULT DSResult; - - dsbc.dwSize = sizeof(dsbc); - DSResult = pdsb->GetCaps(&dsbc); - if ( DSResult == DS_OK && dsbc.dwFlags & DSBCAPS_CTRL3D ) { - DSResult = pdsb->QueryInterface( IID_IDirectSound3DBuffer, (void**)ppds3db ); - if ( DSResult != DS_OK ) { - nprintf(("SOUND","Could not obtain 3D interface for hardware buffer: %s\n", get_DSERR_text(DSResult) )); - } - } -} -#endif - - -// --------------------------------------------------------------------------------------- -// ds_get_free_channel() -// -// Find a free channel to play a sound on. If no free channels exists, free up one based -// on volume levels. -// -// input: new_volume => volume in DS units for sound to play at -// snd_id => which kind of sound to play -// priority => DS_MUST_PLAY -// DS_LIMIT_ONE -// DS_LIMIT_TWO -// DS_LIMIT_THREE -// -// returns: channel number to play sound on -// -1 if no channel could be found -// -// NOTE: snd_id is needed since we limit the number of concurrent samples -// -// - -int ds_get_free_channel(int new_volume, int snd_id, int priority) -{ -#ifdef PLAT_UNIX - int i, first_free_channel, limit; - int lowest_vol = 0, lowest_vol_index = -1; - int instance_count; // number of instances of sound already playing - int lowest_instance_vol, lowest_instance_vol_index; - channel *chp; - int status; - - instance_count = 0; - lowest_instance_vol = 99; - lowest_instance_vol_index = -1; - first_free_channel = -1; - - // Look for a channel to use to play this sample - for ( i = 0; i < MAX_CHANNELS; i++ ) { - chp = &Channels[i]; - if ( chp->source_id == 0 ) { - if ( first_free_channel == -1 ) - first_free_channel = i; - continue; - } - - OpenAL_ErrorCheck( alGetSourcei(chp->source_id, AL_SOURCE_STATE, &status), return -1 ); - - if ( status != AL_PLAYING ) { - if ( first_free_channel == -1 ) - first_free_channel = i; - continue; - } - else { - if ( chp->snd_id == snd_id ) { - instance_count++; - if ( chp->vol < lowest_instance_vol && chp->looping == FALSE ) { - lowest_instance_vol = chp->vol; - lowest_instance_vol_index = i; - } - } - - if ( chp->vol < lowest_vol && chp->looping == FALSE ) { - lowest_vol_index = i; - lowest_vol = chp->vol; - } - } - } - - // determine the limit of concurrent instances of this sound - switch(priority) { - case DS_MUST_PLAY: - limit = 100; - break; - case DS_LIMIT_ONE: - limit = 1; - break; - case DS_LIMIT_TWO: - limit = 2; - break; - case DS_LIMIT_THREE: - limit = 3; - break; - default: - Int3(); // get Alan - limit = 100; - break; - } - - - // If we've exceeded the limit, then maybe stop the duplicate if it is lower volume - if ( instance_count >= limit ) { - // If there is a lower volume duplicate, stop it.... otherwise, don't play the sound - if ( lowest_instance_vol_index >= 0 && (Channels[lowest_instance_vol_index].vol <= new_volume) ) { - first_free_channel = lowest_instance_vol_index; - } else { - first_free_channel = -1; - } - } else { - // there is no limit barrier to play the sound, so see if we've ran out of channels - if ( first_free_channel == -1 ) { - // stop the lowest volume instance to play our sound if priority demands it - if ( lowest_vol_index != -1 && priority == DS_MUST_PLAY ) { - // Check if the lowest volume playing is less than the volume of the requested sound. - // If so, then we are going to trash the lowest volume sound. - if ( Channels[lowest_vol_index].vol <= new_volume ) { - first_free_channel = lowest_vol_index; - } - } - } - } - - return first_free_channel; -#else - int i, first_free_channel, limit; - int lowest_vol = 0, lowest_vol_index = -1; - int instance_count; // number of instances of sound already playing - int lowest_instance_vol, lowest_instance_vol_index; - unsigned long status; - HRESULT hr; - channel *chp; - - instance_count = 0; - lowest_instance_vol = 99; - lowest_instance_vol_index = -1; - first_free_channel = -1; - - // Look for a channel to use to play this sample - for ( i = 0; i < MAX_CHANNELS; i++ ) { - chp = &Channels[i]; - if ( chp->pdsb == NULL ) { - if ( first_free_channel == -1 ) - first_free_channel = i; - continue; - } - - hr = chp->pdsb->GetStatus(&status); - if ( hr != DS_OK ) { - nprintf(("Sound", "SOUND ==> GetStatus failed with return value %s\n", get_DSERR_text(hr) )); - return -1; - } - if ( !(status & DSBSTATUS_PLAYING) ) { - if ( first_free_channel == -1 ) - first_free_channel = i; - ds_close_channel(i); - continue; - } - else { - if ( chp->snd_id == snd_id ) { - instance_count++; - if ( chp->vol < lowest_instance_vol && chp->looping == FALSE ) { - lowest_instance_vol = chp->vol; - lowest_instance_vol_index = i; - } - } - - if ( chp->vol < lowest_vol && chp->looping == FALSE ) { - lowest_vol_index = i; - lowest_vol = chp->vol; - } - } - } - - // determine the limit of concurrent instances of this sound - switch(priority) { - case DS_MUST_PLAY: - limit = 100; - break; - case DS_LIMIT_ONE: - limit = 1; - break; - case DS_LIMIT_TWO: - limit = 2; - break; - case DS_LIMIT_THREE: - limit = 3; - break; - default: - Int3(); // get Alan - limit = 100; - break; - } - - - // If we've exceeded the limit, then maybe stop the duplicate if it is lower volume - if ( instance_count >= limit ) { - // If there is a lower volume duplicate, stop it.... otherwise, don't play the sound - if ( lowest_instance_vol_index >= 0 && (Channels[lowest_instance_vol_index].vol <= new_volume) ) { - ds_close_channel(lowest_instance_vol_index); - first_free_channel = lowest_instance_vol_index; - } else { - first_free_channel = -1; - } - } else { - // there is no limit barrier to play the sound, so see if we've ran out of channels - if ( first_free_channel == -1 ) { - // stop the lowest volume instance to play our sound if priority demands it - if ( lowest_vol_index != -1 && priority == DS_MUST_PLAY ) { - // Check if the lowest volume playing is less than the volume of the requested sound. - // If so, then we are going to trash the lowest volume sound. - if ( Channels[lowest_vol_index].vol <= new_volume ) { - ds_close_channel(lowest_vol_index); - first_free_channel = lowest_vol_index; - } - } - } - } - - return first_free_channel; -#endif -} - - -// --------------------------------------------------------------------------------------- -// ds_channel_dup() -// -// Find a free channel to play a sound on. If no free channels exists, free up one based -// on volume levels. -// -// returns: 0 => dup was successful -// -1 => dup failed (Channels[channel].pdsb will be NULL) -// -#ifndef PLAT_UNIX -int ds_channel_dup(LPDIRECTSOUNDBUFFER pdsb, int channel, int use_ds3d) -{ - HRESULT DSResult; - - // Duplicate the master buffer into a channel buffer. - DSResult = pDirectSound->DuplicateSoundBuffer(pdsb, &Channels[channel].pdsb ); - if ( DSResult != DS_OK ) { - nprintf(("Sound", "SOUND ==> DuplicateSoundBuffer failed with return value %s\n", get_DSERR_text(DSResult) )); - Channels[channel].pdsb = NULL; - return -1; - } - - // get the 3d interface for the buffer if it exists - if ( use_ds3d ) { - if (Channels[channel].pds3db == NULL) { - ds_get_3d_interface(Channels[channel].pdsb, &Channels[channel].pds3db); - } - } - - return 0; -} - - -// --------------------------------------------------------------------------------------- -// ds_restore_buffer() -// -// -void ds_restore_buffer(LPDIRECTSOUNDBUFFER pdsb) -{ - HRESULT hr; - - Int3(); // get Alan, he wants to see this - hr = pdsb->Restore(); - if ( hr != DS_OK ) { - nprintf(("Sound", "Sound ==> Lost a buffer, tried restoring but got %s\n", get_DSERR_text(hr) )); - } -} -#endif - -// Create a direct sound buffer in software, without locking any data in -int ds_create_buffer(int frequency, int bits_per_sample, int nchannels, int nseconds) -{ -#ifdef PLAT_UNIX - ALuint i; - int sid; - - if (!ds_initialized) { - return -1; - } - - sid = ds_get_sid(); - if ( sid == -1 ) { - nprintf(("Sound","SOUND ==> No more OpenAL buffers available\n")); - return -1; - } - - OpenAL_ErrorCheck( alGenBuffers (1, &i), return -1 ); - - sound_buffers[sid].buf_id = i; - sound_buffers[sid].source_id = -1; - sound_buffers[sid].frequency = frequency; - sound_buffers[sid].bits_per_sample = bits_per_sample; - sound_buffers[sid].nchannels = nchannels; - sound_buffers[sid].nseconds = nseconds; - sound_buffers[sid].nbytes = nseconds * (bits_per_sample / 8) * nchannels * frequency; - - return sid; -#else - HRESULT dsrval; - DSBUFFERDESC dsbd; - WAVEFORMATEX wfx; - int sid; - - if (!ds_initialized) { - return -1; - } - - sid = ds_get_sid(); - if ( sid == -1 ) { - nprintf(("Sound","SOUND ==> No more software secondary buffers available\n")); - return -1; - } - - // Set up buffer format - wfx.wFormatTag = WAVE_FORMAT_PCM; - wfx.nChannels = (unsigned short)nchannels; - wfx.nSamplesPerSec = frequency; - wfx.wBitsPerSample = (unsigned short)bits_per_sample; - wfx.cbSize = 0; - wfx.nBlockAlign = (unsigned short)(wfx.nChannels * (wfx.wBitsPerSample / 8)); - wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec; - - memset(&dsbd, 0, sizeof(DSBUFFERDESC)); - dsbd.dwSize = sizeof(DSBUFFERDESC); - dsbd.dwBufferBytes = wfx.nAvgBytesPerSec * nseconds; - dsbd.lpwfxFormat = &wfx; - dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLDEFAULT | DSBCAPS_LOCSOFTWARE; - - dsrval = pDirectSound->CreateSoundBuffer(&dsbd, &ds_software_buffers[sid].pdsb, NULL); - if ( dsrval != DS_OK ) { - return -1; - } - - ds_software_buffers[sid].desc = dsbd; - return sid; -#endif -} - -// Lock data into an existing buffer -int ds_lock_data(int sid, unsigned char *data, int size) -{ -#ifdef PLAT_UNIX - Assert(sid >= 0); - - ALuint buf_id = sound_buffers[sid].buf_id; - ALenum format; - - if (sound_buffers[sid].bits_per_sample == 16) { - if (sound_buffers[sid].nchannels == 2) { - format = AL_FORMAT_STEREO16; - } else if (sound_buffers[sid].nchannels == 1) { - format = AL_FORMAT_MONO16; - } else { - return -1; - } - } else if (sound_buffers[sid].bits_per_sample == 8) { - if (sound_buffers[sid].nchannels == 2) { - format = AL_FORMAT_STEREO8; - } else if (sound_buffers[sid].nchannels == 1) { - format = AL_FORMAT_MONO8; - } else { - return -1; - } - } else { - return -1; - } - - sound_buffers[sid].nbytes = size; - - OpenAL_ErrorCheck( alBufferData(buf_id, format, data, size, sound_buffers[sid].frequency), return -1 ); - - return 0; -#else - HRESULT dsrval; - LPDIRECTSOUNDBUFFER pdsb; - DSBCAPS caps; - void *buffer_data, *buffer_data2; - DWORD buffer_size, buffer_size2; - - Assert(sid >= 0); - pdsb = ds_software_buffers[sid].pdsb; - - memset(&caps, 0, sizeof(DSBCAPS)); - caps.dwSize = sizeof(DSBCAPS); - dsrval = pdsb->GetCaps(&caps); - if ( dsrval != DS_OK ) { - return -1; - } - - pdsb->SetCurrentPosition(0); - - // lock the entire buffer - dsrval = pdsb->Lock(0, caps.dwBufferBytes, &buffer_data, &buffer_size, &buffer_data2, &buffer_size2, 0 ); - if ( dsrval != DS_OK ) { - return -1; - } - - // first clear it out with silence - memset(buffer_data, 0x80, buffer_size); - memcpy(buffer_data, data, size); - - dsrval = pdsb->Unlock(buffer_data, buffer_size, 0, 0); - if ( dsrval != DS_OK ) { - return -1; - } - - return 0; -#endif -} - -// Stop a buffer from playing directly -void ds_stop_easy(int sid) -{ -#ifdef PLAT_UNIX - Assert(sid >= 0); - - int cid = sound_buffers[sid].source_id; - - if (cid != -1) { - ALuint source_id = Channels[cid].source_id; - - OpenAL_ErrorPrint( alSourceStop(source_id) ); - } -#else - HRESULT dsrval; - LPDIRECTSOUNDBUFFER pdsb; - - Assert(sid >= 0); - pdsb = ds_software_buffers[sid].pdsb; - dsrval = pdsb->Stop(); -#endif -} - -// Play a sound without the usual baggage (used for playing back real-time voice) -// -// parameters: -// sid => software id of sound -// volume => volume of sound effect in DirectSound units -int ds_play_easy(int sid, int volume) -{ -#ifdef PLAT_UNIX - if (!ds_initialized) - return -1; - - int channel = ds_get_free_channel(volume, -1, DS_MUST_PLAY); - - if (channel > -1) { - ALuint source_id = Channels[channel].source_id; - - OpenAL_ErrorPrint( alSourceStop(source_id) ); - - if (Channels[channel].buf_id != sid) { - ALuint buffer_id = sound_buffers[sid].buf_id; - - OpenAL_ErrorCheck( alSourcei(source_id, AL_BUFFER, buffer_id), return -1 ); - } - - Channels[channel].buf_id = sid; - - ALfloat alvol = (volume != -10000) ? powf(10.0f, (float)volume / (-600.0f / log10f(.5f))): 0.0f; - - OpenAL_ErrorPrint( alSourcef(source_id, AL_GAIN, alvol) ); - - OpenAL_ErrorPrint( alSourcei(source_id, AL_LOOPING, AL_FALSE) ); - - OpenAL_ErrorPrint( alSourcePlay(source_id) ); - - return 0; - } - - return -1; -#else - HRESULT dsrval; - LPDIRECTSOUNDBUFFER pdsb; - - Assert(sid >= 0); - pdsb = ds_software_buffers[sid].pdsb; - - pdsb->SetVolume(volume); - dsrval=pdsb->Play(0, 0, 0); - if ( dsrval != DS_OK ) { - return -1; - } - - return 0; -#endif -} - -// --------------------------------------------------------------------------------------- -// Play a DirectSound secondary buffer. -// -// -// parameters: -// sid => software id of sound -// hid => hardware id of sound ( -1 if not in hardware ) -// snd_id => what kind of sound this is -// priority => DS_MUST_PLAY -// DS_LIMIT_ONE -// DS_LIMIT_TWO -// DS_LIMIT_THREE -// volume => volume of sound effect in DirectSound units -// pan => pan of sound in DirectSound units -// looping => whether the sound effect is looping or not -// -// returns: -1 => sound effect could not be started -// >=0 => sig for sound effect successfully started -// -int ds_play(int sid, int hid, int snd_id, int priority, int volume, int pan, int looping, bool is_voice_msg) -{ -#ifdef PLAT_UNIX - int channel; - - if (!ds_initialized) - return -1; - - channel = ds_get_free_channel(volume, snd_id, priority); - - if (channel > -1) { - if ( Channels[channel].source_id == 0 ) { - return -1; - } - - if ( ds_using_ds3d() ) { - } - - // Actually play it - Channels[channel].vol = volume; - Channels[channel].looping = looping; - Channels[channel].priority = priority; - - // set new position for pan or zero out if none - ALfloat alpan = (float)pan / MAX_PAN; - - if ( alpan ) { - OpenAL_ErrorPrint( alSource3f(Channels[channel].source_id, AL_POSITION, alpan, 0.0, 1.0) ); - } else { - OpenAL_ErrorPrint( alSource3f(Channels[channel].source_id, AL_POSITION, 0.0, 0.0, 0.0) ); - } - - OpenAL_ErrorPrint( alSource3f(Channels[channel].source_id, AL_VELOCITY, 0.0, 0.0, 0.0) ); - - OpenAL_ErrorPrint( alSourcef(Channels[channel].source_id, AL_PITCH, 1.0) ); - - ALfloat alvol = (volume != -10000) ? powf(10.0f, (float)volume / (-600.0f / log10f(.5f))): 0.0f; - OpenAL_ErrorPrint( alSourcef(Channels[channel].source_id, AL_GAIN, alvol) ); - - Channels[channel].is_voice_msg = is_voice_msg; - - - ALint status; - OpenAL_ErrorCheck( alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status), return -1 ); - - if (status == AL_PLAYING) - OpenAL_ErrorPrint( alSourceStop(Channels[channel].source_id) ); - - - OpenAL_ErrorCheck( alSourcei(Channels[channel].source_id, AL_BUFFER, sound_buffers[sid].buf_id), return -1 ); - - - // setup default listener position/orientation - // this is needed for 2D pan - OpenAL_ErrorPrint( alListener3f(AL_POSITION, 0.0, 0.0, 0.0) ); - - ALfloat list_orien[] = { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f }; - OpenAL_ErrorPrint( alListenerfv(AL_ORIENTATION, list_orien) ); - - OpenAL_ErrorPrint( alSourcei(Channels[channel].source_id, AL_SOURCE_RELATIVE, AL_FALSE) ); - - OpenAL_ErrorPrint( alSourcei(Channels[channel].source_id, AL_LOOPING, (looping) ? AL_TRUE : AL_FALSE) ); - - OpenAL_ErrorPrint( alSourcePlay(Channels[channel].source_id) ); - - sound_buffers[sid].source_id = channel; - Channels[channel].buf_id = sid; - } - else { -// nprintf(( "Sound", "SOUND ==> Not playing sound requested at volume %.2f\n", ds_get_percentage_vol(volume) )); - return -1; - } - - Channels[channel].snd_id = snd_id; - Channels[channel].sig = channel_next_sig++; - if (channel_next_sig < 0 ) { - channel_next_sig = 1; - } - - Channels[channel].last_position = 0; - - // make sure there aren't any looping voice messages - for (int i=0; i -1) { - if ( Channels[channel].pdsb != NULL ) { - return -1; - } - - // First check if the sound is in hardware, and try to duplicate from there - if ( hid != -1 ) { - Int3(); - if ( ds_channel_dup(ds_hardware_buffers[hid].pdsb, channel, 0) == 0 ) { -// nprintf(("Sound", "SOUND ==> Played sound in hardware..\n")); - } - } - - // Channel will be NULL if hardware dup failed, or there was no hardware dup attempted - if ( Channels[channel].pdsb == NULL ) { - if ( ds_channel_dup(ds_software_buffers[sid].pdsb, channel, 0) == 0 ) { -// nprintf(("Sound", "SOUND ==> Played sound in software..\n")); - } - } - - if ( Channels[channel].pdsb == NULL ) { - return -1; - } - - if ( ds_using_ds3d() ) { - if ( ds_is_3d_buffer(Channels[channel].pdsb) ) { - if (Channels[channel].pds3db == NULL) { - ds_get_3d_interface(Channels[channel].pdsb, &Channels[channel].pds3db); - } - if ( Channels[channel].pds3db ) { - Channels[channel].pds3db->SetMode(DS3DMODE_DISABLE,DS3D_IMMEDIATE); - } - } - } - - // Actually play it - Channels[channel].vol = volume; - Channels[channel].looping = looping; - Channels[channel].priority = priority; - Channels[channel].pdsb->SetPan(pan); - Channels[channel].pdsb->SetVolume(volume); - Channels[channel].is_voice_msg = is_voice_msg; - - int ds_flags = 0; - if ( looping ) - ds_flags |= DSBPLAY_LOOPING; - - DSResult = Channels[channel].pdsb->Play(0, 0, ds_flags ); - - /* - if (Stop_logging_sounds == false) { - char buf[256]; - sprintf(buf, "channel %d, address: %x, ds_flags: %d", channel, Channels[channel].pdsb, ds_flags); - HUD_add_to_scrollback(buf, 3); - } - */ - - if ( DSResult == DSERR_BUFFERLOST ) { - ds_restore_buffer(Channels[channel].pdsb); - DSResult = Channels[channel].pdsb->Play(0, 0, ds_flags ); - } - - if ( DSResult != DS_OK ) { - nprintf(("Sound", "Sound ==> Play failed with return value %s\n", get_DSERR_text(DSResult) )); - return -1; - } - } - else { -// nprintf(( "Sound", "SOUND ==> Not playing sound requested at volume %.2f\n", ds_get_percentage_vol(volume) )); - return -1; - } - - Channels[channel].snd_id = snd_id; - Channels[channel].sig = channel_next_sig++; - if (channel_next_sig < 0 ) { - channel_next_sig = 1; - } - - /* - if (Stop_logging_sounds == false) { - if (is_voice_msg) { - char buf[256]; - sprintf(buf, "VOICE sig: %d, sid: %d, snd_id: %d, ch: %d", Channels[channel].sig, sid, snd_id, channel); - HUD_add_to_scrollback(buf, 3); - } - } - */ - - Channels[channel].last_position = 0; - - // make sure there aren't any looping voice messages - for (int i=0; iGetStatus(&status); - if ( hr != DS_OK ) { - nprintf(("Sound", "SOUND ==> GetStatus failed with return value %s\n", get_DSERR_text(hr) )); - return 0; - } - - if ( status & DSBSTATUS_PLAYING ) - return TRUE; - else - return FALSE; -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_stop_channel() -// -// -void ds_stop_channel(int channel) -{ -#ifdef PLAT_UNIX - if ( Channels[channel].source_id != 0 ) { - OpenAL_ErrorPrint( alSourceStop(Channels[channel].source_id) ); - } -#else - ds_close_channel(channel); -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_stop_channel_all() -// -// -void ds_stop_channel_all() -{ -#ifdef PLAT_UNIX - int i; - - for ( i=0; iGetStatus(&status); - if ( hr != DS_OK ) { - nprintf(("Sound", "SOUND ==> GetStatus failed with return value %s\n", get_DSERR_text(hr) )); - return; - } - - if ( status & DSBSTATUS_PLAYING ) { - Channels[channel].pdsb->SetVolume(vol); - } -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_set_pan() -// -// Set the pan for a channel. The pan is expected to be in DirectSound units -// -void ds_set_pan( int channel, int pan ) -{ -#ifdef PLAT_UNIX - ALint state; - - OpenAL_ErrorCheck( alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &state), return ); - - if (state == AL_PLAYING) { - ALfloat alpan = (pan != 0) ? ((float)pan / MAX_PAN) : 0.0f; - OpenAL_ErrorPrint( alSource3f(Channels[channel].source_id, AL_POSITION, alpan, 0.0, 1.0) ); - } -#else - HRESULT hr; - unsigned long status; - - hr = Channels[channel].pdsb->GetStatus(&status); - if ( hr != DS_OK ) { - nprintf(("Sound", "SOUND ==> GetStatus failed with return value %s\n", get_DSERR_text(hr) )); - return; - } - - if ( status & DSBSTATUS_PLAYING ) { - Channels[channel].pdsb->SetPan(pan); - } -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_get_pitch() -// -// Get the pitch of a channel -// -int ds_get_pitch(int channel) -{ -#ifdef PLAT_UNIX - ALint status; - ALfloat alpitch = 0; - int pitch; - - OpenAL_ErrorCheck( alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status), return -1 ); - - if (status == AL_PLAYING) - OpenAL_ErrorPrint( alGetSourcef(Channels[channel].source_id, AL_PITCH, &alpitch) ); - - // convert OpenAL values to DirectSound values and return - pitch = fl2i( pow(10.0, (alpitch + 2.0)) ); - - return pitch; -#else - unsigned long status, pitch = 0; - HRESULT hr; - - hr = Channels[channel].pdsb->GetStatus(&status); - - if ( hr != DS_OK ) { - nprintf(("Sound", "SOUND ==> GetStatus failed with return value %s\n", get_DSERR_text(hr) )); - return -1; - } - - if ( status & DSBSTATUS_PLAYING ) { - hr = Channels[channel].pdsb->GetFrequency(&pitch); - if ( hr != DS_OK ) { - nprintf(("Sound", "SOUND ==> GetFrequency failed with return value %s\n", get_DSERR_text(hr) )); - return -1; - } - } - - return (int)pitch; -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_set_pitch() -// -// Set the pitch of a channel -// -void ds_set_pitch(int channel, int pitch) -{ -#ifdef PLAT_UNIX - ALint status; - - if ( pitch < MIN_PITCH ) - pitch = MIN_PITCH; - - if ( pitch > MAX_PITCH ) - pitch = MAX_PITCH; - - OpenAL_ErrorCheck( alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status), return ); - - if (status == AL_PLAYING) { - ALfloat alpitch = log10f((float)pitch) - 2.0f; - OpenAL_ErrorPrint( alSourcef(Channels[channel].source_id, AL_PITCH, alpitch) ); - } -#else - unsigned long status; - HRESULT hr; - - hr = Channels[channel].pdsb->GetStatus(&status); - if ( hr != DS_OK ) { - nprintf(("Sound", "SOUND ==> GetStatus failed with return value %s\n", get_DSERR_text(hr) )); - return; - } - - if ( pitch < MIN_PITCH ) - pitch = MIN_PITCH; - - if ( pitch > MAX_PITCH ) - pitch = MAX_PITCH; - - if ( status & DSBSTATUS_PLAYING ) { - Channels[channel].pdsb->SetFrequency((unsigned long)pitch); - } -#endif -} - -// --------------------------------------------------------------------------------------- -// ds_chg_loop_status() -// -// -void ds_chg_loop_status(int channel, int loop) -{ -#ifdef PLAT_UNIX - ALuint source_id = Channels[channel].source_id; - - OpenAL_ErrorPrint( alSourcei(source_id, AL_LOOPING, loop ? AL_TRUE : AL_FALSE) ); -#else - unsigned long status; - HRESULT hr; - - hr = Channels[channel].pdsb->GetStatus(&status); - if ( hr != DS_OK ) { - nprintf(("Sound", "SOUND ==> GetStatus failed with return value %s\n", get_DSERR_text(hr) )); - return; - } - - if ( !(status & DSBSTATUS_PLAYING) ) - return; // sound is not playing anymore - - if ( status & DSBSTATUS_LOOPING ) { - if ( loop ) - return; // we are already looping - else { - // stop the sound from looping - hr = Channels[channel].pdsb->Play(0,0,0); - } - } - else { - if ( !loop ) - return; // the sound is already not looping - else { - // start the sound looping - hr = Channels[channel].pdsb->Play(0,0,DSBPLAY_LOOPING); - } - } -#endif -} - -// --------------------------------------------------------------------------------------- -// ds3d_play() -// -// Starts a ds3d sound playing -// -// input: -// -// sid => software id for sound to play -// hid => hardware id for sound to play (-1 if not in hardware) -// snd_id => identifies what type of sound is playing -// pos => world pos of sound -// vel => velocity of object emitting sound -// min => distance at which sound doesn't get any louder -// max => distance at which sound becomes inaudible -// looping => boolean, whether to loop the sound or not -// max_volume => volume (-10000 to 0) for 3d sound at maximum -// estimated_vol => manual estimated volume -// priority => DS_MUST_PLAY -// DS_LIMIT_ONE -// DS_LIMIT_TWO -// DS_LIMIT_THREE -// -// returns: 0 => sound started successfully -// -1 => sound could not be played -// -int ds3d_play(int sid, int hid, int snd_id, vector *pos, vector *vel, int min, int max, int looping, int max_volume, int estimated_vol, int priority ) -{ -#ifdef PLAT_UNIX - STUB_FUNCTION; - - return -1; -#else - int channel; - HRESULT hr; - - if (!ds_initialized) - return -1; - - channel = ds_get_free_channel(estimated_vol, snd_id, priority); - - if (channel > -1) { - Assert(Channels[channel].pdsb == NULL); - - // First check if the sound is in hardware, and try to duplicate from there - if ( hid != -1 ) { - Int3(); - if ( ds_is_3d_buffer(ds_hardware_buffers[hid].pdsb) == FALSE ) { - nprintf(("Sound", "SOUND ==> Tried to play non-3d buffer in ds3d_play()..\n")); - return -1; - } - - if ( ds_channel_dup(ds_hardware_buffers[hid].pdsb, channel, 1) == 0 ) { - nprintf(("Sound", "SOUND ==> Played sound using DirectSound3D in hardware..\n")); - } - } - - // Channel will be NULL if hardware dup failed, or there was no hardware dup attempted - if ( Channels[channel].pdsb == NULL ) { - -/* - if ( ds_is_3d_buffer(ds_software_buffers[sid].pdsb) == FALSE ) { - nprintf(("Sound", "SOUND ==> Tried to play non-3d buffer in ds3d_play()..\n")); - return -1; - } -*/ - - if ( ds_channel_dup(ds_software_buffers[sid].pdsb, channel, 1) == 0 ) { -// nprintf(("Sound", "SOUND ==> Played sound using DirectSound3D \n")); - } - } - - if ( Channels[channel].pdsb == NULL ) { - return -1; -/* - DSBUFFERDESC desc; - - desc = ds_software_buffers[sid].desc; - desc.lpwfxFormat = &ds_software_buffers[sid].wfx; - - // duplicate buffer failed, so call CreateBuffer instead - - hr = pDirectSound->CreateSoundBuffer(&desc, &Channels[channel].pdsb, NULL ); - // lock the data in - if ( (hr == DS_OK) && (Channels[channel].pdsb) ) { - BYTE *pdest, *pdest2; - BYTE *psrc, *psrc2; - DWORD src_ds_size, dest_ds_size, not_used; - int src_size; - - if ( ds_get_size(sid, &src_size) != 0 ) { - Int3(); - Channels[channel].pdsb->Release(); - return -1; - } - - // lock the src buffer - hr = ds_software_buffers[sid].pdsb->Lock(0, src_size, (void**)&psrc, &src_ds_size, (void**)&psrc2, ¬_used, 0); - if ( hr != DS_OK ) { - mprintf(("err: %s\n", get_DSERR_text(hr))); - Int3(); - Channels[channel].pdsb->Release(); - return -1; - } - - if ( Channels[channel].pdsb->Lock(0, src_ds_size, (void**)(&pdest), &dest_ds_size, (void**)&pdest2, ¬_used, 0) == DS_OK) { - memcpy(pdest, psrc, src_ds_size); - Channels[channel].pdsb->Unlock(pdest, dest_ds_size, 0, 0); - ds_get_3d_interface(Channels[channel].pdsb, &Channels[channel].pds3db); - } else { - Channels[channel].pdsb->Release(); - return -1; - } - } -*/ - } - - Assert(Channels[channel].pds3db ); - Channels[channel].pds3db->SetMode(DS3DMODE_NORMAL,DS3D_IMMEDIATE); - - // set up 3D sound data here - ds3d_update_buffer(channel, i2fl(min), i2fl(max), pos, vel); - - Channels[channel].vol = estimated_vol; - Channels[channel].looping = looping; - - // sets the maximum "inner cone" volume - Channels[channel].pdsb->SetVolume(max_volume); - - int ds_flags = 0; - if ( looping ) - ds_flags |= DSBPLAY_LOOPING; - - // Actually play it - hr = Channels[channel].pdsb->Play(0, 0, ds_flags ); - - if ( hr == DSERR_BUFFERLOST ) { - ds_restore_buffer(Channels[channel].pdsb); - hr = Channels[channel].pdsb->Play(0, 0, ds_flags ); - } - - if ( hr != DS_OK ) { - nprintf(("Sound", "Sound ==> Play failed with return value %s\n", get_DSERR_text(hr) )); - if ( Channels[channel].pdsb ) { - int attempts = 0; - while(++attempts < 10) { - hr = Channels[channel].pdsb->Release(); - if ( hr == DS_OK ) { - break; - } else { - nprintf(("Sound","SOUND ==> DirectSound Release() failed with code %s\n.",get_DSERR_text(hr) )); - continue; - } - } - Channels[channel].pdsb = NULL; - } - return -1; - } - } - else { - nprintf(( "Sound", "SOUND ==> Not playing requested 3D sound\n")); - return -1; - } - - Channels[channel].snd_id = snd_id; - Channels[channel].sig = channel_next_sig++; - if (channel_next_sig < 0 ) { - channel_next_sig = 1; - } - return Channels[channel].sig; -#endif -} - -void ds_set_position(int channel, DWORD offset) -{ -#ifdef PLAT_UNIX - STUB_FUNCTION; -#else - // set the position of the sound buffer - Channels[channel].pdsb->SetCurrentPosition(offset); -#endif -} - -DWORD ds_get_play_position(int channel) -{ -#ifdef PLAT_UNIX - ALint pos = -1; - int buf_id; - - if (!AL_play_position) - return 0; - - buf_id = Channels[channel].buf_id; - - if (buf_id == -1) - return 0; - - OpenAL_ErrorCheck( alGetSourcei( Channels[channel].source_id, AL_BYTE_LOKI, &pos), return 0 ); - - - if ( pos < 0 ) { - pos = 0; - } else if ( pos > 0 ) { - // AL_BYTE_LOKI returns position in canon format which may differ - // from our sample, so we may have to scale it - ALuint buf = sound_buffers[buf_id].buf_id; - ALint size; - - OpenAL_ErrorCheck( alGetBufferi(buf, AL_SIZE, &size), return 0 ); - - pos = (ALint)(pos * ((float)sound_buffers[buf_id].nbytes / size)); - } - - return pos; -#else - DWORD play,write; - if ( Channels[channel].pdsb ) { - Channels[channel].pdsb->GetCurrentPosition((LPDWORD)&play,(LPDWORD)&write); - } else { - play = 0; - } - - return play; -#endif -} - -DWORD ds_get_write_position(int channel) -{ -#ifdef PLAT_UNIX - STUB_FUNCTION; - - return 0; -#else - DWORD play,write; - if ( Channels[channel].pdsb ) { - Channels[channel].pdsb->GetCurrentPosition((LPDWORD)&play,(LPDWORD)&write); - } else { - write = 0; - } - - return write; -#endif -} - -int ds_get_channel_size(int channel) -{ -#ifdef PLAT_UNIX - int buf_id = Channels[channel].buf_id; - - if (buf_id != -1) { - return sound_buffers[buf_id].nbytes; - } - - return 0; -#else - int size; - DSBCAPS caps; - HRESULT dsrval; - - if ( Channels[channel].pdsb ) { - memset(&caps, 0, sizeof(DSBCAPS)); - caps.dwSize = sizeof(DSBCAPS); - dsrval = Channels[channel].pdsb->GetCaps(&caps); - if ( dsrval != DS_OK ) { - return 0; - } - size = caps.dwBufferBytes; - } else { - size = 0; - } - - return size; -#endif -} - -// Returns the number of channels that are actually playing -int ds_get_number_channels() -{ -#ifdef PLAT_UNIX - int i,n; - - if (!ds_initialized) { - return 0; - } - - n = 0; - for ( i = 0; i < MAX_CHANNELS; i++ ) { - if ( Channels[i].source_id ) { - if ( ds_is_channel_playing(i) == TRUE ) { - n++; - } - } - } - - return n; -#else - int i,n; - - n = 0; - for ( i = 0; i < MAX_CHANNELS; i++ ) { - if ( Channels[i].pdsb ) { - if ( ds_is_channel_playing(i) == TRUE ) { - n++; - } - } - } - - return n; -#endif -} - -// retreive raw data from a sound buffer -int ds_get_data(int sid, char *data) -{ -#ifdef PLAT_UNIX - STUB_FUNCTION; - - return -1; -#else - HRESULT dsrval; - LPDIRECTSOUNDBUFFER pdsb; - DSBCAPS caps; - void *buffer_data; - DWORD buffer_size; - - Assert(sid >= 0); - pdsb = ds_software_buffers[sid].pdsb; - - memset(&caps, 0, sizeof(DSBCAPS)); - caps.dwSize = sizeof(DSBCAPS); - dsrval = pdsb->GetCaps(&caps); - if ( dsrval != DS_OK ) { - return -1; - } - - // lock the entire buffer - dsrval = pdsb->Lock(0, caps.dwBufferBytes, &buffer_data, &buffer_size, 0, 0, 0); - if ( dsrval != DS_OK ) { - return -1; - } - - memcpy(data, buffer_data, buffer_size); - - dsrval = pdsb->Unlock(buffer_data, buffer_size, 0, 0); - if ( dsrval != DS_OK ) { - return -1; - } - - return 0; -#endif -} - -// return the size of the raw sound data -int ds_get_size(int sid, int *size) -{ -#ifdef PLAT_UNIX - Assert(sid >= 0); - - STUB_FUNCTION; - - return -1; -#else - HRESULT dsrval; - LPDIRECTSOUNDBUFFER pdsb; - DSBCAPS caps; - - Assert(sid >= 0); - pdsb = ds_software_buffers[sid].pdsb; - - memset(&caps, 0, sizeof(DSBCAPS)); - caps.dwSize = sizeof(DSBCAPS); - dsrval = pdsb->GetCaps(&caps); - if ( dsrval != DS_OK ) { - return -1; - } - - *size = caps.dwBufferBytes; -#endif -} - -int ds_using_ds3d() -{ - return Ds_use_ds3d; -} - -// Return the primary buffer interface. Note that we cast to a uint to avoid -// having to include dsound.h (and thus windows.h) in ds.h. -// -uint ds_get_primary_buffer_interface() -{ -#ifdef PLAT_UNIX - // unused - return 0; -#else - return (uint)pPrimaryBuffer; -#endif -} - -// Return the DirectSound Interface. -// -uint ds_get_dsound_interface() -{ -#ifdef PLAT_UNIX - // unused - return 0; -#else - return (uint)pDirectSound; -#endif -} - -uint ds_get_property_set_interface() -{ -#ifdef PLAT_UNIX - return 0; -#else - return (uint)pPropertySet; -#endif -} - -// -------------------- -// -// EAX Functions below -// -// -------------------- - -// Set the master volume for the reverb added to all sound sources. -// -// volume: volume, range from 0 to 1.0 -// -// returns: 0 if the volume is set successfully, otherwise return -1 -// -int ds_eax_set_volume(float volume) -{ -#ifdef PLAT_UNIX - return -1; -#else - HRESULT hr; - - if (Ds_eax_inited == 0) { - return -1; - } - - Assert(Ds_eax_reverb); - - CAP(volume, 0.0f, 1.0f); - - hr = Ds_eax_reverb->Set(DSPROPSETID_EAX_ReverbProperties_Def, DSPROPERTY_EAX_VOLUME, NULL, 0, &volume, sizeof(float)); - if (SUCCEEDED(hr)) { - return 0; - } else { - return -1; - } -#endif -} - -// Set the decay time for the EAX environment (ie all sound sources) -// -// seconds: decay time in seconds -// -// returns: 0 if decay time is successfully set, otherwise return -1 -// -int ds_eax_set_decay_time(float seconds) -{ -#ifdef PLAT_UNIX - return -1; -#else - HRESULT hr; - - if (Ds_eax_inited == 0) { - return -1; - } - - Assert(Ds_eax_reverb); - - CAP(seconds, 0.1f, 20.0f); - - hr = Ds_eax_reverb->Set(DSPROPSETID_EAX_ReverbProperties_Def, DSPROPERTY_EAX_DECAYTIME, NULL, 0, &seconds, sizeof(float)); - if (SUCCEEDED(hr)) { - return 0; - } else { - return -1; - } -#endif -} - -// Set the damping value for the EAX environment (ie all sound sources) -// -// damp: damp value from 0 to 2.0 -// -// returns: 0 if the damp value is successfully set, otherwise return -1 -// -int ds_eax_set_damping(float damp) -{ -#ifdef PLAT_UNIX - return -1; -#else - HRESULT hr; - - if (Ds_eax_inited == 0) { - return -1; - } - - Assert(Ds_eax_reverb); - - CAP(damp, 0.0f, 2.0f); - - hr = Ds_eax_reverb->Set(DSPROPSETID_EAX_ReverbProperties_Def, DSPROPERTY_EAX_DAMPING, NULL, 0, &damp, sizeof(float)); - if (SUCCEEDED(hr)) { - return 0; - } else { - return -1; - } -#endif -} - -// Set up the environment type for all sound sources. -// -// envid: value from the EAX_ENVIRONMENT_* enumeration in ds_eax.h -// -// returns: 0 if the environment is set successfully, otherwise return -1 -// -int ds_eax_set_environment(unsigned long envid) -{ -#ifdef PLAT_UNIX - return -1; -#else - HRESULT hr; - - if (Ds_eax_inited == 0) { - return -1; - } - - Assert(Ds_eax_reverb); - - hr = Ds_eax_reverb->Set(DSPROPSETID_EAX_ReverbProperties_Def, DSPROPERTY_EAX_ENVIRONMENT, NULL, 0, &envid, sizeof(unsigned long)); - if (SUCCEEDED(hr)) { - return 0; - } else { - return -1; - } -#endif -} - -// Set up a predefined environment for EAX -// -// envid: value from teh EAX_ENVIRONMENT_* enumeration -// -// returns: 0 if successful, otherwise return -1 -// -int ds_eax_set_preset(unsigned long envid) -{ -#ifdef PLAT_UNIX - return -1; -#else - HRESULT hr; - - if (Ds_eax_inited == 0) { - return -1; - } - - Assert(Ds_eax_reverb); - Assert(envid < EAX_ENVIRONMENT_COUNT); - - hr = Ds_eax_reverb->Set(DSPROPSETID_EAX_ReverbProperties_Def, DSPROPERTY_EAX_ALL, NULL, 0, &Ds_eax_presets[envid], sizeof(EAX_REVERBPROPERTIES)); - if (SUCCEEDED(hr)) { - return 0; - } else { - return -1; - } -#endif -} - - -// Set up all the parameters for an environment -// -// id: value from teh EAX_ENVIRONMENT_* enumeration -// volume: volume for the environment (0 to 1.0) -// damping: damp value for the environment (0 to 2.0) -// decay: decay time in seconds (0.1 to 20.0) -// -// returns: 0 if successful, otherwise return -1 -// -int ds_eax_set_all(unsigned long id, float vol, float damping, float decay) -{ -#ifdef PLAT_UNIX - return -1; -#else - HRESULT hr; - - if (Ds_eax_inited == 0) { - return -1; - } - - Assert(Ds_eax_reverb); - Assert(id < EAX_ENVIRONMENT_COUNT); - - EAX_REVERBPROPERTIES er; - - er.environment = id; - er.fVolume = vol; - er.fDecayTime_sec = decay; - er.fDamping = damping; - - hr = Ds_eax_reverb->Set(DSPROPSETID_EAX_ReverbProperties_Def, DSPROPERTY_EAX_ALL, NULL, 0, &er, sizeof(EAX_REVERBPROPERTIES)); - if (SUCCEEDED(hr)) { - return 0; - } else { - return -1; - } -#endif -} - -// Get up the parameters for the current environment -// -// er: (output) hold environment parameters -// -// returns: 0 if successful, otherwise return -1 -// -int ds_eax_get_all(EAX_REVERBPROPERTIES *er) -{ -#ifdef PLAT_UNIX - return -1; -#else - HRESULT hr; - unsigned long outsize; - - if (Ds_eax_inited == 0) { - return -1; - } - - Assert(Ds_eax_reverb); - - hr = Ds_eax_reverb->Get(DSPROPSETID_EAX_ReverbProperties_Def, DSPROPERTY_EAX_ALL, NULL, 0, er, sizeof(EAX_REVERBPROPERTIES), &outsize); - if (SUCCEEDED(hr)) { - return 0; - } else { - return -1; - } -#endif -} - -// Close down EAX, freeing any allocated resources -// -void ds_eax_close() -{ -#ifndef PLAT_UNIX - if (Ds_eax_inited == 0) { - return; - } - - Ds_eax_inited = 0; -#endif -} - -// Initialize EAX -// -// returns: 0 if initialization is successful, otherwise return -1 -// -int ds_eax_init() -{ -#ifndef PLAT_UNIX - HRESULT hr; - unsigned long driver_support = 0; - - if (Ds_eax_inited) { - return 0; - } - - Assert(Ds_eax_reverb == NULL); - - Ds_eax_reverb = (LPKSPROPERTYSET)ds_get_property_set_interface(); - if (Ds_eax_reverb == NULL) { - return -1; - } - - // check if the listener property is supported by the audio driver - hr = Ds_eax_reverb->QuerySupport(DSPROPSETID_EAX_ReverbProperties_Def, DSPROPERTY_EAX_ALL, &driver_support); - if (FAILED(hr)) { - nprintf(("Sound", "QuerySupport for the EAX Listener property set failed.. disabling EAX\n")); - goto ds_eax_init_failed; - } - - if ((driver_support & (KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET)) != (KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET)) { - goto ds_eax_init_failed; - } - - ds_eax_set_all(EAX_ENVIRONMENT_GENERIC, 0.0f, 0.0f, 0.0f); - - Ds_eax_inited = 1; - return 0; - -ds_eax_init_failed: - if (Ds_eax_reverb != NULL) { - Ds_eax_reverb->Release(); - Ds_eax_reverb = NULL; - } - - Ds_eax_inited = 0; -#endif - - return -1; -} - -int ds_eax_is_inited() -{ -#ifdef PLAT_UNIX - return 0; -#else - return Ds_eax_inited; -#endif -} - -bool ds_using_a3d() -{ -#ifdef PLAT_UNIX - return false; -#else - if (Ds_use_a3d == 0) { - return false; - } else { - return true; - } -#endif -} - -// Called once per game frame to make sure voice messages aren't looping -// -void ds_do_frame() -{ - channel *cp; - - if (!ds_initialized) { - return; - } - - for (int i=0; iis_voice_msg == true) { - if (cp->source_id == 0) { - continue; - } - - DWORD current_position = ds_get_play_position(i); - if (current_position != 0) { - if (current_position < (DWORD)cp->last_position) { -#ifdef PLAT_UNIX - ds_stop_channel(i); -#else - ds_close_channel(i); -#endif - } else { - cp->last_position = current_position; - } - } - } - } -} - -#ifdef PLAT_UNIX -void ds3d_close() -{ - STUB_FUNCTION; -} - -int ds3d_update_buffer(int channel, float min, float max, vector *pos, vector *vel) -{ - STUB_FUNCTION; - - return -1; -} - -int ds3d_update_listener(vector *pos, vector *vel, matrix *orient) -{ - STUB_FUNCTION; - -#if 0 - ALfloat posv[] = { pos->x, pos->y, pos->z }; - ALfloat velv[] = { vel->x, vel->y, vel->z }; - ALfloat oriv[] = { orient->a1d[0], - orient->a1d[1], orient->a1d[2], - orient->a1d[3], orient->a1d[4], - orient->a1d[5] }; - alListenerfv(AL_POSITION, posv); - alListenerfv(AL_VELOCITY, velv); - alListenerfv(AL_ORIENTATION, oriv); -#endif - - return -1; -} - -int ds3d_init (int unused) -{ - STUB_FUNCTION; - -#if 0 - ALfloat pos[] = { 0.0, 0.0, 0.0 }, - vel[] = { 0.0, 0.0, 0.0 }, - ori[] = { 0.0, 0.0, 1.0, 0.0, -1.0, 0.0 }; - - alListenerfv (AL_POSITION, pos); - alListenerfv (AL_VELOCITY, vel); - alListenerfv (AL_ORIENTATION, ori); - - if(alGetError() != AL_NO_ERROR) - return -1; - - return 0; -#endif - - return -1; -} - -void dscap_close() -{ - STUB_FUNCTION; -} - -int dscap_create_buffer(int freq, int bits_per_sample, int nchannels, int nseconds) -{ - STUB_FUNCTION; - - return -1; -} - -int dscap_get_raw_data(unsigned char *outbuf, unsigned int max_size) -{ - STUB_FUNCTION; - - return -1; -} - -int dscap_max_buffersize() -{ - STUB_FUNCTION; - - return -1; -} - -void dscap_release_buffer() -{ - STUB_FUNCTION; -} - -int dscap_start_record() -{ - STUB_FUNCTION; - - return -1; -} - -int dscap_stop_record() -{ - STUB_FUNCTION; - - return -1; -} - -int dscap_supported() -{ - STUB_FUNCTION; - - return 0; -} -#endif diff --git a/src/sound/ds3d.cpp b/src/sound/ds3d.cpp deleted file mode 100644 index d363c14..0000000 --- a/src/sound/ds3d.cpp +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright (C) Volition, Inc. 1999. All rights reserved. - * - * All source code herein is the property of Volition, Inc. You may not sell - * or otherwise commercially exploit the source or things you created based on - * the source. - */ - -/* - * $Logfile: /Freespace2/code/Sound/ds3d.cpp $ - * $Revision$ - * $Date$ - * $Author$ - * - * C file for interface to DirectSound3D - * - * $Log$ - * Revision 1.2 2002/06/09 04:41:27 relnev - * added copyright header - * - * Revision 1.1.1.1 2002/05/03 03:28:10 root - * Initial import. - * - * - * 12 8/05/99 4:45p Alanl - * the FINAL tweak to rolloffs! - * - * 11 8/05/99 4:34p Alanl - * change rolloff factors again - * - * 10 8/05/99 4:27p Danw - * would you believe we're still tweaking the EAX?? :) - * - * 9 8/05/99 4:04p Danw - * tweak rolloffs for EAX - * 8 8/05/99 2:54p Danw - * tweak rolloffs for A3D and EAX - * 7 8/05/99 10:54a Alanl - * change EAX rolloff to 3.0 - * - * 6 8/04/99 11:51a Danw - * tweak rolloffs for A3D and EAX - * 5 8/04/99 11:42a Danw - * tweak rolloffs for A3D and EAX - * - * 4 8/01/99 2:06p Alanl - * increase the rolloff for A3D - * - * 3 5/23/99 8:11p Alanl - * Added support for EAX - * - * 2 10/07/98 10:54a Dave - * Initial checkin. - * - * 1 10/07/98 10:51a Dave - * - * 15 5/06/98 2:16p Dan - * - * 14 5/05/98 4:49p Lawrance - * Put in code to authenticate A3D, improve A3D support - * - * 13 4/19/98 9:30p Lawrance - * Use Aureal_enabled flag - * - * 12 9/09/97 3:39p Sandeep - * warning level 4 bugs - * - * 11 8/01/97 10:40a Lawrance - * decrease rolloff for DirectSound3D sounds - * - * 10 7/29/97 2:54p Lawrance - * - * 9 7/28/97 11:39a Lawrance - * allow individual volume scaling on 3D buffers - * - * 8 7/17/97 9:32a John - * made all directX header files name start with a v - * - * 7 6/09/97 11:50p Lawrance - * integrating DirectSound3D - * - * 6 6/09/97 8:53a Lawrance - * remove warning - * - * 5 6/08/97 5:59p Lawrance - * integrate DirectSound3D into sound system - * - * 4 6/02/97 1:45p Lawrance - * implementing hardware mixing - * - * 3 5/29/97 4:02p Lawrance - * listener interface in place - * - * 2 5/29/97 12:03p Lawrance - * creation of file to hold DirectSound3D specific code - * - * $NoKeywords: $ - */ - -#include "pstypes.h" -#include -#include -#include "vdsound.h" - -#include "ds3d.h" -#include "ds.h" -#include "channel.h" -#include "sound.h" -#include "object.h" - -typedef enum -{ - DSPROPERTY_VMANAGER_MODE = 0, - DSPROPERTY_VMANAGER_PRIORITY, - DSPROPERTY_VMANAGER_STATE -} DSPROPERTY_VMANAGER; - - -typedef enum -{ - DSPROPERTY_VMANAGER_MODE_DEFAULT = 0, - DSPROPERTY_VMANAGER_MODE_AUTO, - DSPROPERTY_VMANAGER_MODE_REPORT, - DSPROPERTY_VMANAGER_MODE_USER -} VmMode; - - -typedef enum -{ - DSPROPERTY_VMANAGER_STATE_PLAYING3DHW = 0, - DSPROPERTY_VMANAGER_STATE_SILENT, - DSPROPERTY_VMANAGER_STATE_BUMPED, - DSPROPERTY_VMANAGER_STATE_PLAYFAILED -} VmState; - - -extern LPDIRECTSOUND pDirectSound; - -int DS3D_inited = FALSE; - -LPDIRECTSOUND3DLISTENER pDS3D_listener = NULL; - -GUID DSPROPSETID_VoiceManager_Def = {0x62a69bae, 0xdf9d, 0x11d1, {0x99, 0xa6, 0x0, 0xc0, 0x4f, 0xc9, 0x9d, 0x46}}; - -// --------------------------------------------------------------------------------------- -// ds3d_update_buffer() -// -// parameters: channel => identifies the 3D sound to update -// min => the distance at which sound doesn't get any louder -// max => the distance at which sound doesn't attenuate any further -// pos => world position of sound -// vel => velocity of the objects producing the sound -// -// returns: 0 => success -// -1 => failure -// -// -int ds3d_update_buffer(int channel, float min, float max, vector *pos, vector *vel) -{ - HRESULT hr; - LPDIRECTSOUND3DBUFFER pds3db; - float max_dist, min_dist; - - if (DS3D_inited == FALSE) - return 0; - - if ( channel == -1 ) - return 0; - - pds3db = Channels[channel].pds3db; - Assert( pds3db != NULL); - - // set the buffer position - if ( pos != NULL ) { - hr = pds3db->SetPosition(pos->x, pos->y, pos->z, DS3D_DEFERRED); - } - - // set the buffer veclocity - if ( vel != NULL ) { - hr = pds3db->SetVelocity(vel->x, vel->y, vel->z, DS3D_DEFERRED); - } - else { - hr = pds3db->SetVelocity(0.0f, 0.0f, 0.0f, DS3D_DEFERRED); - } - - // set the min distance - hr = pds3db->GetMinDistance(&min_dist); - hr = pds3db->SetMinDistance( min, DS3D_DEFERRED ); - // set the max distance - hr = pds3db->GetMaxDistance(&max_dist); -// hr = pds3db->SetMaxDistance( max, DS3D_DEFERRED ); - hr = pds3db->SetMaxDistance( 100000.0f, DS3D_DEFERRED ); - - return 0; -} - - -// --------------------------------------------------------------------------------------- -// ds3d_update_listener() -// -// returns: 0 => success -// -1 => failure -// -int ds3d_update_listener(vector *pos, vector *vel, matrix *orient) -{ - HRESULT hr; - - if (DS3D_inited == FALSE) - return 0; - - if ( pDS3D_listener == NULL ) - return -1; - - // set the listener position - if ( pos != NULL ) { - hr = pDS3D_listener->SetPosition(pos->x, pos->y, pos->z, DS3D_DEFERRED); - } - - // set the listener veclocity - if ( vel != NULL ) { - hr = pDS3D_listener->SetVelocity(vel->x, vel->y, vel->z, DS3D_DEFERRED); - } - - if ( orient != NULL ) { - hr = pDS3D_listener->SetOrientation( orient->fvec.x, orient->fvec.y, orient->fvec.z, - orient->uvec.x, orient->uvec.y, orient->uvec.z, - DS3D_DEFERRED ); - } - - float rolloff_factor = 1.0f; - if (ds_using_a3d() == true) { - rolloff_factor = 3.0f; // A3D rolloff - } else { - rolloff_factor = 3.0f; // EAX rolloff - } - - hr = pDS3D_listener->SetRolloffFactor( rolloff_factor, DS3D_DEFERRED ); - hr = pDS3D_listener->SetDopplerFactor( 1.0f, DS3D_DEFERRED ); - - hr = pDS3D_listener->CommitDeferredSettings(); - if ( hr != DS_OK ) { - nprintf(("SOUND","Error in pDS3D_listener->CommitDeferredSettings(): %s\n", get_DSERR_text(hr) )); - return -1; - } - - return 0; -} - -// --------------------------------------------------------------------------------------- -// ds3d_init_listener() -// -// -// returns: 0 => success -// -1 => failure -// -int ds3d_init_listener() -{ - HRESULT hr; - - if ( pDS3D_listener != NULL ) - return 0; - - hr = pPrimaryBuffer->QueryInterface(IID_IDirectSound3DListener, (void**)&pDS3D_listener); - if (hr != DS_OK) { - nprintf(("Sound","SOUND => Fatal error calling pPrimaryBuffer->QueryInterface(): %s\n", get_DSERR_text(hr) )); - return -1; - } - - return 0; -} - -// --------------------------------------------------------------------------------------- -// ds3d_close_listener() -// -// -void ds3d_close_listener() -{ - if ( pDS3D_listener != NULL ) { - pDS3D_listener->Release(); - pDS3D_listener = NULL; - } -} - - -// --------------------------------------------------------------------------------------- -// ds3d_init() -// -// Initialize the DirectSound3D system. Call the initalization for the pDS3D_listener -// -// returns: -1 => init failed -// 0 => success -int ds3d_init(int voice_manager_required) -{ - if ( DS3D_inited == TRUE ) - return 0; - - if (voice_manager_required == 1) { - LPKSPROPERTYSET pset; - pset = (LPKSPROPERTYSET)ds_get_property_set_interface(); - - if (pset == NULL) { - nprintf(("Sound", "Disabling DirectSound3D since unable to get property set interface\n")); - return -1; - } - - HRESULT hr; - unsigned long driver_support = 0; - - hr = pset->QuerySupport(DSPROPSETID_VoiceManager_Def, DSPROPERTY_VMANAGER_MODE, &driver_support); - if (FAILED(hr)) { - nprintf(("Sound", "Driver does not support Voice Manager extension, so abort DirectSound3D initialization\n")); - return -1; - } - - if ((driver_support & KSPROPERTY_SUPPORT_SET|KSPROPERTY_SUPPORT_GET) != (KSPROPERTY_SUPPORT_SET|KSPROPERTY_SUPPORT_GET)) { - nprintf(("Sound", "Driver does not support Voice Manager extension, so abort DirectSound3D initialization\n")); - return -1; - } - - VmMode vmode = DSPROPERTY_VMANAGER_MODE_AUTO; - hr = pset->Set(DSPROPSETID_VoiceManager_Def, DSPROPERTY_VMANAGER_MODE, NULL, 0, &vmode, sizeof(float)); - if (FAILED(hr)) { - nprintf(("Sound", "Driver does not support Voice Manager extension, so abort DirectSound3D initialization\n")); - return -1; - } - } - - if (ds3d_init_listener() != 0) { - return -1; - } - - DS3D_inited = TRUE; - return 0; -} - - -// --------------------------------------------------------------------------------------- -// ds3d_close() -// -// De-initialize the DirectSound3D system -// -void ds3d_close() -{ - if ( DS3D_inited == FALSE ) - return; - - ds3d_close_listener(); - DS3D_inited = FALSE; -} - diff --git a/src/sound/dscap.cpp b/src/sound/dscap.cpp deleted file mode 100644 index ac31712..0000000 --- a/src/sound/dscap.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (C) Volition, Inc. 1999. All rights reserved. - * - * All source code herein is the property of Volition, Inc. You may not sell - * or otherwise commercially exploit the source or things you created based on - * the source. - */ - -/* - * $Logfile: /Freespace2/code/Sound/dscap.cpp $ - * $Revision$ - * $Date$ - * $Author$ - * - * C module for DirectSoundCapture code - * - * $Log$ - * Revision 1.3 2002/06/09 04:41:27 relnev - * added copyright header - * - * Revision 1.2 2002/05/07 03:16:52 theoddone33 - * The Great Newline Fix - * - * Revision 1.1.1.1 2002/05/03 03:28:10 root - * Initial import. - * - * - * 2 10/07/98 10:54a Dave - * Initial checkin. - * - * 1 10/07/98 10:51a Dave - * - * 11 5/05/98 4:49p Lawrance - * Put in code to authenticate A3D, improve A3D support - * - * 10 4/24/98 2:17a Lawrance - * Clear out record buffer when recording begins - * - * 9 3/24/98 9:37a Lawrance - * Only read up to a safe offset in the capture buffer. - * - * 8 3/22/98 7:13p Lawrance - * Get streaming of recording voice working - * - * 7 2/26/98 2:54p Lawrance - * Don't recreate capture buffer each time recording starts... just use - * one. - * - * 6 2/15/98 11:10p Lawrance - * more work on real-time voice system - * - * 5 2/15/98 4:43p Lawrance - * work on real-time voice - * - * 4 2/09/98 8:07p Lawrance - * get buffer create working - * - * 3 2/04/98 6:08p Lawrance - * Read function pointers from dsound.dll, further work on - * DirectSoundCapture. - * - * 2 2/03/98 11:53p Lawrance - * Adding support for DirectSoundCapture - * - * 1 2/03/98 4:48p Lawrance - * - * $NoKeywords: $ - */ - -#include "pstypes.h" -#include "ds.h" -#include "dscap.h" - -int dscap_inited=0; // flag to indicate that DirectSoundCapture inited ok -int dscap_recording; // flag to indicate that sound is being recorded - -static LPDIRECTSOUNDCAPTURE pDSC; // global capture interface -static LPDIRECTSOUNDCAPTUREBUFFER pDSCB; // global capture buffer - -static WAVEFORMATEX Dscap_wfx; - -static unsigned long Dscap_last_capture_offset; - -// init the DirectSoundCapture system -// exit: 0 -> success -// !0 -> failure -int dscap_init() -{ - HRESULT dsrval; - - if ( dscap_inited ) { - return 0; - } - - if ( !pfn_DirectSoundCaptureCreate ) { - nprintf(( "Sound", "SOUND ==> Could not get DirectSoundCaptureCreate function pointer\n" )); - return -1; - } - - dsrval = pfn_DirectSoundCaptureCreate(NULL, &pDSC, NULL); - - if ( dsrval != DS_OK ) { - nprintf(( "Sound", "SOUND ==> Error '%s' initializing DirectSoundCapture.\n", get_DSERR_text(dsrval) )); - return -1; - } - - pDSCB=NULL; - - dscap_recording=0; - dscap_inited=1; - - return 0; -} - -void dscap_release_buffer() -{ - if ( !pDSCB ) { - return; - } - - pDSCB->Release(); - pDSCB = NULL; -} - -// create a capture buffer with the specified format -// exit: 0 -> buffer created successfully -// !0 -> error creating the buffer -int dscap_create_buffer(int freq, int bits_per_sample, int nchannels, int nseconds) -{ - HRESULT dsrval; - DSCBUFFERDESC dscbd; - WAVEFORMATEX wfx; - - if ( !dscap_inited ) { - dscap_init(); - } - - if ( !dscap_inited ) { - return -1; - } - - // Set up recording format - wfx.wFormatTag = WAVE_FORMAT_PCM; - wfx.nChannels = (unsigned short)nchannels; - wfx.nSamplesPerSec = freq; - wfx.wBitsPerSample = (unsigned short)bits_per_sample; - wfx.cbSize = 0; - wfx.nBlockAlign = (unsigned short)(wfx.nChannels * (wfx.wBitsPerSample / 8)); - wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec; - - Dscap_wfx = wfx; // save the recording format - - if ( pDSCB ) { - dscap_release_buffer(); - } - - memset(&dscbd, 0, sizeof(DSCBUFFERDESC)); - dscbd.dwSize = sizeof(DSCBUFFERDESC); - dscbd.dwBufferBytes = wfx.nAvgBytesPerSec * nseconds; - dscbd.lpwfxFormat = &wfx; - - dsrval = pDSC->CreateCaptureBuffer(&dscbd, &pDSCB, NULL); - if ( dsrval != DS_OK ) { - nprintf(( "Sound", "SOUND ==> Error '%s' creating a DirectSoundCapture buffer.\n", get_DSERR_text(dsrval) )); - return -1; - } - - Dscap_last_capture_offset=0; - return 0; -} - -// check if DirectSoundCapture is supported -int dscap_supported() -{ - if ( !dscap_inited ) { - dscap_init(); - } - return dscap_inited; -} - -// fill up the capture buffer with silence -int dscap_fill_buffer_with_silence() -{ - HRESULT dsrval; - unsigned long buffer_len, size1, size2; - void *data1=NULL, *data2=NULL; - - buffer_len = dscap_max_buffersize(); - - Assert(pDSCB); - - dsrval = pDSCB->Lock(0, buffer_len, &data1, &size1, &data2, &size2, 0); - if ( dsrval != DS_OK ) { - return -1; - } - - unsigned char silence_byte; - - switch(Dscap_wfx.wBitsPerSample) { - case 8: - silence_byte = 0x80; - break; - case 16: - silence_byte = 0x00; - break; - default: - Int3(); - return -1; - } - - if ( (data1) && (size1 > 0) ) { - memset(data1, silence_byte, size1); - } - - if ( (data2) && (size2 > 0) ) { - memset(data2, silence_byte, size2); - } - - dsrval = pDSCB->Unlock(data1, size1, data2, size2); - if ( dsrval != DS_OK ) { - return -1; - } - - return 0; -} - -// start recording into the buffer -int dscap_start_record() -{ - HRESULT dsrval; - - if ( !dscap_inited ) { - dscap_init(); - } - - if ( !dscap_inited ) { - return -1; - } - - if ( dscap_recording ) { - return -1; - } - - Assert(pDSCB); - - dscap_fill_buffer_with_silence(); - - dsrval = pDSCB->Start(DSCBSTART_LOOPING); - if ( dsrval != DS_OK ) { - return -1; - } - - dscap_recording=1; -// nprintf(("Alan","RTVOICE => start record\n")); - return 0; -} - -// stop recording into the buffer -int dscap_stop_record() -{ - HRESULT dsrval; - - if ( !dscap_inited ) { - return -1; - } - - if ( !dscap_recording ) { - return -1; - } - - Assert(pDSCB); - dsrval = pDSCB->Stop(); - if ( dsrval != DS_OK ) { - return -1; - } - - dscap_recording=0; -// nprintf(("Alan","RTVOICE => stop record\n")); - return 0; -} - -// close the DirectSoundCapture system -void dscap_close() -{ - dscap_stop_record(); - dscap_release_buffer(); - - if ( pDSC ) { - pDSC->Release(); - pDSC=NULL; - } -} - -// return the max buffer size -int dscap_max_buffersize() -{ - DSCBCAPS caps; - - if ( !dscap_inited ) { - dscap_init(); - } - - if ( !dscap_inited ) { - return -1; - } - - if (!pDSCB) { - return 0; - } - - caps.dwSize = sizeof(DSCBCAPS); - caps.dwFlags = 0; - - pDSCB->GetCaps(&caps); - - return caps.dwBufferBytes; -} - -// retreive the recorded voice data -int dscap_get_raw_data(unsigned char *outbuf, unsigned int max_size) -{ - HRESULT dsrval; - unsigned long capture_offset, read_offset, num_bytes_captured, size1, size2; - void *data1=NULL, *data2=NULL; - - if ( !dscap_inited ) { - dscap_init(); - } - - if ( !dscap_inited ) { - return -1; - } - - if ( !pDSCB ) { - return -1; - } - - dsrval = pDSCB->GetCurrentPosition(&capture_offset, &read_offset); - if ( dsrval != DS_OK ) { - return -1; - } - - if ( read_offset >= Dscap_last_capture_offset ) { - num_bytes_captured = read_offset-Dscap_last_capture_offset; - } else { - unsigned long max_size = dscap_max_buffersize(); - num_bytes_captured = max_size - Dscap_last_capture_offset + read_offset; - } - - if ( num_bytes_captured <= 0 ) { - return -1; - } - - dsrval = pDSCB->Lock(Dscap_last_capture_offset, num_bytes_captured, &data1, &size1, &data2, &size2, 0); - if ( dsrval != DS_OK ) { - return -1; - } - - if ( max_size < (size1+size2) ) { - return -1; - } - - if ( (data1) && (size1 > 0) ) { - memcpy(outbuf, data1, size1); - } - - if ( (data2) && (size2 > 0) ) { - memcpy(outbuf+size1, data2, size2); - } - - dsrval = pDSCB->Unlock(data1, size1, data2, size2); - if ( dsrval != DS_OK ) { - return -1; - } - - Dscap_last_capture_offset = read_offset; - return (size1+size2); -} - diff --git a/src/sound/oal.cpp b/src/sound/oal.cpp new file mode 100644 index 0000000..e381410 --- /dev/null +++ b/src/sound/oal.cpp @@ -0,0 +1,1275 @@ +/* + * Copyright (C) Volition, Inc. 1999. All rights reserved. + * + * All source code herein is the property of Volition, Inc. You may not sell + * or otherwise commercially exploit the source or things you created based on + * the source. + */ + +#include +#include + +#include "pstypes.h" +#include "oal.h" +#include "oal_efx.h" +#include "cfile.h" +#include "sound.h" +#include "acm.h" + + +static int OAL_inited = 0; + +static ALCdevice *al_device = NULL; +static ALCcontext *al_context = NULL; + + +struct sound_buffer { + ALuint buf_id; // OpenAL buffer id + int chan_idx; // channel index this buffer is currently bound to + + int frequency; + int bits_per_sample; + int nchannels; + int nseconds; + int nbytes; + + sound_buffer() : buf_id(0), chan_idx(-1), frequency(0), bits_per_sample(0), + nchannels(0), nseconds(0), nbytes(0) + { + } +}; + +static std::vector Buffers; + +static std::vector Channels; +static int channel_next_sig = 1; + + +bool oal_check_for_errors(const char *location) +{ + ALenum err = alGetError(); + + if (err != AL_NO_ERROR) { + if (location) { + const char *str = alGetString(err); + + nprintf(("OpenAL", "AL-ERROR (%s) => 0x%x: %s", location, err, (str) ? str : "??")); + } else { + nprintf(("OpenAL", "AL-ERROR => 0x%x: %s", err, alGetString(err))); + } + + return true; + } + + return false; +} + +static void oal_init_channels() +{ + const int MAX_SOURCES = 32; + + Channels.reserve(MAX_SOURCES); + + for (int n = 0; n < MAX_SOURCES; n++) { + sound_channel n_channel; + + alGenSources(1, &n_channel.source_id); + + if ( !n_channel.source_id || (alGetError() != AL_NO_ERROR) ) { + break; + } + + Channels.push_back(n_channel); + } +} + +int oal_init(int use_eax) +{ + ALint ver_major = 0, ver_minor = 0; + + if (OAL_inited) { + return 0; + } + + nprintf(( "Sound", "SOUND ==> Initializing OpenAL...\n" )); + + oal_check_for_errors("oal_init() begin"); + + alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &ver_major); + alcGetIntegerv(NULL, ALC_MINOR_VERSION, 1, &ver_minor); + + if ( (ver_major < 1) || (ver_minor < 1) ) { + nprintf(("Sound", "SOUND ==> Minimum supported OpenAL version is 1.1\n")); + return -1; + } + + al_device = alcOpenDevice(NULL); + + if (al_device == NULL) { + nprintf(("Sound", "SOUND ==> Unable to open device!\n")); + nprintf(("Sound", "SOUND ==> %s", alcGetString(al_device, alcGetError(al_device)))); + return -1; + } + + al_context = alcCreateContext(al_device, NULL); + + if (al_context == NULL) { + nprintf(("Sound", "SOUND ==> Unable to create context!\n")); + nprintf(("Sound", "SOUND ==> %s", alcGetString(al_device, alcGetError(al_device)))); + + alcCloseDevice(al_device); + al_device = NULL; + + return -1; + } + + alcMakeContextCurrent(al_context); + + oal_init_channels(); + + Buffers.reserve(64); + + if (use_eax) { + oal_efx_init(); + } + + OAL_inited = 1; + + oal_check_for_errors("oal_init() end"); + + return 0; +} + +void oal_close() +{ + if ( !OAL_inited ) { + return; + } + + while ( !Channels.empty() ) { + ALint processed = 0; + ALuint bid; + ALuint sid = Channels.back().source_id; + + alSourceStop(sid); + + alGetSourcei(sid, AL_BUFFERS_PROCESSED, &processed); + + while (processed > 0) { + alSourceUnqueueBuffers(sid, 1, &bid); + --processed; + } + + alSourcei(sid, AL_BUFFER, 0); + + alDeleteSources(1, &sid); + + Channels.pop_back(); + } + + while ( !Buffers.empty() ) { + ALuint bid = Buffers.back().buf_id; + + alDeleteBuffers(1, &bid); + + Buffers.pop_back(); + } + + Channels.clear(); + Buffers.clear(); + + alcMakeContextCurrent(NULL); + alcDestroyContext(al_context); + alcCloseDevice(al_device); + + al_context = NULL; + al_device = NULL; + + OAL_inited = 0; +} + +int oal_get_channel(int sig) +{ + int i; + + if ( !OAL_inited ) { + return -1; + } + + int size = (int)Channels.size(); + + for (i = 0; i < size; i++) { + if (Channels[i].sig == sig) { + ALint status; + + alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &status); + + if (status == AL_PLAYING) { + return i; + } else { + return -1; + } + } + } + + return -1; +} + +int oal_get_number_channels() +{ + int i; + ALint status; + int count = 0; + + if ( !OAL_inited ) { + return -1; + } + + int size = (int)Channels.size(); + + for (i = 0; i < size; i++) { + alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &status); + + if (status == AL_PLAYING) { + count++; + } + } + + return count; +} + +void oal_stop_buffer(int sid) +{ + if ( !OAL_inited ) { + return; + } + + oal_check_for_errors("oal_stop_buffer() begin"); + + SDL_assert( sid >= 0 ); + SDL_assert( sid < (int)Buffers.size() ); + + int cid = Buffers[sid].chan_idx; + + if (cid != -1) { + ALuint source_id = Channels[cid].source_id; + + alSourceStop(source_id); + } + + oal_check_for_errors("oal_stop_buffer() end"); +} + +void oal_stop_channel(int channel) +{ + ALint processed = 0; + ALuint bid; + + if ( !OAL_inited ) { + return; + } + + SDL_assert( channel >= 0 ); + SDL_assert( channel < (int)Channels.size() ); + + oal_check_for_errors("oal_stop_channel() begin"); + + alSourceStop(Channels[channel].source_id); + + // if this channel was used for streaming, make sure to unqueue any buffers + if (Channels[channel].snd_id < 0) { + alGetSourcei(Channels[channel].source_id, AL_BUFFERS_PROCESSED, &processed); + + while (processed > 0) { + alSourceUnqueueBuffers(Channels[channel].source_id, 1, &bid); + --processed; + } + } + + oal_check_for_errors("oal_stop_channel() end"); +} + +void oal_stop_channel_all() +{ + if ( !OAL_inited ) { + return; + } + + int size = (int)Channels.size(); + + for (int i = 0; i < size; i++) { + oal_stop_channel(i); + } +} + +int oal_get_buffer_size(int sid, int *size) +{ + if ( !OAL_inited ) { + return -1; + } + + if ( (sid < 0) || (sid >= (int)Buffers.size()) ) { + return -1; + } + + *size = Buffers[sid].nbytes; + + return 0; +} + +int oal_get_channel_size(int channel) +{ + if ( !OAL_inited ) { + return -1; + } + + if ( (channel < 0) || (channel >= (int)Channels.size()) ) { + return -1; + } + + if (Channels[channel].buf_idx >= 0) { + return Buffers[Channels[channel].buf_idx].nbytes; + } + + return 0; +} + +// ----------------------------------------------------------------------------- +// Source properties *set functions +// ----------------------------------------------------------------------------- + +void oal_set_volume(int channel, float volume) +{ + if ( !OAL_inited ) { + return; + } + + SDL_assert( channel >= 0 ); + SDL_assert( channel < (int)Channels.size() ); + + oal_check_for_errors("oal_set_volume() begin"); + + alSourcef(Channels[channel].source_id, AL_GAIN, volume); + + oal_check_for_errors("oal_set_volume() end"); +} + +void oal_set_pan(int channel, float pan) +{ + if ( !OAL_inited ) { + return; + } + + SDL_assert( channel >= 0 ); + SDL_assert( channel < (int)Channels.size() ); + + oal_check_for_errors("oal_set_pan() begin"); + + alSource3f(Channels[channel].source_id, AL_POSITION, pan, 0.0f, 0.0f); + + oal_check_for_errors("oal_set_pan() end"); +} + +void oal_set_pitch(int channel, float pitch) +{ + if ( !OAL_inited ) { + return; + } + + SDL_assert( channel >= 0 ); + SDL_assert( channel < (int)Channels.size() ); + + oal_check_for_errors("oal_set_pitch() begin"); + + alSourcef(Channels[channel].source_id, AL_PITCH, pitch); + + oal_check_for_errors("oal_set_pitch() end"); +} + +void oal_set_play_position(int channel, int position) +{ + if ( !OAL_inited ) { + return; + } + + SDL_assert( channel >= 0 ); + SDL_assert( channel < (int)Channels.size() ); + + oal_check_for_errors("oal_set_play_position() begin"); + + alSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, position); + + oal_check_for_errors("oal_set_play_position() end"); +} + +void oal_set_source_properties_all(ALenum param, ALint *props) +{ + if (props == NULL) { + return; + } + + oal_check_for_errors("oal_set_source_properties_all() begin"); + + int size = (int)Channels.size(); + + // make sure there aren't any looping voice messages + for (int i = 0; i < size; i++) { + alSourceiv(Channels[i].source_id, param, props); + } + + oal_check_for_errors("oal_set_source_properties_all() end"); +} + +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// Source properties *get functions +// ----------------------------------------------------------------------------- + +float oal_get_pitch(int channel) +{ + float pitch = 1.0f; + + if ( !OAL_inited ) { + return 1.0f; + } + + SDL_assert( channel >= 0 ); + SDL_assert( channel < (int)Channels.size() ); + + oal_check_for_errors("oal_get_pitch() begin"); + + alGetSourcef(Channels[channel].source_id, AL_PITCH, &pitch); + + oal_check_for_errors("oal_get_pitch() end"); + + return pitch; +} + +int oal_get_play_position(int channel) +{ + ALint offset = 0; + + if ( !OAL_inited ) { + return 0; + } + + if (channel < 0) { + return 0; + } + + //SDL_assert( channel >= 0 ); + SDL_assert( channel < (int)Channels.size() ); + + oal_check_for_errors("oal_get_play_position() begin"); + + alGetSourcei(Channels[channel].source_id, AL_BYTE_OFFSET, &offset); + + if (alGetError() != AL_NO_ERROR) { + return offset; + } + + return 0; +} + +// ----------------------------------------------------------------------------- + +int oal_is_initted() +{ + return OAL_inited; +} + +int oal_is_channel_playing(int channel) +{ + ALint status; + + if ( !OAL_inited ) { + return 0; + } + + SDL_assert( channel >= 0 ); + SDL_assert( channel < (int)Channels.size() ); + + oal_check_for_errors("oal_is_channel_playing() begin"); + + alGetSourcei(Channels[channel].source_id, AL_SOURCE_STATE, &status); + + oal_check_for_errors("oal_is_channel_playing() end"); + + if (status == AL_PLAYING) { + return 1; + } + + return 0; +} + +void oal_chg_loop_status(int channel, int loop) +{ + if ( !OAL_inited ) { + return; + } + + SDL_assert( channel >= 0 ); + SDL_assert( channel < (int)Channels.size() ); + + oal_check_for_errors("oal_chg_loop_status() begin"); + + alSourcei(Channels[channel].source_id, AL_LOOPING, (loop) ? AL_TRUE : AL_FALSE); + + if (loop) { + Channels[channel].flags |= SND_FLAG_LOOPING; + } else { + Channels[channel].flags &= ~SND_FLAG_LOOPING; + } + + oal_check_for_errors("oal_chg_loop_status() end"); +} + +static int oal_get_free_channel_idx(float new_volume, int snd_id, int priority) +{ + int i, limit; + float lowest_vol = 0.0f; + int lowest_vol_index = -1; + int status; + int instance_count = 0; // number of instances of sound already playing + float lowest_instance_vol = 1.0f; + int lowest_instance_vol_index = -1; + + int first_free_channel = -1; + + int size = (int)Channels.size(); + + oal_check_for_errors("oal_get_free_channel_idx() begin"); + + // Look for a channel to use to play this sample + for (i = 0; i < size; i++) { + sound_channel *chp = &Channels[i]; + int looping = chp->flags & SND_FLAG_LOOPING; + + if (chp->snd_id == 0) { + if (first_free_channel == -1) { + first_free_channel = i; + } + + continue; + } + + alGetSourcei(chp->source_id, AL_SOURCE_STATE, &status); + + if (status != AL_PLAYING) { + if (first_free_channel == -1) { + first_free_channel = i; + } + + continue; + } else { + if (chp->snd_id == snd_id) { + instance_count++; + + if ( (chp->vol < lowest_instance_vol) && !looping ) { + lowest_instance_vol = chp->vol; + lowest_instance_vol_index = i; + } + } + + if ( (chp->vol < lowest_vol) && !looping ) { + lowest_vol_index = i; + lowest_vol = chp->vol; + } + } + } + + // determine the limit of concurrent instances of this sound + switch (priority) { + case SND_PRIORITY_MUST_PLAY: + limit = 100; + break; + + case SND_PRIORITY_SINGLE_INSTANCE: + limit = 1; + break; + + case SND_PRIORITY_DOUBLE_INSTANCE: + limit = 2; + break; + + case SND_PRIORITY_TRIPLE_INSTANCE: + limit = 3; + break; + + default: + Int3(); // get Alan + limit = 100; + break; + } + + + // If we've exceeded the limit, then maybe stop the duplicate if it is lower volume + if (instance_count >= limit) { + // If there is a lower volume duplicate, stop it.... otherwise, don't play the sound + if ( (lowest_instance_vol_index >= 0) && (Channels[lowest_instance_vol_index].vol <= new_volume) ) { + first_free_channel = lowest_instance_vol_index; + } else { + first_free_channel = -1; + } + } else { + // there is no limit barrier to play the sound, so see if we've ran out of channels + if (first_free_channel == -1) { + // stop the lowest volume instance to play our sound if priority demands it + if ( (lowest_vol_index != -1) && (priority == SND_PRIORITY_MUST_PLAY) ) { + // Check if the lowest volume playing is less than the volume of the requested sound. + // If so, then we are going to trash the lowest volume sound. + if (Channels[lowest_vol_index].vol <= new_volume) { + first_free_channel = lowest_vol_index; + } + } + } + } + + oal_check_for_errors("oal_get_free_channel_idx() end"); + + return first_free_channel; +} + +// get a channel for use elsewhere (MVE playback, streaming audio, etc.) +sound_channel *oal_get_free_channel(float volume, int snd_id, int priority) +{ + if ( !OAL_inited ) { + return NULL; + } + + int chan = oal_get_free_channel_idx(volume, snd_id, priority); + + if (chan < 0) { + return NULL; + } + + SDL_assert( Channels[chan].source_id != 0 ); + + Channels[chan].buf_idx = -1; + Channels[chan].snd_id = -1; + Channels[chan].sig = channel_next_sig++; + + if (channel_next_sig < 0) { + channel_next_sig = 1; + } + + return &Channels[chan]; +} + +int oal_parse_wave(const char *filename, ubyte **dest, uint *dest_size, WAVE_chunk **header) +{ + CFILE *cfp = NULL; + int id = 0; + unsigned int tag = 0, size = 0, next_chunk; + WAVE_chunk hdr; + + if ( !OAL_inited ) { + return 0; + } + + cfp = cfopen(filename, "rb"); + + if (cfp == NULL) { + nprintf(("Error", "Couldn't open '%s'\n", filename )); + return -1; + } + + // check for valid file type + id = cfread_int(cfp); + + // 'RIFF' + if (id != 0x46464952) { + nprintf(("Error", "Not a WAVE file '%s'\n", filename)); + cfclose(cfp); + return -1; + } + + // skip RIFF size + cfread_int(cfp); + + // check for valid RIFF type + id = cfread_int(cfp); + + // 'WAVE' + if (id != 0x45564157) { + nprintf(("Error", "Not a WAVE file '%s'\n", filename)); + cfclose(cfp); + return -1; + } + + // parse WAVE tags + while ( !cfeof(cfp) ) { + tag = cfread_uint(cfp); + size = cfread_uint(cfp); + + next_chunk = cftell(cfp) + size; + + switch (tag) { + // 'fmt ' + case 0x20746d66: { + hdr.code = cfread_short(cfp); + hdr.num_channels = cfread_ushort(cfp); + hdr.sample_rate = cfread_uint(cfp); + hdr.bytes_per_second = cfread_uint(cfp); + hdr.block_align = cfread_ushort(cfp); + hdr.bits_per_sample = cfread_ushort(cfp); + + if (hdr.code != 1) { + hdr.extra_size = cfread_ushort(cfp); + } + + (*header) = (WAVE_chunk*) malloc (sizeof(WAVE_chunk)); + SDL_assert( (*header) != NULL ); + + memcpy((*header), &hdr, sizeof(WAVE_chunk)); + + if (hdr.extra_size) { + (*header)->extra_data = (ubyte*) malloc (hdr.extra_size); + SDL_assert( (*header)->extra_data != NULL ); + + cfread((*header)->extra_data, hdr.extra_size, 1, cfp); + } + + break; + } + + // 'data' + case 0x61746164: { + *dest_size = size; + + (*dest) = (ubyte*) malloc (size); + SDL_assert( (*dest) != NULL ); + + cfread((*dest), size, 1, cfp); + + break; + } + + // drop everything else + default: + break; + } + + cfseek(cfp, next_chunk, CF_SEEK_SET); + } + + cfclose(cfp); + + return 0; +} + +static int oal_get_free_buffer() +{ + if ( !OAL_inited ) { + return -1; + } + + int size = (int)Buffers.size(); + + for (int i = 0; i < size; i++) { + if (Buffers[i].buf_id == 0) { + return i; + } + } + + sound_buffer nbuf; + + Buffers.push_back(nbuf); + + return (int)(Buffers.size()-1); +} + +int oal_load_buffer(int *sid, int *final_size, WAVE_chunk *header, sound_info *si, int flags) +{ + SDL_assert( final_size != NULL ); + SDL_assert( header != NULL ); + SDL_assert( si != NULL ); + + if ( !OAL_inited ) { + return 0; + } + + int buf_idx = oal_get_free_buffer(); + + if (buf_idx < 0) { + return -1; + } + + *sid = buf_idx; + + sound_buffer *buf = &Buffers[buf_idx]; + + oal_check_for_errors("oal_load_buffer() begin"); + + alGenBuffers(1, &buf->buf_id); + + if ( !buf->buf_id ) { + return -1; + } + + ALenum format = AL_INVALID; + ALsizei size; + ALint bits, bps; + ALuint frequency; + ALvoid *data = NULL; + + // the below conversion variables are only used when the wav format is not PCM. + ubyte *convert_buffer = NULL; // storage for converted wav file + int convert_len; // num bytes of converted wav file + uint src_bytes_used; // number of source bytes actually converted (should always be equal to original size) + + + switch (si->format) { + case WAVE_FORMAT_PCM: { + SDL_assert( si->data != NULL ); + + bits = si->bits; + bps = si->avg_bytes_per_sec; + size = si->size; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + // swap 16-bit sound data + if (bits == 16) { + ushort *swap_tmp; + + for (uint i=0; idata + i); + *swap_tmp = INTEL_SHORT(*swap_tmp); + } + } +#endif + + data = si->data; + + break; + } + + case WAVE_FORMAT_ADPCM: { + SDL_assert( si->data != NULL ); + + // this ADPCM decoder decodes to 16-bit only so keep that in mind + nprintf(( "Sound", "SOUND ==> converting sound from ADPCM to PCM\n" )); + + int rc = ACM_convert_ADPCM_to_PCM(header, si->data, si->size, &convert_buffer, 0, &convert_len, &src_bytes_used, 16); + + // ACM conversion failed? + if ( (rc == -1) || (src_bytes_used != si->size) ) { + alDeleteBuffers(1, &buf->buf_id); + buf->buf_id = 0; + + if (convert_buffer != NULL) { + free(convert_buffer); + } + + return -1; + } + + bits = 16; + bps = (((si->n_channels * bits) / 8) * si->sample_rate); + size = convert_len; + data = convert_buffer; + + nprintf(( "Sound", "SOUND ==> Coverted sound from ADPCM to PCM successfully\n" )); + + break; + } + + default: + nprintf(( "Sound", "Unsupported sound encoding\n" )); + alDeleteBuffers(1, &buf->buf_id); + buf->buf_id = 0; + return -1; + } + + // format is now in pcm + frequency = si->sample_rate; + + if (bits == 16) { + if (si->n_channels == 2) { + format = AL_FORMAT_STEREO16; + } else if (si->n_channels == 1) { + format = AL_FORMAT_MONO16; + } + } else if (bits == 8) { + if (si->n_channels == 2) { + format = AL_FORMAT_STEREO8; + } else if (si->n_channels == 1) { + format = AL_FORMAT_MONO8; + } + } + + if (format == AL_INVALID) { + alDeleteBuffers(1, &buf->buf_id); + buf->buf_id = 0; + + if (convert_buffer != NULL) { + free(convert_buffer); + } + + return -1; + } + + Snd_sram += size; + *final_size = size; + + alBufferData(buf->buf_id, format, data, size, frequency); + + buf->chan_idx = -1; + buf->frequency = frequency; + buf->bits_per_sample = bits; + buf->nchannels = si->n_channels; + buf->nseconds = size / bps; + buf->nbytes = size; + + if (convert_buffer != NULL) { + free(convert_buffer); + } + + oal_check_for_errors("oal_load_buffer() end"); + + return 0; +} + +void oal_unload_buffer(int sid) +{ + if ( !OAL_inited ) { + return; + } + + if ( (sid < 0) || (sid >= (int)Buffers.size()) ) { + return; + } + + oal_check_for_errors("oal_unload_buffer() begin"); + + sound_buffer *buf = &Buffers[sid]; + + if (buf->buf_id) { + alDeleteBuffers(1, &buf->buf_id); + buf->buf_id = 0; + } + + oal_check_for_errors("oal_unload_buffer() end"); +} + +int oal_create_buffer(int frequency, int bits_per_sample, int nchannels, int nseconds) +{ + if ( !OAL_inited ) { + return -1; + } + + int buf_idx = oal_get_free_buffer(); + + if (buf_idx < 0) { + return -1; + } + + sound_buffer *buf = &Buffers[buf_idx]; + + oal_check_for_errors("oal_load_buffer() begin"); + + alGenBuffers(1, &buf->buf_id); + + if ( !buf->buf_id ) { + return -1; + } + + buf->chan_idx = -1; + buf->frequency = frequency; + buf->bits_per_sample = bits_per_sample; + buf->nchannels = nchannels; + buf->nseconds = nseconds; + buf->nbytes = nseconds * (bits_per_sample / 8) * nchannels * frequency; + + return buf_idx; +} + +int oal_lock_data(int sid, ubyte *data, int size) +{ + if ( !OAL_inited ) { + return -1; + } + + oal_check_for_errors("oal_lock_data() begin"); + + SDL_assert( sid >= 0 ); + SDL_assert( sid < (int)Buffers.size() ); + + ALuint buf_id = Buffers[sid].buf_id; + ALenum format; + + if (Buffers[sid].bits_per_sample == 16) { + if (Buffers[sid].nchannels == 2) { + format = AL_FORMAT_STEREO16; + } else if (Buffers[sid].nchannels == 1) { + format = AL_FORMAT_MONO16; + } else { + return -1; + } + } else if (Buffers[sid].bits_per_sample == 8) { + if (Buffers[sid].nchannels == 2) { + format = AL_FORMAT_STEREO8; + } else if (Buffers[sid].nchannels == 1) { + format = AL_FORMAT_MONO8; + } else { + return -1; + } + } else { + return -1; + } + + Buffers[sid].nbytes = size; + + alBufferData(buf_id, format, data, size, Buffers[sid].frequency); + + if ( oal_check_for_errors("oal_lock_data() end") ) { + return -1; + } + + return 0; +} + +int oal_play(int sid, int snd_id, int priority, float volume, float pan, int flags) +{ + if ( !OAL_inited ) { + return -1; + } + + SDL_assert( sid >= 0 ); + SDL_assert( sid < (int)Buffers.size() ); + + oal_check_for_errors("oal_play() begin"); + + int channel = oal_get_free_channel_idx(volume, snd_id, priority); + + if (channel < 0) { + return -1; + } + + sound_channel *chan = &Channels[channel]; + + ALint status; + alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status); + + if (status == AL_PLAYING) { + oal_stop_channel(channel); + } + + // set all the things + chan->vol = volume; + chan->flags = flags; + chan->priority = priority; + chan->last_position = 0; + chan->buf_idx = sid; + chan->snd_id = snd_id; + chan->sig = channel_next_sig++; + + Buffers[sid].chan_idx = channel; + + alSource3f(chan->source_id, AL_POSITION, pan, 0.0f, -1.0f); + alSource3f(chan->source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + alSourcef(chan->source_id, AL_PITCH, 1.0f); + alSourcef(chan->source_id, AL_GAIN, volume); + alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id); + alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_TRUE); + alSourcei(chan->source_id, AL_LOOPING, (flags & SND_FLAG_LOOPING) ? AL_TRUE : AL_FALSE); + + // Actually play it + alSourcePlay(chan->source_id); + + if (channel_next_sig < 0) { + channel_next_sig = 1; + } + + oal_check_for_errors("oal_play() end"); + + return chan->sig; +} + +int oal_play_3d( int sid, int snd_id, vector *pos, vector *vel, int min, int max, int looping, float max_volume, float estimated_vol, int priority) +{ + if ( !OAL_inited ) { + return -1; + } + + SDL_assert( sid >= 0 ); + SDL_assert( sid < (int)Buffers.size() ); + + oal_check_for_errors("oal_play_3d() begin"); + + int channel = oal_get_free_channel_idx(estimated_vol, snd_id, priority); + + if (channel < 0) { + return -1; + } + + sound_channel *chan = &Channels[channel]; + + ALint status; + alGetSourcei(chan->source_id, AL_SOURCE_STATE, &status); + + if (status == AL_PLAYING) { + oal_stop_channel(channel); + } + + int flags = SND_FLAG_3D; + + if (looping) { + flags |= SND_FLAG_LOOPING; + } + + // set all the things + chan->vol = max_volume; + chan->flags = flags; + chan->priority = priority; + chan->last_position = 0; + chan->buf_idx = sid; + chan->snd_id = snd_id; + chan->sig = channel_next_sig++; + + Buffers[sid].chan_idx = channel; + + oal_update_source(channel, min, max, pos, vel); + + alSourcef(chan->source_id, AL_PITCH, 1.0f); + alSourcef(chan->source_id, AL_GAIN, max_volume); + alSourcei(chan->source_id, AL_BUFFER, Buffers[sid].buf_id); + alSourcei(chan->source_id, AL_SOURCE_RELATIVE, AL_FALSE); + alSourcei(chan->source_id, AL_LOOPING, (looping) ? AL_TRUE : AL_FALSE); + + // Actually play it + alSourcePlay(chan->source_id); + + if (channel_next_sig < 0) { + channel_next_sig = 1; + } + + oal_check_for_errors("oal_play_3d() end"); + + return chan->sig; +} + +void oal_do_frame() +{ + ALint state, current_position; + + oal_check_for_errors("oal_do_frame() begin"); + + int size = (int)Channels.size(); + + // make sure there aren't any looping voice messages + for (int i = 0; i < size; i++) { + + if ( (Channels[i].flags & SND_FLAG_VOICE) && (Channels[i].flags & SND_FLAG_LOOPING) ) { + alGetSourcei(Channels[i].source_id, AL_SOURCE_STATE, &state); + + if (state != AL_PLAYING) { + continue; + } + + alGetSourcei(Channels[i].source_id, AL_BYTE_OFFSET, ¤t_position); + + if (current_position != 0) { + if (current_position < Channels[i].last_position) { + alSourceStop(Channels[i].source_id); + } else { + Channels[i].last_position = current_position; + } + } + } + } + + oal_check_for_errors("oal_do_frame() end"); +} + +int oal_update_source(int channel, int min, int max, vector *pos, vector *vel) +{ + if ( !OAL_inited ) { + return 0; + } + + if (channel < 0) { + return 0; + } + + if ( !Channels[channel].flags & SND_FLAG_3D ) { + return 1; + } + + ALuint source_id = Channels[channel].source_id; + ALfloat rolloff = 1.0f; + + oal_check_for_errors("oal_update_source() begin"); + + if (pos) { + alSource3f(source_id, AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z); + } + + if (vel) { + alSource3f(source_id, AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z); + } else { + alSource3f(source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + } + + if (min >= 0) { + if (max <= min) { + rolloff = 0.0f; + } else { + const float MIN_GAIN = 0.05f; + float minf = i2fl(min); + float maxf = i2fl(max); + + // yep, just making this shit up + rolloff = (minf / (minf + (maxf - minf))) / MIN_GAIN; + + if (rolloff < 0.0f) { + rolloff = 0.0f; + } + } + + alSourcef(source_id, AL_ROLLOFF_FACTOR, rolloff); + + alSourcei(source_id, AL_REFERENCE_DISTANCE, min); + alSourcei(source_id, AL_MAX_DISTANCE, max); + } + + oal_check_for_errors("oal_update_source() end"); + + return 0; +} + +int oal_update_listener(vector *pos, vector *vel, matrix *orient) +{ + if ( !OAL_inited ) { + return 0; + } + + oal_check_for_errors("oal_update_listener() begin"); + + if (pos) { + alListener3f(AL_POSITION, pos->xyz.x, pos->xyz.y, -pos->xyz.z); + } + + if (vel) { + alListener3f(AL_VELOCITY, vel->xyz.x, vel->xyz.y, vel->xyz.z); + } + + if (orient) { + ALfloat alOrient[6]; + + alOrient[0] = orient->v.fvec.xyz.x; + alOrient[1] = orient->v.fvec.xyz.y; + alOrient[2] = -orient->v.fvec.xyz.z; + + alOrient[3] = orient->v.uvec.xyz.x; + alOrient[4] = orient->v.uvec.xyz.y; + alOrient[5] = -orient->v.uvec.xyz.z; + + alListenerfv(AL_ORIENTATION, alOrient); + } + + oal_check_for_errors("oal_update_listener() end"); + + return 0; +} diff --git a/src/sound/oal_capture.cpp b/src/sound/oal_capture.cpp new file mode 100644 index 0000000..aaa8439 --- /dev/null +++ b/src/sound/oal_capture.cpp @@ -0,0 +1,188 @@ +/* + * Copyright (C) Volition, Inc. 1999. All rights reserved. + * + * All source code herein is the property of Volition, Inc. You may not sell + * or otherwise commercially exploit the source or things you created based on the + * source. + * +*/ + +#include "pstypes.h" +#include "oal.h" + + +static int OAL_capture_recording = 0; + +struct capture_buffer { + uint samples_per_second; + uint bits_per_sample; + uint n_channels; + uint block_align; + + ALenum format; + ALsizei buffer_size; +}; + +static capture_buffer Capture; + +static ALCdevice *al_capture_device = NULL; + + +void oal_capture_release_buffer() +{ + if (al_capture_device != NULL) { + alcCaptureCloseDevice(al_capture_device); + al_capture_device = NULL; + } +} + +// create a capture buffer with the specified format +// exit: 0 -> buffer created successfully +// !0 -> error creating the buffer +int oal_capture_create_buffer(int freq, int bits_per_sample, int nchannels, int nseconds) +{ + ALenum al_format = AL_FORMAT_MONO8; + ALsizei buf_size = freq * nseconds; + + SDL_assert( (nchannels == 1) || (nchannels == 2) ); + SDL_assert( (bits_per_sample == 8) || (bits_per_sample == 16) ); + + if ( !oal_is_initted() ) { + return -1; + } + + if (nchannels == 1) { + if (bits_per_sample == 8) { + al_format = AL_FORMAT_MONO8; + } else if (bits_per_sample == 16) { + al_format = AL_FORMAT_MONO16; + } + } else if (nchannels == 2) { + if (bits_per_sample == 8) { + al_format = AL_FORMAT_STEREO8; + } else if (bits_per_sample == 16) { + al_format = AL_FORMAT_STEREO16; + } + } + + al_capture_device = alcCaptureOpenDevice(NULL, freq, al_format, buf_size); + + if (al_capture_device == NULL) { + return -1; + } + + if ( alcGetError(al_capture_device) != ALC_NO_ERROR ) { + return -1; + } + + Capture.format = al_format; + Capture.bits_per_sample = bits_per_sample; + Capture.n_channels = nchannels; + Capture.samples_per_second = freq; + Capture.block_align = (nchannels * bits_per_sample) / 8; + + return 0; +} + +int oal_capture_supported() +{ + return oal_is_initted(); +} + +// start recording into the buffer +int oal_capture_start_record() +{ + if ( !oal_is_initted() ) { + return -1; + } + + if (OAL_capture_recording) { + return -1; + } + + alcCaptureStart(al_capture_device); + + OAL_capture_recording = 1; + +// nprintf(("Alan","RTVOICE => start record\n")); + + return 0; +} + +// stop recording into the buffer +int oal_capture_stop_record() +{ + if ( !oal_is_initted() ) { + return -1; + } + + if ( !OAL_capture_recording ) { + return -1; + } + + alcCaptureStop(al_capture_device); + + OAL_capture_recording = 0; + +// nprintf(("Alan","RTVOICE => stop record\n")); + + return 0; +} + +void oal_capture_close() +{ + oal_capture_stop_record(); + + if (al_capture_device != NULL) { + alcCaptureCloseDevice(al_capture_device); + al_capture_device = NULL; + } +} + +// return the max buffer size +int oal_capture_max_buffersize() +{ + if ( !oal_is_initted() ) { + return 0; + } + + ALCsizei num_samples = 0; + + alcGetIntegerv(al_capture_device, ALC_CAPTURE_SAMPLES, sizeof(ALCsizei), &num_samples); + + if (alcGetError(al_capture_device) != ALC_NO_ERROR) { + return 0; + } + + return (num_samples * Capture.block_align); +} + +// retrieve the recorded voice data +int oal_capture_get_raw_data(ubyte *outbuf, uint max_size) +{ + if ( !oal_is_initted() ) { + return 0; + } + + if (outbuf == NULL) { + return 0; + } + + ALCsizei num_samples = 0; + + alcGetIntegerv(al_capture_device, ALC_CAPTURE_SAMPLES, sizeof(ALCsizei), &num_samples); + + if (num_samples <= 0) { + return 0; + } + + ALCsizei max_buf_size = min(num_samples, ALsizei(max_size / Capture.block_align)); + + alcCaptureSamples(al_capture_device, outbuf, max_buf_size); + + if (alcGetError(al_capture_device) != ALC_NO_ERROR) { + return 0; + } + + return (int)max_buf_size * Capture.block_align; +} diff --git a/src/sound/oal_efx.cpp b/src/sound/oal_efx.cpp new file mode 100644 index 0000000..5fd1b07 --- /dev/null +++ b/src/sound/oal_efx.cpp @@ -0,0 +1,352 @@ +/* + * Copyright (C) Volition, Inc. 1999. All rights reserved. + * + * All source code herein is the property of Volition, Inc. You may not sell + * or otherwise commercially exploit the source or things you created based on + * the source. + */ + +#include "pstypes.h" +#include "oal.h" +#include "sound.h" +#include "oal_efx.h" + +#include "alext.h" +#include "efx-presets.h" + + +// effects +LPALGENEFFECTS alGenEffects; +LPALDELETEEFFECTS alDeleteEffects; +LPALEFFECTI alEffecti; +LPALEFFECTF alEffectf; +LPALEFFECTFV alEffectfv; +LPALGETEFFECTF alGetEffectf; + +// aux effect slots +LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots; +LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots; +LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot; +LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti; +LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv; +LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf; +LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv; + +static uint EFX_active_environment = SND_ENV_GENERIC; +static EFXEAXREVERBPROPERTIES EFX_properties = EFX_REVERB_PRESET_GENERIC; + +static ALuint AL_EFX_aux_id = 0; +static ALuint AL_EFX_effect_id = 0; + +static int OAL_efx_inited = 0; + + +static void oal_efx_set_effect_properties() +{ + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DENSITY, EFX_properties.flDensity); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DIFFUSION, EFX_properties.flDiffusion); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAIN, EFX_properties.flGain); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAINHF, EFX_properties.flGainHF); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAINLF, EFX_properties.flGainLF); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_TIME, EFX_properties.flDecayTime); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_HFRATIO, EFX_properties.flDecayHFRatio); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_LFRATIO, EFX_properties.flDecayLFRatio); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_REFLECTIONS_GAIN, EFX_properties.flReflectionsGain); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_REFLECTIONS_DELAY, EFX_properties.flReflectionsDelay); + alEffectfv(AL_EFX_effect_id, AL_EAXREVERB_REFLECTIONS_PAN, EFX_properties.flReflectionsPan); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_LATE_REVERB_GAIN, EFX_properties.flLateReverbGain); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_LATE_REVERB_DELAY, EFX_properties.flLateReverbDelay); + alEffectfv(AL_EFX_effect_id, AL_EAXREVERB_LATE_REVERB_PAN, EFX_properties.flLateReverbPan); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_ECHO_TIME, EFX_properties.flEchoTime); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_ECHO_DEPTH, EFX_properties.flEchoDepth); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_MODULATION_TIME, EFX_properties.flModulationTime); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_MODULATION_DEPTH, EFX_properties.flModulationDepth); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, EFX_properties.flAirAbsorptionGainHF); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_HFREFERENCE, EFX_properties.flHFReference); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_LFREFERENCE, EFX_properties.flLFReference); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, EFX_properties.flRoomRolloffFactor); + alEffecti(AL_EFX_effect_id, AL_EAXREVERB_DECAY_HFLIMIT, EFX_properties.iDecayHFLimit); +} + +static void oal_efx_update_effect_properties() +{ + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAIN, EFX_properties.flGain); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_TIME, EFX_properties.flDecayTime); + alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_HFRATIO, EFX_properties.flDecayHFRatio); +} + +static void oal_efx_set_environment(uint id) +{ + uint n_id = id; + + if (n_id == SND_ENV_GENERIC) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_GENERIC; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_PADDEDCELL) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_PADDEDCELL; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_ROOM) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_ROOM; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_BATHROOM) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_BATHROOM; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_LIVINGROOM) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_LIVINGROOM; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_STONEROOM) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_STONEROOM; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_AUDITORIUM) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_AUDITORIUM; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_CONCERTHALL) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_CONCERTHALL; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_CAVE) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_CAVE; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_ARENA) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_ARENA; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_HANGAR) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_HANGAR; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_CARPETEDHALLWAY) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_CARPETEDHALLWAY; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_HALLWAY) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_HALLWAY; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_STONECORRIDOR) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_STONECORRIDOR; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_ALLEY) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_ALLEY; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_FOREST) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_FOREST; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_CITY) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_CITY; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_MOUNTAINS) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_MOUNTAINS; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_QUARRY) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_QUARRY; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_PLAIN) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_PLAIN; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_PARKINGLOT) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_PARKINGLOT; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_SEWERPIPE) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_SEWERPIPE; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_UNDERWATER) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_UNDERWATER; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_DRUGGED) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_DRUGGED; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_DIZZY) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_DIZZY; + EFX_properties = ptmp; + } else if (n_id == SND_ENV_PSYCHOTIC) { + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_PSYCHOTIC; + EFX_properties = ptmp; + } else { + n_id = SND_ENV_GENERIC; + EFXEAXREVERBPROPERTIES ptmp = EFX_REVERB_PRESET_GENERIC; + EFX_properties = ptmp; + } + + oal_efx_set_effect_properties(); + + EFX_active_environment = n_id; +} + +int oal_efx_init() +{ + if (OAL_efx_inited) { + return 0; + } + + // make sure we support EFX and the EAXREVERB effect + if ( !alcIsExtensionPresent(alcGetContextsDevice(alcGetCurrentContext()), "ALC_EXT_EFX") ) { + return -1; + } + + if ( !alGetEnumValue("AL_EFFECT_EAXREVERB") ) { + return -1; + } + + // effects + alGenEffects = (LPALGENEFFECTS) alGetProcAddress("alGenEffects"); + alDeleteEffects = (LPALDELETEEFFECTS) alGetProcAddress("alDeleteEffects"); + alEffecti = (LPALEFFECTI) alGetProcAddress("alEffecti"); + alEffectf = (LPALEFFECTF) alGetProcAddress("alEffectf"); + alEffectfv = (LPALEFFECTFV) alGetProcAddress("alEffectfv"); + alGetEffectf = (LPALGETEFFECTF) alGetProcAddress("alGetEffectf"); + + SDL_assert_release( alGenEffects != NULL ); + SDL_assert_release( alDeleteEffects != NULL ); + SDL_assert_release( alEffecti != NULL ); + SDL_assert_release( alEffectf != NULL ); + SDL_assert_release( alEffectfv != NULL ); + SDL_assert_release( alGetEffectf != NULL ); + + // aux effect slots + alGenAuxiliaryEffectSlots = (LPALGENAUXILIARYEFFECTSLOTS) alGetProcAddress("alGenAuxiliaryEffectSlots"); + alDeleteAuxiliaryEffectSlots = (LPALDELETEAUXILIARYEFFECTSLOTS) alGetProcAddress("alDeleteAuxiliaryEffectSlots"); + alIsAuxiliaryEffectSlot = (LPALISAUXILIARYEFFECTSLOT) alGetProcAddress("alIsAuxiliaryEffectSlot"); + alAuxiliaryEffectSloti = (LPALAUXILIARYEFFECTSLOTI) alGetProcAddress("alAuxiliaryEffectSloti"); + alAuxiliaryEffectSlotiv = (LPALAUXILIARYEFFECTSLOTIV) alGetProcAddress("alAuxiliaryEffectSlotiv"); + alAuxiliaryEffectSlotf = (LPALAUXILIARYEFFECTSLOTF) alGetProcAddress("alAuxiliaryEffectSlotf"); + alAuxiliaryEffectSlotfv = (LPALAUXILIARYEFFECTSLOTFV) alGetProcAddress("alAuxiliaryEffectSlotfv"); + + SDL_assert_release( alGenAuxiliaryEffectSlots != NULL ); + SDL_assert_release( alDeleteAuxiliaryEffectSlots != NULL ); + SDL_assert_release( alIsAuxiliaryEffectSlot != NULL ); + SDL_assert_release( alAuxiliaryEffectSloti != NULL ); + SDL_assert_release( alAuxiliaryEffectSlotiv != NULL ); + SDL_assert_release( alAuxiliaryEffectSlotf != NULL ); + SDL_assert_release( alAuxiliaryEffectSlotfv != NULL ); + + + EFX_active_environment = SND_ENV_GENERIC; + + + alGenAuxiliaryEffectSlots(1, &AL_EFX_aux_id); + + if (alGetError() != AL_NO_ERROR) { + mprintf(("\n EFX: Unable to create Aux effect!\n")); + return -1; + } + + alGenEffects(1, &AL_EFX_effect_id); + + if (alGetError() != AL_NO_ERROR) { + mprintf(("\n EFX: Unable to create effect!\n")); + return -1; + } + + alEffecti(AL_EFX_effect_id, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB); + + if (alGetError() != AL_NO_ERROR) { + mprintf(("\n EFX: EAXReverb not supported!\n")); + return -1; + } + + alAuxiliaryEffectSloti(AL_EFX_aux_id, AL_EFFECTSLOT_EFFECT, AL_EFX_effect_id); + + if (alGetError() != AL_NO_ERROR) { + mprintf(("\n EFX: Couldn't load effect!\n")); + return -1; + } + + oal_efx_set_effect_properties(); + + OAL_efx_inited = 1; + + return 0; +} + +int oal_efx_is_inited() +{ + return OAL_efx_inited; +} + +void oal_efx_close() +{ + if ( !OAL_efx_inited ) { + return; + } + + alAuxiliaryEffectSloti(AL_EFX_aux_id, AL_EFFECTSLOT_EFFECT, AL_EFFECT_NULL); + + alDeleteEffects(1, &AL_EFX_effect_id); + AL_EFX_effect_id = 0; + + alDeleteAuxiliaryEffectSlots(1, &AL_EFX_aux_id); + AL_EFX_aux_id = 0; + + OAL_efx_inited = 0; +} + +// Get up the parameters for the current environment +// +// er: (output) hold environment parameters +// id: if set will get specified preset env, otherwise current env +// +// returns: 0 if successful, otherwise return -1 +// +int oal_efx_get_all(EAX_REVERBPROPERTIES *er, int id) +{ + if (er == NULL) { + return -1; + } + + if ( (id < 0) || (id == (int)EFX_active_environment) ) { + er->environment = EFX_active_environment; + er->fVolume = EFX_properties.flGain; + er->fDecayTime_sec = EFX_properties.flDecayTime; + er->fDamping = EFX_properties.flDecayHFRatio; + } else { + // ignoring alternate environments for now + return -1; + } + + return 0; +} + +// Set up all the parameters for an environment +// +// id: value from teh EAX_ENVIRONMENT_* enumeration +// volume: volume for the environment (0 to 1.0) +// damping: damp value for the environment (0 to 2.0) +// decay: decay time in seconds (0.1 to 20.0) +// +// returns: 0 if successful, otherwise return -1 +// +int oal_efx_set_all(uint id, float vol, float damping, float decay) +{ + if ( !OAL_efx_inited ) { + return -1; + } + + oal_check_for_errors("oal_efx_set_all() begin"); + + // special disabled case + if ( (id == SND_ENV_GENERIC) && (vol == 0.0f) && (damping == 0.0f) && (decay == 0.0f) ) { + ALint props[3] = { AL_EFFECT_NULL, 0, AL_FILTER_NULL }; + + oal_set_source_properties_all(AL_AUXILIARY_SEND_FILTER, props); + + return 0; + } + + if (id != EFX_active_environment) { + oal_efx_set_environment(id); + } + + CAP(vol, AL_EAXREVERB_MIN_GAIN, AL_EAXREVERB_MAX_GAIN); + CAP(decay, AL_EAXREVERB_MIN_DECAY_TIME, AL_EAXREVERB_MAX_DECAY_TIME); + CAP(damping, AL_EAXREVERB_MIN_DECAY_HFRATIO, AL_EAXREVERB_MAX_DECAY_HFRATIO); + + EFX_properties.flGain = vol; + EFX_properties.flDecayTime = decay; + EFX_properties.flDecayHFRatio = damping; + + oal_efx_update_effect_properties(); + + alAuxiliaryEffectSloti(AL_EFX_aux_id, AL_EFFECTSLOT_EFFECT, AL_EFX_effect_id); + + if ( oal_check_for_errors("oal_efx_set_all() end") ) { + return -1; + } + + return 0; +} diff --git a/src/sound/rtvoice.cpp b/src/sound/rtvoice.cpp index 8ab5b21..79008f0 100644 --- a/src/sound/rtvoice.cpp +++ b/src/sound/rtvoice.cpp @@ -111,8 +111,8 @@ #include "pstypes.h" #include "sound.h" -#include "ds.h" -#include "dscap.h" +#include "oal.h" +#include "oal_capture.h" #include "codec1.h" #include "rtvoice.h" @@ -149,7 +149,7 @@ static int Rtv_recording=0; // Voice is currently being recorded #define RTV_OUT_FLAG_USED (1<<0) typedef struct rtv_out_buffer { - int ds_handle; // handle to directsound buffer + int buf_handle; // handle to sound buffer int flags; // see RTV_OUT_FLAG_ #defines above } rtv_out_buffer; static rtv_out_buffer Rtv_output_buffers[MAX_RTV_OUT_BUFFERS]; // data for output buffers @@ -157,7 +157,7 @@ static rtv_out_buffer Rtv_output_buffers[MAX_RTV_OUT_BUFFERS]; // data for outp static struct t_CodeInfo Rtv_code_info; // Parms will need to be transmitted with packets // recording timer data -static int Rtv_record_timer_id; // unique id for callback timer +static SDL_TimerID Rtv_record_timer_id; // unique id for callback timer static int Rtv_callback_time; // callback time in ms void (*Rtv_callback)(); @@ -182,14 +182,26 @@ static int Decode_buffer_size; // RECORD/ENCODE ///////////////////////////////////////////////////////////////////////////////////////////////// -void CALLBACK TimeProc(unsigned int id, unsigned int msg, unsigned long userdata, unsigned long dw1, unsigned long dw2) +Uint32 TimeProc(Uint32 interval, void *param) { if ( !Rtv_callback ) { - return; + SDL_RemoveTimer(Rtv_record_timer_id); + Rtv_record_timer_id = 0; + + return 0; } nprintf(("Alan","In callback\n")); Rtv_callback(); + + if (Rtv_callback_time) { + return interval; + } else { + SDL_RemoveTimer(Rtv_record_timer_id); + Rtv_record_timer_id = 0; + + return 0; + } } // Try to pick the most appropriate recording format @@ -201,8 +213,8 @@ int rtvoice_pick_record_format() int i; for (i=0; i failure int rtvoice_start_recording( void (*user_callback)(), int callback_time ) { - if ( !dscap_supported() ) { + if ( !oal_capture_supported() ) { return -1; } @@ -341,20 +351,15 @@ int rtvoice_start_recording( void (*user_callback)(), int callback_time ) return -1; } - if ( dscap_start_record() ) { + if ( oal_capture_start_record() ) { return -1; } if ( user_callback ) { -#ifndef PLAT_UNIX - Rtv_record_timer_id = timeSetEvent(callback_time, callback_time, TimeProc, 0, TIME_PERIODIC); -#else - STUB_FUNCTION; - - return -1; -#endif + Rtv_record_timer_id = SDL_AddTimer(callback_time, TimeProc, NULL); + if ( !Rtv_record_timer_id ) { - dscap_stop_record(); + oal_capture_stop_record(); return -1; } Rtv_callback = user_callback; @@ -473,7 +478,7 @@ int rtvoice_maybe_convert_data(unsigned char *data, int size) void rtvoice_get_data(unsigned char **outbuf, int *compressed_size, int *uncompressed_size, double *gain, unsigned char **outbuf_raw, int *outbuf_size_raw) { int max_size, raw_size, csize; - max_size = dscap_max_buffersize(); + max_size = oal_capture_max_buffersize(); *compressed_size=0; *uncompressed_size=0; @@ -483,7 +488,7 @@ void rtvoice_get_data(unsigned char **outbuf, int *compressed_size, int *uncompr return; } - raw_size = dscap_get_raw_data(Rtv_capture_raw_buffer, max_size); + raw_size = oal_capture_get_raw_data(Rtv_capture_raw_buffer, max_size); // convert data to 8bit, 11KHz if necessary raw_size = rtvoice_maybe_convert_data(Rtv_capture_raw_buffer, raw_size); @@ -553,7 +558,7 @@ void rtvoice_reset_out_buffers() for ( i=0; ifrequency, rtvf->bits_per_sample, 1, RTV_BUFFER_TIME); - if ( Rtv_output_buffers[index].ds_handle == -1 ) { + Rtv_output_buffers[index].buf_handle = oal_create_buffer(rtvf->frequency, rtvf->bits_per_sample, 1, RTV_BUFFER_TIME); + if ( Rtv_output_buffers[index].buf_handle == -1 ) { return -1; } @@ -643,8 +648,8 @@ void rtvoice_stop_playback(int index) Assert(index >=0 && index < MAX_RTV_OUT_BUFFERS); if ( Rtv_output_buffers[index].flags & RTV_OUT_FLAG_USED ) { - if ( Rtv_output_buffers[index].ds_handle != -1 ) { - ds_stop_easy(Rtv_output_buffers[index].ds_handle); + if ( Rtv_output_buffers[index].buf_handle != -1 ) { + oal_stop_buffer(Rtv_output_buffers[index].buf_handle); } } } @@ -665,11 +670,11 @@ void rtvoice_free_playback_buffer(int index) if ( Rtv_output_buffers[index].flags & RTV_OUT_FLAG_USED ) { Rtv_output_buffers[index].flags=0; - if ( Rtv_output_buffers[index].ds_handle != -1 ) { - ds_stop_easy(Rtv_output_buffers[index].ds_handle); - ds_unload_buffer(Rtv_output_buffers[index].ds_handle, -1); + if ( Rtv_output_buffers[index].buf_handle != -1 ) { + oal_stop_buffer(Rtv_output_buffers[index].buf_handle); + oal_unload_buffer(Rtv_output_buffers[index].buf_handle); } - Rtv_output_buffers[index].ds_handle=-1; + Rtv_output_buffers[index].buf_handle=-1; } } @@ -678,12 +683,12 @@ void rtvoice_free_playback_buffer(int index) // -1 => error, voice not played int rtvoice_play_compressed(int index, unsigned char *data, int size, int uncompressed_size, double gain) { - int ds_handle, rval; + int buf_handle, rval; - ds_handle = Rtv_output_buffers[index].ds_handle; + buf_handle = Rtv_output_buffers[index].buf_handle; // Stop any currently playing voice output - ds_stop_easy(ds_handle); + oal_stop_buffer(buf_handle); Assert(uncompressed_size <= Rtv_playback_uncompressed_buffer_size); @@ -693,12 +698,12 @@ int rtvoice_play_compressed(int index, unsigned char *data, int size, int uncomp } // lock the data in - if ( ds_lock_data(ds_handle, Rtv_playback_uncompressed_buffer, uncompressed_size) ) { + if ( oal_lock_data(buf_handle, Rtv_playback_uncompressed_buffer, uncompressed_size) ) { return -1; } // play the voice - rval = ds_play(ds_handle, -1, -100, DS_MUST_PLAY, ds_convert_volume(Master_voice_volume), 0, 0); + rval = oal_play(buf_handle, -1, SND_PRIORITY_MUST_PLAY, Master_voice_volume, 0.0f, 0); return rval; } @@ -707,20 +712,20 @@ int rtvoice_play_compressed(int index, unsigned char *data, int size, int uncomp // -1 => error, voice not played int rtvoice_play_uncompressed(int index, unsigned char *data, int size) { - int ds_handle, rval; + int buf_handle, rval; - ds_handle = Rtv_output_buffers[index].ds_handle; + buf_handle = Rtv_output_buffers[index].buf_handle; // Stop any currently playing voice output - ds_stop_easy(ds_handle); + oal_stop_buffer(buf_handle); // lock the data in - if ( ds_lock_data(ds_handle, data, size) ) { + if ( oal_lock_data(buf_handle, data, size) ) { return -1; } // play the voice - rval = ds_play(ds_handle, -1, -100, DS_MUST_PLAY, ds_convert_volume(Master_voice_volume), 0, 0); + rval = oal_play(buf_handle, -1, SND_PRIORITY_MUST_PLAY, Master_voice_volume, 0.0f, 0); return rval; } diff --git a/src/sound/sound.cpp b/src/sound/sound.cpp index 081c9e9..ea2e7b3 100644 --- a/src/sound/sound.cpp +++ b/src/sound/sound.cpp @@ -329,14 +329,8 @@ * * $NoKeywords: $ */ -#include "pstypes.h" - -#ifndef PLAT_UNIX -#include -#include -#include "vdsound.h" -#endif +#include "pstypes.h" #include "3dinternal.h" #include "sound.h" #include "audiostr.h" @@ -347,16 +341,16 @@ #include "gamesnd.h" #include "alphacolors.h" -#include "ds.h" -#include "ds3d.h" +#include "oal.h" +#include "oal_capture.h" +#include "oal_efx.h" #include "acm.h" -#include "dscap.h" - + + #define SND_F_USED (1<<0) // Sounds[] element is used typedef struct sound { int sid; // software id - int hid; // hardware id, -1 if sound is not in hardware char filename[MAX_FILENAME_LEN]; int sig; int flags; @@ -367,34 +361,16 @@ typedef struct sound { sound Sounds[MAX_SOUNDS]; -int Sound_enabled = TRUE; // global flag to turn sound on/off +int Sound_enabled = 0; // global flag to turn sound on/off int Snd_sram; // mem (in bytes) used up by storing sounds in system memory -int Snd_hram; // mem (in bytes) used up by storing sounds in soundcard memory float Master_sound_volume = 1.0f; // range is 0 -> 1, used for non-music sound fx float Master_voice_volume = 0.7f; // range is 0 -> 1, used for all voice playback // min volume to play a sound after all volume processing (range is 0.0 -> 1.0) -#define MIN_SOUND_VOLUME 0.10f +#define MIN_SOUND_VOLUME 0.05f static int snd_next_sig = 1; -// convert the game level sound priorities to the DirectSound priority descriptions -int ds_priority(int priority) -{ - switch(priority){ - case SND_PRIORITY_MUST_PLAY: - return DS_MUST_PLAY; - case SND_PRIORITY_SINGLE_INSTANCE: - return DS_LIMIT_ONE; - case SND_PRIORITY_DOUBLE_INSTANCE: - return DS_LIMIT_TWO; - case SND_PRIORITY_TRIPLE_INSTANCE: - return DS_LIMIT_THREE; - default: - Int3(); - return DS_MUST_PLAY; - } -} void snd_clear() { @@ -404,12 +380,10 @@ void snd_clear() for (i=0; i init success // 0 => init failed // -int snd_init(int use_a3d, int use_eax) +int snd_init(int use_eax) { - int rval; + int rval = 0; if ( Cmdline_freespace_no_sound ) return 0; - if (ds_initialized) { - nprintf(( "Sound", "SOUND => Direct Sound is already initialized!\n" )); + if (Sound_enabled) { + nprintf(( "Sound", "SOUND => Sound is already initialized!\n" )); return 1; } snd_clear(); - // Init DirectSound - - // Connect to DirectSound - int num_tries=0; - int gave_warning = 0; - while(1) { - rval = ds_init(use_a3d, use_eax); - - if( rval != 0 ) { - nprintf(( "Sound", "SOUND ==> Error initializing DirectSound, trying again in 1 second.\n")); - Sleep(1000); - } else { - break; - } + // Init OpenAL + rval = oal_init(use_eax); - if ( num_tries++ > 5 ) { - if ( !gave_warning ) { -#ifndef PLAT_UNIX - MessageBox(NULL, XSTR("DirectSound could not be initialized. If you are running any applications playing sound in the background, you should stop them before continuing.",971), NULL, MB_OK); -#else - fprintf (stderr, "Sound could not be initialized\n"); -#endif - gave_warning = 1; - } else { - goto Failure; - } - } + if (rval < 0) { + nprintf(( "Sound", "SOUND => Direct Sound init unsuccessful, continuing without sound.\n" )); + return 0; } // Init the audio streaming stuff audiostream_init(); - ds_initialized = 1; - return 1; + Sound_enabled = 1; -Failure: -// Warning(LOCATION, "Sound system was unable to be initialized. If you continue, sound will be disabled.\n"); - nprintf(( "Sound", "SOUND => Direct Sound init unsuccessful, continuing without sound.\n" )); - return 0; + return 1; } @@ -579,12 +528,16 @@ void snd_spew_debug_info() // failure => -1 // //int snd_load( char *filename, int hardware, int use_ds3d, int *sig) -int snd_load( game_snd *gs, int allow_hardware_load ) +int snd_load(game_snd *gs) { - int n, rc, type; + int n, rc; sound_info *si; sound *snd; - WAVEFORMATEX *header = NULL; + WAVE_chunk *header = NULL; + + if ( !Sound_enabled ) { + return -1; + } if ( gs->filename == NULL || gs->filename[0] == 0 ) return -1; @@ -610,37 +563,28 @@ int snd_load( game_snd *gs, int allow_hardware_load ) snd = &Sounds[n]; - if ( !ds_initialized ) - return -1; - si = &snd->info; - if ( ds_parse_wave(gs->filename, &si->data, &si->size, &header) == -1 ) + if ( oal_parse_wave(gs->filename, &si->data, &si->size, &header) == -1 ) return -1; - si->format = header->wFormatTag; // 16-bit flag (wFormatTag) - si->n_channels = header->nChannels; // 16-bit channel count (nChannels) - si->sample_rate = header->nSamplesPerSec; // 32-bit sample rate (nSamplesPerSec) - si->avg_bytes_per_sec = header->nAvgBytesPerSec; // 32-bit average bytes per second (nAvgBytesPerSec) - si->n_block_align = header->nBlockAlign; // 16-bit block alignment (nBlockAlign) - si->bits = header->wBitsPerSample; // Read 16-bit bits per sample + si->format = header->code; // 16-bit flag (wFormatTag) + si->n_channels = header->num_channels; // 16-bit channel count (nChannels) + si->sample_rate = header->sample_rate; // 32-bit sample rate (nSamplesPerSec) + si->avg_bytes_per_sec = header->bytes_per_second; // 32-bit average bytes per second (nAvgBytesPerSec) + si->n_block_align = header->block_align; // 16-bit block alignment (nBlockAlign) + si->bits = header->bits_per_sample; // Read 16-bit bits per sample snd->duration = fl2i(1000.0f * (si->size / (si->bits/8.0f)) / si->sample_rate); -nprintf(("SOUND", "SOUND ==> duration = %dms (%d %d %d)\n", snd->duration, -si->size, si->bits, si->sample_rate)); - type = 0; - if ( allow_hardware_load ) { - if ( gs->preload ) { - type |= DS_HARDWARE; - } - } + nprintf(("SOUND", "SOUND ==> duration = %dms (%d %d %d)\n", snd->duration, + si->size, si->bits, si->sample_rate)); + + rc = oal_load_buffer(&snd->sid, &snd->uncompressed_size, header, si, gs->flags); - if ( (gs->flags&GAME_SND_USE_DS3D) ) { - type |= DS_USE_DS3D; + if (header->extra_data != NULL) { + free(header->extra_data); } - - rc = ds_load_buffer(&snd->sid, &snd->hid, &snd->uncompressed_size, header, si, type); free(header); free(si->data); // don't want to keep this around @@ -657,6 +601,7 @@ si->size, si->bits, si->sample_rate)); gs->id = n; nprintf(("Sound", "Loaded %s\n", gs->filename)); + return n; } @@ -668,8 +613,9 @@ si->size, si->bits, si->sample_rate)); // int snd_unload( int n ) { - if (!ds_initialized) + if ( !Sound_enabled ) { return 0; + } if ( (n < 0) || ( n >= MAX_SOUNDS) ) return 0; @@ -677,13 +623,11 @@ int snd_unload( int n ) if ( !(Sounds[n].flags & SND_F_USED) ) return 0; - ds_unload_buffer(Sounds[n].sid, Sounds[n].hid); + oal_unload_buffer(Sounds[n].sid); + if ( Sounds[n].sid != -1 ) { Snd_sram -= Sounds[n].uncompressed_size; } - if ( Sounds[n].hid != -1 ) { - Snd_hram -= Sounds[n].uncompressed_size; - } Sounds[n].flags &= ~SND_F_USED; @@ -698,6 +642,10 @@ int snd_unload( int n ) // void snd_unload_all() { + if ( !Sound_enabled ) { + return; + } + int i; for (i=0; iflags & SND_F_USED) ) return -1; - if (!ds_initialized) - return -1; + if (is_voice_msg) { + flags |= SND_FLAG_VOICE; + } if ( volume > MIN_SOUND_VOLUME ) { - handle = ds_play( snd->sid, snd->hid, gs->id_sig, ds_priority(priority), ds_convert_volume(volume), fl2i(pan*MAX_PAN), 0, is_voice_msg); + handle = oal_play( snd->sid, gs->id_sig, priority, volume, pan, flags); } return handle; @@ -844,7 +802,7 @@ int snd_play_3d(game_snd *gs, vector *source_pos, vector *listen_pos, float radi int handle, min_range, max_range; vector vector_to_sound; sound *snd; - float volume, distance, pan, max_volume; + float volume, distance, max_volume; if ( !Sound_enabled ) return -1; @@ -873,10 +831,6 @@ int snd_play_3d(game_snd *gs, vector *source_pos, vector *listen_pos, float radi min_range = fl2i( (gs->min + radius) * range_factor); max_range = fl2i( (gs->max + radius) * range_factor + 0.5f); - if (!ds_initialized) - return -1; - - // DirectSound3D will not cut off sounds, no matter how quite they become.. so manually // prevent sounds from playing past the max distance. distance = vm_vec_normalized_dir_quick( &vector_to_sound, source_pos, listen_pos ); max_volume = gs->default_volume * vol_scale; @@ -906,32 +860,7 @@ int snd_play_3d(game_snd *gs, vector *source_pos, vector *listen_pos, float radi return -1; } - int play_using_ds3d = 0; - - if (ds_using_ds3d()) { - if ( ds_is_3d_buffer(snd->sid) ) { - play_using_ds3d = 1; - } - } - - if ( play_using_ds3d ) { - // play through DirectSound3D - handle = ds3d_play( snd->sid, snd->hid, gs->id_sig, source_pos, source_vel, min_range, max_range, looping, ds_convert_volume(max_volume*Master_sound_volume), ds_convert_volume(volume), ds_priority(priority)); - } - else { - // play sound as a fake 3D sound - if ( distance <= 0 ) { - pan = 0.0f; - } - else { - pan = vm_vec_dot(&View_matrix.v.rvec,&vector_to_sound); - } - if(looping){ - handle = snd_play_looping( gs, pan, -1, -1, volume/gs->default_volume, priority, force ); - } else { - handle = snd_play( gs, pan, volume/gs->default_volume, priority); - } - } + handle = oal_play_3d( snd->sid, gs->id_sig, source_pos, source_vel, min_range, max_range, looping, max_volume*Master_sound_volume, volume, priority); return handle; } @@ -940,15 +869,32 @@ int snd_play_3d(game_snd *gs, vector *source_pos, vector *listen_pos, float radi void snd_update_3d_pos(int soundnum, game_snd *gs, vector *new_pos) { float vol, pan; - - // get new volume and pan vals - snd_get_3d_vol_and_pan(gs, new_pos, &vol, &pan); - // set volume - snd_set_volume(soundnum, vol); + if ( !Sound_enabled ) { + return; + } + + if (soundnum < 0) + return; + + int channel = oal_get_channel(soundnum); + + if ( channel == -1 ) { + nprintf(( "Sound", "WARNING: Trying to update position for a non-playing sound.\n" )); + return; + } + + // oal_update_source returns non-zero if sound is 2D + if ( oal_update_source(channel, -1, -1, new_pos, NULL) ) { + // get new volume and pan vals + snd_get_3d_vol_and_pan(gs, new_pos, &vol, &pan); - // set pan - snd_set_pan(soundnum, pan); + // set volume + snd_set_volume(soundnum, vol); + + // set pan + snd_set_pan(soundnum, pan); + } } // --------------------------------------------------------------------------------------- @@ -979,8 +925,9 @@ int snd_get_3d_vol_and_pan(game_snd *gs, vector *pos, float* vol, float *pan, fl *vol = 0.0f; *pan = 0.0f; - if (!ds_initialized) + if ( !Sound_enabled ) { return -1; + } Assert(gs != NULL); @@ -1037,20 +984,17 @@ int snd_get_3d_vol_and_pan(game_snd *gs, vector *pos, float* vol, float *pan, fl // returns: -1 => sound could not be played // n => handle for instance of sound // -int snd_play_looping( game_snd *gs, float pan, int start_loop, int stop_loop, float vol_scale, int priority, int force ) +int snd_play_looping( game_snd *gs, float pan, float vol_scale, int priority, int force ) { float volume; int handle = -1; - sound *snd; + sound *snd; if (!Sound_enabled) return -1; Assert( gs != NULL ); - if (!ds_initialized) - return -1; - if ( gs->id == -1 ) { gs->id = snd_load(gs); } @@ -1068,11 +1012,13 @@ int snd_play_looping( game_snd *gs, float pan, int start_loop, int stop_loop, fl volume = gs->default_volume * vol_scale; volume *= Master_sound_volume; + if ( volume > 1.0f ) volume = 1.0f; + if ( (volume > MIN_SOUND_VOLUME) || force) { - handle = ds_play( snd->sid, snd->hid, gs->id_sig, ds_priority(priority), ds_convert_volume(volume), fl2i(pan*MAX_PAN), 1); + handle = oal_play( snd->sid, gs->id_sig, priority, volume, pan, SND_FLAG_LOOPING); } return handle; @@ -1089,14 +1035,19 @@ void snd_stop( int sig ) { int channel; - if (!ds_initialized) return; - if ( sig < 0 ) return; + if ( !Sound_enabled ) { + return; + } - channel = ds_get_channel(sig); + if (sig < 0) { + return; + } + + channel = oal_get_channel(sig); if ( channel == -1 ) return; - ds_stop_channel(channel); + oal_stop_channel(channel); } // --------------------------------------------------------------------------------------- @@ -1112,20 +1063,22 @@ void snd_set_volume( int sig, float volume ) int channel; float new_volume; - if (!ds_initialized) + if ( !Sound_enabled ) { return; + } - if ( sig < 0 ) + if (sig < 0) { return; + } - channel = ds_get_channel(sig); + channel = oal_get_channel(sig); if ( channel == -1 ) { nprintf(( "Sound", "WARNING: Trying to set volume for a non-playing sound.\n" )); return; } new_volume = volume * Master_sound_volume; - ds_set_volume( channel, ds_convert_volume(new_volume) ); + oal_set_volume( channel, new_volume ); } // --------------------------------------------------------------------------------------- @@ -1140,19 +1093,21 @@ void snd_set_pan( int sig, float pan ) { int channel; - if (!ds_initialized) + if ( !Sound_enabled ) { return; + } - if ( sig < 0 ) + if (sig < 0) { return; + } - channel = ds_get_channel(sig); + channel = oal_get_channel(sig); if ( channel == -1 ) { nprintf(( "Sound", "WARNING: Trying to set pan for a non-playing sound.\n" )); return; } - ds_set_pan( channel, fl2i(pan*MAX_PAN) ); + oal_set_pan( channel, pan ); } // --------------------------------------------------------------------------------------- @@ -1160,27 +1115,30 @@ void snd_set_pan( int sig, float pan ) // // Return the pitch of a currently playing sound // -// returns: pitch of sound ( range: 100 to 100000) +// returns: pitch of sound ( range: > 0) // // parameters: sig => handle to sound, what is returned from snd_play() // -int snd_get_pitch(int sig) +float snd_get_pitch(int sig) { - int channel, pitch=10000; + int channel; + float pitch; - if (!ds_initialized) - return -1; + if ( !Sound_enabled ) { + return 1.0f; + } - if ( sig < 0 ) - return -1; + if (sig < 0) { + return 1.0f; + } - channel = ds_get_channel(sig); + channel = oal_get_channel(sig); if ( channel == -1 ) { nprintf(( "Sound", "WARNING: Trying to get pitch for a non-playing sound.\n" )); - return -1; + return 1.0f; } - pitch = ds_get_pitch(channel); + pitch = oal_get_pitch(channel); return pitch; } @@ -1193,20 +1151,25 @@ int snd_get_pitch(int sig) // parameters: sig => handle to sound, what is returned from snd_play() // pan => pitch of sound (range: 100 to 100000) // -void snd_set_pitch( int sig, int pitch ) +void snd_set_pitch( int sig, float pitch ) { int channel; - if (!ds_initialized) return; - if ( sig < 0 ) return; + if ( !Sound_enabled ) { + return; + } + + if (sig < 0) { + return; + } - channel = ds_get_channel(sig); + channel = oal_get_channel(sig); if ( channel == -1 ) { nprintf(( "Sound", "WARNING: Trying to set pitch for a non-playing sound.\n" )); return; } - ds_set_pitch(channel, pitch); + oal_set_pitch(channel, pitch); } // --------------------------------------------------------------------------------------- @@ -1221,24 +1184,21 @@ void snd_set_pitch( int sig, int pitch ) // int snd_is_playing( int sig ) { - int channel, is_playing; + int channel; - if (!ds_initialized) + if ( !Sound_enabled ) { return 0; + } - if ( sig < 0 ) + if (sig < 0) { return 0; + } - channel = ds_get_channel(sig); + channel = oal_get_channel(sig); if ( channel == -1 ) return 0; - is_playing = ds_is_channel_playing(channel); - if ( is_playing == TRUE ) { - return 1; - } - - return 0; + return oal_is_channel_playing(channel); } @@ -1254,19 +1214,21 @@ void snd_chg_loop_status(int sig, int loop) { int channel; - if (!ds_initialized) + if ( !Sound_enabled ) { return; + } - if ( sig < 0 ) + if (sig < 0) { return; + } - channel = ds_get_channel(sig); + channel = oal_get_channel(sig); if ( channel == -1 ) { nprintf(( "Sound", "WARNING: Trying to change loop status of a non-playing sound!\n" )); return; } - ds_chg_loop_status(channel, loop); + oal_chg_loop_status(channel, loop); } // --------------------------------------------------------------------------------------- @@ -1279,26 +1241,11 @@ void snd_chg_loop_status(int sig, int loop) // void snd_stop_all() { - if (!ds_initialized) + if ( !Sound_enabled ) { return; + } - ds_stop_channel_all(); -} - -// --------------------------------------------------------------------------------------- -// sound_get_ds() -// -// Return the pointer to the DirectSound interface -// -// -uint sound_get_ds() -{ -#ifdef PLAT_UNIX - // unused - return 0; -#else - return (uint)pDirectSound; -#endif + oal_stop_channel_all(); } // --------------------------------------------------------------------------------------- @@ -1307,10 +1254,11 @@ uint sound_get_ds() // int snd_is_inited() { - if ( !ds_initialized ) - return FALSE; + if ( !Sound_enabled ) { + return 0; + } - return TRUE; + return 1; } // return the time in ms for the duration of the sound @@ -1329,8 +1277,21 @@ MONITOR( SoundChannels ); // using void snd_update_listener(vector *pos, vector *vel, matrix *orient) { - MONITOR_INC( SoundChannels, ds_get_number_channels() ); - ds3d_update_listener(pos, vel, orient); + MONITOR_INC( SoundChannels, oal_get_number_channels() ); + oal_update_listener(pos, vel, orient); +} + +void snd_update_source(int snd_handle, int min, int max, vector *pos, vector *vel) +{ + if ( !Sound_enabled ) { + return; + } + + if (snd_handle < 0) { + return; + } + + oal_update_source(oal_get_channel(snd_handle), min, max, pos, vel); } // this could probably be optimized a bit @@ -1338,15 +1299,28 @@ void snd_rewind(int snd_handle, game_snd *gs, float seconds) { float current_time,desired_time; float bps; - DWORD current_offset,desired_offset; + int current_offset, desired_offset; sound_info *snd; + int channel; + + if ( !Sound_enabled ) { + return; + } - if(!snd_is_playing(snd_handle)) + if (snd_handle < 0) { return; + } + + channel = oal_get_channel(snd_handle); + + // invalid snd handle, or sound not playing + if (channel < 0) { + return; + } snd = &Sounds[gs->id].info; - current_offset = ds_get_play_position(ds_get_channel(snd_handle)); // current offset into the sound + current_offset = oal_get_play_position(channel); // current offset into the sound bps = (float)snd->sample_rate * (float)snd->bits; // data rate current_time = (float)current_offset/bps; // how many seconds we're into the sound @@ -1355,28 +1329,38 @@ void snd_rewind(int snd_handle, game_snd *gs, float seconds) return; desired_time = current_time - seconds; // where we want to be - desired_offset = (DWORD)(desired_time * bps); // the target + desired_offset = desired_time * bps; // the target - ds_set_position(ds_get_channel(snd_handle),desired_offset); + oal_set_play_position(channel, desired_offset); } // this could probably be optimized a bit void snd_ffwd(int snd_handle, game_snd *gs, float seconds) { - if(!snd_is_playing(snd_handle)) - return; - float current_time,desired_time; float bps; - DWORD current_offset,desired_offset; + int current_offset,desired_offset; sound_info *snd; + int channel; + + if ( !Sound_enabled ) { + return; + } + + if (snd_handle < 0) { + return; + } + + channel = oal_get_channel(snd_handle); - if(!snd_is_playing(snd_handle)) + // invalid snd handle, or sound not playing + if (channel < 0) { return; + } snd = &Sounds[gs->id].info; - current_offset = ds_get_play_position(ds_get_channel(snd_handle)); // current offset into the sound + current_offset = oal_get_play_position(channel); // current offset into the sound bps = (float)snd->sample_rate * (float)snd->bits; // data rate current_time = (float)current_offset/bps; // how many seconds we're into the sound @@ -1385,38 +1369,56 @@ void snd_ffwd(int snd_handle, game_snd *gs, float seconds) return; desired_time = current_time + seconds; // where we want to be - desired_offset = (DWORD)(desired_time * bps); // the target + desired_offset = desired_time * bps; // the target - ds_set_position(ds_get_channel(snd_handle),desired_offset); + oal_set_play_position(channel, desired_offset); } // this could probably be optimized a bit void snd_set_pos(int snd_handle, game_snd *gs, float val,int as_pct) { - if(!snd_is_playing(snd_handle)) + sound_info *snd; + int channel; + + if ( !Sound_enabled ) { return; + } - sound_info *snd; + if (snd_handle < 0) { + return; + } + + channel = oal_get_channel(snd_handle); + + // invalid snd handle, or sound not playing + if (channel < 0) { + return; + } + + snd = &Sounds[gs->id].info; - snd = &Sounds[gs->id].info; // set position as an absolute from 0 to 1 - if(as_pct){ + if (as_pct) { Assert((val >= 0.0) && (val <= 1.0)); - ds_set_position(ds_get_channel(snd_handle),(DWORD)((float)snd->size * val)); + oal_set_play_position(channel, fl2i((float)snd->size * val)); } // set the position as an absolute # of seconds from the beginning of the sound else { float bps; Assert(val <= (float)snd->duration/1000.0f); bps = (float)snd->sample_rate * (float)snd->bits; // data rate - ds_set_position(ds_get_channel(snd_handle),(DWORD)(bps * val)); + oal_set_play_position(channel, fl2i(bps * val)); } } // Return the number of sounds currently playing int snd_num_playing() { - return ds_get_number_channels(); + if ( !Sound_enabled ) { + return 0; + } + + return oal_get_number_channels(); } // Stop the first channel found that is playing a sound @@ -1424,9 +1426,13 @@ void snd_stop_any_sound() { int i; + if ( !Sound_enabled ) { + return; + } + for ( i = 0; i < 16; i++ ) { - if ( ds_is_channel_playing(i) ) { - ds_stop_channel(i); + if ( oal_is_channel_playing(i) ) { + oal_stop_channel(i); break; } } @@ -1441,19 +1447,40 @@ void snd_stop_any_sound() // !0 => fail int snd_get_data(int handle, char *data) { + if ( !Sound_enabled ) { + return -1; + } + Assert(handle >= 0 && handle < MAX_SOUNDS); - if ( ds_get_data(Sounds[handle].sid, data) ) { + + sound *snd = &Sounds[handle]; + uint size; + WAVE_chunk *header = NULL; + ubyte *u_data = (ubyte*)data; + + if ( oal_parse_wave(snd->filename, &u_data, &size, &header) == -1 ) { return -1; } + if (header->extra_data != NULL) { + free(header->extra_data); + } + + free(header); + return 0; } // return the size of the sound data associated with the sound handle int snd_size(int handle, int *size) { + if ( !Sound_enabled ) { + return -1; + } + Assert(handle >= 0 && handle < MAX_SOUNDS); - if ( ds_get_size(Sounds[handle].sid, size) ) { + + if ( oal_get_buffer_size(Sounds[handle].sid, size) ) { return -1; } @@ -1471,29 +1498,27 @@ void snd_get_format(int handle, int *bits_per_sample, int *frequency) // return the time for the sound to play in milliseconds int snd_time_remaining(int handle, int bits_per_sample, int frequency) { - int channel, is_playing, time_remaining = 0; + int channel, time_remaining = 0; + int current_offset, max_offset = 0; - if (!ds_initialized) + if ( !Sound_enabled ) { return 0; + } - if ( handle < 0 ) + if (handle < 0) { return 0; + } - channel = ds_get_channel(handle); - if ( channel == -1 ) - return 0; + channel = oal_get_channel(handle); - is_playing = ds_is_channel_playing(channel); - if ( !is_playing ) { + if (channel < 0) { return 0; } - int current_offset, max_offset; - - current_offset = ds_get_play_position(channel); - max_offset = ds_get_channel_size(channel); + current_offset = oal_get_play_position(channel); + max_offset = oal_get_channel_size(channel); - if ( current_offset < max_offset ) { + if (current_offset < max_offset) { int bytes_remaining = max_offset - current_offset; int samples_remaining = bytes_remaining / fl2i(bits_per_sample/8.0f); time_remaining = fl2i(1000 * samples_remaining/frequency + 0.5f); @@ -1506,7 +1531,7 @@ int snd_time_remaining(int handle, int bits_per_sample, int frequency) // snd_env_ interface -static unsigned long Sound_env_id; +static unsigned int Sound_env_id; static float Sound_env_volume; static float Sound_env_damping; static float Sound_env_decay; @@ -1515,7 +1540,7 @@ static float Sound_env_decay; // int sound_env_set(sound_env *se) { - if (ds_eax_set_all(se->id, se->volume, se->damping, se->decay) == 0) { + if ( !oal_efx_set_all(se->id, se->volume, se->damping, se->decay) ) { Sound_env_id = se->id; Sound_env_volume = se->volume; Sound_env_damping = se->damping; @@ -1532,7 +1557,7 @@ int sound_env_get(sound_env *se) { EAX_REVERBPROPERTIES er; - if (ds_eax_get_all(&er) == 0) { + if (oal_efx_get_all(&er, -1) == 0) { se->id = er.environment; se->volume = er.fVolume; se->decay = er.fDecayTime_sec; @@ -1560,12 +1585,12 @@ int sound_env_disable() // int sound_env_supported() { - return ds_eax_is_inited(); + return oal_efx_is_inited(); } // Called once per game frame // void snd_do_frame() { - ds_do_frame(); + oal_do_frame(); } diff --git a/src/vcodec/codec1.cpp b/src/vcodec/codec1.cpp index 561db35..5f6121e 100644 --- a/src/vcodec/codec1.cpp +++ b/src/vcodec/codec1.cpp @@ -5,14 +5,10 @@ // // Written by Matthew F. Storch, Ph.D., copyright (c) 1998 Volition Inc. -#ifndef PLAT_UNIX -#include -#endif #include "pstypes.h" #include -#include #include "codec1.h" @@ -114,7 +110,7 @@ extern "C" #define lpc10init() #define lpc10encode(in, out, inlen) 0 #define lpc10decode(in, out, inlen) { out = 0; } -#define AssertLPC10Available() assert(0) +#define AssertLPC10Available() SDL_assert(0) #endif // defined(USE_LPC10) // @@ -159,7 +155,6 @@ t_Sample* TempEncoderBuf2 = NULL; void InitDecoder(int QoS, t_Sample* tempBuf) { - QoS = QoS; // just to shut compiler up TempDecoderBuf = tempBuf; lpc10init(); // call unconditionally because we don't know what kind of // coded packets we might receive @@ -451,27 +446,27 @@ int Encode(t_Sample* bufIn, t_Sample* bufOut, int sizeIn, int sizeOut, #pragma pack(1) #define PACKED #else -#define PACKED __attribute__((packed)) +#define PACKED __attribute__((packed, aligned(2))) #endif // most general notion of a packet pair struct t_PacketPair { - unsigned long Mode1 : 3; - unsigned long Mode1Ex : 1; - unsigned long Data1 : 8; - unsigned long Mode0 : 3; - unsigned long Mode0Ex : 1; - unsigned long Data0 : 8; + unsigned int Mode1 : 3; + unsigned int Mode1Ex : 1; + unsigned int Data1 : 8; + unsigned int Mode0 : 3; + unsigned int Mode0Ex : 1; + unsigned int Data0 : 8; } PACKED; // nominal packet pair struct t_PacketPairNom { - unsigned long Mode1 : 3; - unsigned long Data1 : 9; - unsigned long Mode0 : 3; - unsigned long Data0 : 9; + unsigned int Mode1 : 3; + unsigned int Data1 : 9; + unsigned int Mode0 : 3; + unsigned int Data0 : 9; } PACKED; // run-length packet, case 1 @@ -508,24 +503,24 @@ struct t_PacketHFData // run-length packet, case 0 struct t_PacketRL0 { - unsigned long Mode1 : 3; // mode of previous packet in pair - unsigned long Data1 : 9; // data of previous packet in pair - unsigned long Mode0 : 3; // mode of this packet (always 0) - unsigned long Mode0Ex : 1; // extra bit to distinguish RL & HF (always 0) - unsigned long Length : 8; // length of run + unsigned int Mode1 : 3; // mode of previous packet in pair + unsigned int Data1 : 9; // data of previous packet in pair + unsigned int Mode0 : 3; // mode of this packet (always 0) + unsigned int Mode0Ex : 1; // extra bit to distinguish RL & HF (always 0) + unsigned int Length : 8; // length of run } PACKED; // high-frequency packet, case 0 struct t_PacketHF0 { - unsigned long Mode1 : 3; // mode of previous packet in pair - unsigned long Data1 : 9; // data of previous packet in pair - unsigned long Mode0 : 3; // mode of this packet (always 0) - unsigned long Mode0Ex : 1; // extra bit to distinguish RL & HF (always 1) - unsigned long Table : 1; // 1 ==> DataT is lookup table number - unsigned long Data0 : 3; // absolute sample data - unsigned long DataT : 3; // absolute sample data or lookup table number - unsigned long Unused : 1; + unsigned int Mode1 : 3; // mode of previous packet in pair + unsigned int Data1 : 9; // data of previous packet in pair + unsigned int Mode0 : 3; // mode of this packet (always 0) + unsigned int Mode0Ex : 1; // extra bit to distinguish RL & HF (always 1) + unsigned int Table : 1; // 1 ==> DataT is lookup table number + unsigned int Data0 : 3; // absolute sample data + unsigned int DataT : 3; // absolute sample data or lookup table number + unsigned int Unused : 1; } PACKED; // medium-frequency packet, case 1 @@ -540,12 +535,12 @@ struct t_PacketMF1 // medium-frequency packet, case 0 struct t_PacketMF0 { - unsigned long Mode1 : 3; // mode of previous packet in pair - unsigned long Data1 : 9; // data of previous packet in pair - unsigned long Mode0 : 3; // mode of this packet (always 7) - unsigned long Mult : 1; // 0 ==> mult data by 1, 1 ==> mult data by 2 - long DataX : 2; // not currently used - long Data0 : 6; // total rise or fall over next 4 samples + unsigned int Mode1 : 3; // mode of previous packet in pair + unsigned int Data1 : 9; // data of previous packet in pair + unsigned int Mode0 : 3; // mode of this packet (always 7) + unsigned int Mult : 1; // 0 ==> mult data by 1, 1 ==> mult data by 2 + int DataX : 2; // not currently used + int Data0 : 6; // total rise or fall over next 4 samples } PACKED; // restore state of compiler padding of structures @@ -1043,10 +1038,10 @@ static int Encode1(t_Sample* bufIn, t_Sample* bufOut, int size, int sizeOut) int tableNum = 0; - assert(sizeof(t_PacketRL1) == 2); - assert(sizeof(t_PacketHF1) == 2); - assert(sizeof(t_PacketHFData) == 2); - assert(sizeof(t_PacketHF0) == 4); + SDL_assert(sizeof(t_PacketRL1) == 2); + SDL_assert(sizeof(t_PacketHF1) == 2); + SDL_assert(sizeof(t_PacketHFData) == 2); + SDL_assert(sizeof(t_PacketHF0) == 4); // First byte in encoded data is unencoded (literal mode) initial level. level = *out++ = *in++; @@ -1176,10 +1171,10 @@ static int Encode1(t_Sample* bufIn, t_Sample* bufOut, int size, int sizeOut) packet.ModeEx = 0; packet.Length = (unsigned short)len; *(t_PacketRL1*)out = packet; - out += sizeof packet; + out += sizeof(packet); // packetPos remains at 1 #if defined(CODEC_DEMO) - samples[0] += len; storage[0] += 2*sizeof packet; + samples[0] += len; storage[0] += 2*sizeof(packet); #endif } else @@ -1189,10 +1184,10 @@ static int Encode1(t_Sample* bufIn, t_Sample* bufOut, int size, int sizeOut) packet.Mode0Ex = 0; packet.Length = len; *(t_PacketRL0*)out = packet; - out += 3; // sizeof packet; + out += 3; // sizeof(packet); packetPos = 1; #if defined(CODEC_DEMO) - samples[0] += len; storage[0] += 3; // sizeof packet; + samples[0] += len; storage[0] += 3; // sizeof(packet}; #endif } in += len; @@ -1296,7 +1291,7 @@ static int Encode1(t_Sample* bufIn, t_Sample* bufOut, int size, int sizeOut) else if (delta < -32) packet.Data0 = -32; else packet.Data0 = delta; *(t_PacketMF1*)out = packet; - out += sizeof packet; + out += sizeof(packet); in += 4; #if defined(CODEC_DEMO) @@ -1312,7 +1307,7 @@ static int Encode1(t_Sample* bufIn, t_Sample* bufOut, int size, int sizeOut) assert(temp2 == level + packet.Data0); for (i = 0; i < 8; i++) *modes++ = 7; - samples[7] += 8; storage[7] += 2*sizeof packet; + samples[7] += 8; storage[7] += 2*sizeof(packet); #endif level += packet.Data0; @@ -1324,7 +1319,7 @@ static int Encode1(t_Sample* bufIn, t_Sample* bufOut, int size, int sizeOut) packet.DataX = 0; packet.Data0 = delta; *(t_PacketMF0*)out = packet; - out += sizeof packet; + out += sizeof(packet); #if defined(CODEC_DEMO) temp2 = level; @@ -1335,7 +1330,7 @@ static int Encode1(t_Sample* bufIn, t_Sample* bufOut, int size, int sizeOut) assert(temp2 == level + packet.Data0); for (i = 0; i < 4; i++) *modes++ = 7; - samples[7] += 4; storage[7] += 3; // sizeof packet; + samples[7] += 4; storage[7] += 3; // sizeof(packet); #endif level += packet.Data0; @@ -1367,7 +1362,7 @@ static int Encode1(t_Sample* bufIn, t_Sample* bufOut, int size, int sizeOut) packet.Data0 = (unsigned short)(EncTable[table][*in]); data0 = *in++; *(t_PacketHF1*)out = packet; - out += sizeof packet; + out += sizeof(packet); #if defined(CODEC_DEMO) *levels++ = t_Sample(DecTable[table][packet.Data2] + ZERO); @@ -1376,7 +1371,7 @@ static int Encode1(t_Sample* bufIn, t_Sample* bufOut, int size, int sizeOut) *modes++ = 8; *modes++ = 8; *modes++ = 8; - samples[8] += 3; storage[8] += 2*sizeof packet; + samples[8] += 3; storage[8] += 2*sizeof(packet); #endif } else @@ -1401,12 +1396,12 @@ static int Encode1(t_Sample* bufIn, t_Sample* bufOut, int size, int sizeOut) finalPacketData = packet.DataT = EncTable[table = tableNum][*in++]; } *(t_PacketHF0*)out = packet; - out += 3; // sizeof packet; + out += 3; // sizeof(packet); #if defined(CODEC_DEMO) *levels++ = t_Sample(DecTable[table][packet.Data0] + ZERO); *modes++ = 8; - samples[8] += 1; storage[8] += 3; // sizeof packet; + samples[8] += 1; storage[8] += 3; // sizeof(packet); if (packet.Table == 0) { *levels++ = t_Sample(DecTable[table][packet.DataT] + ZERO); @@ -1483,7 +1478,7 @@ static int Encode1(t_Sample* bufIn, t_Sample* bufOut, int size, int sizeOut) tableNum = table; *(t_PacketHFData*)out = packet; - out += sizeof packet; + out += sizeof(packet); #if defined(CODEC_DEMO) *levels++ = t_Sample(DecTable[table][packet.Data3] + ZERO); @@ -1491,7 +1486,7 @@ static int Encode1(t_Sample* bufIn, t_Sample* bufOut, int size, int sizeOut) *levels++ = t_Sample(DecTable[table][packet.Data1] + ZERO); *levels++ = t_Sample(DecTable[table][packet.Data0] + ZERO); *modes++ = 8; *modes++ = 8; *modes++ = 8; *modes++ = 8; - samples[8] += 4; storage[8] += 2*sizeof packet; + samples[8] += 4; storage[8] += 2*sizeof(packet); if (packet.Table == 0) { *levels++ = t_Sample(DecTable[table][packet.DataT] + ZERO); @@ -1547,6 +1542,8 @@ static int ComputeNomData(t_Sample*& in, const int deltas[], int& level) // esi in // ebp data +//#define CODEC1_USE_ASM + #if defined(CODEC_DEMO) static int ComputeNomDataF(t_Sample*& inp, const int deltas[], int& level, t_Sample*& levels) @@ -1554,7 +1551,7 @@ static int ComputeNomDataF(t_Sample*& inp, const int deltas[], int& level, static int ComputeNomDataF(t_Sample*& inp, const int deltas[], int& level) #endif { -#ifndef PLAT_UNIX +#ifdef CODEC1_USE_ASM int data; __asm { @@ -1611,8 +1608,26 @@ static int ComputeNomDataF(t_Sample*& inp, const int deltas[], int& level) } return data; #else - STUB_FUNCTION; - return 0; + int data = 0; + + for (int i = 0; i < 9; i++, inp++) + { + if (level+deltas[0] < *inp) + { + data = (data << 1) | 1; + level += deltas[1]; + } + else + { + data <<= 1; + level += deltas[0]; + } + #if defined(CODEC_DEMO) + *levels++ = t_Sample(level); + #endif + } + + return data; #endif } @@ -1661,14 +1676,14 @@ static int DoEncode(int mode, BOOL& packetPos, t_Sample*& in, t_Sample*& out, packet = *(t_PacketPairNom*)out; packet.Mode0 = mode; packet.Data0 = ComputeNomDataF(in,Deltas[mode], level EXTRA_CODEC_DEMO_ARGS1); - advanceOutput = 3; // sizeof packet; + advanceOutput = 3; // sizeof(packet); } *(t_PacketPairNom*)out = packet; packetPos = !packetPos; #if defined(CODEC_DEMO) for (int i = 0; i < 9; i++) *modes++ = mode; - samples[mode] += 9; storage[mode] += 3; // sizeof packet; + samples[mode] += 9; storage[mode] += 3; // sizeof(packet); #endif return advanceOutput; -- 2.39.2