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

Tekkotsu v2.3
Generated Sat Jan 29 02:25:23 2005 by Doxygen 1.4.0