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   erouter->addTrapper(&etrans);
00127   observer[obsReceiveEventTranslatorQueue]->AssertReady();
00128   cout << "done" << endl;
00129 }
00130 
00131 void
00132 SoundPlay::GotSoundMsg(const ONotifyEvent& event) {
00133   //  OSYSDEBUG(("SoundPlay::GotSoundMsg()\n"));
00134   sndman->ReceivedMsg(event);
00135   unsigned int curact=sndman->GetNumPlaying();
00136   //  std::cout << "got-active=" << active << " cur=" << curact << std::endl;
00137   if(active==0 && curact>0) {
00138     active=curact;
00139     doSendSound();
00140   }
00141   observer[obsSoundManagerComm]->AssertReady();
00142 }
00143 
00144 void
00145 SoundPlay::doSendSound() {
00146   //  std::cout << "do-active=" << active << std::endl;
00147   static unsigned int bufInUse=0;
00148 
00149   active=sndman->GetNumPlaying();
00150   if(active==0) { //if we don't have any active channels, don't send a buffer
00151     if(bufInUse>0)
00152       bufInUse--;
00153     return;
00154   }
00155 
00156   RCRegion* rgn = FindFreeRegion();
00157   if(rgn==NULL) //this can happen if a wakeup message comes in right after a sound stopped
00158     return;
00159   active=sndman->CopyTo(reinterpret_cast<OSoundVectorData*>(rgn->Base()));
00160   subject[sbjSpeaker]->SetData(rgn);
00161 
00162   if(bufInUse<SOUND_NUM_BUFFER-1) {
00163     bufInUse++;
00164     doSendSound();
00165   } else //recursive base case
00166     subject[sbjSpeaker]->NotifyObservers();
00167 }
00168 
00169 void
00170 SoundPlay::OpenSpeaker()
00171 {
00172   OStatus result = OPENR::OpenPrimitive(SpeakerLocator, &speakerID);
00173   if (result != oSUCCESS)
00174     OSYSLOG1((osyslogERROR, "%s : %s %d","SoundPlay::OpenSpeaker()","OPENR::OpenPrimitive() FAILED", result));
00175 }
00176 
00177 void
00178 SoundPlay::NewSoundVectorData()
00179 {
00180   OStatus result;
00181   MemoryRegionID    soundVecDataID;
00182   OSoundVectorData* soundVecData;
00183 
00184   /*soundUnitSize (bytes/buffer) = sample_rate (samples/sec)
00185    *                               * sample_bits (bits/sample)
00186    *                               * [1/8] (bytes/bit)
00187    *                               * SoundBufferTime (ms/buffer)
00188    *                               * [1/1000] (sec/ms)
00189    */
00190   size_t soundUnitSize = config->sound.sample_rate*config->sound.sample_bits/8*SoundBufferTime/1000;
00191 
00192   for (unsigned int i = 0; i < SOUND_NUM_BUFFER; i++) {
00193     result = OPENR::NewSoundVectorData(1, soundUnitSize,&soundVecDataID, &soundVecData);
00194     if (result != oSUCCESS) {
00195       OSYSLOG1((osyslogERROR, "%s : %s %d","SoundPlay::NewSoundVectorData()","OPENR::NewSoundVectorData() FAILED", result));
00196       return;
00197     }
00198 
00199     soundVecData->SetNumData(1);
00200     OSoundInfo* sinfo = soundVecData->GetInfo(0);
00201     sinfo->Set(odataSOUND_VECTOR,speakerID,soundUnitSize);
00202     sinfo->dataSize      = soundUnitSize;
00203     sinfo->format        = osoundformatPCM;
00204     sinfo->channel       = osoundchannelMONO;
00205     sinfo->samplingRate  = config->sound.sample_rate;
00206     sinfo->bitsPerSample = config->sound.sample_bits;
00207 
00208     region[i] = new RCRegion(soundVecData->vectorInfo.memRegionID,soundVecData->vectorInfo.offset,(void*)soundVecData,soundVecData->vectorInfo.totalSize);
00209   }
00210 }
00211 
00212 void
00213 SoundPlay::SetPowerAndVolume()
00214 {
00215   OStatus result;
00216 
00217   result = OPENR::ControlPrimitive(speakerID,oprmreqSPEAKER_MUTE_OFF, 0, 0, 0, 0);
00218   if (result != oSUCCESS)
00219     OSYSLOG1((osyslogERROR, "%s : %s %d","SoundPlay::SetPowerAndVolume()","OPENR::ControlPrimitive(SPEAKER_MUTE_OFF) FAILED", result));
00220 
00221   OPrimitiveControl_SpeakerVolume volume(config->sound.volume);
00222   result = OPENR::ControlPrimitive(speakerID,oprmreqSPEAKER_SET_VOLUME,&volume, sizeof(volume), 0, 0);
00223   if (result != oSUCCESS)
00224     OSYSLOG1((osyslogERROR, "%s : %s %d","SoundPlay::SetPowerAndVolume()","OPENR::ControlPrimitive(SPEAKER_SET_VOLUME) FAILED",result));
00225 
00226   if (config->sound.sample_rate == 16000 && config->sound.sample_bits == 16) {
00227     OPrimitiveControl_SpeakerSoundType soundType(ospksndMONO16K16B);
00228     result = OPENR::ControlPrimitive(speakerID,oprmreqSPEAKER_SET_SOUND_TYPE,&soundType, sizeof(soundType), 0, 0);
00229     if (result != oSUCCESS)
00230       OSYSLOG1((osyslogERROR, "%s : %s %d","SoundPlay::SetPowerAndVolume()","OPENR::ControlPrimitive(SPEAKER_SET_SOUND_TYPE) FAILED",result));
00231   }
00232 }
00233 
00234 /*! Will round up size to the nearest page */
00235 RCRegion*
00236 SoundPlay::InitRegion(unsigned int size) {
00237   unsigned int pagesize=4096;
00238   sError err=GetPageSize(&pagesize);
00239   ASSERT(err==sSUCCESS,"Error "<<err<<" getting page size");
00240   unsigned int pages=(size+pagesize-1)/pagesize;
00241   return new RCRegion(pages*pagesize);
00242 }
00243 
00244 RCRegion*
00245 SoundPlay::FindFreeRegion()
00246 {
00247   for (unsigned int i = 0; i < SOUND_NUM_BUFFER; i++)
00248     if (region[i]->NumberOfReference() == 1)
00249       return region[i];
00250   return 0;
00251 }
00252 
00253 /*! @file
00254  * @brief Implements the SoundPlay process (a.k.a. OObject), which is responsible for sending sound buffers to the system to play
00255  * @author Sony (Creator)
00256  *
00257  * This is basically the SoundPlay example from the Sony code, with a few modifications.
00258  * Here's the license Sony provided with it:
00259  *
00260  * Copyright 2002,2003 Sony Corporation 
00261  *
00262  * Permission to use, copy, modify, and redistribute this software for
00263  * non-commercial use is hereby granted.
00264  *
00265  * This software is provided "as is" without warranty of any kind,
00266  * either expressed or implied, including but not limited to the
00267  * implied warranties of fitness for a particular purpose.
00268  *
00269  * $Author: dst $
00270  * $Name: tekkotsu-2_2_2 $
00271  * $Revision: 1.14 $
00272  * $State: Exp $
00273  * $Date: 2004/12/16 22:46:21 $
00274  */
00275 

Tekkotsu v2.2.2
Generated Tue Jan 4 15:43:15 2005 by Doxygen 1.4.0