📄 maccoreaudio.cxx
字号:
if (err) { return FALSE; } PTRACE(2, __func__ << " AudioDevice buffer size set to " << targetSizeBytes); UInt32 targetSizeFrames = targetSizeBytes / hwASBD.mBytesPerFrame; if (direction == Player) { err = AudioDeviceSetProperty( mDeviceID, 0, //&ts, timestruct 0, // output channel true, // isInput // kAudioDevicePropertyBufferSize, kAudioDevicePropertyBufferFrameSize, sizeof(UInt32), &targetSizeFrames); } else { err = AudioDeviceSetProperty( mDeviceID, 0, //&ts, timestruct 1, // input channel false, // isInput kAudioDevicePropertyBufferFrameSize, sizeof(UInt32), &targetSizeFrames); } checkStatus(err); */ /** * Allocate byte array passed as input to the converter */ UInt32 bufferSizeFrames, bufferSizeBytes; UInt32 propertySize = sizeof(UInt32); err = AudioDeviceGetProperty( mDeviceID, 0, // output channel, true, // isInput kAudioDevicePropertyBufferFrameSize, &propertySize, &bufferSizeFrames); checkStatus(err); bufferSizeBytes = bufferSizeFrames * hwASBD.mBytesPerFrame; //UInt32 bufferSizeBytes = targetSizeBytes; if (direction == Player) { UInt32 propertySize = sizeof(UInt32); err = AudioConverterGetProperty(converter, kAudioConverterPropertyCalculateInputBufferSize, &propertySize, &bufferSizeBytes); checkStatus(err); converter_buffer_size = bufferSizeBytes; } else { // on each turn the device spits out bufferSizeBytes bytes // the input ringbuffer has at most MIN_INPUT_FILL frames in it // all other frames were converter during the last callback converter_buffer_size = bufferSizeBytes + 2 * MIN_INPUT_FILL * hwASBD.mBytesPerFrame; } converter_buffer = (char*)malloc(converter_buffer_size); if(converter_buffer == NULL) PTRACE(1, "Failed to allocate converter_buffer"); else PTRACE(2, "Allocated converter_buffer of size " << converter_buffer_size ); /** In case of Recording we need a couple of buffers more */ if(direction == Recorder){ SetupAdditionalRecordBuffers(); } /* * AU Setup, allocates necessary buffers... */ err = AudioUnitInitialize(mAudioUnit); checkStatus(err); state = setbuffer_; return TRUE;}OSStatus PSoundChannelCoreAudio::SetupAdditionalRecordBuffers(){ OSStatus err = noErr; UInt32 bufferSizeFrames, bufferSizeBytes; /** * build buffer list to take over the data from the microphone */ UInt32 propertySize = sizeof(UInt32); err = AudioDeviceGetProperty( mDeviceID, 0, // channel, probably all true, // isInput //false, // isInput () kAudioDevicePropertyBufferFrameSize, &propertySize, &bufferSizeFrames); checkStatus(err); bufferSizeBytes = bufferSizeFrames * hwASBD.mBytesPerFrame; bufferSizeBytes += bufferSizeBytes / 10; // +10% //calculate size of ABL given the last field, assum non-interleaved UInt32 propsize = offsetof(AudioBufferList, mBuffers[hwASBD.mChannelsPerFrame]); //malloc buffer lists mInputBufferList = (AudioBufferList *)malloc(propsize); mInputBufferList->mNumberBuffers = hwASBD.mChannelsPerFrame; //pre-malloc buffers for AudioBufferLists for(UInt32 i =0; i< mInputBufferList->mNumberBuffers ; i++) { mInputBufferList->mBuffers[i].mNumberChannels = 1; mInputBufferList->mBuffers[i].mDataByteSize = bufferSizeBytes; mInputBufferList->mBuffers[i].mData = malloc(bufferSizeBytes); } mRecordInputBufferSize = bufferSizeBytes; /** allocate ringbuffer to cache data before passing them to the converter */ // take only one buffer -> mono, use double buffering mInputCircularBuffer = new CircularBuffer(bufferSizeBytes * 2); /** * Build buffer list that is passed to the Converter to be filled with * the converted frames. */ // given the number of input bytes how many bytes to expect at the output? bufferSizeBytes += MIN_INPUT_FILL * hwASBD.mBytesPerFrame; propertySize = sizeof(UInt32); err = AudioConverterGetProperty(converter, kAudioConverterPropertyCalculateOutputBufferSize, &propertySize, &bufferSizeBytes); checkStatus(err); //calculate number of buffers from channels propsize = offsetof(AudioBufferList, mBuffers[pwlibASBD.mChannelsPerFrame]); //malloc buffer lists mOutputBufferList = (AudioBufferList *)malloc(propsize); mOutputBufferList->mNumberBuffers = pwlibASBD.mChannelsPerFrame; //pre-malloc buffers for AudioBufferLists for(UInt32 i =0; i< mOutputBufferList->mNumberBuffers ; i++) { mOutputBufferList->mBuffers[i].mNumberChannels = 1; mOutputBufferList->mBuffers[i].mDataByteSize = bufferSizeBytes; mOutputBufferList->mBuffers[i].mData = malloc(bufferSizeBytes); } mRecordOutputBufferSize = bufferSizeBytes; return err;} BOOL PSoundChannelCoreAudio::GetBuffers(PINDEX & size, PINDEX & count){ size = bufferSizeBytes; count = bufferCount; return TRUE;}BOOL PSoundChannelCoreAudio::SetVolume(unsigned volume){ OSStatus err = noErr; Boolean isWritable; bool isInput = (direction == Player ? false : true); if(mDeviceID == kAudioDeviceDummy){ PTRACE(1, "Dummy device"); return FALSE; } // changing volume can not go through the master channel (0) err = AudioDeviceGetPropertyInfo(mDeviceID, 1, isInput, kAudioDevicePropertyVolumeScalar, NULL, &isWritable); checkStatus(err); if ((err == kAudioHardwareNoError) && isWritable) { // volume is between 0 and 100 ? float theValue = ((float)volume)/100.0; err = AudioDeviceSetProperty(mDeviceID, NULL, 1, isInput, kAudioDevicePropertyVolumeScalar, sizeof(float), &theValue); } if (!err) return TRUE; else return FALSE;}BOOL PSoundChannelCoreAudio::GetVolume(unsigned & volume){ OSStatus err = noErr; UInt32 theSize; Float32 theValue; bool isInput = (direction == Player ? false : true); if(mDeviceID == kAudioDeviceDummy){ PTRACE(1, "Dummy device"); return FALSE; } theSize = sizeof(theValue); // changing volume can not go through the master channel (0) err = AudioDeviceGetProperty(mDeviceID, 1, isInput, kAudioDevicePropertyVolumeScalar, &theSize, &theValue); if (!err) { // volume is between 0 and 100? volume = (unsigned) (theValue * 100); return TRUE; } else return FALSE; } BOOL PSoundChannelCoreAudio::Write(const void *buf, PINDEX len){ PTRACE(1, "Write called with len " << len); if(state < setbuffer_){ PTRACE(1, __func__ << " Please initialize device first"); return FALSE; } if (mDeviceID == kAudioDeviceDummy) { lastWriteCount = len; // safe to assume non-interleaved or mono UInt32 nr_samples = len / pwlibASBD.mBytesPerFrame; usleep(UInt32(nr_samples/pwlibASBD.mSampleRate * 1000000)); // 10E-6 [s] return TRUE; /* Null device */ } // Write to circular buffer with locking lastWriteCount = mCircularBuffer->Fill((const char*)buf, len, true); // Start it after putting the first data into the buffer // this might cause troubles in case more data are written // than space is available if(state == setbuffer_){ PTRACE(1, "Starting " << direction << " device."); OSStatus err = AudioOutputUnitStart(mAudioUnit); checkStatus(err); state = running_; } return (TRUE);}BOOL PSoundChannelCoreAudio::PlaySound(const PSound & sound, BOOL wait){ if (!Write((const BYTE *)sound, sound.GetSize())) return FALSE; if (wait) return WaitForPlayCompletion(); return TRUE;}BOOL PSoundChannelCoreAudio::PlayFile(const PFilePath & file, BOOL wait){ PTRACE(1, __func__ ); PAssert(0, PUnimplementedFunction); return TRUE; }BOOL PSoundChannelCoreAudio::HasPlayCompleted(){ PTRACE(1, __func__ ); PAssert(0, PUnimplementedFunction); return false;}BOOL PSoundChannelCoreAudio::WaitForPlayCompletion(){ PTRACE(1, __func__ ); PAssert(0, PUnimplementedFunction); return false;}BOOL PSoundChannelCoreAudio::Read(void *buf, PINDEX len){ PTRACE(6, "Read called with len " << len); if(state < setbuffer_){ PTRACE(1, __func__ << " Please initialize device first"); return FALSE; } if (mDeviceID == kAudioDeviceDummy) { lastReadCount = len; bzero(buf, len); // we are working with non-interleaved or mono UInt32 nr_samples = len / pwlibASBD.mBytesPerFrame; usleep(UInt32(nr_samples/pwlibASBD.mSampleRate * 1000000)); // 10E-6 [s] return TRUE; /* Null device */ } if(state == setbuffer_){ PTRACE(1, "Starting " << direction << " device."); OSStatus err = AudioOutputUnitStart(mAudioUnit); checkStatus(err); state = running_; } lastReadCount = mCircularBuffer->Drain((char*)buf, len, true); return (TRUE);}BOOL PSoundChannelCoreAudio::RecordSound(PSound & sound){ PTRACE(1, __func__ ); PAssert(0, PUnimplementedFunction); return false;}BOOL PSoundChannelCoreAudio::RecordFile(const PFilePath & file){ PTRACE(1, __func__ ); PAssert(0, PUnimplementedFunction); return false;}BOOL PSoundChannelCoreAudio::StartRecording(){ PTRACE(1, __func__ ); if(state != setbuffer_){ PTRACE(1, __func__ << " Initialize the device first"); return FALSE; } if(state == setbuffer_){ PTRACE(1, "Starting " << direction << " device."); OSStatus err = AudioOutputUnitStart(mAudioUnit); checkStatus(err); state = running_; } return false;}BOOL PSoundChannelCoreAudio::isRecordBufferFull(){ PAssert(direction == Recorder, PInvalidParameter); if(state != setbuffer_){ PTRACE(1, __func__ << " Initialize the device first"); return FALSE; } return (mCircularBuffer->size() > bufferSizeBytes);}BOOL PSoundChannelCoreAudio::AreAllRecordBuffersFull(){ PAssert(direction == Recorder, PInvalidParameter); if(state != setbuffer_){ PTRACE(1, __func__ << " Initialize the device first"); return FALSE; } return (mCircularBuffer->Full());}BOOL PSoundChannelCoreAudio::WaitForRecordBufferFull(){ PTRACE(1, __func__ ); PAssert(0, PUnimplementedFunction); if (os_handle < 0) { return FALSE; } return PXSetIOBlock(PXReadBlock, readTimeout);}BOOL PSoundChannelCoreAudio::WaitForAllRecordBuffersFull(){ PTRACE(1, __func__ ); PAssert(0, PUnimplementedFunction); return false;}// End of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -