Homepage Demos Overview Downloads Tutorials Reference
Credits

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

Tekkotsu v2.1
Generated Tue Mar 16 23:19:15 2004 by Doxygen 1.3.5