📄 pa_mac_core_old.c
字号:
/*
* $Id: pa_mac_core_old.c 770 2006-10-13 17:57:42Z bennylp $
* pa_mac_core.c
* Implementation of PortAudio for Mac OS X CoreAudio
*
* PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com
*
* Authors: Ross Bencina and Phil Burk
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <CoreAudio/CoreAudio.h>
#include <AudioToolbox/AudioToolbox.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include "portaudio.h"
#include "pa_trace.h"
#include "pa_util.h"
#include "pa_allocation.h"
#include "pa_hostapi.h"
#include "pa_stream.h"
#include "pa_cpuload.h"
#include "pa_process.h"
// ===== constants =====
// ===== structs =====
#pragma mark structs
// PaMacCoreHostApiRepresentation - host api datastructure specific to this implementation
typedef struct PaMacCore_HAR
{
PaUtilHostApiRepresentation inheritedHostApiRep;
PaUtilStreamInterface callbackStreamInterface;
PaUtilStreamInterface blockingStreamInterface;
PaUtilAllocationGroup *allocations;
AudioDeviceID *macCoreDeviceIds;
}
PaMacCoreHostApiRepresentation;
typedef struct PaMacCore_DI
{
PaDeviceInfo inheritedDeviceInfo;
}
PaMacCoreDeviceInfo;
// PaMacCoreStream - a stream data structure specifically for this implementation
typedef struct PaMacCore_S
{
PaUtilStreamRepresentation streamRepresentation;
PaUtilCpuLoadMeasurer cpuLoadMeasurer;
PaUtilBufferProcessor bufferProcessor;
int primeStreamUsingCallback;
AudioDeviceID inputDevice;
AudioDeviceID outputDevice;
// Processing thread management --------------
// HANDLE abortEvent;
// HANDLE processingThread;
// DWORD processingThreadId;
char throttleProcessingThreadOnOverload; // 0 -> don't throtte, non-0 -> throttle
int processingThreadPriority;
int highThreadPriority;
int throttledThreadPriority;
unsigned long throttledSleepMsecs;
int isStopped;
volatile int isActive;
volatile int stopProcessing; // stop thread once existing buffers have been returned
volatile int abortProcessing; // stop thread immediately
// DWORD allBuffersDurationMs; // used to calculate timeouts
}
PaMacCoreStream;
// Data needed by the CoreAudio callback functions
typedef struct PaMacCore_CD
{
PaMacCoreStream *stream;
PaStreamCallback *callback;
void *userData;
PaUtilConverter *inputConverter;
PaUtilConverter *outputConverter;
void *inputBuffer;
void *outputBuffer;
int inputChannelCount;
int outputChannelCount;
PaSampleFormat inputSampleFormat;
PaSampleFormat outputSampleFormat;
PaUtilTriangularDitherGenerator *ditherGenerator;
}
PaMacClientData;
// ===== CoreAudio-PortAudio bridge functions =====
#pragma mark CoreAudio-PortAudio bridge functions
// Maps CoreAudio OSStatus codes to PortAudio PaError codes
static PaError conv_err(OSStatus error)
{
PaError result;
switch (error) {
case kAudioHardwareNoError:
result = paNoError; break;
case kAudioHardwareNotRunningError:
result = paInternalError; break;
case kAudioHardwareUnspecifiedError:
result = paInternalError; break;
case kAudioHardwareUnknownPropertyError:
result = paInternalError; break;
case kAudioHardwareBadPropertySizeError:
result = paInternalError; break;
case kAudioHardwareIllegalOperationError:
result = paInternalError; break;
case kAudioHardwareBadDeviceError:
result = paInvalidDevice; break;
case kAudioHardwareBadStreamError:
result = paBadStreamPtr; break;
//bennylp:
//case kAudioHardwareUnsupportedOperationError:
// result = paInternalError; break;
case kAudioDeviceUnsupportedFormatError:
result = paSampleFormatNotSupported; break;
case kAudioDevicePermissionsError:
result = paDeviceUnavailable; break;
default:
result = paInternalError;
}
return result;
}
/* This function is unused
static AudioStreamBasicDescription *InitializeStreamDescription(const PaStreamParameters *parameters, double sampleRate)
{
struct AudioStreamBasicDescription *streamDescription = PaUtil_AllocateMemory(sizeof(AudioStreamBasicDescription));
streamDescription->mSampleRate = sampleRate;
streamDescription->mFormatID = kAudioFormatLinearPCM;
streamDescription->mFormatFlags = 0;
streamDescription->mFramesPerPacket = 1;
if (parameters->sampleFormat & paNonInterleaved) {
streamDescription->mFormatFlags |= kLinearPCMFormatFlagIsNonInterleaved;
streamDescription->mChannelsPerFrame = 1;
streamDescription->mBytesPerFrame = Pa_GetSampleSize(parameters->sampleFormat);
streamDescription->mBytesPerPacket = Pa_GetSampleSize(parameters->sampleFormat);
}
else {
streamDescription->mChannelsPerFrame = parameters->channelCount;
}
streamDescription->mBytesPerFrame = Pa_GetSampleSize(parameters->sampleFormat) * streamDescription->mChannelsPerFrame;
streamDescription->mBytesPerPacket = streamDescription->mBytesPerFrame * streamDescription->mFramesPerPacket;
if (parameters->sampleFormat & paFloat32) {
streamDescription->mFormatFlags |= kLinearPCMFormatFlagIsFloat;
streamDescription->mBitsPerChannel = 32;
}
else if (parameters->sampleFormat & paInt32) {
streamDescription->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
streamDescription->mBitsPerChannel = 32;
}
else if (parameters->sampleFormat & paInt24) {
streamDescription->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
streamDescription->mBitsPerChannel = 24;
}
else if (parameters->sampleFormat & paInt16) {
streamDescription->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
streamDescription->mBitsPerChannel = 16;
}
else if (parameters->sampleFormat & paInt8) {
streamDescription->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
streamDescription->mBitsPerChannel = 8;
}
else if (parameters->sampleFormat & paInt32) {
streamDescription->mBitsPerChannel = 8;
}
return streamDescription;
}
*/
static PaStreamCallbackTimeInfo *InitializeTimeInfo(const AudioTimeStamp* now, const AudioTimeStamp* inputTime, const AudioTimeStamp* outputTime)
{
PaStreamCallbackTimeInfo *timeInfo = PaUtil_AllocateMemory(sizeof(PaStreamCallbackTimeInfo));
timeInfo->inputBufferAdcTime = inputTime->mSampleTime;
timeInfo->currentTime = now->mSampleTime;
timeInfo->outputBufferDacTime = outputTime->mSampleTime;
return timeInfo;
}
// ===== support functions =====
#pragma mark support functions
static void CleanUp(PaMacCoreHostApiRepresentation *macCoreHostApi)
{
if( macCoreHostApi->allocations )
{
PaUtil_FreeAllAllocations( macCoreHostApi->allocations );
PaUtil_DestroyAllocationGroup( macCoreHostApi->allocations );
}
PaUtil_FreeMemory( macCoreHostApi );
}
static PaError GetChannelInfo(PaDeviceInfo *deviceInfo, AudioDeviceID macCoreDeviceId, int isInput)
{
UInt32 propSize;
PaError err = paNoError;
UInt32 i;
int numChannels = 0;
AudioBufferList *buflist;
err = conv_err(AudioDeviceGetPropertyInfo(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreamConfiguration, &propSize, NULL));
buflist = PaUtil_AllocateMemory(propSize);
err = conv_err(AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreamConfiguration, &propSize, buflist));
if (!err) {
for (i = 0; i < buflist->mNumberBuffers; ++i) {
numChannels += buflist->mBuffers[i].mNumberChannels;
}
if (isInput)
deviceInfo->maxInputChannels = numChannels;
else
deviceInfo->maxOutputChannels = numChannels;
int frameLatency;
propSize = sizeof(UInt32);
err = conv_err(AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyLatency, &propSize, &frameLatency));
if (!err) {
double secondLatency = frameLatency / deviceInfo->defaultSampleRate;
if (isInput) {
deviceInfo->defaultLowInputLatency = secondLatency;
deviceInfo->defaultHighInputLatency = secondLatency;
}
else {
deviceInfo->defaultLowOutputLatency = secondLatency;
deviceInfo->defaultHighOutputLatency = secondLatency;
}
}
}
PaUtil_FreeMemory(buflist);
return err;
}
static PaError InitializeDeviceInfo(PaMacCoreDeviceInfo *macCoreDeviceInfo, AudioDeviceID macCoreDeviceId, PaHostApiIndex hostApiIndex )
{
PaDeviceInfo *deviceInfo = &macCoreDeviceInfo->inheritedDeviceInfo;
deviceInfo->structVersion = 2;
deviceInfo->hostApi = hostApiIndex;
PaError err = paNoError;
UInt32 propSize;
err = conv_err(AudioDeviceGetPropertyInfo(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, NULL));
// FIXME: this allocation should be part of the allocations group
char *name = PaUtil_AllocateMemory(propSize);
err = conv_err(AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, name));
if (!err) {
deviceInfo->name = name;
}
Float64 sampleRate;
propSize = sizeof(Float64);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -