📄 pa_asio.cpp
字号:
/*
* $Id: pa_asio.cpp,v 1.7.4.5 2003/06/30 16:27:10 stephane Exp $
* Portable Audio I/O Library for ASIO Drivers
*
* Author: Stephane Letz
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 2000-2001 Stephane Letz, 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.
*
* 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.
*
* 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.
*/
/* Modification History
08-03-01 First version : Stephane Letz
08-06-01 Tweaks for PC, use C++, buffer allocation, Float32 to Int32 conversion : Phil Burk
08-20-01 More conversion, PA_StreamTime, Pa_GetHostError : Stephane Letz
08-21-01 PaUInt8 bug correction, implementation of ASIOSTFloat32LSB and ASIOSTFloat32MSB native formats : Stephane Letz
08-24-01 MAX_INT32_FP hack, another Uint8 fix : Stephane and Phil
08-27-01 Implementation of hostBufferSize < userBufferSize case, better management of the ouput buffer when
the stream is stopped : Stephane Letz
08-28-01 Check the stream pointer for null in bufferSwitchTimeInfo, correct bug in bufferSwitchTimeInfo when
the stream is stopped : Stephane Letz
10-12-01 Correct the PaHost_CalcNumHostBuffers function: computes FramesPerHostBuffer to be the lowest that
respect requested FramesPerUserBuffer and userBuffersPerHostBuffer : Stephane Letz
10-26-01 Management of hostBufferSize and userBufferSize of any size : Stephane Letz
10-27-01 Improve calculus of hostBufferSize to be multiple or divisor of userBufferSize if possible : Stephane and Phil
10-29-01 Change MAX_INT32_FP to (2147483520.0f) to prevent roundup to 0x80000000 : Phil Burk
10-31-01 Clear the ouput buffer and user buffers in PaHost_StartOutput, correct bug in GetFirstMultiple : Stephane Letz
11-06-01 Rename functions : Stephane Letz
11-08-01 New Pa_ASIO_Adaptor_Init function to init Callback adpatation variables, cleanup of Pa_ASIO_Callback_Input: Stephane Letz
11-29-01 Break apart device loading to debug random failure in Pa_ASIO_QueryDeviceInfo ; Phil Burk
01-03-02 Desallocate all resources in PaHost_Term for cases where Pa_CloseStream is not called properly : Stephane Letz
02-01-02 Cleanup, test of multiple-stream opening : Stephane Letz
19-02-02 New Pa_ASIO_loadDriver that calls CoInitialize on each thread on Windows : Stephane Letz
09-04-02 Correct error code management in PaHost_Term, removes various compiler warning : Stephane Letz
12-04-02 Add Mac includes for <Devices.h> and <Timer.h> : Phil Burk
13-04-02 Removes another compiler warning : Stephane Letz
30-04-02 Pa_ASIO_QueryDeviceInfo bug correction, memory allocation checking, better error handling : D Viens, P Burk, S Letz
01-12-02 Fix Pa_GetDefaultInputDeviceID and Pa_GetDefaultOuputDeviceID result when no driver are available : S Letz
05-12-02 More debug messages : S Letz
01-23-03 Increased max channels to 128. Fixed comparison of (OutputChannels > kMaxInputChannels) : P Burk
02-17-03 Better termination handling : PaHost_CloseStream is called in PaHost_term is the the stream was not explicitely closed by the application : S Letz
04-02-03 More robust ASIO driver buffer size initialization : some buggy drivers (like the Hoontech DSP24) give incorrect [min, preferred, max] values
They should work with the preferred size value, thus if Pa_ASIO_CreateBuffers fails with the hostBufferSize computed in PaHost_CalcNumHostBuffers,
we try again with the preferred size. Fix an old (never detected?) bug in the buffer adapdation code : S Letz
30-06-03 The audio callback was not protected against reentrancy : some drivers (like the Hoontech DSP24) seems to cause this behaviour
that corrupted the buffer adapdation state and finally caused crashes. The reentrancy state is now checked in bufferSwitchTimeInfo : S Letz
TO DO :
- Check Pa_StopSteam and Pa_AbortStream
- Optimization for Input only or Ouput only (really necessary ??)
*/
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "portaudio.h"
#include "pa_host.h"
#include "pa_trace.h"
#include "asiosys.h"
#include "asio.h"
#include "asiodrivers.h"
#if MAC
#include <Devices.h>
#include <Timer.h>
#include <Math64.h>
#else
#include <math.h>
#include <windows.h>
#include <mmsystem.h>
#endif
enum {
// number of input and outputs supported by the host application
// you can change these to higher or lower values
kMaxInputChannels = 128,
kMaxOutputChannels = 128
};
/* ASIO specific device information. */
typedef struct internalPortAudioDevice
{
PaDeviceInfo pad_Info;
} internalPortAudioDevice;
/* ASIO driver internal data storage */
typedef struct PaHostSoundControl
{
// ASIOInit()
ASIODriverInfo pahsc_driverInfo;
// ASIOGetChannels()
int32 pahsc_NumInputChannels;
int32 pahsc_NumOutputChannels;
// ASIOGetBufferSize() - sizes in frames per buffer
int32 pahsc_minSize;
int32 pahsc_maxSize;
int32 pahsc_preferredSize;
int32 pahsc_granularity;
// ASIOGetSampleRate()
ASIOSampleRate pahsc_sampleRate;
// ASIOOutputReady()
bool pahsc_postOutput;
// ASIOGetLatencies ()
int32 pahsc_inputLatency;
int32 pahsc_outputLatency;
// ASIOCreateBuffers ()
ASIOBufferInfo bufferInfos[kMaxInputChannels + kMaxOutputChannels]; // buffer info's
// ASIOGetChannelInfo()
ASIOChannelInfo pahsc_channelInfos[kMaxInputChannels + kMaxOutputChannels]; // channel info's
// The above two arrays share the same indexing, as the data in them are linked together
// Information from ASIOGetSamplePosition()
// data is converted to double floats for easier use, however 64 bit integer can be used, too
double nanoSeconds;
double samples;
double tcSamples; // time code samples
// bufferSwitchTimeInfo()
ASIOTime tInfo; // time info state
unsigned long sysRefTime; // system reference time, when bufferSwitch() was called
// Signal the end of processing in this example
bool stopped;
ASIOCallbacks pahsc_asioCallbacks;
int32 pahsc_userInputBufferFrameOffset; // Position in Input user buffer
int32 pahsc_userOutputBufferFrameOffset; // Position in Output user buffer
int32 pahsc_hostOutputBufferFrameOffset; // Position in Output ASIO buffer
int32 past_FramesPerHostBuffer; // Number of frames in ASIO buffer
int32 pahsc_InputBufferOffset; // Number of null frames for input buffer alignement
int32 pahsc_OutputBufferOffset; // Number of null frames for ouput buffer alignement
#if MAC
UInt64 pahsc_EntryCount;
UInt64 pahsc_LastExitCount;
#elif WINDOWS
LARGE_INTEGER pahsc_EntryCount;
LARGE_INTEGER pahsc_LastExitCount;
#endif
PaTimestamp pahsc_NumFramesDone;
internalPortAudioStream *past;
int32 reenterCount; // Counter of audio callback reentrancy
int32 reenterError; // Counter of audio callback reentrancy detection
} PaHostSoundControl;
//----------------------------------------------------------
#define PRINT(x) { printf x; fflush(stdout); }
#define ERR_RPT(x) PRINT(x)
#define DBUG(x) /* PRINT(x) */
#define DBUGX(x) /* PRINT(x) */
/* We are trying to be compatible with CARBON but this has not been thoroughly tested. */
#define CARBON_COMPATIBLE (0)
#define PA_MAX_DEVICE_INFO (32)
#define MIN_INT8 (-0x80)
#define MAX_INT8 (0x7F)
#define MIN_INT8_FP ((float)-0x80)
#define MAX_INT8_FP ((float)0x7F)
#define MIN_INT16_FP ((float)-0x8000)
#define MAX_INT16_FP ((float)0x7FFF)
#define MIN_INT16 (-0x8000)
#define MAX_INT16 (0x7FFF)
#define MAX_INT32_FP (2147483520.0f) /* 0x0x7FFFFF80 - seems safe */
/************************************************************************************/
/****************** Data ************************************************************/
/************************************************************************************/
static int sNumDevices = 0;
static internalPortAudioDevice sDevices[PA_MAX_DEVICE_INFO] = { 0 };
static int32 sPaHostError = 0;
static int sDefaultOutputDeviceID = 0;
static int sDefaultInputDeviceID = 0;
PaHostSoundControl asioDriverInfo = {0};
#ifdef MAC
static bool swap = true;
#elif WINDOWS
static bool swap = false;
#endif
// Prototypes
static void bufferSwitch(long index, ASIOBool processNow);
static ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow);
static void sampleRateChanged(ASIOSampleRate sRate);
static long asioMessages(long selector, long value, void* message, double* opt);
static void Pa_StartUsageCalculation( internalPortAudioStream *past );
static void Pa_EndUsageCalculation( internalPortAudioStream *past );
static void Pa_ASIO_Convert_Inter_Input(
ASIOBufferInfo* nativeBuffer,
void* inputBuffer,
long NumInputChannels,
long NumOuputChannels,
long framePerBuffer,
long hostFrameOffset,
long userFrameOffset,
ASIOSampleType nativeFormat,
PaSampleFormat paFormat,
PaStreamFlags flags,
long index);
static void Pa_ASIO_Convert_Inter_Output(
ASIOBufferInfo* nativeBuffer,
void* outputBuffer,
long NumInputChannels,
long NumOuputChannels,
long framePerBuffer,
long hostFrameOffset,
long userFrameOffset,
ASIOSampleType nativeFormat,
PaSampleFormat paFormat,
PaStreamFlags flags,
long index);
static void Pa_ASIO_Clear_Output(ASIOBufferInfo* nativeBuffer,
ASIOSampleType nativeFormat,
long NumInputChannels,
long NumOuputChannels,
long index,
long hostFrameOffset,
long frames);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -