#ifndef _SOUND_HPP_ #define _SOUND_HPP_ #include #include namespace sound { // type of sound. // the envelope settings modify each sound. enum Sound { SoundFrequency=0, // one frequency SoundWhiteNoise=1, // all frequencies are equal SoundBrownianNoise=2, // 1/f^2 noise SoundPinkNoise=3, // 1/f noise }; enum EnvelopeState { New=0, // newly spawned Wait, // ready but not yet started (waiting before starting or before repeating) Rise, // increasing BeginOvershoot, EndOvershoot, Hold, // staying at normal level Decay, // deacying Done, // done }; enum SoundDecayType { SoundDecayLinear = 0, SoundDecayExp = 1 }; typedef struct { // just for debugging/logging. don't rely on use const char *name; // unique ID for accessing them via lookups etc. if sound is dead, this will be never reused int uid; // if true, don't deallocate once this is done. bool keep_when_done; // these are public and can be changed by the user. enum EnvelopeState envelope; /****************************************************************/ /* Special Parameters for specific types */ /****************************************************************/ /******************** SoundFrequency ****************************/ float freq; // base frequency for type: SoundFrequency /******************** White / Brownian / Pink Noise ****************/ float leakage; // influence of previous state on current value (0..1) float scaling; // influence of white noise on next value // If true and the value goes outside (-1..1), do the step in the other // direction to stay inside the valid range. bool skipDirectionIfClamping; /******************** SoundFrequency: ***************************/ /****************************************************************/ /* Common sound state / parameters */ /****************************************************************/ // progress of the sound which is used for the envelope but can be used for // other things too float time; // scalar state that can be used arbitrarily to derive the waveform from it float state; // time when the sound is done // if != 0.0, the sound changes with that // TODO: make attack gain decay stuff as envelope // TODO: add amplitude noise float _riseTime; float _relativeOvershootTime; // percentage of end of rise time that is used for overshoot (max amplitude at t_overshoot/2) float _holdTime; float _decayTime; float _waitTime; // waveform of type of rise. default: linear enum SoundDecayType riseType; // waveform of type of decay. default: linear enum SoundDecayType decayType; // if true, play infinitely bool looping; // base amplitude of the sound float amplitude; // amplitude when signal is at minimum (before rise, after release and in wait time) float minAmplitude; // these are al private! // never acces them enum Sound _type; // which type of sound int _loopCount; // if true, will get removed bool _done; bool _useEnvelope; float *history; // if != 0, history is a pointer to 2*numHistorySamples samples. size_t numHistorySamples; // if != 0, save history for this sound. size_t lastHistorySample; // index/2 of last history sample. used } SoundHandle; // initialize sound subsystem. return true if working, false on errors. bool initSound(void); // start playing a sound. // args: // type - type of sound. // amplitude : 0..1 // handle: if != NULL will point to the internal sound handle to change the // manipulate playing of the sound. // TODO: add sound from file to play too SoundHandle *playSound(enum Sound type, float amplitude); // start playing a looping frequency. // args: // freq: frequency in Hz SoundHandle *playFrequency(float freq, float amplitude); // set them. // args: // time of phases bool configureEnvelope(SoundHandle *handle, float rise, float hold, float decay); bool configureOvershoot(SoundHandle *handle, float relativeOvershootTime); // same as above but set to looping and set wait time between intervals bool configureEnvelopeWait(SoundHandle *handle, float rise, float hold, float decay, float wait); // without looping but with wait bool configureEnvelopeLooping(SoundHandle *handle, float rise, float hold, float decay, float wait); // getter for attributes. if 0.0, unused. float getRiseDuration(SoundHandle *handle); float getHoldDuration(SoundHandle *handle); float getDecayDuration(SoundHandle *handle); float getWaitTime(SoundHandle *handle); void configureWaitTime(SoundHandle *handle, float waitTime); // Set looping behaviour of the sound. // args: // / > 0, sound is looping for this number of repetitions // numRepetitions { == 0, sound is stopped when it is over // \ == -1, loop the sound forever // void setLoopCount(SoundHandle *handle, int numRepetitions); // stop playing a sound. the handle is invalid now. bool stopSound(SoundHandle *handle); // stop and remove all playing sounds. all handle become invalid after calling // this. void stopAllSounds(void); void teardownSound(void); // for debugging bool startDumpingWav(const char *filename); // is deletede when 'keep' not set after stopping void stopDumpingWav(void); int numActiveSounds(void); void deleteSound(SoundHandle *handle); //SoundHandle *playFreqEnvelope(float freq, float rise, float hold, float decay); // TODO: add fade out/fade in overlay stuff for stopping sounds smoothly } #endif