00001 #include "Shared/Config.h"
00002 #include "SoundManager.h"
00003 #include "Shared/LockScope.h"
00004 #include "WAV.h"
00005 #include "Events/EventRouter.h"
00006 #include <sys/types.h>
00007 #include <sys/stat.h>
00008 #include <unistd.h>
00009 #include <fstream>
00010 #include <OPENR/OSubject.h>
00011 #include <OPENR/ObjcommEvent.h>
00012
00013
00014 SoundManager * sndman=NULL;
00015
00016
00017 typedef LockScope<ProcessID::NumProcesses> AutoLock;
00018
00019 SoundManager::SoundManager()
00020 : mixerBuffer(0), mixerBufferSize(0),
00021 sndlist(),playlist(),chanlist(),mix_mode(Fast),queue_mode(Override),max_chan(4),lock()
00022 {
00023 }
00024
00025 SoundManager::~SoundManager() {
00026 delete[] mixerBuffer;
00027 }
00028
00029 void
00030 SoundManager::InitAccess(OSubject* subj) {
00031 subjs[ProcessID::getID()]=subj;
00032 }
00033
00034
00035 SoundManager::Snd_ID
00036 SoundManager::LoadFile(std::string const &name) {
00037 AutoLock autolock(lock,ProcessID::getID());
00038 if (name.size() == 0) {
00039 cout << "SoundManager::LoadFile() null filename" << endl;
00040 return invalid_Snd_ID;
00041 };
00042 std::string path(config->sound.makePath(name));
00043 Snd_ID id=lookupPath(path);
00044 if(id!=invalid_Snd_ID) {
00045
00046 sndlist[id].ref++;
00047 } else {
00048
00049 struct stat buf;
00050 if(stat(path.c_str(),&buf)==-1) {
00051 cout << "SoundManager::LoadFile(): Sound file not found: " << path << endl;
00052 return invalid_Snd_ID;
00053 }
00054 byte * sndbuf=new byte[buf.st_size];
00055 std::ifstream file(path.c_str());
00056 file.read(reinterpret_cast<char*>(sndbuf),buf.st_size);
00057 WAV wav;
00058 WAVError error = wav.Set(sndbuf);
00059 if (error != WAV_SUCCESS) {
00060 OSYSLOG1((osyslogERROR, "%s : %s %d: '%s'","SoundManager::LoadFile()","wav.Set() FAILED",
00061 error, path.c_str()));
00062 return invalid_Snd_ID;
00063 }
00064 if(wav.GetSamplingRate()!=config->sound.sample_rate || wav.GetBitsPerSample()!=config->sound.sample_bits) {
00065 OSYSLOG1((osyslogERROR, "%s : %s %s","SoundManager::LoadFile()","bad sample rate/bits", error));
00066 return invalid_Snd_ID;
00067 }
00068 id=LoadBuffer(reinterpret_cast<char*>(wav.GetDataStart()),wav.GetDataEnd()-wav.GetDataStart());
00069 delete [] sndbuf;
00070 strncpy(sndlist[id].name,path.c_str(),MAX_NAME_LEN);
00071 }
00072 return id;
00073 }
00074
00075 SoundManager::Snd_ID
00076 SoundManager::LoadBuffer(const char buf[], unsigned int len) {
00077 cout << "SoundManager::LoadBuffer() of " << len << " bytes" << endl;
00078 if(buf==NULL || len==0)
00079 return invalid_Snd_ID;
00080 AutoLock autolock(lock,ProcessID::getID());
00081
00082 RCRegion * region=initRegion(len+SoundManagerMsg::MSG_SIZE);
00083
00084 SoundManagerMsg * msg=new (reinterpret_cast<SoundManagerMsg*>(region->Base())) SoundManagerMsg;
00085 msg->setAdd(sndlist.new_front());
00086
00087 sndlist[msg->getID()].rcr=NULL;
00088 sndlist[msg->getID()].data=NULL;
00089 sndlist[msg->getID()].ref=1;
00090 sndlist[msg->getID()].len=len;
00091
00092 const byte* src=reinterpret_cast<const byte*>(buf);
00093 byte* dest=reinterpret_cast<byte*>(region->Base())+SoundManagerMsg::MSG_SIZE;
00094 byte* end=dest+len;
00095 if (config->sound.sample_bits==8)
00096 while (dest < end)
00097 *dest++ = *src++ ^ 0x80;
00098 else
00099 while (dest < end)
00100 *dest++ = *src++;
00101
00102 if(ProcessID::getID()==ProcessID::SoundProcess) {
00103
00104 sndlist[msg->getID()].rcr=region;
00105 sndlist[msg->getID()].data=reinterpret_cast<byte*>(region->Base()+SoundManagerMsg::MSG_SIZE);
00106 } else {
00107 subjs[ProcessID::getID()]->SetData(region);
00108 subjs[ProcessID::getID()]->NotifyObservers();
00109 }
00110 return msg->getID();
00111 }
00112
00113 void
00114 SoundManager::ReleaseFile(std::string const &name) {
00115 AutoLock autolock(lock,ProcessID::getID());
00116 Release(lookupPath(name));
00117 }
00118
00119 void
00120 SoundManager::Release(Snd_ID id) {
00121 if(id==invalid_Snd_ID)
00122 return;
00123 if(sndlist[id].ref==0) {
00124 cout << "SoundManager::Release() " << id << " extra release" << endl;
00125 return;
00126 }
00127 AutoLock autolock(lock,ProcessID::getID());
00128 sndlist[id].ref--;
00129 if(sndlist[id].ref==0) {
00130
00131
00132 RCRegion * region=initRegion(SoundManagerMsg::MSG_SIZE);
00133
00134 SoundManagerMsg * msg=new (reinterpret_cast<SoundManagerMsg*>(region->Base())) SoundManagerMsg;
00135 msg->setDelete(sndlist[id].rcr);
00136
00137 sndlist.erase(id);
00138
00139 if(ProcessID::getID()==ProcessID::SoundProcess) {
00140 msg->region->RemoveReference();
00141 } else {
00142 subjs[ProcessID::getID()]->SetData(region);
00143 subjs[ProcessID::getID()]->NotifyObservers();
00144 }
00145 }
00146 }
00147
00148 SoundManager::Play_ID
00149 SoundManager::PlayFile(std::string const &name) {
00150 if(playlist.size()>=playlist_t::MAX_ENTRIES)
00151 return invalid_Play_ID;
00152 AutoLock autolock(lock,ProcessID::getID());
00153 Snd_ID sndid=LoadFile(name);
00154 if(sndid==invalid_Snd_ID)
00155 return invalid_Play_ID;
00156 sndlist[sndid].ref--;
00157 return Play(sndid);
00158 }
00159
00160 SoundManager::Play_ID
00161 SoundManager::PlayBuffer(const char buf[], unsigned int len) {
00162 if(playlist.size()>=playlist_t::MAX_ENTRIES || buf==NULL || len==0)
00163 return invalid_Play_ID;
00164 AutoLock autolock(lock,ProcessID::getID());
00165 Snd_ID sndid=LoadBuffer(buf,len);
00166 if(sndid==invalid_Snd_ID)
00167 return invalid_Play_ID;
00168 sndlist[sndid].ref--;
00169 return Play(sndid);
00170 }
00171
00172 SoundManager::Play_ID
00173 SoundManager::Play(Snd_ID id) {
00174
00175 if(id==invalid_Snd_ID)
00176 return invalid_Play_ID;
00177 AutoLock autolock(lock,ProcessID::getID());
00178 Play_ID playid=playlist.new_front();
00179 if(playid!=invalid_Play_ID) {
00180 sndlist[id].ref++;
00181 playlist[playid].snd_id=id;
00182 playlist[playid].offset=0;
00183
00184
00185 chanlist.push_front(playid);
00186
00187
00188
00189
00190 if(ProcessID::getID()!=ProcessID::SoundProcess) {
00191 RCRegion * region=initRegion(SoundManagerMsg::MSG_SIZE);
00192 ASSERT(region!=NULL,"initRegion returned NULL");
00193 SoundManagerMsg * msg=new (reinterpret_cast<SoundManagerMsg*>(region->Base())) SoundManagerMsg;
00194 msg->setWakeup();
00195 subjs[ProcessID::getID()]->SetData(region);
00196 subjs[ProcessID::getID()]->NotifyObservers();
00197 }
00198
00199
00200 if(sndlist[id].rcr!=NULL)
00201 erouter->postEvent(EventBase::audioEGID,playid,EventBase::activateETID,0);
00202 }
00203 return playid;
00204 }
00205
00206 SoundManager::Play_ID
00207 SoundManager::ChainFile(Play_ID base, std::string const &next) {
00208 if(base==invalid_Play_ID)
00209 return base;
00210 Play_ID orig=base;
00211 while(playlist[base].next_id!=invalid_Play_ID)
00212 base=playlist[base].next_id;
00213 Play_ID nplay=playlist.new_front();
00214 if(nplay==invalid_Play_ID)
00215 return nplay;
00216 Snd_ID nsnd=LoadFile(next);
00217 if(nsnd==invalid_Snd_ID) {
00218 playlist.pop_front();
00219 return invalid_Play_ID;
00220 }
00221 playlist[nplay].snd_id=nsnd;
00222 playlist[base].next_id=nplay;
00223 return orig;
00224 }
00225
00226 SoundManager::Play_ID
00227 SoundManager::ChainBuffer(Play_ID base, const char buf[], unsigned int len) {
00228 if(base==invalid_Play_ID || buf==NULL || len==0)
00229 return base;
00230 Play_ID orig=base;
00231 while(playlist[base].next_id!=invalid_Play_ID)
00232 base=playlist[base].next_id;
00233 Play_ID nplay=playlist.new_front();
00234 if(nplay==invalid_Play_ID)
00235 return nplay;
00236 Snd_ID nsnd=LoadBuffer(buf,len);
00237 if(nsnd==invalid_Snd_ID) {
00238 playlist.pop_front();
00239 return invalid_Play_ID;
00240 }
00241 playlist[nplay].snd_id=nsnd;
00242 playlist[base].next_id=nplay;
00243 return orig;
00244 }
00245
00246 SoundManager::Play_ID
00247 SoundManager::Chain(Play_ID base, Snd_ID next) {
00248 if(base==invalid_Play_ID || next==invalid_Snd_ID)
00249 return base;
00250 Play_ID orig=base;
00251 while(playlist[base].next_id!=invalid_Play_ID)
00252 base=playlist[base].next_id;
00253 Play_ID nplay=playlist.new_front();
00254 if(nplay==invalid_Play_ID)
00255 return nplay;
00256 playlist[nplay].snd_id=next;
00257 playlist[base].next_id=nplay;
00258 return orig;
00259 }
00260
00261 void
00262 SoundManager::StopPlay() {
00263 while(!playlist.empty())
00264 StopPlay(playlist.begin());
00265 }
00266
00267 void
00268 SoundManager::StopPlay(Play_ID id) {
00269
00270 if(id==invalid_Play_ID)
00271 return;
00272 AutoLock autolock(lock,ProcessID::getID());
00273
00274 for(chanlist_t::index_t it=chanlist.prev(chanlist.end()); it!=chanlist.end(); it=chanlist.prev(it))
00275 if(chanlist[it]==id) {
00276 Release(playlist[id].snd_id);
00277 playlist.erase(id);
00278 chanlist.erase(it);
00279 playlist[id].cumulative+=playlist[id].offset;
00280 unsigned int ms=playlist[id].cumulative/(config->sound.sample_bits/8)/(config->sound.sample_rate/1000);
00281 erouter->postEvent(EventBase::audioEGID,id,EventBase::deactivateETID,ms);
00282 return;
00283 }
00284 cout << "SoundManager::StopPlay(): " << id << " does not seem to be playing" << endl;
00285 }
00286
00287 void
00288 SoundManager::PausePlay(Play_ID id) {
00289 if(id==invalid_Play_ID)
00290 return;
00291 AutoLock autolock(lock,ProcessID::getID());
00292 for(chanlist_t::index_t it=chanlist.begin(); it!=chanlist.end(); it=chanlist.next(it))
00293 if(chanlist[it]==id) {
00294 chanlist.erase(it);
00295 return;
00296 }
00297 }
00298
00299 void
00300 SoundManager::ResumePlay(Play_ID id) {
00301 if(id==invalid_Play_ID)
00302 return;
00303 AutoLock autolock(lock,ProcessID::getID());
00304 for(chanlist_t::index_t it=chanlist.begin(); it!=chanlist.end(); it=chanlist.next(it))
00305 if(chanlist[it]==id)
00306 return;
00307 chanlist.push_front(id);
00308 }
00309
00310 void
00311 SoundManager::SetMode(unsigned int max_channels, MixMode_t mixer_mode, QueueMode_t queuing_mode) {
00312 AutoLock autolock(lock,ProcessID::getID());
00313 max_chan=max_channels;
00314 mix_mode=mixer_mode;
00315 queue_mode=queuing_mode;
00316 }
00317
00318 unsigned int
00319 SoundManager::GetRemainTime(Play_ID id) const {
00320 AutoLock autolock(lock,ProcessID::getID());
00321 unsigned int t=0;
00322 while(id!=invalid_Play_ID) {
00323 t+=sndlist[playlist[id].snd_id].len-playlist[id].offset;
00324 id=playlist[id].next_id;
00325 }
00326 const unsigned int bytesPerMS=config->sound.sample_bits/8*config->sound.sample_rate/1000;
00327 return t/bytesPerMS;
00328 }
00329
00330 void
00331 SoundManager::MixChannel(Play_ID channelId, void* buf, size_t destSize) {
00332 char *dest = (char*) buf;
00333
00334 PlayState& channel = playlist[channelId];
00335 while (destSize > 0) {
00336 const SoundData& buffer = sndlist[channel.snd_id];
00337 const char* samples = ((char*) (buffer.data)) + channel.offset;
00338 const unsigned int samplesSize = buffer.len - channel.offset;
00339 if (samplesSize > destSize) {
00340 memcpy(dest, samples, destSize);
00341 channel.offset += destSize;
00342 dest += destSize;
00343 destSize = 0;
00344 return;
00345 } else {
00346 memcpy(dest, samples, samplesSize);
00347 channel.offset += samplesSize;
00348 dest += samplesSize;
00349 destSize -= samplesSize;
00350 if (endPlay(channelId)) {
00351 break;
00352 }
00353 }
00354 }
00355 if (destSize > 0) {
00356 memset(dest, 0, destSize);
00357 }
00358 }
00359
00360 void
00361 SoundManager::MixChannelAdditively(Play_ID channelId, int bitsPerSample, MixMode_t mode,
00362 short scalingFactor, void* buf, size_t destSize)
00363 {
00364 PlayState& channel = playlist[channelId];
00365 while (destSize > 0) {
00366 const SoundData& buffer = sndlist[channel.snd_id];
00367 const unsigned int samplesSize = buffer.len - channel.offset;
00368 const unsigned int mixedSamplesSize =
00369 ((mode == Fast)
00370 ? ((samplesSize > destSize) ? destSize : samplesSize)
00371 : ((samplesSize > destSize / 2) ? destSize / 2 : samplesSize));
00372
00373 if (bitsPerSample == 8) {
00374
00375 const char* samples = (char*) (buffer.data + channel.offset);
00376 if (mode == Fast) {
00377
00378 char *dest = (char*) buf;
00379 for (size_t i = 0; i < mixedSamplesSize; i++) {
00380 *dest += samples[i] / scalingFactor;
00381 dest++;
00382 }
00383 destSize -= (char*) dest - (char*) buf;
00384 buf = dest;
00385 } else {
00386
00387 short* dest = (short*) buf;
00388 for (size_t i = 0; i < mixedSamplesSize; i++) {
00389 *dest += samples[i];
00390 *dest++;
00391 }
00392 destSize -= (char*) dest - (char*) buf;
00393 buf = dest;
00394 }
00395 } else {
00396
00397 const short* samples = (short*) (buffer.data + channel.offset);
00398 if (mode == Fast) {
00399
00400 short* dest = (short*) buf;
00401 for (size_t i = 0; i < mixedSamplesSize / 2; i++) {
00402 *dest += samples[i] / scalingFactor;
00403 *dest++;
00404 }
00405 destSize -= (char*) dest - (char*) buf;
00406 buf = dest;
00407 } else {
00408
00409 int* dest = (int*) buf;
00410 for (size_t i = 0; i < mixedSamplesSize / 2; i++) {
00411 *dest += samples[i];
00412 *dest++;
00413 }
00414 destSize -= (char*) dest - (char*) buf;
00415 buf = dest;
00416 }
00417 }
00418 channel.offset += mixedSamplesSize;
00419 if (destSize == 0) {
00420 return;
00421 } else {
00422 if (endPlay(channelId)) {
00423 return;
00424 }
00425 }
00426 }
00427 }
00428
00429 unsigned int
00430 SoundManager::CopyTo(OSoundVectorData* data) {
00431 AutoLock autolock(lock,ProcessID::getID());
00432
00433 size_t destSize = data->GetInfo(0)->dataSize;
00434 void* dest = data->GetData(0);
00435
00436 if(chanlist.size() == 0) {
00437 memset(dest, 0, destSize);
00438 return 0;
00439 }
00440
00441 std::vector<Play_ID> channels;
00442 selectChannels(channels);
00443
00444 if (channels.size() == 0) {
00445
00446 memset(dest, 0, destSize);
00447 } else if (channels.size() == 1) {
00448
00449 MixChannel(channels.front(), dest, destSize);
00450 } else {
00451
00452 const MixMode_t mode = mix_mode;
00453 const int bitsPerSample = config->sound.sample_bits;
00454 if (mode == Quality) {
00455
00456 if ((mixerBuffer == 0) || (mixerBufferSize < destSize * 2)) {
00457 delete[] mixerBuffer;
00458 mixerBuffer = 0;
00459 mixerBufferSize = destSize * 2;
00460 mixerBuffer = new int[(mixerBufferSize / 4) + 1];
00461 }
00462 memset(mixerBuffer, 0, mixerBufferSize);
00463 dest = mixerBuffer;
00464 destSize *= 2;
00465 } else {
00466
00467 memset(dest, 0, destSize);
00468 }
00469
00470 const int channelCount = channels.size();
00471 const short scalingFactor = (short) ((mode == Fast) ? channelCount : 1);
00472 for(std::vector<Play_ID>::iterator i = channels.begin(); i != channels.end(); i++)
00473 MixChannelAdditively(*i, bitsPerSample, mode, scalingFactor, dest, destSize);
00474
00475 if (mode == Quality) {
00476
00477
00478 destSize /= 2;
00479 if (bitsPerSample == 8) {
00480
00481 char* destChar = (char*) data->GetData(0);
00482 short* mixerBufferShort = (short*) mixerBuffer;
00483 for (size_t i = 0; i < destSize; i++) {
00484 destChar[i] = (char) (mixerBufferShort[i] / channelCount);
00485 }
00486 } else {
00487
00488 short* destShort = (short*) data->GetData(0);
00489 const size_t destSampleCount = destSize / 2;
00490 for (size_t i = 0; i < destSampleCount; i++) {
00491 destShort[i] = (short) (mixerBuffer[i] / channelCount);
00492 }
00493 }
00494 }
00495 }
00496
00497 updateChannels(channels, data->GetInfo(0)->dataSize);
00498 return channels.size();
00499 }
00500
00501 void
00502 SoundManager::ReceivedMsg(const ONotifyEvent& event) {
00503 for(int x=0; x<event.NumOfData(); x++) {
00504 RCRegion * rcr = event.RCData(x);
00505 SoundManagerMsg * msg = reinterpret_cast<SoundManagerMsg*>(rcr->Base());
00506 switch(msg->type) {
00507 case SoundManagerMsg::add: {
00508 rcr->AddReference();
00509 sndlist[msg->id].rcr=rcr;
00510 sndlist[msg->id].data=reinterpret_cast<byte*>(rcr->Base()+SoundManagerMsg::MSG_SIZE);
00511
00512 for(playlist_t::index_t it=playlist.begin();it!=playlist.end();it=playlist.next(it))
00513 if(playlist[it].snd_id==msg->id)
00514
00515 erouter->postEvent(EventBase::audioEGID,it,EventBase::activateETID,0);
00516 } break;
00517 case SoundManagerMsg::del: {
00518 msg->region->RemoveReference();
00519 } break;
00520 case SoundManagerMsg::wakeup: {
00521
00522 } break;
00523 default:
00524 printf("*** WARNING *** unknown SoundManager msg type received\n");
00525 }
00526 }
00527 }
00528
00529
00530
00531 RCRegion*
00532 SoundManager::initRegion(unsigned int size) {
00533 unsigned int pagesize=4096;
00534 sError err=GetPageSize(&pagesize);
00535 ASSERT(err==sSUCCESS,"Error "<<err<<" getting page size");
00536 unsigned int pages=(size+pagesize-1)/pagesize;
00537 return new RCRegion(pages*pagesize);
00538 }
00539
00540 SoundManager::Snd_ID
00541 SoundManager::lookupPath(std::string const &name) const {
00542 std::string const path(config->sound.makePath(name));
00543 for(sndlist_t::index_t it=sndlist.begin(); it!=sndlist.end(); it=sndlist.next(it))
00544 if(strncasecmp(path.c_str(),sndlist[it].name,MAX_NAME_LEN)==0)
00545 return it;
00546 return invalid_Snd_ID;
00547 }
00548
00549 void
00550 SoundManager::selectChannels(std::vector<Play_ID>& mix) {
00551 unsigned int selected=0;
00552 switch(queue_mode) {
00553 case Enqueue: {
00554 for(chanlist_t::index_t it=chanlist.prev(chanlist.end());it!=chanlist.end();it=chanlist.prev(it)) {
00555 if(sndlist[playlist[chanlist[it]].snd_id].data!=NULL) {
00556 mix.push_back(chanlist[it]);
00557 selected++;
00558 if(selected==max_chan)
00559 return;
00560 }
00561 }
00562 } break;
00563 case Override:
00564 case Pause: {
00565 for(chanlist_t::index_t it=chanlist.begin(); it!=chanlist.end(); it=chanlist.next(it)) {
00566 if(sndlist[playlist[chanlist[it]].snd_id].data!=NULL) {
00567 mix.push_back(chanlist[it]);
00568 selected++;
00569 if(selected==max_chan)
00570 return;
00571 }
00572 }
00573 } break;
00574 case Stop: {
00575 unsigned int numkeep=0;
00576 chanlist_t::index_t it=chanlist.begin();
00577 for(;it!=chanlist.end(); it=chanlist.next(it), numkeep++) {
00578 if(sndlist[playlist[chanlist[it]].snd_id].data!=NULL) {
00579 mix.push_back(chanlist[it]);
00580 selected++;
00581 if(selected==max_chan) {
00582 for(unsigned int i=chanlist.size()-numkeep-1; i>0; i--)
00583 endPlay(chanlist.back());
00584 return;
00585 }
00586 }
00587 }
00588 } break;
00589 default:
00590 cout << "SoundManager::selectChannels(): Illegal queue mode" << endl;
00591 }
00592 }
00593
00594 void
00595 SoundManager::updateChannels(const std::vector<Play_ID>& mixs,size_t used) {
00596 switch(queue_mode) {
00597 case Enqueue:
00598 case Pause:
00599 case Stop:
00600 break;
00601 case Override: {
00602
00603 chanlist_t::index_t it=chanlist.begin();
00604 std::vector<Play_ID>::const_iterator mixit=mixs.begin();
00605 for(;it!=chanlist.end(); it=chanlist.next(it)) {
00606 for(;mixit!=mixs.end(); mixit++)
00607 if(*mixit==chanlist[it])
00608 break;
00609 if(mixit==mixs.end())
00610 break;
00611 }
00612 for(;it!=chanlist.end(); it=chanlist.next(it)) {
00613 const Play_ID channelId = chanlist[it];
00614 PlayState &channel = playlist[channelId];
00615 size_t skip = used;
00616 while (skip > 0) {
00617 SoundData &buffer = sndlist[channel.snd_id];
00618
00619 if (buffer.data != 0) {
00620 size_t remain = buffer.len - channel.offset;
00621 if (remain < skip) {
00622 channel.offset = buffer.len;
00623 skip -= buffer.len;
00624 if (endPlay(channelId)) {
00625 break;
00626 }
00627 } else {
00628 channel.offset += skip;
00629 skip = 0;
00630 }
00631 } else {
00632 break;
00633 }
00634 }
00635 }
00636 } break;
00637 default:
00638 cout << "SoundManager::updateChannels(): Illegal queue mode" << endl;
00639 }
00640 }
00641
00642 bool
00643 SoundManager::endPlay(Play_ID id) {
00644 if(playlist[id].next_id==invalid_Play_ID) {
00645 StopPlay(id);
00646 return true;
00647 } else {
00648
00649 Play_ID next=playlist[id].next_id;
00650
00651 Release(playlist[id].snd_id);
00652 playlist[id].snd_id=playlist[next].snd_id;
00653 playlist[id].cumulative+=playlist[id].offset;
00654 playlist[id].offset=0;
00655 playlist[id].next_id=playlist[next].next_id;
00656 playlist.erase(next);
00657 unsigned int ms=playlist[id].cumulative/(config->sound.sample_bits/8)/(config->sound.sample_rate/1000);
00658 erouter->postEvent(EventBase::audioEGID,id,EventBase::statusETID,ms);
00659 return false;
00660 }
00661 }
00662
00663 SoundManager::SoundData::SoundData()
00664 : rcr(NULL), data(NULL), len(0), ref(0)
00665 {
00666 name[0]='\0';
00667 }
00668
00669 SoundManager::PlayState::PlayState()
00670 : snd_id(invalid_Snd_ID), offset(0), cumulative(0), next_id(invalid_Play_ID)
00671 {}
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748