SoundInstance.cpp
Go to the documentation of this file.00001 //*** SoundInstance.cpp ** 00002 00003 #include "SoundInstance.h" 00004 #include "Platform_Sound.h" 00005 #include "Platform_Sound_SoundStream.h" 00006 #include "Debug.h" 00007 #include "Audio.h" 00008 #include "Asset.h" 00009 #include "Sound.h" 00010 #include "StandardLibrary.h" 00011 00012 00013 00014 //*** Constructor *** 00015 00016 SoundInstance::SoundInstance(const Sound& sound, float priority, bool looping): 00017 sound_(&sound), 00018 priority_(priority), 00019 looping_(looping), 00020 storedPosition_(0), 00021 playing_(false), 00022 volume_(1), 00023 soundStream_(0), 00024 streamBuffer_(0), 00025 nextCopyToStart_(true), 00026 lastCopySourceStart_(0), 00027 lastCopyDestinationStart_(0), 00028 lastCopyByteCount_(0), 00029 lastCopyReachedEnd_(false) 00030 { 00031 streamBuffer_=static_cast<unsigned char*>(siAudio->GetStreamBuffer(Sound_BufferSize)); 00032 } 00033 00034 00035 //*** Destructor *** 00036 00037 SoundInstance::~SoundInstance() 00038 { 00039 streamBuffer_=0; 00040 } 00041 00042 00043 //*** GetPriority *** 00044 00045 float SoundInstance::GetPriority() 00046 { 00047 return priority_; 00048 } 00049 00050 00051 //*** GetSound *** 00052 00053 const Sound* SoundInstance::GetSound() 00054 { 00055 return sound_; 00056 } 00057 00058 00059 //*** Play *** 00060 00061 void SoundInstance::Play() 00062 { 00063 soundStream_=siAudio->AcquireSoundStream(this); 00064 if (soundStream_) 00065 { 00066 soundDefinitionCopyPosition_=0; 00067 CopySoundChunk(0,Sound_BufferSize); 00068 nextCopyToStart_=true; 00069 soundStream_->SetPosition(0); 00070 soundStream_->Play(); 00071 playing_=true; 00072 } 00073 } 00074 00075 00076 //*** Stop *** 00077 00078 void SoundInstance::Stop() 00079 { 00080 Pause(); 00081 storedPosition_=0; 00082 } 00083 00084 00085 //*** Pause *** 00086 00087 void SoundInstance::Pause() 00088 { 00089 if (soundStream_) 00090 { 00091 storedPosition_=GetPosition(); 00092 soundStream_->Stop(); 00093 siAudio->ReleaseSoundStream(this); 00094 soundStream_=0; 00095 } 00096 } 00097 00098 00099 //*** GetLength *** 00100 00101 float SoundInstance::GetLength() 00102 { 00103 return TimeFromPosition(sound_->GetSize()); 00104 } 00105 00106 00107 //*** SoundInstance *** 00108 00109 float SoundInstance::GetPosition() 00110 { 00111 if (soundStream_) 00112 { 00113 int streamPosition=soundStream_->GetPosition(); 00114 int halfStreamSize=Music_BufferSize/2; 00115 if (nextCopyToStart_) 00116 { 00117 return TimeFromPosition(lastCopySourceStart_+streamPosition); 00118 } 00119 else 00120 { 00121 return TimeFromPosition(lastCopySourceStart_+(streamPosition-halfStreamSize)); 00122 } 00123 } 00124 else 00125 { 00126 return storedPosition_; 00127 } 00128 } 00129 00130 00131 //*** SetPosition *** 00132 00133 void SoundInstance::SetPosition(float position) 00134 { 00135 if (soundStream_) 00136 { 00137 Pause(); 00138 storedPosition_=Clamp(position,0.0f,GetLength()); 00139 Play(); 00140 } 00141 else 00142 { 00143 storedPosition_=Clamp(position,0.0f,GetLength()); 00144 } 00145 } 00146 00147 00148 00149 //*** Update *** 00150 00151 void SoundInstance::Update() 00152 { 00153 if (!soundStream_) 00154 { 00155 return; 00156 } 00157 00158 // Get the current position of the sound stream 00159 int streamPosition=soundStream_->GetPosition(); 00160 00161 // Check if we've reached the end of the sound data 00162 if (lastCopyReachedEnd_) 00163 { 00164 int halfStreamSize=Sound_BufferSize/2; 00165 if (nextCopyToStart_) 00166 { 00167 if (streamPosition>=halfStreamSize+lastCopyByteCount_) 00168 { 00169 Stop(); 00170 } 00171 } 00172 else 00173 { 00174 if (streamPosition<halfStreamSize && streamPosition>=lastCopyByteCount_) 00175 { 00176 Stop(); 00177 } 00178 } 00179 } 00180 else // Fill the next chunk of the buffer, as needed 00181 { 00182 int halfStreamSize=Sound_BufferSize/2; 00183 if (nextCopyToStart_) 00184 { 00185 if (streamPosition>=halfStreamSize) 00186 { 00187 CopySoundChunk(0,halfStreamSize); 00188 nextCopyToStart_=false; 00189 } 00190 } 00191 else 00192 { 00193 if (streamPosition<halfStreamSize) 00194 { 00195 CopySoundChunk(halfStreamSize,halfStreamSize); 00196 nextCopyToStart_=true; 00197 } 00198 } 00199 } 00200 } 00201 00202 00203 //*** CopySoundChunk *** 00204 00205 void SoundInstance::CopySoundChunk(int bufferOffset,int maxBytes) 00206 { 00207 // Store the positions of format and stream buffers 00208 lastCopySourceStart_=soundDefinitionCopyPosition_; 00209 lastCopyDestinationStart_=bufferOffset; 00210 00211 // Copy audio data to stream buffer 00212 lastCopyReachedEnd_=false; 00213 if (looping_) 00214 { 00215 // If in looping mode, keep copying until we've filled the whole buffer 00216 lastCopyByteCount_=0; 00217 while (lastCopyByteCount_<maxBytes) 00218 { 00219 int count=Min(maxBytes-lastCopyByteCount_,sound_->GetSize()-soundDefinitionCopyPosition_); 00220 MemCpy(streamBuffer_+lastCopyByteCount_,static_cast<const unsigned char*>(sound_->GetData())+soundDefinitionCopyPosition_,count); 00221 if (count<maxBytes) 00222 { 00223 soundDefinitionCopyPosition_=0; 00224 } 00225 lastCopyByteCount_+=count; 00226 } 00227 } 00228 else 00229 { 00230 lastCopyByteCount_=Min(maxBytes,sound_->GetSize()-soundDefinitionCopyPosition_); 00231 MemCpy(streamBuffer_,static_cast<const unsigned char*>(sound_->GetData())+soundDefinitionCopyPosition_,lastCopyByteCount_); 00232 00233 if (lastCopyByteCount_<maxBytes) 00234 { 00235 lastCopyReachedEnd_=true; 00236 } 00237 } 00238 00239 // Copy from the stream buffer to the actual sound stream 00240 int bytesToCopy=Min(maxBytes,lastCopyByteCount_); 00241 if (bytesToCopy>0) 00242 { 00243 soundStream_->CopySoundToBuffer(bufferOffset,streamBuffer_,bytesToCopy); 00244 } 00245 soundDefinitionCopyPosition_+=bytesToCopy; 00246 00247 // If we've reached the end of the track, pad the rest of the buffer with silence to avoid any ticks 00248 if (lastCopyReachedEnd_) 00249 { 00250 MemSet(streamBuffer_,0,maxBytes); 00251 if (maxBytes-bytesToCopy>0) 00252 { 00253 soundStream_->CopySoundToBuffer(bufferOffset+bytesToCopy,streamBuffer_,maxBytes-bytesToCopy); 00254 } 00255 } 00256 } 00257 00258 00259 00260 //*** PositionFromTime *** 00261 00262 int SoundInstance::PositionFromTime(float time) 00263 { 00264 float sampleSize=(float)(sound_->GetChannels()*sound_->GetFrequency()*(sound_->GetBitsPerSample()/8)); 00265 return (int)(time*sampleSize); 00266 } 00267 00268 00269 //*** TimeFromPosition *** 00270 00271 float SoundInstance::TimeFromPosition(int position) 00272 { 00273 float sampleSize=(float)(sound_->GetChannels()*sound_->GetFrequency()*(sound_->GetBitsPerSample()/8)); 00274 return position/sampleSize; 00275 } 00276 00277 00278 //*** GetVolume *** 00279 00280 float SoundInstance::GetVolume() 00281 { 00282 return soundStream_->GetVolume(); 00283 } 00284 00285 00286 //*** SetVolume *** 00287 00288 void SoundInstance::SetVolume(float level) 00289 { 00290 soundStream_->SetVolume(level); 00291 } 00292
Reproduction/republishing of any material on this site without permission is strictly prohibited.
