RtAAudioDevice.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 #include "RtAAudioDevice.hxx"
00022 
00023 /*
00024 #include "RtAudio.hxx"
00025 #include "AudioIO.hxx"
00026 #include "AudioIn.hxx"
00027 #include "AudioOut.hxx"
00028 #include "AudioDeviceList.hxx"
00029 #include "AudioDevice.hxx"
00030 #include <cstdio>
00031 */
00032 
00033 namespace CLAM {
00034 /*
00035 #ifdef __MACOSX_CORE__
00036 #define MACOSX_WORKAROUND
00037 #endif
00038 */
00039 
00040 //#ifdef __MACOSX_CORE__
00041 /* a kludgy factor 2 (22050->44100) sample rate conversion
00042 ** because macosx drivers do not handle 22050 */ 
00043         /*
00044 #define FACTOR2SRC_KLUDGE
00045 #endif
00046 */
00047 
00048 //#define DEBUG_RDWR_POS
00049 
00050 
00051 /*
00052         typedef signed short  MY_TYPE;
00053         #define FORMAT RtAudio::RTAUDIO_SINT16
00054         class RtAAudioDevice: public AudioDevice
00055         {
00056         private:
00057                 class Buffer
00058                 {
00059                 friend class RtAAudioDevice;
00060                 private:
00061                         Buffer(int channels = 0,int frames = 0)
00062                         {
00063                                 mData = 0;
00064                                 Alloc(channels,frames);
00065                                 mChannelsDone = 0;
00066                                 mReadIndex = 0;
00067                                 mWriteIndex = 0;
00068                         }
00069                         void Alloc(int channels = 0,int frames = 0)
00070                         {
00071                                 if (mData) delete mData;
00072                                 mChannels = channels;
00073                                 mFrames = frames;
00074                                 if (mChannels && mFrames)
00075                                 {
00076                                         mData = new TData[mChannels*mFrames];
00077                                 }else{
00078                                         mData = 0;
00079                                 }
00080                         }
00081                         
00082                         TData* mData;
00083                         int    mReadIndex;
00084                         int    mWriteIndex;
00085                         int    mChannels;
00086                         int    mChannelsDone;
00087                         int    mFrames;
00088                         int    Filled(void)
00089                         {
00090                                 return mWriteIndex >= mReadIndex ? 
00091                                         mWriteIndex - mReadIndex : 
00092                                         mWriteIndex + mFrames - mReadIndex;
00093                         }
00094 
00095                         void CopyTo(MY_TYPE* ptr,int frames)
00096                         {
00097                                 int cnt = frames*mChannels;
00098                                 int limit = mFrames*mChannels;
00099                                 int i = mReadIndex*mChannels;
00100 
00101 #ifdef DEBUG_RDWR_POS                           
00102                                 printf("copyto: r=%d %d\n",mReadIndex,frames);
00103 #endif                          
00104                                 while (cnt--)
00105                                 {
00106                                         *ptr++ = (MY_TYPE)(mData[i++]*32767.);
00107                                         if (i==limit) i = 0;
00108                                 }
00109                                 mReadIndex += frames;
00110                                 if (mReadIndex >= mFrames) mReadIndex -= mFrames;
00111 
00112                         }
00113 
00114 #ifdef FACTOR2SRC_KLUDGE
00115                         void CopyToFactor2SRC(MY_TYPE* ptr,int frames)
00116                         {
00117                                 int cnt = frames*mChannels;
00118                                 int limit = mFrames*mChannels;
00119                                 int i = mReadIndex*mChannels;
00120 
00121 #ifdef DEBUG_RDWR_POS                           
00122                                 printf("copyto: r=%d %d\n",mReadIndex,frames);
00123 #endif                          
00124                                 while (cnt--)
00125                                 {
00126                                         *ptr++ = (MY_TYPE)(mData[i]*32767.);
00127                                         *ptr++ = (MY_TYPE)(mData[i]*32767.);
00128                                         i++;
00129                                         if (i==limit) i = 0;
00130                                 }
00131                                 mReadIndex += frames;
00132                                 if (mReadIndex >= mFrames) mReadIndex -= mFrames;
00133 
00134                         }
00135 #endif
00136 
00137                         void CopyFrom(MY_TYPE* ptr,int frames)
00138                         {
00139                                 int cnt = frames*mChannels;
00140                                 int limit = mFrames*mChannels;
00141                                 int i = mWriteIndex*mChannels;
00142                                 
00143 #ifdef DEBUG_RDWR_POS                           
00144                                 printf("copyfrom: w=%d %d\n",mWriteIndex,frames);
00145 #endif                          
00146                                 while (cnt--)
00147                                 {
00148                                         mData[i++] = TData(*ptr++)/32767.;
00149                                         if (i==limit) i = 0;
00150                                 }
00151                                 mWriteIndex += frames;
00152                                 if (mWriteIndex >= mFrames) mWriteIndex -= mFrames;
00153                         }
00154 
00155 #ifdef FACTOR2SRC_KLUDGE
00156                         void CopyFromDoFactor2SRC(MY_TYPE* ptr,int frames)
00157                         {
00158                                 int cnt = frames*mChannels;
00159                                 int limit = mFrames*mChannels;
00160                                 int i = mWriteIndex*mChannels;
00161                                 
00162 #ifdef DEBUG_RDWR_POS                           
00163                                 printf("copyfrom: w=%d %d\n",mWriteIndex,frames);
00164 #endif                          
00165                                 while (cnt--)
00166                                 {
00167                                         TData t = TData(*ptr++);
00168                                         t += TData(*ptr++);
00169                                         t /= 65534.;
00170                                         mData[i++] = t;
00171                                         if (i==limit) i = 0;
00172                                 }
00173                                 mWriteIndex += frames;
00174                                 if (mWriteIndex >= mFrames) mWriteIndex -= mFrames;
00175                         }
00176 #endif                          
00177 
00178                         void ChannelCopyFrom(TData* ptr,int size,int chnId)
00179                         {
00180                                 int i = mWriteIndex*mChannels+chnId;
00181                                 int n = size;
00182                                 int limit = mChannels*mFrames;
00183 
00184 #ifdef DEBUG_RDWR_POS                           
00185                                 printf("ChannelCopyFrom: w=%d %d\n",mWriteIndex,size);
00186 #endif
00187                                 fflush(stdout);
00188                                 while (n--)
00189                                 {
00190                                         mData[i] = *ptr++;
00191                                         i += mChannels;
00192                                         if (i>=limit) i = chnId;
00193                                 }
00194                                 mChannelsDone++;
00195                                 if (mChannelsDone==mChannels)
00196                                 {
00197                                         mWriteIndex += size;
00198                                         if (mWriteIndex >= mFrames) mWriteIndex -= mFrames;
00199                                         mChannelsDone = 0;
00200                                 }
00201                         }
00202 
00203                         void ChannelCopyTo(TData* ptr,int size,int chnId)
00204                         {
00205                                 int i = mReadIndex*mChannels+chnId;
00206                                 int n = size;
00207                                 int limit = mChannels*mFrames;
00208                                 
00209 #ifdef DEBUG_RDWR_POS                           
00210                                 printf("ChannelCopyTo: r=%d %d\n",mReadIndex,size);
00211 #endif
00212                                 while (n--)
00213                                 {
00214                                         *ptr++ = mData[i];
00215                                         i += mChannels;
00216                                         if (i>=limit) i = chnId;
00217                                 }
00218                                 mChannelsDone++;
00219                                 if (mChannelsDone==mChannels)
00220                                 {
00221                                         mReadIndex += size;
00222                                         if (mReadIndex >= mFrames) mReadIndex -= mFrames;
00223                                         mChannelsDone = 0;
00224                                 }
00225                         }
00226                 };
00227 
00228                 RtAudio *mRtAudio;
00229                 int mRtAudioStream;
00230                 MY_TYPE *mRtAudioBuffer;
00231                 int mRtAudioBufferSize;
00232 #ifdef MACOSX_WORKAROUND
00233                 int mInternalRtAudioBufferSize;
00234 #endif
00235                 Buffer mWriteBuffer;
00236                 Buffer mReadBuffer;
00237                 bool mStarted;
00238                 bool mTickOnRead;
00239                 bool mTickOnWrite;
00240                 int mDevice;
00241 #ifdef FACTOR2SRC_KLUDGE
00242                 bool mDoFactor2SRC;
00243 #endif
00244         public:
00245                 RtAAudioDevice(const std::string& name,int _device);
00246                 ~RtAAudioDevice();
00247                 
00248                 void Start(void) throw(Err);
00249                 void Stop(void) throw(Err);
00250                 void Tick(void);
00251                 void Read(Audio& audio,const int channelID);
00252                 void Write(const Audio& audio,const int channelID);
00253         };
00254         */
00255         RtAAudioDevice::RtAAudioDevice(const std::string& name,int _device): 
00256                 AudioDevice(name)
00257         {
00258                 mStarted = false;
00259                 mRtAudio = 0;
00260                 mTickOnRead = false;
00261                 mTickOnWrite = false;
00262                 mDevice = _device;
00263         }
00264 
00265         void RtAAudioDevice::Start(void) throw(Err)
00266         {
00267                 if (!mRtAudio)
00268                 {
00269                         int fs = SampleRate();
00270                         mRtAudioBufferSize = Latency();
00271 
00272 #ifdef __WINDOWS_DS__
00273                         if (mRtAudioBufferSize<4096)
00274                         {
00275                                 mRtAudioBufferSize = 4096;
00276                         }
00277 #endif
00278 
00279 #ifdef FACTOR2SRC_KLUDGE
00280                         mDoFactor2SRC = false;
00281                         if (fs == 22050)
00282                         {
00283                                 mDoFactor2SRC = true;
00284                         }
00285 
00286                         if (mDoFactor2SRC)
00287                         {
00288                                 /* multiply the rt audio buffer size by two,
00289                                 ** because while we will work on 22050 hz,
00290                                 ** rtaudio will work at 44100, so it's internal
00291                                 ** buffer will be double the size. when we access
00292                                 ** the rt audio buffer in CopyFromDoFactor2SRC
00293                                 ** and CopyToFactor2SRC, we indeed copy double 
00294                                 ** mRtAudioBufferSize.
00295                                 ** We multiply by two now, and device by two
00296                                 ** later on to go back to our buffer size
00297                                 */
00298                                 mRtAudioBufferSize *= 2;
00299                                 fs *= 2;
00300                         }
00301 #endif
00302                         
00303 #ifdef MACOSX_WORKAROUND
00304                         mInternalRtAudioBufferSize = mRtAudioBufferSize;
00305                         if (mInternalRtAudioBufferSize>2048)
00306                         {
00307                                 mInternalRtAudioBufferSize = 2048;
00308                         }
00309 #endif
00310 
00311                 try {
00312                 mRtAudio = new RtAudio(&mRtAudioStream, 
00313                                         mDevice, mOutputs.size(),
00314                                         mDevice, mInputs.size(), 
00315                                         FORMAT, fs, 
00316 #ifdef MACOSX_WORKAROUND
00317                                         &mInternalRtAudioBufferSize,
00318 #else
00319                                         &mRtAudioBufferSize, 
00320 #endif
00321                                 2);
00322                 }
00323                 catch (RtError &) {
00324                 exit(EXIT_FAILURE);
00325                 }
00326 
00327 #ifdef MACOSX_WORKAROUND
00328                         mRtAudioBufferSize = mInternalRtAudioBufferSize*((mRtAudioBufferSize+mInternalRtAudioBufferSize-1)/mInternalRtAudioBufferSize);
00329 #endif
00330 
00331                         
00332 #ifdef FACTOR2SRC_KLUDGE
00333                         if (mDoFactor2SRC)
00334                         {
00335                                 /* see comment above */
00336                                 mRtAudioBufferSize /= 2;
00337 #ifdef MACOSX_WORKAROUND
00338                                 mInternalRtAudioBufferSize /= 2;
00339 #endif
00340                         }
00341 #endif
00342                                         
00343                         /* update the latency value of the audiomanager */
00344                         SetLatency(mRtAudioBufferSize);
00345 
00346 
00347                         mWriteBuffer.Alloc(mOutputs.size(),mRtAudioBufferSize*2);
00348                         mReadBuffer.Alloc(mInputs.size(),mRtAudioBufferSize*2);
00349 
00350                         try {
00351                                 mRtAudioBuffer = (MY_TYPE *) mRtAudio->getStreamBuffer(mRtAudioStream);
00352                         }
00353                         catch (RtError &) {
00354                         exit(EXIT_FAILURE);
00355                         }
00356                 }
00357                 
00358                 mStarted = false;
00359         }
00360 
00361         void RtAAudioDevice::Stop(void) throw(Err)
00362         {
00363                 if (mRtAudio)
00364                 {
00365                   mRtAudio->stopStream(mRtAudioStream);
00366                         mStarted = false;
00367                         delete mRtAudio;
00368                         mRtAudio = 0;
00369                 }
00370         }
00371 
00372         RtAAudioDevice::~RtAAudioDevice()
00373         {
00374                 Stop();
00375         }
00376 
00377         void RtAAudioDevice::Read(Audio& a,const int channelID)
00378         {
00379                 if (!mStarted)
00380                 {
00381             mRtAudio->startStream(mRtAudioStream);
00382                         mStarted = true;
00383                         mTickOnRead = true;
00384                         
00385                         /* TODO: explain this: */
00386                         int k = mRtAudioBufferSize/a.GetSize();
00387                         if (a.GetSize()*k==mRtAudioBufferSize)
00388                         {
00389                                 mWriteBuffer.mWriteIndex = mRtAudioBufferSize;
00390                         }
00391                 }
00392 
00393                 if (mTickOnRead && mReadBuffer.Filled()<a.GetSize())
00394                 {
00395                         Tick();
00396                 }
00397 
00398                 mReadBuffer.ChannelCopyTo(a.GetBuffer().GetPtr(),a.GetSize(),channelID);
00399         }
00400         
00401         void RtAAudioDevice::Write(const Audio& a,const int channelID)
00402         {
00403                 if (!mStarted)
00404                 {
00405             mRtAudio->startStream(mRtAudioStream);
00406                         mStarted = true;
00407                         mTickOnWrite = true;
00408                 }
00409                 
00410                 mWriteBuffer.ChannelCopyFrom(a.GetBuffer().GetPtr(),a.GetSize(),channelID);
00411 
00412                 if (mTickOnWrite && mWriteBuffer.Filled()>=mRtAudioBufferSize)
00413                 {
00414                         Tick();
00415                 }
00416         }
00417         
00418         void RtAAudioDevice::Tick(void)
00419         {
00420 #ifdef MACOSX_WORKAROUND
00421                 int i = mRtAudioBufferSize/mInternalRtAudioBufferSize;
00422                 
00423 #ifdef FACTOR2SRC_KLUDGE
00424                 if (mDoFactor2SRC)
00425                 {
00426                         while (i--)
00427                         {
00428                                 mWriteBuffer.CopyToFactor2SRC(mRtAudioBuffer,mInternalRtAudioBufferSize);
00429                                 mRtAudio->tickStream(mRtAudioStream);
00430                                 mReadBuffer.CopyFromDoFactor2SRC(mRtAudioBuffer,mInternalRtAudioBufferSize);
00431                         }
00432                 }else
00433 #endif
00434                 {
00435                         while (i--)
00436                         {
00437                                 mWriteBuffer.CopyTo(mRtAudioBuffer,mInternalRtAudioBufferSize);
00438                                 mRtAudio->tickStream(mRtAudioStream);
00439                                 mReadBuffer.CopyFrom(mRtAudioBuffer,mInternalRtAudioBufferSize);
00440                         }
00441                 }
00442 #else
00443 #ifdef FACTOR2SRC_KLUDGE
00444                 if (mDoFactor2SRC)
00445                 {
00446                         mWriteBuffer.CopyToFactor2SRC(mRtAudioBuffer,mRtAudioBufferSize);
00447                         mRtAudio->tickStream(mRtAudioStream);
00448                         mReadBuffer.CopyFromDoFactor2SRC(mRtAudioBuffer,mRtAudioBufferSize);
00449                 }
00450                 else
00451 #endif
00452                 {
00453                         mWriteBuffer.CopyTo(mRtAudioBuffer,mRtAudioBufferSize);
00454                         mRtAudio->tickStream(mRtAudioStream);
00455                         mReadBuffer.CopyFrom(mRtAudioBuffer,mRtAudioBufferSize);
00456                 }
00457 #endif
00458         }
00459 
00460         /*
00461         class RtAAudioDeviceList : public AudioDeviceList
00462         {
00463         private:
00464                 static RtAAudioDeviceList sDevices;
00465 
00466                 RtAAudioDeviceList();
00467 
00468                 std::vector< int > mDevIDs;
00469 
00470         protected:
00471 
00472                 void EnumerateAvailableDevices() throw ( Err );
00473 
00474         public:
00475 
00476                 virtual ~RtAAudioDeviceList();
00477                 static std::string foo()
00478                 {
00479                         return std::string("buabua");
00480                 }
00481 
00482                 inline std::string DefaultDevice()
00483                 {
00484                         return "default";
00485                 }
00486 
00487                 AudioDevice* Create( const std::string& name, const std::string& device );
00488 
00489         };
00490         */
00491         RtAAudioDeviceList::RtAAudioDeviceList()
00492                 : AudioDeviceList( std::string("rtaudio") )
00493         {
00494 
00495                 EnumerateAvailableDevices();
00496 
00497                 AddMe();
00498         }
00499 
00500         void RtAAudioDeviceList::init()
00501         {
00502         //      std::cout << "rtaudio initialized" << std::endl;
00503         }
00504 
00505         RtAAudioDeviceList::~RtAAudioDeviceList()
00506         {
00507         }
00508 
00509         void RtAAudioDeviceList::EnumerateAvailableDevices() throw ( Err )
00510         {
00511                 RtAudio* instance = NULL;
00512                 
00513                 try {
00514                                 instance = new RtAudio();
00515                                 
00516                                 int numDevs = instance->getDeviceCount();
00517                                 int k;
00518                                 RtAudio::RTAUDIO_DEVICE devnfo; 
00519 
00520                                 mAvailableDevices.push_back("default");
00521                                 mDevIDs.push_back( 0 );
00522                                 
00523                                 for ( k = 1; k <= numDevs; k++ )
00524                                         {
00525                                                 instance->getDeviceInfo( k, &devnfo );
00526                                                 mAvailableDevices.push_back( devnfo.name );
00527                                                 mDevIDs.push_back( k );
00528                                         }
00529                                 delete instance;
00530                 } catch( ::RtError& err ) {
00531                         if ( instance )
00532                                 delete instance;
00533                         Err new_err("RtAAudioDeviceList::EnumerateAvailableDevices failed");
00534                         new_err.Embed( err.getMessage() );
00535                         throw ( new_err );
00536                 }
00537 
00538         }
00539 
00540         AudioDevice* RtAAudioDeviceList::Create( const std::string& name, const std::string& device )
00541         {
00542                 unsigned int i = 0;
00543 
00544                 for ( i=0; i < mAvailableDevices.size(); i++ )
00545                 {
00546                         if ( device == mAvailableDevices[i] )
00547                                 return new RtAAudioDevice( name, mDevIDs[i] );
00548                 }
00549                 for ( i=0; i < mAvailableDevices.size(); i++ )
00550                 {
00551                         char tmp[16];
00552                         sprintf(tmp,"%d",mDevIDs[i]);
00553                         if ( device == tmp )
00554                                 return new RtAAudioDevice( name, mDevIDs[i] );
00555                 }
00556 
00557                 return 0;
00558         }
00559 
00560         RtAAudioDeviceList RtAAudioDeviceList::sDevices;
00561 }
00562 
00563 
Generated by  doxygen 1.6.3