Music.cpp
Go to the documentation of this file.00001 //*** Music.cpp *** 00002 00003 #include "Music.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 "AudioFormat.h" 00010 #include "StandardLibrary.h" 00011 00012 00013 00014 //*** Constructor *** 00015 00016 Music::Music(const Asset& asset): 00017 soundStream_(0), 00018 format_(0), 00019 streamBuffer_(0), 00020 nextCopyToStart_(true), 00021 looping_(false), 00022 playing_(false), 00023 storedPosition_(0), 00024 lastCopySourceStart_(0), 00025 lastCopyDestinationStart_(0), 00026 lastCopyByteCount_(0), 00027 lastCopyReachedEnd_(false) 00028 { 00029 // Create music format 00030 format_=AudioFormat::CreateAudioFormat(asset); 00031 00032 if (!format_) 00033 { 00034 return; 00035 } 00036 00037 // Create sound buffer 00038 if (Platform::GetPlatform_Sound()) 00039 { 00040 soundStream_=Platform::GetPlatform_Sound()->CreateSoundStream(format_->GetChannels(),format_->GetFrequency(),format_->GetBitsPerSample(),Music_BufferSize); 00041 } 00042 streamBuffer_=static_cast<unsigned char*>(siAudio->GetStreamBuffer(Music_BufferSize)); 00043 00044 siAudio->Register(this); 00045 } 00046 00047 00048 //*** Destructor *** 00049 00050 Music::~Music() 00051 { 00052 if (format_) 00053 { 00054 delete format_; 00055 format_=0; 00056 if (Audio::IsInstanceCreated()) 00057 { 00058 siAudio->Unregister(this); 00059 } 00060 delete soundStream_; 00061 } 00062 } 00063 00064 00065 //*** SetLooping *** 00066 00067 void Music::SetLooping(bool looping) 00068 { 00069 looping_=looping; 00070 } 00071 00072 00073 //*** Play *** 00074 00075 void Music::Play() 00076 { 00077 if (!format_) 00078 { 00079 return; 00080 } 00081 00082 if (IsPlaying()) 00083 { 00084 Stop(); 00085 } 00086 00087 format_->SetPosition(PositionFromTime(storedPosition_)); 00088 CopySoundChunk(0,Music_BufferSize); 00089 nextCopyToStart_=true; 00090 soundStream_->SetPosition(0); 00091 soundStream_->Play(); 00092 playing_=true; 00093 } 00094 00095 00096 //*** Stop *** 00097 00098 void Music::Stop() 00099 { 00100 if (!format_) 00101 { 00102 return; 00103 } 00104 00105 Pause(); 00106 storedPosition_=0; 00107 } 00108 00109 00110 //*** Pause *** 00111 00112 void Music::Pause() 00113 { 00114 if (!format_) 00115 { 00116 return; 00117 } 00118 00119 if (IsPlaying()) 00120 { 00121 storedPosition_=GetPosition(); 00122 soundStream_->Stop(); 00123 playing_=false; 00124 } 00125 } 00126 00127 00128 //*** IsPlaying *** 00129 00130 bool Music::IsPlaying() 00131 { 00132 return playing_; 00133 } 00134 00135 00136 //*** GetLength *** 00137 00138 float Music::GetLength() 00139 { 00140 if (!format_) 00141 { 00142 return 0; 00143 } 00144 00145 return TimeFromPosition(format_->GetSize()); 00146 } 00147 00148 00149 //*** GetPosition *** 00150 00151 float Music::GetPosition() 00152 { 00153 if (!format_) 00154 { 00155 return 0; 00156 } 00157 00158 if (IsPlaying()) 00159 { 00160 int streamPosition=soundStream_->GetPosition(); 00161 int halfStreamSize=Music_BufferSize/2; 00162 if (nextCopyToStart_) 00163 { 00164 return TimeFromPosition(lastCopySourceStart_+streamPosition); 00165 } 00166 else 00167 { 00168 return TimeFromPosition(lastCopySourceStart_+(streamPosition-halfStreamSize)); 00169 } 00170 } 00171 else 00172 { 00173 return storedPosition_; 00174 } 00175 } 00176 00177 00178 //*** SetPosition *** 00179 00180 void Music::SetPosition(float position) 00181 { 00182 if (!format_) 00183 { 00184 return; 00185 } 00186 00187 if (IsPlaying()) 00188 { 00189 Pause(); 00190 storedPosition_=Clamp(position,0.0f,GetLength()); 00191 Play(); 00192 } 00193 else 00194 { 00195 storedPosition_=Clamp(position,0.0f,GetLength()); 00196 } 00197 } 00198 00199 00200 //*** Update *** 00201 00202 void Music::Update() 00203 { 00204 if (!format_) 00205 { 00206 return; 00207 } 00208 00209 if (!IsPlaying()) 00210 { 00211 return; 00212 } 00213 00214 // Get the current position of the sound stream 00215 int streamPosition=soundStream_->GetPosition(); 00216 00217 // Check if we've reached the end of the sound data 00218 if (lastCopyReachedEnd_) 00219 { 00220 int halfStreamSize=Music_BufferSize/2; 00221 if (nextCopyToStart_) 00222 { 00223 if (streamPosition>=halfStreamSize+lastCopyByteCount_) 00224 { 00225 Stop(); 00226 } 00227 } 00228 else 00229 { 00230 if (streamPosition<halfStreamSize && streamPosition>=lastCopyByteCount_) 00231 { 00232 Stop(); 00233 } 00234 } 00235 } 00236 else // Fill the next chunk of the buffer, as needed 00237 { 00238 int halfStreamSize=Music_BufferSize/2; 00239 if (nextCopyToStart_) 00240 { 00241 if (streamPosition>=halfStreamSize) 00242 { 00243 CopySoundChunk(0,halfStreamSize); 00244 nextCopyToStart_=false; 00245 } 00246 } 00247 else 00248 { 00249 if (streamPosition<halfStreamSize) 00250 { 00251 CopySoundChunk(halfStreamSize,halfStreamSize); 00252 nextCopyToStart_=true; 00253 } 00254 } 00255 } 00256 } 00257 00258 00259 //*** CopySoundChunk *** 00260 00261 void Music::CopySoundChunk(int bufferOffset,int maxBytes) 00262 { 00263 if (!format_) 00264 { 00265 return; 00266 } 00267 00268 // Store the positions of format and stream buffers 00269 lastCopySourceStart_=format_->GetPosition(); 00270 lastCopyDestinationStart_=bufferOffset; 00271 00272 // Copy audio data to stream buffer 00273 lastCopyReachedEnd_=false; 00274 if (looping_) 00275 { 00276 // If in looping mode, keep copying until we've filled the whole buffer 00277 lastCopyByteCount_=0; 00278 while (lastCopyByteCount_<maxBytes) 00279 { 00280 int count=format_->CopySoundChunk(streamBuffer_+lastCopyByteCount_,maxBytes-lastCopyByteCount_); 00281 if (count<maxBytes) 00282 { 00283 format_->SetPosition(0); 00284 } 00285 lastCopyByteCount_+=count; 00286 } 00287 } 00288 else 00289 { 00290 lastCopyByteCount_=format_->CopySoundChunk(streamBuffer_,maxBytes); 00291 if (lastCopyByteCount_<maxBytes) 00292 { 00293 lastCopyReachedEnd_=true; 00294 } 00295 } 00296 00297 // Copy from the stream buffer to the actual sound stream 00298 int bytesToCopy=Min(maxBytes,lastCopyByteCount_); 00299 if (bytesToCopy>0) 00300 { 00301 soundStream_->CopySoundToBuffer(bufferOffset,streamBuffer_,bytesToCopy); 00302 00303 } 00304 00305 // If we've reached the end of the track, pad the rest of the buffer with silence to avoid any ticks 00306 if (lastCopyReachedEnd_) 00307 { 00308 MemSet(streamBuffer_,0,maxBytes); 00309 if (maxBytes-bytesToCopy>0) 00310 { 00311 soundStream_->CopySoundToBuffer(bufferOffset+bytesToCopy,streamBuffer_,maxBytes-bytesToCopy); 00312 } 00313 } 00314 } 00315 00316 00317 //*** PositionFromTime *** 00318 00319 int Music::PositionFromTime(float time) 00320 { 00321 if (!format_) 00322 { 00323 return 0; 00324 } 00325 float sampleSize=(float)(format_->GetChannels()*format_->GetFrequency()*(format_->GetBitsPerSample()/8)); 00326 return (int)(time*sampleSize); 00327 } 00328 00329 00330 //*** TimeFromPosition *** 00331 00332 float Music::TimeFromPosition(int position) 00333 { 00334 if (!format_) 00335 { 00336 return 0; 00337 } 00338 00339 float sampleSize=(float)(format_->GetChannels()*format_->GetFrequency()*(format_->GetBitsPerSample()/8)); 00340 return position/sampleSize; 00341 } 00342 00343 00344 //*** GetVolume *** 00345 00346 float Music::GetVolume() 00347 { 00348 if (!format_) 00349 { 00350 return 0; 00351 } 00352 00353 return soundStream_->GetVolume(); 00354 } 00355 00356 00357 //*** SetVolume *** 00358 00359 void Music::SetVolume(float level) 00360 { 00361 if (!format_) 00362 { 00363 return; 00364 } 00365 00366 soundStream_->SetVolume(level); 00367 } 00368
Reproduction/republishing of any material on this site without permission is strictly prohibited.
