Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

RageSoundDriver_Generic_Software.h

Go to the documentation of this file.
00001 #ifndef RAGE_SOUND_GENERIC_SOFTWARE 00002 #define RAGE_SOUND_GENERIC_SOFTWARE 00003 00004 #include "RageSoundDriver.h" 00005 #include "RageThreads.h" 00006 #include "RageTimer.h" 00007 #include "RageUtil_CircularBuffer.h" 00008 00009 static const int samples_per_block = 512; 00010 class RageSound_Generic_Software: public RageSoundDriver 00011 { 00012 public: 00013 virtual void Update(float delta); 00014 00015 void StartMixing( RageSoundBase *snd ); /* used by RageSound */ 00016 void StopMixing( RageSoundBase *snd ); /* used by RageSound */ 00017 00018 RageSound_Generic_Software(); 00019 virtual ~RageSound_Generic_Software(); 00020 00021 protected: 00022 /* Start the decoding. This should be called once the hardware is set up and 00023 * GetSampleRate will return the correct value. */ 00024 void StartDecodeThread(); 00025 00026 /* Call this before calling StartDecodeThread to set the desired decoding buffer 00027 * size. This is the number of frames that Mix() will try to be able to return 00028 * at once. This should generally be slightly larger than the sound writeahead, 00029 * to allow filling the buffer after an underrun. The default is 4096 frames. */ 00030 void SetDecodeBufferSize( int frames ); 00031 00032 /* Override this to set the priority of the decoding thread, which should be above 00033 * normal priority but not realtime. */ 00034 virtual void SetupDecodingThread() { } 00035 00036 /* 00037 * Read mixed data. 00038 * 00039 * frames: buffer to read into 00040 * nframes: number of frames (not samples) to read 00041 * frameno: frame number at which this sound will be heard 00042 * current_frameno: frame number that is currently being heard 00043 * 00044 * current_frameno is used for handling start timing. 00045 * 00046 * This function only mixes data; it will not lock any mutexes or do any file access, and 00047 * is safe to call from a realtime thread. 00048 */ 00049 void Mix( int16_t *frames, int nframes, int64_t frameno, int64_t current_frameno ); 00050 00051 /* This mutex is used for serializing with the decoder thread. Locking this mutex 00052 * can take a while. */ 00053 RageMutex m_Mutex; 00054 00055 /* This mutex locks all sounds[] which are "available". (Other sound may safely 00056 * be accessed, and sounds may be set to available, without locking this.) */ 00057 RageMutex m_SoundListMutex; 00058 00059 private: 00060 /* 00061 * Thread safety and state transitions: 00062 * 00063 * STOPPED: The sound is idle, and can be used to play a new sound. The decoding and 00064 * mixing threads will not touch a sound in this state. 00065 * 00066 * PLAYING: The sound is being decoded by the decoding thread, and played by the mixing 00067 * thread. If the decoding thread hits EOF, the decoding thread will changed the state 00068 * to STOPPING. 00069 * 00070 * STOPPING: The sound is being played by the mixing thread. No new data will be decoded. 00071 * Once the data buffer is empty (all sound has been played), Update() will call StopMixing, 00072 * and the sound will be changed to STOPPED. 00073 * 00074 * HALTING: The main thread has called StopMixing. The mixing thread will flush the buffered 00075 * data without playing it, and then move the sound to STOPPED. 00076 * 00077 * The mixing thread operates without any locks. This can lead to a little overlap. For 00078 * example, if StopMixing() is called, moving the sound from PLAYING to HALTING, the mixing 00079 * thread might be in the middle of mixing data. Although HALTING means "discard buffered 00080 * data", some data will still be mixed. This is OK; the data is valid, and the flush will 00081 * happen on the next iteration. 00082 * 00083 * The only state change made by the decoding thread is on EOF: the state is changed 00084 * from PLAYING to STOPPING. This is done while m_Mutex is held, to prevent 00085 * races with other threads. 00086 * 00087 * The only state change made by the mixing thread is from HALTING to STOPPED. 00088 * This is done with no locks; no other thread can take a sound out of the HALTING state. 00089 */ 00090 struct sound_block 00091 { 00092 int16_t buf[samples_per_block]; 00093 int16_t *p; // beginning of the unread data 00094 int frames_in_buffer; // total number of frames (not samples) at p 00095 int position; // position value of p 00096 sound_block() { frames_in_buffer = position = 0; p = buf; } 00097 }; 00098 00099 struct sound 00100 { 00101 RageSoundBase *snd; 00102 int sound_id; 00103 RageTimer start_time; 00104 float volume; 00105 CircBuf<sound_block> buffer; 00106 00107 /* If true, this sound is in STOPPED and available for use. */ 00108 bool available; 00109 00110 enum 00111 { 00112 STOPPED, /* idle */ 00113 00114 /* This state is set by the decoder thread, indicating that the sound has just 00115 * reached EOF. Once the mixing thread finishes flushing buffer, it'll change 00116 * to the STOPPING_FINISH state. */ 00117 STOPPING, 00118 00119 HALTING, /* stop immediately */ 00120 PLAYING 00121 } state; 00122 00123 sound(); 00124 void Allocate( int frames ); 00125 void Deallocate(); 00126 }; 00127 00128 /* List of currently playing sounds: XXX no vector */ 00129 sound sounds[32]; 00130 00131 bool shutdown_decode_thread; 00132 00133 static int DecodeThread_start(void *p); 00134 void DecodeThread(); 00135 RageThread m_DecodeThread; 00136 00137 int GetDataForSound( sound &s ); 00138 }; 00139 00140 #endif 00141 00142 /* 00143 * (c) 2002-2004 Glenn Maynard 00144 * All rights reserved. 00145 * 00146 * Permission is hereby granted, free of charge, to any person obtaining a 00147 * copy of this software and associated documentation files (the 00148 * "Software"), to deal in the Software without restriction, including 00149 * without limitation the rights to use, copy, modify, merge, publish, 00150 * distribute, and/or sell copies of the Software, and to permit persons to 00151 * whom the Software is furnished to do so, provided that the above 00152 * copyright notice(s) and this permission notice appear in all copies of 00153 * the Software and that both the above copyright notice(s) and this 00154 * permission notice appear in supporting documentation. 00155 * 00156 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00157 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00158 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF 00159 * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS 00160 * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT 00161 * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 00162 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 00163 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 00164 * PERFORMANCE OF THIS SOFTWARE. 00165 */

Generated on Thu Jan 27 20:57:28 2005 for StepMania by doxygen 1.3.7