| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- /******************************************************************************
- Use 'SoundVolume' to set volume for different sound groups
- Use 'SoundPlay' to play custom sounds
- Use 'Sound' to play custom sounds and control them later
- Use 'Listener' to set 3D listener parameters which receives 3D sounds
- /******************************************************************************/
- enum VOLUME_GROUP : Byte // Sound Volume Group
- {
- VOLUME_FX , // Sound Effects
- VOLUME_MUSIC , // Music
- VOLUME_AMBIENT, // Ambient Surroundings
- VOLUME_VOICE , // Voices
- VOLUME_UI , // User Interface
- VOLUME_NUM , // number of volume groups
- };
- /******************************************************************************/
- struct SoundVolumeClass
- {
- void fx (Flt v); Flt fx ()C {return _v[VOLUME_FX ];} // set/get fx volume (0..1)
- void music (Flt v); Flt music ()C {return _v[VOLUME_MUSIC ];} // set/get music volume (0..1)
- void ambient(Flt v); Flt ambient()C {return _v[VOLUME_AMBIENT];} // set/get ambient volume (0..1)
- void voice (Flt v); Flt voice ()C {return _v[VOLUME_VOICE ];} // set/get voice volume (0..1)
- void ui (Flt v); Flt ui ()C {return _v[VOLUME_UI ];} // set/get UI volume (0..1)
- void global (Flt v); Flt global ()C {return _v[VOLUME_NUM ];} // set/get global volume (0..1)
- #if EE_PRIVATE
- void update(); // update sound volumes
- #endif
- #if !EE_PRIVATE
- private:
- #endif
- Flt _v[VOLUME_NUM+1]; // +1 to make room for global
- SoundVolumeClass();
- }extern
- SoundVolume; // Main Sound Volume Control
- /******************************************************************************/
- struct ListenerClass
- {
- #if EE_PRIVATE
- Bool create();
- UInt updateNoLock(); // update listener
- void commitNoLock(); // update all 3D sounds parameters, only after this call all 3D sound changes are updated, this should be called once per frame
- #endif
- // get
- C Vec& pos ()C {return _orn.pos ;} // get listener position
- C Vec& dir ()C {return _orn.dir ;} // get listener forward direction
- C Vec& up ()C {return _orn.perp ;} // get listener up direction
- Vec right()C {return _orn.cross();} // get listener right direction
- C Vec& vel ()C {return _vel ;} // get listener velocity
- // set
- ListenerClass& pos(C Vec &pos ); // set listener position
- ListenerClass& orn(C Vec &dir, C Vec &up=Vec(0, 1, 0)); // set listener orientation, 'dir'=forward direction (must be normalized), 'up'=up direction (must be normalized)
- ListenerClass& vel(C Vec &vel ); // set listener velocity
- #if !EE_PRIVATE
- private:
- #endif
- OrientP _orn;
- Vec _vel;
- Int _flag;
- ListenerClass();
- }extern
- Listener; // Main 3D Sound Listener Control
- /******************************************************************************/
- enum FADE_CURVE : Byte
- {
- FADE_LINEAR,
- FADE_SQRT ,
- FADE_EQUAL_POWER=FADE_SQRT,
- };
- #if EE_PRIVATE
- enum SOUND_FLAG
- {
- SOUND_CHANGED_POS =1<<0,
- SOUND_CHANGED_VEL =1<<1,
- SOUND_CHANGED_ORN =1<<2, // used for Listener
- SOUND_CHANGED_RANGE =1<<3,
- SOUND_CHANGED_VOLUME=1<<4,
- SOUND_CHANGED_SPEED =1<<5,
- SOUND_CHANGED_TIME =1<<6,
- SOUND_CHANGING_TIME =1<<7,
- SOUND_REMOVE =1<<8, // this can be set only if no 'Sound' references a '_Sound' anymore
- SOUND_NO_REF =1<<9, // if there's no external reference to this sound
- //SOUND_CHANGED_PAN =, this is not used
- //SOUND_CHANGED_PLAY =, this is not needed since it's always checked
- };
- const_mem_addr struct _Sound // can be moved however 'memAddressChanged' needs to be called afterwards
- {
- Bool _playing, _buffer_playing, _loop, _is3D, stream_loaded, deleted;
- Byte last_buffer, kill;
- VOLUME_GROUP volume_group;
- FADE_CURVE _fade_curve;
- Int flag;
- Long raw_pos;
- Flt _volume, _speed, _actual_speed, _range, _time, _fade, _fade_d, priority;
- Vec _pos, _vel;
- Str _name;
- SoundDataCallback *_callback;
- SoundStream _stream;
- SoundBuffer _buffer;
- SoundStream& stream();
- C SoundStream& stream()C {return ConstCast(T).stream();}
- void zero();
- void del ();
- void init(C Str &name, const_mem_addr SoundCallback *call, Bool is3D, VOLUME_GROUP volume_group);
- Bool init(C _Sound &src);
- // stop / play
- void stop ();
- void pause();
- void play ();
- // get / set
- Bool noRef ()C {return FlagTest(AtomicGet(flag), SOUND_NO_REF);} // if there's no external reference to this sound
- Bool is ()C; // if created
- Bool is3D ()C {return _is3D ;} // if is 3D
- Bool playing ()C {return _playing;} // if playing
- SOUND_CODEC codec ()C; // get source codec
- C Str& name ()C; // get source file name
- UID id ()C; // get source file name ID
- Long size ()C; // get source raw size in bytes
- Flt length ()C; // get source time length in seconds
- Long samples ()C; // get source number of samples
- Int channels ()C; // get source number of channels
- Int frequency()C; // get source frequency
- Int bitRate ()C; // get source bit rate
- Flt timeLeft ()C; // get sound remaining time , 0..length (), "length()-time()"
- void raw ( Long raw ); Long raw ()C; // set/get sound raw position, 0..size ()
- void sample( Long sample); Long sample ()C; // set/get sound sample position, 0..samples()
- void time ( Flt t ); Flt time ()C {return _time ;} // set/get sound time position, 0..length ()
- void frac ( Flt f ); Flt frac ()C; // set/get sound fraction position, 0..1
- void loop ( Bool loop ); Bool loop ()C {return _loop ;} // set/get sound looping , true/false
- void volume( Flt volume); Flt volume ()C {return _volume ;} // set/get sound volume , 0..1
- void speed ( Flt speed ); Flt speed ()C {return _speed ;} // set/get sound speed , 0..3, default=1
- void range ( Flt range ); Flt range ()C {return _range ;} // set/get sound 3D range , 0..Inf
- void pos (C Vec &pos ); C Vec& pos ()C {return _pos ;} // set/get sound 3D position
- void vel (C Vec &vel ); C Vec& vel ()C {return _vel ;} // set/get sound 3D velocity
- void preciseRaw (Long raw); Long preciseRaw ()C; // set/get sound raw position, 0..size ()
- void preciseTime(Flt t ); Flt preciseTime()C; // set/get sound time position, 0..length()
- void preciseFrac(Flt f ); Flt preciseFrac()C; // set/get sound fraction position, 0..1
- // operations
- Flt actualSpeed ()C;
- void setVolume ();
- void setSpeed ();
- Bool update (Flt dt);
- void updatePlaying(Int thread_index);
- void memAddressChanged();
- // fade
- Flt fade ()C {return _fade ;} // get current fade value
- void fadeCurve (FADE_CURVE curve ); FADE_CURVE fadeCurve()C {return _fade_curve;} // set/get fade curve
- void fadeInFromSilence(Flt fade_duration);
- void fadeIn (Flt fade_duration);
- void fadeOut (Flt fade_duration);
- // io
- Bool save (File &f, CChar *path=null)C; // 'path'=path at which resource is located (this is needed so that the sub-resources can be accessed with relative path), false on fail
- Int loadResult(File &f, CChar *path=null) ; // 'path'=path at which resource is located (this is needed so that the sub-resources can be accessed with relative path)
- // stream
- void setBuffer (Byte *buffer, Int size);
- Bool setBuffer (Bool buffer, Int thread_index);
- Bool setNextBuffer(Int thread_index) {return setBuffer(!last_buffer, thread_index);} // remember that 'last_buffer' can be 0xFF
- Bool testBuffer (Int thread_index);
- ~_Sound() {del();}
- _Sound() {stream_loaded=deleted=false; flag=0; zero();}
- NO_COPY_CONSTRUCTOR(_Sound);
- };
- #endif
- /******************************************************************************/
- struct Sound
- {
- // manage
- #if EE_PRIVATE
- Sound& _create(C Str &name, const_mem_addr SoundCallback *call, Bool is3D, VOLUME_GROUP volume_group);
- #endif
- Sound& del ();
- Sound& close (); // delete and wait until file handle is released, this method is slower than 'del', use it only if you need to modify the sound file
- Sound& create( C Str &name, Bool loop=false, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX); // create sound, 'name'=sound file name , , 'loop'=if sound is looped, 'volume'=sound volume (0..1)
- Sound& create( C UID &id , Bool loop=false, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX); // create sound, 'id' =sound file name ID, , 'loop'=if sound is looped, 'volume'=sound volume (0..1)
- Sound& create(const_mem_addr SoundCallback &call, Bool loop=false, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX); // create sound, 'call'=sound call back , , 'loop'=if sound is looped, 'volume'=sound volume (0..1)
- Sound& create( C Str &name, C Vec &pos, Flt range=1, Bool loop=false, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX); // create 3D sound, 'name'=sound file name , 'pos'=sound position in World, 'range'=sound range multiplier (0..Inf), 'loop'=if sound is looped, 'volume'=sound volume (0..1)
- Sound& create( C UID &id , C Vec &pos, Flt range=1, Bool loop=false, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX); // create 3D sound, 'id' =sound file name ID, 'pos'=sound position in World, 'range'=sound range multiplier (0..Inf), 'loop'=if sound is looped, 'volume'=sound volume (0..1)
- Sound& create(const_mem_addr SoundCallback &call, C Vec &pos, Flt range=1, Bool loop=false, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX); // create 3D sound, 'call'=sound call back , 'pos'=sound position in World, 'range'=sound range multiplier (0..Inf), 'loop'=if sound is looped, 'volume'=sound volume (0..1)
- Sound& play ( C Str &name, Bool loop=false, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX) {return create(name, loop, volume, volume_group).play();} // create and play sound, 'name'=sound file name , , 'loop'=if sound is looped, 'volume'=sound volume (0..1)
- Sound& play ( C UID &id , Bool loop=false, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX) {return create(id , loop, volume, volume_group).play();} // create and play sound, 'id' =sound file name ID, , 'loop'=if sound is looped, 'volume'=sound volume (0..1)
- Sound& play (const_mem_addr SoundCallback &call, Bool loop=false, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX) {return create(call, loop, volume, volume_group).play();} // create and play sound, 'call'=sound call back , , 'loop'=if sound is looped, 'volume'=sound volume (0..1)
- Sound& play ( C Str &name, C Vec &pos, Flt range=1, Bool loop=false, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX) {return create(name, pos, range, loop, volume, volume_group).play();} // create and play 3D sound, 'name'=sound file name , 'pos'=sound position in World, 'range'=sound range multiplier (0..Inf), 'loop'=if sound is looped, 'volume'=sound volume (0..1)
- Sound& play ( C UID &id , C Vec &pos, Flt range=1, Bool loop=false, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX) {return create(id , pos, range, loop, volume, volume_group).play();} // create and play 3D sound, 'id' =sound file name ID, 'pos'=sound position in World, 'range'=sound range multiplier (0..Inf), 'loop'=if sound is looped, 'volume'=sound volume (0..1)
- Sound& play (const_mem_addr SoundCallback &call, C Vec &pos, Flt range=1, Bool loop=false, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX) {return create(call, pos, range, loop, volume, volume_group).play();} // create and play 3D sound, 'call'=sound call back , 'pos'=sound position in World, 'range'=sound range multiplier (0..Inf), 'loop'=if sound is looped, 'volume'=sound volume (0..1)
- // stop / play
- Sound& stop (); // stop
- Sound& pause(); // pause
- Sound& play (); // play
- // get / set
- Bool is ()C; // if created
- Bool playing ()C; // if playing
- SOUND_CODEC codec ()C; // get source codec
- CChar8* codecName()C; // get source codec name
- C Str& name ()C; // get source file name
- UID id ()C; // get source file name ID
- Long size ()C; // get source raw size in bytes
- Flt length ()C; // get source time length in seconds
- Long samples ()C; // get source number of samples
- Int channels ()C; // get source number of channels
- Int frequency()C; // get source frequency
- Int bitRate ()C; // get source bit rate
- Flt timeLeft ()C; // get sound remaining time , 0..length (), "length()-time()"
- Sound& raw ( Long raw ); Long raw ()C; // set/get sound raw position , 0..size ()
- Sound& sample( Long sample); Long sample ()C; // set/get sound sample position , 0..samples()
- Sound& time ( Flt t ); Flt time ()C; // set/get sound time position , 0..length ()
- Sound& frac ( Flt f ); Flt frac ()C; // set/get sound fraction position , 0..1
- Sound& loop ( Bool loop ); Bool loop ()C; // set/get sound looping , true/false
- Sound& volume( Flt volume); Flt volume ()C; // set/get sound volume , 0..1
- Sound& speed ( Flt speed ); Flt speed ()C; // set/get sound speed , 0..3, default=1
- Sound& range ( Flt range ); Flt range ()C; // set/get sound 3D range multiplier, 0..Inf
- Sound& pos (C Vec &pos ); C Vec& pos ()C; // set/get sound 3D position
- Sound& vel (C Vec &vel ); C Vec& vel ()C; // set/get sound 3D velocity
- // volume fade
- Flt fade ()C; // get current fade value
- Sound& fadeCurve (FADE_CURVE curve ); FADE_CURVE fadeCurve()C; // set/get fade curve
- Sound& fadeInFromSilence(Flt fade_duration); // perform volume fade-in from silence to max volume
- Sound& fadeIn (Flt fade_duration); // perform volume fade-in from current volume level to max volume
- Sound& fadeOut (Flt fade_duration); // perform volume fade-out from current volume level to zero volume
- // data callback
- Sound& callback(SoundDataCallback *callback); SoundDataCallback* callback()C; // set/get data callback, it will be called every time a new portion of data is processed by the sound
- // io
- Bool save(File &f, CChar *path=null)C; // 'path'=path at which resource is located (this is needed so that the sub-resources can be accessed with relative path), false on fail
- Bool load(File &f, CChar *path=null) ; // 'path'=path at which resource is located (this is needed so that the sub-resources can be accessed with relative path), false on fail
- ~Sound() {del();}
- Sound() {sound=null;}
- Sound(C Sound &src);
- void operator=(C Sound &src);
- private:
- #if EE_PRIVATE
- _Sound *sound;
- #else
- Ptr sound;
- #endif
- };
- /******************************************************************************/
- Bool CacheSound(C Str &name); // cache sound file into memory so it won't be played every time from the disk, usage of this function is optional, you can call it at some initialization stage of your game, false on fail
- Bool CacheSound(C UID &id ); // cache sound file into memory so it won't be played every time from the disk, usage of this function is optional, you can call it at some initialization stage of your game, false on fail
- void SoundPlay( C Str &name, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX, Flt speed=1); // play sound, 'name'=sound file name , 'volume'=sound volume (0..1), 'speed'=sound speed (0..3)
- void SoundPlay( C UID &id , Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX, Flt speed=1); // play sound, 'id' =sound file name ID , 'volume'=sound volume (0..1), 'speed'=sound speed (0..3)
- void SoundPlay(const_mem_addr SoundCallback &call, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX, Flt speed=1); // play sound, 'call'=sound call back , 'volume'=sound volume (0..1), 'speed'=sound speed (0..3)
- void SoundPlay( C Str &name, C Vec &pos, Flt range=1, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX, Flt speed=1); // play 3D sound, 'name'=sound file name , 'pos'=sound position in World, 'range'=sound range multiplier (0..Inf), 'volume'=sound volume (0..1), 'speed'=sound speed (0..3)
- void SoundPlay( C UID &id , C Vec &pos, Flt range=1, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX, Flt speed=1); // play 3D sound, 'id' =sound file name ID, 'pos'=sound position in World, 'range'=sound range multiplier (0..Inf), 'volume'=sound volume (0..1), 'speed'=sound speed (0..3)
- void SoundPlay(const_mem_addr SoundCallback &call, C Vec &pos, Flt range=1, Flt volume=1, VOLUME_GROUP volume_group=VOLUME_FX, Flt speed=1); // play 3D sound, 'call'=sound call back , 'pos'=sound position in World, 'range'=sound range multiplier (0..Inf), 'volume'=sound volume (0..1), 'speed'=sound speed (0..3)
- Flt SoundMinVolume (); void SoundMinVolume (Flt volume); // get/set minimum volume required to play a sound , default=0.02, if volume of a sound is less than the specified value then it will be skipped for faster processing
- Int SoundMaxConcurrent(); void SoundMaxConcurrent(Int max ); // get/set maximum number of concurrent sounds , default=16 , if number of sounds exceeds the specified limit then sounds with lower priority will be skipped for faster processing, specifying negative value (-1) is the same as allowing unlimited number of concurrent sounds
- Int SoundMaxThreads (); void SoundMaxThreads (Int max ); // get/set maximum number of threads used for sound processing, default=1
- /******************************************************************************/
- #if EE_PRIVATE
- extern SyncLock SoundAPILock; // Sound API Lock
- extern Bool SoundAPI , // if Sound API is available
- SoundFunc ; // if we can access Sound functions
- void InitSound ();
- void ShutSound ();
- void InitSound2 ();
- void ShutSound2 ();
- void UpdateSound ();
- void PauseSound ();
- void ResumeSound ();
- void VolumeSound ();
- void EmulateSound3D();
- void SpeedSound ();
- Bool PlayingAnySound();
- #define MAX_SOUND_SPEED 2
- inline Flt SoundSpeed(Flt speed) {return Mid(speed, 0.0f, (Flt)MAX_SOUND_SPEED);}
- #if HAS_THREADS
- #define SOUND_TIMER 26 // 26 ms which is 38.5 Hz(fps), recommended value to be between 17ms(58.8Hz fps) .. 34ms(29.4Hz fps), also the callback will be triggered at least once per frame (due to 'SoundEvent' being triggered at the end of each frame to immediately process any changes), shorter timers result in smaller memory usage at the cost of additional overhead on the CPU
- #define SOUND_TIME (SOUND_TIMER*2*2*MAX_SOUND_SPEED) // 2 (2 half buffers) * 2 (safety due to sounds being started at different times) * MAX_SOUND_SPEED
- #define SOUND_TIME_RECORD (SOUND_TIMER*2*2) // 2 (2 half buffers) * 2 (safety due to sounds being started at different times), this doesn't need MAX_SOUND_SPEED because sounds are always recorded with speed=1
- #else
- #define SOUND_TIMER 50
- #define SOUND_TIME 1200 // when there are no threads available, set a big sound buffer, to allow some tolerance for pauses during loading
- #define SOUND_TIME_RECORD 500 // when there are no threads available, set a big sound buffer, to allow some tolerance for pauses during loading
- #endif
- #endif
- /******************************************************************************/
|