|
Blender
V2.59
|
00001 /* 00002 * $Id: AUD_SoftwareDevice.cpp 35141 2011-02-25 10:21:56Z jesterking $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * Copyright 2009-2011 Jörg Hermann Müller 00007 * 00008 * This file is part of AudaSpace. 00009 * 00010 * Audaspace is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * AudaSpace is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU General Public License 00021 * along with Audaspace; if not, write to the Free Software Foundation, 00022 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00032 #include "AUD_SoftwareDevice.h" 00033 #include "AUD_IReader.h" 00034 #include "AUD_DefaultMixer.h" 00035 #include "AUD_IFactory.h" 00036 00037 #include <cstring> 00038 #include <limits> 00039 00041 struct AUD_SoftwareHandle : AUD_Handle 00042 { 00044 AUD_IReader* reader; 00045 00047 bool keep; 00048 00050 float volume; 00051 00053 int loopcount; 00054 00056 stopCallback stop; 00057 00059 void* stop_data; 00060 }; 00061 00062 typedef std::list<AUD_SoftwareHandle*>::iterator AUD_HandleIterator; 00063 00064 void AUD_SoftwareDevice::create() 00065 { 00066 m_playback = false; 00067 m_volume = 1.0f; 00068 m_mixer = new AUD_DefaultMixer(m_specs); 00069 00070 pthread_mutexattr_t attr; 00071 pthread_mutexattr_init(&attr); 00072 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 00073 00074 pthread_mutex_init(&m_mutex, &attr); 00075 00076 pthread_mutexattr_destroy(&attr); 00077 } 00078 00079 void AUD_SoftwareDevice::destroy() 00080 { 00081 if(m_playback) 00082 playing(m_playback = false); 00083 00084 delete m_mixer; 00085 00086 AUD_SoftwareHandle* handle; 00087 00088 // delete all playing sounds 00089 while(!m_playingSounds.empty()) 00090 { 00091 handle = m_playingSounds.front(); 00092 m_playingSounds.pop_front(); 00093 delete handle->reader; 00094 delete handle; 00095 } 00096 00097 // delete all paused sounds 00098 while(!m_pausedSounds.empty()) 00099 { 00100 handle = m_pausedSounds.front(); 00101 m_pausedSounds.pop_front(); 00102 delete handle->reader; 00103 delete handle; 00104 } 00105 00106 pthread_mutex_destroy(&m_mutex); 00107 } 00108 00109 void AUD_SoftwareDevice::mix(data_t* buffer, int length) 00110 { 00111 lock(); 00112 00113 { 00114 AUD_SoftwareHandle* sound; 00115 int len; 00116 int pos; 00117 sample_t* buf; 00118 std::list<AUD_SoftwareHandle*> stopSounds; 00119 std::list<AUD_Buffer*> tempBufs; 00120 AUD_Buffer* tempbuf; 00121 int samplesize = AUD_SAMPLE_SIZE(m_specs); 00122 00123 // for all sounds 00124 AUD_HandleIterator it = m_playingSounds.begin(); 00125 while(it != m_playingSounds.end()) 00126 { 00127 sound = *it; 00128 // increment the iterator to make sure it's valid, 00129 // in case the sound gets deleted after stopping 00130 ++it; 00131 00132 // get the buffer from the source 00133 pos = 0; 00134 len = length; 00135 sound->reader->read(len, buf); 00136 00137 // in case of looping 00138 while(pos + len < length && sound->loopcount) 00139 { 00140 tempbuf = new AUD_Buffer(len * samplesize); 00141 memcpy(tempbuf->getBuffer(), buf, len * samplesize); 00142 tempBufs.push_back(tempbuf); 00143 m_mixer->add(tempbuf->getBuffer(), pos, len, sound->volume); 00144 00145 pos += len; 00146 00147 if(sound->loopcount > 0) 00148 sound->loopcount--; 00149 00150 sound->reader->seek(0); 00151 00152 len = length - pos; 00153 sound->reader->read(len, buf); 00154 00155 // prevent endless loop 00156 if(!len) 00157 break; 00158 } 00159 00160 m_mixer->add(buf, pos, len, sound->volume); 00161 pos += len; 00162 00163 // in case the end of the sound is reached 00164 if(pos < length) 00165 { 00166 if(sound->stop) 00167 sound->stop(sound->stop_data); 00168 00169 if(sound->keep) 00170 pause(sound); 00171 else 00172 stopSounds.push_back(sound); 00173 } 00174 } 00175 00176 // superpose 00177 m_mixer->superpose(buffer, length, m_volume); 00178 00179 // cleanup 00180 while(!stopSounds.empty()) 00181 { 00182 sound = stopSounds.front(); 00183 stopSounds.pop_front(); 00184 stop(sound); 00185 } 00186 00187 while(!tempBufs.empty()) 00188 { 00189 tempbuf = tempBufs.front(); 00190 tempBufs.pop_front(); 00191 delete tempbuf; 00192 } 00193 } 00194 00195 unlock(); 00196 } 00197 00198 bool AUD_SoftwareDevice::isValid(AUD_Handle* handle) 00199 { 00200 for(AUD_HandleIterator i = m_playingSounds.begin(); 00201 i != m_playingSounds.end(); i++) 00202 if(*i == handle) 00203 return true; 00204 for(AUD_HandleIterator i = m_pausedSounds.begin(); 00205 i != m_pausedSounds.end(); i++) 00206 if(*i == handle) 00207 return true; 00208 return false; 00209 } 00210 00211 AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const 00212 { 00213 return m_specs; 00214 } 00215 00216 AUD_Handle* AUD_SoftwareDevice::play(AUD_IReader* reader, bool keep) 00217 { 00218 // prepare the reader 00219 reader = m_mixer->prepare(reader); 00220 if(reader == NULL) 00221 return NULL; 00222 00223 // play sound 00224 AUD_SoftwareHandle* sound = new AUD_SoftwareHandle; 00225 sound->keep = keep; 00226 sound->reader = reader; 00227 sound->volume = 1.0f; 00228 sound->loopcount = 0; 00229 sound->stop = NULL; 00230 sound->stop_data = NULL; 00231 00232 lock(); 00233 m_playingSounds.push_back(sound); 00234 00235 if(!m_playback) 00236 playing(m_playback = true); 00237 unlock(); 00238 00239 return sound; 00240 } 00241 00242 AUD_Handle* AUD_SoftwareDevice::play(AUD_IFactory* factory, bool keep) 00243 { 00244 return play(factory->createReader(), keep); 00245 } 00246 00247 bool AUD_SoftwareDevice::pause(AUD_Handle* handle) 00248 { 00249 bool result = false; 00250 00251 lock(); 00252 00253 // only songs that are played can be paused 00254 for(AUD_HandleIterator i = m_playingSounds.begin(); 00255 i != m_playingSounds.end(); i++) 00256 { 00257 if(*i == handle) 00258 { 00259 m_pausedSounds.push_back(*i); 00260 m_playingSounds.erase(i); 00261 if(m_playingSounds.empty()) 00262 playing(m_playback = false); 00263 result = true; 00264 break; 00265 } 00266 } 00267 00268 unlock(); 00269 00270 return result; 00271 } 00272 00273 bool AUD_SoftwareDevice::resume(AUD_Handle* handle) 00274 { 00275 bool result = false; 00276 00277 lock(); 00278 00279 // only songs that are paused can be resumed 00280 for(AUD_HandleIterator i = m_pausedSounds.begin(); 00281 i != m_pausedSounds.end(); i++) 00282 { 00283 if(*i == handle) 00284 { 00285 m_playingSounds.push_back(*i); 00286 m_pausedSounds.erase(i); 00287 if(!m_playback) 00288 playing(m_playback = true); 00289 result = true; 00290 break; 00291 } 00292 } 00293 00294 unlock(); 00295 00296 return result; 00297 } 00298 00299 bool AUD_SoftwareDevice::stop(AUD_Handle* handle) 00300 { 00301 bool result = false; 00302 00303 lock(); 00304 00305 for(AUD_HandleIterator i = m_playingSounds.begin(); 00306 i != m_playingSounds.end(); i++) 00307 { 00308 if(*i == handle) 00309 { 00310 delete (*i)->reader; 00311 delete *i; 00312 m_playingSounds.erase(i); 00313 if(m_playingSounds.empty()) 00314 playing(m_playback = false); 00315 result = true; 00316 break; 00317 } 00318 } 00319 if(!result) 00320 { 00321 for(AUD_HandleIterator i = m_pausedSounds.begin(); 00322 i != m_pausedSounds.end(); i++) 00323 { 00324 if(*i == handle) 00325 { 00326 delete (*i)->reader; 00327 delete *i; 00328 m_pausedSounds.erase(i); 00329 result = true; 00330 break; 00331 } 00332 } 00333 } 00334 00335 unlock(); 00336 00337 return result; 00338 } 00339 00340 bool AUD_SoftwareDevice::getKeep(AUD_Handle* handle) 00341 { 00342 bool result = false; 00343 00344 lock(); 00345 00346 if(isValid(handle)) 00347 result = ((AUD_SoftwareHandle*)handle)->keep; 00348 00349 unlock(); 00350 00351 return result; 00352 } 00353 00354 bool AUD_SoftwareDevice::setKeep(AUD_Handle* handle, bool keep) 00355 { 00356 bool result = false; 00357 00358 lock(); 00359 00360 if(isValid(handle)) 00361 { 00362 ((AUD_SoftwareHandle*)handle)->keep = keep; 00363 result = true; 00364 } 00365 00366 unlock(); 00367 00368 return result; 00369 } 00370 00371 bool AUD_SoftwareDevice::seek(AUD_Handle* handle, float position) 00372 { 00373 lock(); 00374 00375 bool result = false; 00376 00377 if(isValid(handle)) 00378 { 00379 AUD_IReader* reader = ((AUD_SoftwareHandle*)handle)->reader; 00380 reader->seek((int)(position * reader->getSpecs().rate)); 00381 result = true; 00382 } 00383 00384 unlock(); 00385 00386 return result; 00387 } 00388 00389 float AUD_SoftwareDevice::getPosition(AUD_Handle* handle) 00390 { 00391 lock(); 00392 00393 float position = 0.0f; 00394 00395 if(isValid(handle)) 00396 { 00397 AUD_SoftwareHandle* h = (AUD_SoftwareHandle*)handle; 00398 position = h->reader->getPosition() / (float)m_specs.rate; 00399 } 00400 00401 unlock(); 00402 00403 return position; 00404 } 00405 00406 AUD_Status AUD_SoftwareDevice::getStatus(AUD_Handle* handle) 00407 { 00408 AUD_Status status = AUD_STATUS_INVALID; 00409 00410 lock(); 00411 00412 for(AUD_HandleIterator i = m_playingSounds.begin(); 00413 i != m_playingSounds.end(); i++) 00414 { 00415 if(*i == handle) 00416 { 00417 status = AUD_STATUS_PLAYING; 00418 break; 00419 } 00420 } 00421 if(status == AUD_STATUS_INVALID) 00422 { 00423 for(AUD_HandleIterator i = m_pausedSounds.begin(); 00424 i != m_pausedSounds.end(); i++) 00425 { 00426 if(*i == handle) 00427 { 00428 status = AUD_STATUS_PAUSED; 00429 break; 00430 } 00431 } 00432 } 00433 00434 unlock(); 00435 00436 return status; 00437 } 00438 00439 void AUD_SoftwareDevice::lock() 00440 { 00441 pthread_mutex_lock(&m_mutex); 00442 } 00443 00444 void AUD_SoftwareDevice::unlock() 00445 { 00446 pthread_mutex_unlock(&m_mutex); 00447 } 00448 00449 float AUD_SoftwareDevice::getVolume() const 00450 { 00451 return m_volume; 00452 } 00453 00454 void AUD_SoftwareDevice::setVolume(float volume) 00455 { 00456 m_volume = volume; 00457 } 00458 00459 float AUD_SoftwareDevice::getVolume(AUD_Handle* handle) 00460 { 00461 lock(); 00462 float result = std::numeric_limits<float>::quiet_NaN(); 00463 if(isValid(handle)) 00464 result = ((AUD_SoftwareHandle*)handle)->volume; 00465 unlock(); 00466 return result; 00467 } 00468 00469 bool AUD_SoftwareDevice::setVolume(AUD_Handle* handle, float volume) 00470 { 00471 lock(); 00472 bool result = isValid(handle); 00473 if(result) 00474 ((AUD_SoftwareHandle*)handle)->volume = volume; 00475 unlock(); 00476 return result; 00477 } 00478 00479 float AUD_SoftwareDevice::getPitch(AUD_Handle* handle) 00480 { 00481 return std::numeric_limits<float>::quiet_NaN(); 00482 } 00483 00484 bool AUD_SoftwareDevice::setPitch(AUD_Handle* handle, float pitch) 00485 { 00486 return false; 00487 } 00488 00489 int AUD_SoftwareDevice::getLoopCount(AUD_Handle* handle) 00490 { 00491 lock(); 00492 int result = 0; 00493 if(isValid(handle)) 00494 result = ((AUD_SoftwareHandle*)handle)->loopcount; 00495 unlock(); 00496 return result; 00497 } 00498 00499 bool AUD_SoftwareDevice::setLoopCount(AUD_Handle* handle, int count) 00500 { 00501 lock(); 00502 bool result = isValid(handle); 00503 if(result) 00504 ((AUD_SoftwareHandle*)handle)->loopcount = count; 00505 unlock(); 00506 return result; 00507 } 00508 00509 bool AUD_SoftwareDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data) 00510 { 00511 lock(); 00512 bool result = isValid(handle); 00513 if(result) 00514 { 00515 AUD_SoftwareHandle* h = (AUD_SoftwareHandle*)handle; 00516 h->stop = callback; 00517 h->stop_data = data; 00518 } 00519 unlock(); 00520 return result; 00521 }