Homepage Demos Overview Downloads Tutorials Reference
Credits
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Search

SoundPlay.cc

Go to the documentation of this file.
00001 //
00002 // Copyright 2002,2003 Sony Corporation 
00003 //
00004 // Permission to use, copy, modify, and redistribute this software for
00005 // non-commercial use is hereby granted.
00006 //
00007 // This software is provided "as is" without warranty of any kind,
00008 // either expressed or implied, including but not limited to the
00009 // implied warranties of fitness for a particular purpose.
00010 //
00011 
00012 // Additional modifications for Tekkotsu framework
00013 
00014 #include <OPENR/OPENRAPI.h>
00015 #include <OPENR/OSyslog.h>
00016 #include <OPENR/core_macro.h>
00017 #include "SoundPlay.h"
00018 
00019 #include <iostream>
00020 #include "SoundPlay/SoundManager.h"
00021 #include "Shared/RobotInfo.h"
00022 #include "Shared/Config.h"
00023 #include "Shared/debuget.h"
00024 #include "Events/EventRouter.h"
00025 
00026 SoundPlay::SoundPlay()
00027   : active(0), eventTranslatorQueueMemRgn(NULL), etrans(), speakerID(oprimitiveID_UNDEF)
00028 {
00029   for (int i = 0; i < SOUND_NUM_BUFFER; i++)
00030     region[i] = 0;
00031 }
00032 
00033 OStatus
00034 SoundPlay::DoInit(const OSystemEvent& event)
00035 {
00036   //OSYSDEBUG(("SoundPlay::DoInit()\n"));
00037 
00038   NEW_ALL_SUBJECT_AND_OBSERVER;
00039   REGISTER_ALL_ENTRY;
00040   SET_ALL_READY_AND_NOTIFY_ENTRY;
00041 
00042   observer[obsSoundManagerComm]->SetBufCtrlParam(0,1,SoundManager::MAX_SND+1);
00043   //+1 to MAX_SND so that we can still get a delete message after we've filled up
00044 
00045   //Read config file
00046   config=new Config("/ms/config/tekkotsu.cfg");
00047 
00048   erouter = new EventRouter;
00049 
00050   //Set process ID
00051   ProcessID::setID(ProcessID::SoundProcess);
00052 
00053   //soundManagerMemRgn -> sndman setup
00054   soundManagerMemRgn = InitRegion(sizeof(SoundManager));
00055   sndman=new ((SoundManager*)soundManagerMemRgn->Base()) SoundManager;
00056   sndman->InitAccess(subject[sbjSoundManagerComm]);
00057   for(unsigned int i=0; i<config->sound.preload.size(); i++)
00058     sndman->LoadFile(config->sound.preload[i].c_str());
00059 
00060   OpenSpeaker();
00061   NewSoundVectorData();
00062   SetPowerAndVolume();
00063 
00064   return oSUCCESS;
00065 }
00066 
00067 OStatus
00068 SoundPlay::DoStart(const OSystemEvent& event)
00069 {
00070   //OSYSDEBUG(("SoundPlay::DoStart()\n"));
00071 
00072   ENABLE_ALL_SUBJECT;
00073   ASSERT_READY_TO_ALL_OBSERVER;
00074 
00075   return oSUCCESS;
00076 }
00077 
00078 OStatus
00079 SoundPlay::DoStop(const OSystemEvent& event)
00080 {
00081   //OSYSDEBUG(("SoundPlay::DoStop()\n"));
00082 
00083   DISABLE_ALL_SUBJECT;
00084   DEASSERT_READY_TO_ALL_OBSERVER;
00085 
00086   return oSUCCESS;
00087 }
00088 
00089 OStatus
00090 SoundPlay::DoDestroy(const OSystemEvent& event)
00091 {
00092   for(unsigned int i=0; i<config->sound.preload.size(); i++)
00093     sndman->ReleaseFile(config->sound.preload[i].c_str());
00094   delete erouter;
00095   eventTranslatorQueueMemRgn->RemoveReference();
00096   DELETE_ALL_SUBJECT_AND_OBSERVER;
00097   return oSUCCESS;
00098 }
00099 
00100 void
00101 SoundPlay::ReadySendSound(const OReadyEvent&)
00102 {
00103   //  OSYSDEBUG(("SoundPlay::Ready()\n"));
00104   doSendSound();
00105 }
00106 
00107 void
00108 SoundPlay::ReadyRegisterSoundManager(const OReadyEvent&) {
00109   static bool is_init=true;
00110   if(is_init) {
00111     is_init=false;
00112     cout << objectName << " Registering SoundManager" << endl;
00113     subject[sbjRegisterSoundManager]->SetData(soundManagerMemRgn);
00114     subject[sbjRegisterSoundManager]->NotifyObservers();
00115   }
00116 }
00117 
00118 void
00119 SoundPlay::GotEventTranslatorQueue(const ONotifyEvent& event){
00120   std::cout << "SoundPlay-GOTEventTranslatorQueue..." << std::flush;
00121   ASSERT(event.NumOfData()==1,"Too many EventTranslatorQueue");
00122   eventTranslatorQueueMemRgn = event.RCData(0);
00123   eventTranslatorQueueMemRgn->AddReference();
00124   etrans.setQueue(reinterpret_cast<EventTranslator::Queue_t*>(eventTranslatorQueueMemRgn->Base()));
00125   erouter->addTrapper(&etrans);
00126   observer[obsReceiveEventTranslatorQueue]->AssertReady();
00127   cout << "done" << endl;
00128 }
00129 
00130 void
00131 SoundPlay::GotSoundMsg(const ONotifyEvent& event) {
00132   //  OSYSDEBUG(("SoundPlay::GotSoundMsg()\n"));
00133   sndman->ReceivedMsg(event);
00134   unsigned int curact=sndman->GetNumPlaying();
00135   //  std::cout << "got-active=" << active << " cur=" << curact << std::endl;
00136   if(active==0 && curact>0) {
00137     active=curact;
00138     doSendSound();
00139   }
00140   observer[obsSoundManagerComm]->AssertReady();
00141 }
00142 
00143 void
00144 SoundPlay::doSendSound() {
00145   //  std::cout << "do-active=" << active << std::endl;
00146   static unsigned int bufInUse=0;
00147 
00148   active=sndman->GetNumPlaying();
00149   if(active==0) { //if we don't have any active channels, don't send a buffer
00150     if(bufInUse>0)
00151       bufInUse--;
00152     return;
00153   }
00154 
00155   RCRegion* rgn = FindFreeRegion();
00156   if(rgn==NULL) //this can happen if a wakeup message comes in right after a sound stopped
00157     return;
00158   active=sndman->CopyTo(reinterpret_cast<OSoundVectorData*>(rgn->Base()));
00159   subject[sbjSpeaker]->SetData(rgn);
00160 
00161   if(bufInUse<SOUND_NUM_BUFFER-1) {
00162     bufInUse++;
00163     doSendSound();
00164   } else //recursive base case
00165     subject[sbjSpeaker]->NotifyObservers();
00166 }
00167 
00168 void
00169 SoundPlay::OpenSpeaker()
00170 {
00171   OStatus result = OPENR::OpenPrimitive(SPEAKER_LOCATOR, &speakerID);
00172   if (result != oSUCCESS)
00173     OSYSLOG1((osyslogERROR, "%s : %s %d","SoundPlay::OpenSpeaker()","OPENR::OpenPrimitive() FAILED", result));
00174 }
00175 
00176 void
00177 SoundPlay::NewSoundVectorData()
00178 {
00179   OStatus result;
00180   MemoryRegionID    soundVecDataID;
00181   OSoundVectorData* soundVecData;
00182 
00183   /*soundUnitSize (bytes/buffer) = sample_rate (samples/sec)
00184    *                               * sample_bits (bits/sample)
00185    *                               * [1/8] (bytes/bit)
00186    *                               * SoundBufferTime (ms/buffer)
00187    *                               * [1/1000] (sec/ms)
00188    */
00189   size_t soundUnitSize = config->sound.sample_rate*config->sound.sample_bits/8*SoundBufferTime/1000;
00190 
00191   for (int i = 0; i < SOUND_NUM_BUFFER; i++) {
00192     result = OPENR::NewSoundVectorData(1, soundUnitSize,&soundVecDataID, &soundVecData);
00193     if (result != oSUCCESS) {
00194       OSYSLOG1((osyslogERROR, "%s : %s %d","SoundPlay::NewSoundVectorData()","OPENR::NewSoundVectorData() FAILED", result));
00195       return;
00196     }
00197 
00198     soundVecData->SetNumData(1);
00199     OSoundInfo* sinfo = soundVecData->GetInfo(0);
00200     sinfo->Set(odataSOUND_VECTOR,speakerID,soundUnitSize);
00201     sinfo->dataSize      = soundUnitSize;
00202     sinfo->format        = osoundformatPCM;
00203     sinfo->channel       = osoundchannelMONO;
00204     sinfo->samplingRate  = config->sound.sample_rate;
00205     sinfo->bitsPerSample = config->sound.sample_bits;
00206 
00207     region[i] = new RCRegion(soundVecData->vectorInfo.memRegionID,soundVecData->vectorInfo.offset,(void*)soundVecData,soundVecData->vectorInfo.totalSize);
00208   }
00209 }
00210 
00211 void
00212 SoundPlay::SetPowerAndVolume()
00213 {
00214   OStatus result;
00215 
00216   result = OPENR::ControlPrimitive(speakerID,oprmreqSPEAKER_MUTE_OFF, 0, 0, 0, 0);
00217   if (result != oSUCCESS)
00218     OSYSLOG1((osyslogERROR, "%s : %s %d","SoundPlay::SetPowerAndVolume()","OPENR::ControlPrimitive(SPEAKER_MUTE_OFF) FAILED", result));
00219 
00220   OPrimitiveControl_SpeakerVolume volume(ospkvol10dB);
00221   result = OPENR::ControlPrimitive(speakerID,oprmreqSPEAKER_SET_VOLUME,&volume, sizeof(volume), 0, 0);
00222   if (result != oSUCCESS)
00223     OSYSLOG1((osyslogERROR, "%s : %s %d","SoundPlay::SetPowerAndVolume()","OPENR::ControlPrimitive(SPEAKER_SET_VOLUME) FAILED",result));
00224 
00225   if (config->sound.sample_rate == 16000 && config->sound.sample_bits == 16) {
00226     OPrimitiveControl_SpeakerSoundType soundType(ospksndMONO16K16B);
00227     result = OPENR::ControlPrimitive(speakerID,oprmreqSPEAKER_SET_SOUND_TYPE,&soundType, sizeof(soundType), 0, 0);
00228     if (result != oSUCCESS)
00229       OSYSLOG1((osyslogERROR, "%s : %s %d","SoundPlay::SetPowerAndVolume()","OPENR::ControlPrimitive(SPEAKER_SET_SOUND_TYPE) FAILED",result));
00230   }
00231 }
00232 
00233 /*! Will round up size to the nearest page */
00234 RCRegion*
00235 SoundPlay::InitRegion(unsigned int size) {
00236   unsigned int pagesize=4096;
00237   sError err=GetPageSize(&pagesize);
00238   ASSERT(err==sSUCCESS,"Error "<<err<<" getting page size");
00239   unsigned int pages=(size+pagesize-1)/pagesize;
00240   return new RCRegion(pages*pagesize);
00241 }
00242 
00243 RCRegion*
00244 SoundPlay::FindFreeRegion()
00245 {
00246   for (int i = 0; i < SOUND_NUM_BUFFER; i++)
00247     if (region[i]->NumberOfReference() == 1)
00248       return region[i];
00249   return 0;
00250 }
00251 
00252 /*! @file
00253  * @brief Implements the SoundPlay process (a.k.a. OObject), which is responsible for sending sound buffers to the system to play
00254  * @author Sony (Creator)
00255  *
00256  * This is basically the SoundPlay example from the Sony code, with a few modifications.
00257  * Here's the license Sony provided with it:
00258  *
00259  * Copyright 2002,2003 Sony Corporation 
00260  *
00261  * Permission to use, copy, modify, and redistribute this software for
00262  * non-commercial use is hereby granted.
00263  *
00264  * This software is provided "as is" without warranty of any kind,
00265  * either expressed or implied, including but not limited to the
00266  * implied warranties of fitness for a particular purpose.
00267  *
00268  * $Author: ejt $
00269  * $Name: tekkotsu-1_4_1 $
00270  * $Revision: 1.7 $
00271  * $State: Exp $
00272  * $Date: 2003/06/12 23:41:41 $
00273  */
00274 

Tekkotsu v1.4
Generated Sat Jul 19 00:06:31 2003 by Doxygen 1.3.2