SoundManager.ccGo to the documentation of this file.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 const char * name=sndlist[playlist[playid].snd_id].name;
00202 if(name[0]!='\0')
00203 erouter->postEvent(EventBase::audioEGID,playid,EventBase::activateETID,0,name,1);
00204 else
00205 erouter->postEvent(EventBase::audioEGID,playid,EventBase::activateETID,0);
00206 }
00207 }
00208 return playid;
00209 }
00210
00211 SoundManager::Play_ID
00212 SoundManager::ChainFile(Play_ID base, std::string const &next) {
00213 if(base==invalid_Play_ID)
00214 return base;
00215 Play_ID orig=base;
00216 while(playlist[base].next_id!=invalid_Play_ID)
00217 base=playlist[base].next_id;
00218 Play_ID nplay=playlist.new_front();
00219 if(nplay==invalid_Play_ID)
00220 return nplay;
00221 Snd_ID nsnd=LoadFile(next);
00222 if(nsnd==invalid_Snd_ID) {
00223 playlist.pop_front();
00224 return invalid_Play_ID;
00225 }
00226 playlist[nplay].snd_id=nsnd;
00227 playlist[base].next_id=nplay;
00228 return orig;
00229 }
00230
00231 SoundManager::Play_ID
00232 SoundManager::ChainBuffer(Play_ID base, const char buf[], unsigned int len) {
00233 if(base==invalid_Play_ID || buf==NULL || len==0)
00234 return base;
00235 Play_ID orig=base;
00236 while(playlist[base].next_id!=invalid_Play_ID)
00237 base=playlist[base].next_id;
00238 Play_ID nplay=playlist.new_front();
00239 if(nplay==invalid_Play_ID)
00240 return nplay;
00241 Snd_ID nsnd=LoadBuffer(buf,len);
00242 if(nsnd==invalid_Snd_ID) {
00243 playlist.pop_front();
00244 return invalid_Play_ID;
00245 }
00246 playlist[nplay].snd_id=nsnd;
00247 playlist[base].next_id=nplay;
00248 return orig;
00249 }
00250
00251 SoundManager::Play_ID
00252 SoundManager::Chain(Play_ID base, Snd_ID next) {
00253 if(base==invalid_Play_ID || next==invalid_Snd_ID)
00254 return base;
00255 Play_ID orig=base;
00256 while(playlist[base].next_id!=invalid_Play_ID)
00257 base=playlist[base].next_id;
00258 Play_ID nplay=playlist.new_front();
00259 if(nplay==invalid_Play_ID)
00260 return nplay;
00261 playlist[nplay].snd_id=next;
00262 playlist[base].next_id=nplay;
00263 return orig;
00264 }
00265
00266 void
00267 SoundManager::StopPlay() {
00268 while(!playlist.empty())
00269 StopPlay(playlist.begin());
00270 }
00271
00272 void
00273 SoundManager::StopPlay(Play_ID id) {
00274
00275 if(id==invalid_Play_ID)
00276 return;
00277 AutoLock autolock(lock,ProcessID::getID());
00278
00279 for(chanlist_t::index_t it=chanlist.prev(chanlist.end()); it!=chanlist.end(); it=chanlist.prev(it))
00280 if(chanlist[it]==id) {
00281 std::string name=sndlist[playlist[id].snd_id].name;
00282 Release(playlist[id].snd_id);
00283 playlist.erase(id);
00284 chanlist.erase(it);
00285 playlist[id].cumulative+=playlist[id].offset;
00286 unsigned int ms=playlist[id].cumulative/(config->sound.sample_bits/8)/(config->sound.sample_rate/1000);
00287 if(name.size()>0)
00288 erouter->postEvent(EventBase::audioEGID,id,EventBase::deactivateETID,ms,name,0);
00289 else
00290 erouter->postEvent(EventBase::audioEGID,id,EventBase::deactivateETID,ms);
00291 return;
00292 }
00293 cout << "SoundManager::StopPlay(): " << id << " does not seem to be playing" << endl;
00294 }
00295
00296 void
00297 SoundManager::PausePlay(Play_ID id) {
00298 if(id==invalid_Play_ID)
00299 return;
00300 AutoLock autolock(lock,ProcessID::getID());
00301 for(chanlist_t::index_t it=chanlist.begin(); it!=chanlist.end(); it=chanlist.next(it))
00302 if(chanlist[it]==id) {
00303 chanlist.erase(it);
00304 return;
00305 }
00306 }
00307
00308 void
00309 SoundManager::ResumePlay(Play_ID id) {
00310 if(id==invalid_Play_ID)
00311 return;
00312 AutoLock autolock(lock,ProcessID::getID());
00313 for(chanlist_t::index_t it=chanlist.begin(); it!=chanlist.end(); it=chanlist.next(it))
00314 if(chanlist[it]==id)
00315 return;
00316 chanlist.push_front(id);
00317 }
00318
00319 void
00320 SoundManager::SetMode(unsigned int max_channels, MixMode_t mixer_mode, QueueMode_t queuing_mode) {
00321 AutoLock autolock(lock,ProcessID::getID());
00322 max_chan=max_channels;
00323 mix_mode=mixer_mode;
00324 queue_mode=queuing_mode;
00325 }
00326
00327 unsigned int
00328 SoundManager::GetRemainTime(Play_ID id) const {
00329 AutoLock autolock(lock,ProcessID::getID());
00330 unsigned int t=0;
00331 while(id!=invalid_Play_ID) {
00332 t+=sndlist[playlist[id].snd_id].len-playlist[id].offset;
00333 id=playlist[id].next_id;
00334 }
00335 const unsigned int bytesPerMS=config->sound.sample_bits/8*config->sound.sample_rate/1000;
00336 return t/bytesPerMS;
00337 }
00338
00339 void
00340 SoundManager::MixChannel(Play_ID channelId, void* buf, size_t destSize) {
00341 char *dest = (char*) buf;
00342
00343 PlayState& channel = playlist[channelId];
00344 while (destSize > 0) {
00345 const SoundData& buffer = sndlist[channel.snd_id];
00346 const char* samples = ((char*) (buffer.data)) + channel.offset;
00347 const unsigned int samplesSize = buffer.len - channel.offset;
00348 if (samplesSize > destSize) {
00349 memcpy(dest, samples, destSize);
00350 channel.offset += destSize;
00351 dest += destSize;
00352 destSize = 0;
00353 return;
00354 } else {
00355 memcpy(dest, samples, samplesSize);
00356 channel.offset += samplesSize;
00357 dest += samplesSize;
00358 destSize -= samplesSize;
00359 if (endPlay(channelId)) {
00360 break;
00361 }
00362 }
00363 }
00364 if (destSize > 0) {
00365 memset(dest, 0, destSize);
00366 }
00367 }
00368
00369 void
00370 SoundManager::MixChannelAdditively(Play_ID channelId, int bitsPerSample, MixMode_t mode,
00371 short scalingFactor, void* buf, size_t destSize)
00372 {
00373 PlayState& channel = playlist[channelId];
00374 while (destSize > 0) {
00375 const SoundData& buffer = sndlist[channel.snd_id];
00376 const unsigned int samplesSize = buffer.len - channel.offset;
00377 const unsigned int mixedSamplesSize =
00378 ((mode == Fast)
00379 ? ((samplesSize > destSize) ? destSize : samplesSize)
00380 : ((samplesSize > destSize / 2) ? destSize / 2 : samplesSize));
00381
00382 if (bitsPerSample == 8) {
00383
00384 const char* samples = (char*) (buffer.data + channel.offset);
00385 if (mode == Fast) {
00386
00387 char *dest = (char*) buf;
00388 for (size_t i = 0; i < mixedSamplesSize; i++) {
00389 *dest += samples[i] / scalingFactor;
00390 dest++;
00391 }
00392 destSize -= (char*) dest - (char*) buf;
00393 buf = dest;
00394 } else {
00395
00396 short* dest = (short*) buf;
00397 for (size_t i = 0; i < mixedSamplesSize; i++) {
00398 *dest += samples[i];
00399 *dest++;
00400 }
00401 destSize -= (char*) dest - (char*) buf;
00402 buf = dest;
00403 }
00404 } else {
00405
00406 const short* samples = (short*) (buffer.data + channel.offset);
00407 if (mode == Fast) {
00408
00409 short* dest = (short*) buf;
00410 for (size_t i = 0; i < mixedSamplesSize / 2; i++) {
00411 *dest += samples[i] / scalingFactor;
00412 *dest++;
00413 }
00414 destSize -= (char*) dest - (char*) buf;
00415 buf = dest;
00416 } else {
00417
00418 int* dest = (int*) buf;
00419 for (size_t i = 0; i < mixedSamplesSize / 2; i++) {
00420 *dest += samples[i];
00421 *dest++;
00422 }
00423 destSize -= (char*) dest - (char*) buf;
00424 buf = dest;
00425 }
00426 }
00427 channel.offset += mixedSamplesSize;
00428 if (destSize == 0) {
00429 return;
00430 } else {
00431 if (endPlay(channelId)) {
00432 return;
00433 }
00434 }
00435 }
00436 }
00437
00438 unsigned int
00439 SoundManager::CopyTo(OSoundVectorData* data) {
00440 AutoLock autolock(lock,ProcessID::getID());
00441
00442 size_t destSize = data->GetInfo(0)->dataSize;
00443 void* dest = data->GetData(0);
00444
00445 if(chanlist.size() == 0) {
00446 memset(dest, 0, destSize);
00447 return 0;
00448 }
00449
00450 std::vector<Play_ID> channels;
00451 selectChannels(channels);
00452
00453 if (channels.size() == 0) {
00454
00455 memset(dest, 0, destSize);
00456 } else if (channels.size() == 1) {
00457
00458 MixChannel(channels.front(), dest, destSize);
00459 } else {
00460
00461 const MixMode_t mode = mix_mode;
00462 const int bitsPerSample = config->sound.sample_bits;
00463 if (mode == Quality) {
00464
00465 if ((mixerBuffer == 0) || (mixerBufferSize < destSize * 2)) {
00466 delete[] mixerBuffer;
00467 mixerBuffer = 0;
00468 mixerBufferSize = destSize * 2;
00469 mixerBuffer = new int[(mixerBufferSize / 4) + 1];
00470 }
00471 memset(mixerBuffer, 0, mixerBufferSize);
00472 dest = mixerBuffer;
00473 destSize *= 2;
00474 } else {
00475
00476 memset(dest, 0, destSize);
00477 }
00478
00479 const int channelCount = channels.size();
00480 const short scalingFactor = (short) ((mode == Fast) ? channelCount : 1);
00481 for(std::vector<Play_ID>::iterator i = channels.begin(); i != channels.end(); i++)
00482 MixChannelAdditively(*i, bitsPerSample, mode, scalingFactor, dest, destSize);
00483
00484 if (mode == Quality) {
00485
00486
00487 destSize /= 2;
00488 if (bitsPerSample == 8) {
00489
00490 char* destChar = (char*) data->GetData(0);
00491 short* mixerBufferShort = (short*) mixerBuffer;
00492 for (size_t i = 0; i < destSize; i++) {
00493 destChar[i] = (char) (mixerBufferShort[i] / channelCount);
00494 }
00495 } else {
00496
00497 short* destShort = (short*) data->GetData(0);
00498 const size_t destSampleCount = destSize / 2;
00499 for (size_t i = 0; i < destSampleCount; i++) {
00500 destShort[i] = (short) (mixerBuffer[i] / channelCount);
00501 }
00502 }
00503 }
00504 }
00505
00506 updateChannels(channels, data->GetInfo(0)->dataSize);
00507 return channels.size();
00508 }
00509
00510 void
00511 SoundManager::ReceivedMsg(const ONotifyEvent& event) {
00512 for(int x=0; x<event.NumOfData(); x++) {
00513 RCRegion * rcr = event.RCData(x);
00514 SoundManagerMsg * msg = reinterpret_cast<SoundManagerMsg*>(rcr->Base());
00515 switch(msg->type) {
00516 case SoundManagerMsg::add: {
00517 rcr->AddReference();
00518 sndlist[msg->id].rcr=rcr;
00519 sndlist[msg->id].data=reinterpret_cast<byte*>(rcr->Base()+SoundManagerMsg::MSG_SIZE);
00520
00521 for(playlist_t::index_t it=playlist.begin();it!=playlist.end();it=playlist.next(it))
00522 if(playlist[it].snd_id==msg->id) {
00523
00524 const char * name=sndlist[playlist[it].snd_id].name;
00525 if(name[0]!='\0')
00526 erouter->postEvent(EventBase::audioEGID,it,EventBase::activateETID,0,name,1);
00527 else
00528 erouter->postEvent(EventBase::audioEGID,it,EventBase::activateETID,0);
00529 }
00530 } break;
00531 case SoundManagerMsg::del: {
00532 msg->region->RemoveReference();
00533 } break;
00534 case SoundManagerMsg::wakeup: {
00535
00536 } break;
00537 default:
00538 printf("*** WARNING *** unknown SoundManager msg type received\n");
00539 }
00540 }
00541 }
00542
00543
00544
00545 RCRegion*
00546 SoundManager::initRegion(unsigned int size) {
00547 unsigned int pagesize=4096;
00548 sError err=GetPageSize(&pagesize);
00549 ASSERT(err==sSUCCESS,"Error "<<err<<" getting page size");
00550 unsigned int pages=(size+pagesize-1)/pagesize;
00551 return new RCRegion(pages*pagesize);
00552 }
00553
00554 SoundManager::Snd_ID
00555 SoundManager::lookupPath(std::string const &name) const {
00556 std::string const path(config->sound.makePath(name));
00557 for(sndlist_t::index_t it=sndlist.begin(); it!=sndlist.end(); it=sndlist.next(it))
00558 if(strncasecmp(path.c_str(),sndlist[it].name,MAX_NAME_LEN)==0)
00559 return it;
00560 return invalid_Snd_ID;
00561 }
00562
00563 void
00564 SoundManager::selectChannels(std::vector<Play_ID>& mix) {
00565 unsigned int selected=0;
00566 switch(queue_mode) {
00567 case Enqueue: {
00568 for(chanlist_t::index_t it=chanlist.prev(chanlist.end());it!=chanlist.end();it=chanlist.prev(it)) {
00569 if(sndlist[playlist[chanlist[it]].snd_id].data!=NULL) {
00570 mix.push_back(chanlist[it]);
00571 selected++;
00572 if(selected==max_chan)
00573 return;
00574 }
00575 }
00576 } break;
00577 case Override:
00578 case Pause: {
00579 for(chanlist_t::index_t it=chanlist.begin(); it!=chanlist.end(); it=chanlist.next(it)) {
00580 if(sndlist[playlist[chanlist[it]].snd_id].data!=NULL) {
00581 mix.push_back(chanlist[it]);
00582 selected++;
00583 if(selected==max_chan)
00584 return;
00585 }
00586 }
00587 } break;
00588 case Stop: {
00589 unsigned int numkeep=0;
00590 chanlist_t::index_t it=chanlist.begin();
00591 for(;it!=chanlist.end(); it=chanlist.next(it), numkeep++) {
00592 if(sndlist[playlist[chanlist[it]].snd_id].data!=NULL) {
00593 mix.push_back(chanlist[it]);
00594 selected++;
00595 if(selected==max_chan) {
00596 for(unsigned int i=chanlist.size()-numkeep-1; i>0; i--)
00597 endPlay(chanlist.back());
00598 return;
00599 }
00600 }
00601 }
00602 } break;
00603 default:
00604 cout << "SoundManager::selectChannels(): Illegal queue mode" << endl;
00605 }
00606 }
00607
00608 void
00609 SoundManager::updateChannels(const std::vector<Play_ID>& mixs,size_t used) {
00610 switch(queue_mode) {
00611 case Enqueue:
00612 case Pause:
00613 case Stop:
00614 break;
00615 case Override: {
00616
00617 chanlist_t::index_t it=chanlist.begin();
00618 std::vector<Play_ID>::const_iterator mixit=mixs.begin();
00619 for(;it!=chanlist.end(); it=chanlist.next(it)) {
00620 for(;mixit!=mixs.end(); mixit++)
00621 if(*mixit==chanlist[it])
00622 break;
00623 if(mixit==mixs.end())
00624 break;
00625 }
00626 for(;it!=chanlist.end(); it=chanlist.next(it)) {
00627 const Play_ID channelId = chanlist[it];
00628 PlayState &channel = playlist[channelId];
00629 size_t skip = used;
00630 while (skip > 0) {
00631 SoundData &buffer = sndlist[channel.snd_id];
00632
00633 if (buffer.data != 0) {
00634 size_t remain = buffer.len - channel.offset;
00635 if (remain < skip) {
00636 channel.offset = buffer.len;
00637 skip -= buffer.len;
00638 if (endPlay(channelId)) {
00639 break;
00640 }
00641 } else {
00642 channel.offset += skip;
00643 skip = 0;
00644 }
00645 } else {
00646 break;
00647 }
00648 }
00649 }
00650 } break;
00651 default:
00652 cout << "SoundManager::updateChannels(): Illegal queue mode" << endl;
00653 }
00654 }
00655
00656 bool
00657 SoundManager::endPlay(Play_ID id) {
00658 if(playlist[id].next_id==invalid_Play_ID) {
00659 StopPlay(id);
00660 return true;
00661 } else {
00662
00663 Play_ID next=playlist[id].next_id;
00664
00665 Release(playlist[id].snd_id);
00666 playlist[id].snd_id=playlist[next].snd_id;
00667 playlist[id].cumulative+=playlist[id].offset;
00668 playlist[id].offset=0;
00669 playlist[id].next_id=playlist[next].next_id;
00670 playlist.erase(next);
00671 unsigned int ms=playlist[id].cumulative/(config->sound.sample_bits/8)/(config->sound.sample_rate/1000);
00672 const char * name=sndlist[playlist[id].snd_id].name;
00673 if(name[0]!='\0')
00674 erouter->postEvent(EventBase::audioEGID,id,EventBase::statusETID,ms,name,1);
00675 else
00676 erouter->postEvent(EventBase::audioEGID,id,EventBase::statusETID,ms);
00677 return false;
00678 }
00679 }
00680
00681 SoundManager::SoundData::SoundData()
00682 : rcr(NULL), data(NULL), len(0), ref(0)
00683 {
00684 name[0]='\0';
00685 }
00686
00687 SoundManager::PlayState::PlayState()
00688 : snd_id(invalid_Snd_ID), offset(0), cumulative(0), next_id(invalid_Play_ID)
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
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
|