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

📄 maccoreaudio.cxx

📁 安装 H323需要的pwlib库
💻 CXX
📖 第 1 页 / 共 4 页
字号:
   PTRACE(2, __func__ << " requested " << *ioNumberDataPackets <<          " packets, " <<  " fetching " << minPackets << " packets");   if(outBytes > This->converter_buffer_size){      PTRACE(1, This->direction << " Converter buffer too small");      // doesn't matter converter will ask right again for remaining data      // converter buffer multiple of packet size      outBytes = This->converter_buffer_size;   }   // dequeue data from circular buffer, without locking(false)   outBytes = circBuf->Drain(This->converter_buffer, outBytes, false);   UInt32 reqBytes = *ioNumberDataPackets * pwlibASBD.mBytesPerPacket;   if(outBytes < reqBytes && outBytes < This->converter_buffer_size) {      reqBytes = MIN(reqBytes, This->converter_buffer_size);      PTRACE(1, "Buffer underrun, filling up with silence "             << (reqBytes - outBytes) << " bytes ");      bzero(This->converter_buffer + outBytes, reqBytes - outBytes );      outBytes = reqBytes;   }   // fill structure that gets returned to converter   ioData->mBuffers[0].mData = (char*)This->converter_buffer;   ioData->mBuffers[0].mDataByteSize = outBytes;   *ioNumberDataPackets = outBytes / pwlibASBD.mBytesPerPacket;   return err;}/* * CoreAudio Player callback function */OSStatus PSoundChannelCoreAudio::PlayRenderProc(         void*                         inRefCon,         AudioUnitRenderActionFlags*   ioActionFlags,         const struct AudioTimeStamp*  TimeStamp,         UInt32                        inBusNumber,         UInt32                        inNumberFrames,         struct AudioBufferList*       ioData){     OSStatus err = noErr;   PSoundChannelCoreAudio *This =          static_cast<PSoundChannelCoreAudio *>(inRefCon);   if( This->state != running_  || This->mCircularBuffer->Empty() ) {   //   PTRACE(1, __func__ << " terminating");      return noErr;   }   PTRACE(1, __func__ << ", frames " << inNumberFrames);   err = AudioConverterFillComplexBuffer(This->converter,           PSoundChannelCoreAudio::ComplexBufferFillPlayback,            This,            &inNumberFrames, // should be packets           ioData,           NULL /*outPacketDescription*/);   checkStatus(err);   // make fake stereo from mono    //ioData->mBuffers[1] = ioData->mBuffers[0];   /* now that cpu intensive work is done, make stereo from mono    * assume non-interleaved ==> 1 buffer per channel */   UInt32 len = ioData->mBuffers[0].mDataByteSize;   if(len > 0 && This->state == running_){      unsigned i = 1;      while(i < ioData->mNumberBuffers) {         memcpy(ioData->mBuffers[i].mData, ioData->mBuffers[0].mData, len);           ioData->mBuffers[i].mDataByteSize = len;         i++;      }   }   return err;}OSStatus PSoundChannelCoreAudio::RecordProc(           void*                        inRefCon,           AudioUnitRenderActionFlags*  ioActionFlags,           const AudioTimeStamp*        inTimeStamp,           UInt32                       inBusNumber,           UInt32                       inNumberFrames,           AudioBufferList *            ioData){   PTRACE(2,  __func__ << ", frames  " << inNumberFrames );   OSStatus err = noErr;   PSoundChannelCoreAudio *This =                static_cast<PSoundChannelCoreAudio *>(inRefCon);   CircularBuffer* inCircBuf   = This->mInputCircularBuffer;	AudioStreamBasicDescription asbd = This->hwASBD;      if(This->state != running_){      return noErr;   }	if( This->mRecordInputBufferSize < inNumberFrames * asbd.mFramesPerPacket){		PTRACE(1, "Allocated ABL RecordBuffer is too small ");		inNumberFrames = This->mRecordInputBufferSize / asbd.mFramesPerPacket;	}   /* fetch the data from the microphone or other input device */   AudioBufferList*  inputData =  This->mInputBufferList;   err= AudioUnitRender(This->mAudioUnit,            ioActionFlags,            inTimeStamp,             inBusNumber,            inNumberFrames, //# of frames  requested            inputData);// Audio Buffer List to hold data       checkStatus(err);   /* in any case reduce to mono by taking only the first buffer */   AudioBuffer *audio_buf = &inputData->mBuffers[0];   inCircBuf->Fill((char *)audio_buf->mData, audio_buf->mDataByteSize,          false, true); // do not wait, overwrite oldest frames    /*    * Sample Rate Conversion(SRC)    */   unsigned int frames = inCircBuf->size() / This->hwASBD.mBytesPerFrame;   /* given the number of Microphone frames how many 8kHz frames are    * to expect, keeping a minimum buffer fill of MIN_INPUT_FILL frames to     * have some data handy in case the converter requests more Data */   if(frames > MIN_INPUT_FILL){      UInt32 pullFrames = int(float(frames-MIN_INPUT_FILL)/This->rateTimes8kHz);      UInt32 pullBytes = MIN( This->converter_buffer_size,                              pullFrames * This->pwlibASBD.mBytesPerFrame);      UInt32 pullPackets = pullBytes / This->pwlibASBD.mBytesPerPacket;      PTRACE(1, __func__ << " going to pull " << pullPackets << " packets");      /* now pull the frames through the converter */      AudioBufferList* outputData = This->mOutputBufferList;      err = AudioConverterFillComplexBuffer(This->converter,              PSoundChannelCoreAudio::ComplexBufferFillRecord,               This,               &pullPackets,               outputData,               NULL /*outPacketDescription*/);      checkStatus(err);      /* put the converted data into the main CircularBuffer for later        * fetching by the public Read function */      audio_buf = &outputData->mBuffers[0];      This->mCircularBuffer->Fill((char*)audio_buf->mData,             audio_buf->mDataByteSize,             false, true); // do not wait, overwrite oldest frames   }   return err;}/**  * Callback function called by the converter to fetch more date  */OSStatus PSoundChannelCoreAudio::ComplexBufferFillRecord(          AudioConverterRef            inAudioConverter,         UInt32                   *ioNumberDataPackets,         AudioBufferList           *ioData,         AudioStreamPacketDescription **outDataPacketDesc,         void             *inUserData){   OSStatus err = noErr;   PSoundChannelCoreAudio *This =         static_cast<PSoundChannelCoreAudio *>(inUserData);   CircularBuffer* inCircBuf   = This->mInputCircularBuffer;   AudioStreamBasicDescription& hwASBD = This->hwASBD;      // make sure it's always a multiple of packets   UInt32 minPackets = MIN(*ioNumberDataPackets,             inCircBuf->size() / hwASBD.mBytesPerPacket );   UInt32 ioBytes = minPackets * hwASBD.mBytesPerPacket;      PTRACE(1, __func__ << " " << *ioNumberDataPackets << " requested "          << " fetching " << minPackets << " packets");   if(ioBytes > This->converter_buffer_size){      PTRACE(1, "converter_buffer too small " << ioBytes << " requested "             << " but only " << This->converter_buffer_size << " fit in");      ioBytes = This->converter_buffer_size;   }      ioBytes = inCircBuf->Drain((char*)This->converter_buffer, ioBytes, false);      if(ioBytes  != minPackets * hwASBD.mBytesPerPacket) {      // no more a multiple of packet problably !!!      PTRACE(1, "Failed to fetch the computed number of packets");   }   ioData->mBuffers[0].mData = This->converter_buffer;   ioData->mBuffers[0].mDataByteSize = ioBytes;   // assuming non-interleaved or mono    *ioNumberDataPackets = ioBytes / hwASBD.mBytesPerPacket;   return err;   }OSStatus PSoundChannelCoreAudio::CallbackSetup(){   OSStatus err = noErr;   AURenderCallbackStruct callback;   callback.inputProcRefCon = this;   if (direction == Recorder) {      callback.inputProc = RecordProc;      /* kAudioOutputUnit stands for both Microphone/Speaker */      err = AudioUnitSetProperty(mAudioUnit,               kAudioOutputUnitProperty_SetInputCallback,               kAudioUnitScope_Global,               0,               &callback,               sizeof(callback));               }   else {      callback.inputProc = PlayRenderProc;      err = AudioUnitSetProperty(mAudioUnit,                kAudioUnitProperty_SetRenderCallback,               kAudioUnitScope_Input,               0,               &callback,               sizeof(callback));   }   checkStatus(err);   return err;}/********* Function for configuring & initialization of audio units *********//** * Functions to open an AUHAL component and assign it the device indicated  * by deviceID. Conigures the unit for match user desired format  as close as * possible while not assuming special hardware. (able to change sampling rate) */OSStatus PSoundChannelCoreAudio::SetupInputUnit(AudioDeviceID in){     OSStatus err = noErr;            Component comp;               ComponentDescription desc;   //There are several different types of Audio Units.   //Some audio units serve as Outputs, Mixers, or DSP   //units. See AUComponent.h for listing   desc.componentType = kAudioUnitType_Output;   //Every Component has a subType, which will give a clearer picture   //of what this components function will be.   desc.componentSubType = kAudioUnitSubType_HALOutput;   //all Audio Units in AUComponent.h must use    //"kAudioUnitManufacturer_Apple" as the Manufacturer   desc.componentManufacturer = kAudioUnitManufacturer_Apple;   desc.componentFlags = 0;   desc.componentFlagsMask = 0;   //Finds a component that meets the desc spec's   comp = FindNextComponent(NULL, &desc);   if (comp == NULL) return kAudioCodecUnspecifiedError;   //gains access to the services provided by the component   err = OpenAComponent(comp, &mAudioUnit);   checkStatus(err);   err = EnableIO();   checkStatus(err);   err= SetDeviceAsCurrent(in);   checkStatus(err);   return err;}          /** * By default all units are configured for output. If we want to use a  * unit for input we must configure it, before assigning the corresponding * device to it. This to make sure that it asks the device driver for the ASBD * of the input direction. */OSStatus PSoundChannelCoreAudio::EnableIO(){   OSStatus err = noErr;   UInt32 enableIO;   ///////////////   //ENABLE IO (INPUT)   //You must enable the Audio Unit (AUHAL) for input and disable output    //BEFORE setting the AUHAL's current device.   //Enable input on the AUHAL   enableIO = 1;   err =  AudioUnitSetProperty(mAudioUnit,          kAudioOutputUnitProperty_EnableIO,          kAudioUnitScope_Input,          1, // input element          &enableIO,          sizeof(enableIO));   checkStatus(err);   //disable Output on the AUHAL   enableIO = 0;   err = AudioUnitSetProperty(mAudioUnit,         kAudioOutputUnitProperty_EnableIO,         kAudioUnitScope_Output,         0,   //output element         &enableIO,         sizeof(enableIO));   return err;}          /* * Functions to open an AUHAL component and assign it the device indicated  * by deviceID. The builtin converter is configured to accept non-interleaved * data. */OSStatus PSoundChannelCoreAudio::SetupOutputUnit(AudioDeviceID out){   OSStatus err;  //An Audio Unit is a OS component  //The component description must be setup, then used to   //initialize an AudioUnit  ComponentDescription desc;    desc.componentType = kAudioUnitType_Output;  desc.componentSubType = kAudioUnitSubType_HALOutput;  //desc.componentSubType = kAudioUnitSubType_DefaultOutput;  desc.componentManufacturer = kAudioUnitManufacturer_Apple;  desc.componentFlags = 0;  desc.componentFlagsMask = 0;    //Finds an component that meets the desc spec's   Component comp = FindNextComponent(NULL, &desc);    if (comp == NULL) return kAudioCodecUnspecifiedError;      //gains access to the services provided by the component  err = OpenAComponent(comp, &mAudioUnit);    checkStatus(err);  //enableIO not needed, because output is default  err = SetDeviceAsCurrent(out);  return err;}OSStatus PSoundChannelCoreAudio::SetDeviceAsCurrent(AudioDeviceID id){                          UInt32 size = sizeof(AudioDeviceID);   OSStatus err = noErr;   //get the default input device if device is unknown   if(in == kAudioDeviceUnknown)    {        if(direction == Recorder) {         err = AudioHardwareGetProperty(                  kAudioHardwarePropertyDefaultOutputDevice, &size, &id);      } else {         err = AudioHardwareGetProperty(               kAudioHardwarePropertyDefaultInputDevice, &size, &id);      }      checkStatus(err);      }                      mDeviceID = id;   // Set the Current Device to the AUHAL.   // this should be done only after IO has been enabled on the AUHAL.   // to make sure the ASBD for the proper direction is requested   err = AudioUnitSetProperty(mAudioUnit,       kAudioOutputUnitProperty_CurrentDevice,       kAudioUnitScope_Global,       0,         &mDeviceID,       sizeof(mDeviceID));   checkStatus(err);   return err;}  /* * The major task of Open() is to find the matching device ID. * */

⌨️ 快捷键说明

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