⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 maccoreaudio.cxx

📁 安装 H323需要的pwlib库
💻 CXX
📖 第 1 页 / 共 4 页
字号:
/* * maccoreaudio.cxx * * Copyright (c) 2004 Network for Educational Technology ETH * * Written by Hannes Friederich, Andreas Fenkart. * Based on work of Shawn Pai-Hsiang Hsiao * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. *           */ #pragma implementation "maccoreaudio.h" #include <ptlib/unix/ptlib/maccoreaudio.h> namespace PWLibStupidOSXHacks{	int loadCoreAudioStuff;}PCREATE_SOUND_PLUGIN(CoreAudio, PSoundChannelCoreAudio);/************** util *******************/#ifdef PTRACING// should also produce output when ptracing is disabled#define checkStatus( err ) \    if(err) {\      OSStatus error = static_cast<OSStatus>(err);\      PTRACE(1, "CoreAudio Error " << __func__ << " "  \           <<  error   << "("  << (char*)&err <<  ")" ); \    }            ostream& operator<<(ostream &os, AudioStreamBasicDescription &inDesc){   os << "- - - - - - - - - - - - - - - - - - - -\n";   os << "  Sample Rate: " << inDesc.mSampleRate << endl;   os << "  Format ID: " << (char*)&inDesc.mFormatID << endl;   os << "  Format Flags: " << hex << inDesc.mFormatFlags << dec << endl;   os << "  Bytes per Packet: " << inDesc.mBytesPerPacket << endl;   os << "  Frames per Packet: " << inDesc.mFramesPerPacket << endl;   os << "  Bytes per Frame: " << inDesc.mBytesPerFrame << endl;   os << "  Channels per Frame: " << inDesc.mChannelsPerFrame << endl;    os << "  Bits per Channel: " << inDesc.mBitsPerChannel << endl;   os << "- - - - - - - - - - - - - - - - - - - -\n";   return os;}ostream& operator<<(ostream &os, PSoundChannel::Directions &dir){   if(dir == PSoundChannel::Player)      os << " Player ";   else if(dir == PSoundChannel::Recorder)      os << " Recorder ";   else      os << " Unknown direction ";   return os;}ostream& operator<<(ostream &os, AudioValueRange range){   os << range.mMinimum << " " << range.mMaximum ;   return os;}ostream& operator<<(ostream &os, PSoundChannelCoreAudio::State &state){   switch(state){      case PSoundChannelCoreAudio::init_:         os << "init";         break;      case PSoundChannelCoreAudio::open_:         os << "open";         break;      case PSoundChannelCoreAudio::setformat_:         os << "setformat";         break;      case PSoundChannelCoreAudio::setbuffer_:         os << "setbuffer";         break;      case PSoundChannelCoreAudio::running_:         os << "running";         break;      case PSoundChannelCoreAudio::destroy_:         os << "destroy";         break;      default:      os << " Unknown state ";   }   return os;}#endif/***** PSound implementation *****/PSound::PSound(unsigned   channels,            unsigned   sampleRate,            unsigned   bitsPerSample,            PINDEX     bufferSize,            const BYTE *data){  PAssert(0, PUnimplementedFunction); }PSound::PSound(const PFilePath & filename){  PAssert(0, PUnimplementedFunction); }PSound & PSound::operator=(const PBYTEArray & data){  PAssert(0, PUnimplementedFunction);   return *this;}BOOL PSound::Load(const PFilePath & filename){    PAssert(0, PUnimplementedFunction);   return false;}BOOL PSound::Save(const PFilePath & filename){     PAssert(0, PUnimplementedFunction);    return false;}BOOL PSound::Play(){   PAssert(0, PUnimplementedFunction);    return false;}void PSound::SetFormat(unsigned numChannels,                  unsigned sampleRate,                  unsigned bitsPerSample){   this->numChannels = numChannels;   this->sampleRate = sampleRate;   this->sampleSize = bitsPerSample;   formatInfo.SetSize(0);}BOOL PSound::PlayFile(const PFilePath & file,           BOOL wait){   PAssert(0, PUnimplementedFunction);    return false;}void PSound::Beep(){   PAssert(0, PUnimplementedFunction); }#include "maccoreaudio/circular_buffer.inl"/***** PSoundChannel implementation *****/void PSoundChannelCoreAudio::Init(){   PWLIB_StaticLoader_CoreAudio_PSoundChannel();}PSoundChannelCoreAudio::PSoundChannelCoreAudio()    : state(init_), mCircularBuffer(NULL), converter_buffer(NULL),     mInputCircularBuffer(NULL), mInputBufferList(NULL), mOutputBufferList(NULL){   CommonConstruct();}PSoundChannelCoreAudio::PSoundChannelCoreAudio(const PString & device,                Directions dir,                unsigned numChannels,                unsigned sampleRate,                unsigned bitsPerSample)   : mCircularBuffer(NULL), converter_buffer(NULL),     mInputCircularBuffer(NULL), mInputBufferList(NULL), mOutputBufferList(NULL){   CommonConstruct();   Open(device, dir, numChannels, sampleRate, bitsPerSample);}PSoundChannelCoreAudio::~PSoundChannelCoreAudio(){   OSStatus err = noErr;   PTRACE(2, __func__ << " destructor " << direction << " " << state );   State curr(state);   state = destroy_;   usleep(1000*20); // about the intervall between two callbacks                    // ensures that current callback has terminated    /* OutputUnit also for input device,    * Stop everything before deallocating buffers */   switch(curr) {      case running_:         err = AudioOutputUnitStop(mAudioUnit);         checkStatus(err);         PTRACE(1, direction << " AudioUnit stopped" );         usleep(1000*20); // ensure that all callbacks terminated         /* fall through */      case setbuffer_:         /* check for all buffers unconditionally */         err = AudioUnitUninitialize(mAudioUnit);         checkStatus(err);         /* fall through */      case setformat_:         err = AudioConverterDispose(converter);         checkStatus(err);         /* fall through */      case open_:         err = CloseComponent(mAudioUnit);         checkStatus(err);         /* fall through */      case init_:      case destroy_:         /* nop */;   }   /* now free all buffers */   if(this->converter_buffer != NULL){      free(this->converter_buffer);      this->converter_buffer = NULL;   }   if(this->mCircularBuffer != NULL){      delete this->mCircularBuffer;      this->mCircularBuffer = NULL;   }   if(this->mInputCircularBuffer !=NULL) {      delete this->mInputCircularBuffer;      this->mInputCircularBuffer = NULL;   }   if(this->mInputBufferList != NULL){      free(this->mInputBufferList);      this->mInputBufferList = NULL;   }   if(this->mOutputBufferList != NULL){      free(this->mOutputBufferList);      this->mOutputBufferList = NULL;   }   // tell PChannel::IsOpen() that the channel is closed.   os_handle = -1;  }unsigned PSoundChannelCoreAudio::GetChannels() const{   if(state >= setformat_)      return pwlibASBD.mChannelsPerFrame;   else       return 0;}unsigned PSoundChannelCoreAudio::GetSampleRate() const{   if(state >= setformat_)      return (unsigned)(pwlibASBD.mSampleRate);   else       return 0;}unsigned PSoundChannelCoreAudio::GetSampleSize() const{   if(state >= setformat_)      return (pwlibASBD.mBitsPerChannel);   else       return 0;}/* * Functions for retrieving AudioDevice list */#include "maccoreaudio/maccoreaudio_devices.inl"PString PSoundChannelCoreAudio::GetDefaultDevice(Directions dir){  OSStatus err = noErr;  UInt32 theSize;  AudioDeviceID theID;  theSize = sizeof(AudioDeviceID);  if (dir == Player) {    err = AudioHardwareGetProperty(          kAudioHardwarePropertyDefaultOutputDevice,               &theSize, &theID);  }  else {    err =  AudioHardwareGetProperty(           kAudioHardwarePropertyDefaultInputDevice,                &theSize, &theID);  }  if (err == 0) {     return CADeviceName(theID);  } else {     return CA_DUMMY_DEVICE_NAME;  }}PStringList PSoundChannelCoreAudio::GetDeviceNames(Directions dir){  PStringList devices;  int numDevices;  AudioDeviceID *deviceList;  bool isInput = (dir == Recorder);  numDevices = CADeviceList(&deviceList);  for (int i = 0; i < numDevices; i++) {    PString s = CADeviceName(deviceList[i]);    if (CADeviceSupportDirection(deviceList[i], isInput) > 0) {      devices.AppendString(s);    }  }  devices.AppendString(CA_DUMMY_DEVICE_NAME);  if(deviceList != NULL) {     free(deviceList);     deviceList = NULL;  }  return devices;}/* * Functions responsible for converting 8kHz to 44k1Hz. It works like this.  * The AudioHardware is abstracted by an AudioUnit(AUHAL). Each time the device * has more data available or needs new data a callback function is called. * These are PlayRenderProc and RecordProc.  * * The user data is stored in a format a set by ::SetFormat. Usually 8kHz, mono, * 16bit unsigned. The AudioUnit usually provides 44,1kHz, stereo, 32bit float. * So conversion is needed. The conversion is done by the AUConverter from  * the AudioToolbox framework. * * Currently inside the callback functions from the AUHAL, we pass the request * to the Converter, that in turn uses another callback function to grab some * of data in the input format. All this is done on-the-fly, which means inside * the thread managing the AudioHardware. The callback functions of the  * converter are ComplexBufferFillPlayback, ComplexbufferFillRecord. * * The problem we have that 44,1kHz is not a multiple of 8kHz, so we can never  * be sure about how many data the converter is going to ask exactly,  * sometimes it might be 102, 106.. This is especially true in case of the  * first request, where it might ask some additional data depending on  * PrimeMethod that garantues smoth resampling at the border. * * To summarize, when the AudioUnit device is ready to handle more data. It  * calls its callback function, within these functions the data is processed or  * prepared by pulling through AUConverter. The converter in turn calls its  * callback function to request more input data. Depending on whether we talk  * about Read or Write, this includes more or less complex buffering.  *//* *  Callback function called by the converter to request more data for  *  playback. *   *  outDataPacketDesc is unused, because all our packets have the same *  format and do not need individual description */OSStatus PSoundChannelCoreAudio::ComplexBufferFillPlayback(          AudioConverterRef            inAudioConverter,         UInt32                   *ioNumberDataPackets,         AudioBufferList           *ioData,         AudioStreamPacketDescription **outDataPacketDesc,         void             *inUserData){   OSStatus err = noErr;   PSoundChannelCoreAudio *This =              static_cast<PSoundChannelCoreAudio*>(inUserData);   AudioStreamBasicDescription pwlibASBD = This->pwlibASBD;   CircularBuffer* circBuf = This->mCircularBuffer;   // output might stop in case there is a complete buffer underrun!!!   UInt32 minPackets = MIN(*ioNumberDataPackets,             circBuf->size() / pwlibASBD.mBytesPerPacket );   UInt32 outBytes = minPackets* pwlibASBD.mBytesPerPacket;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -