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

📄 pa_asio.cpp

📁 ppciaxclient softphone
💻 CPP
📖 第 1 页 / 共 5 页
字号:
static void Pa_ASIO_Callback_Input(long index);
static void Pa_ASIO_Callback_Output(long index, long framePerBuffer);
static void Pa_ASIO_Callback_End();
static void Pa_ASIO_Clear_User_Buffers();

// Some external references
extern AsioDrivers* asioDrivers ;
bool loadAsioDriver(char *name);
unsigned long get_sys_reference_time();


/************************************************************************************/
/****************** Macro  ************************************************************/
/************************************************************************************/

#define SwapLong(v) ((((v)>>24)&0xFF)|(((v)>>8)&0xFF00)|(((v)&0xFF00)<<8)|(((v)&0xFF)<<24)) ;   
#define SwapShort(v) ((((v)>>8)&0xFF)|(((v)&0xFF)<<8)) ;        

#define ClipShort(v) (((v)<MIN_INT16)?MIN_INT16:(((v)>MAX_INT16)?MAX_INT16:(v)))
#define ClipChar(v) (((v)<MIN_INT8)?MIN_INT8:(((v)>MAX_INT8)?MAX_INT8:(v)))
#define ClipFloat(v) (((v)<-1.0f)?-1.0f:(((v)>1.0f)?1.0f:(v)))

#ifndef min
#define min(a,b) ((a)<(b)?(a):(b))
#endif

#ifndef max
#define max(a,b) ((a)>=(b)?(a):(b))
#endif


static bool Pa_ASIO_loadAsioDriver(char *name)
{
	#ifdef	WINDOWS
		CoInitialize(0);
	#endif
	return loadAsioDriver(name);
}
 


// Utilities for alignement buffer size computation
static int PGCD (int a, int b) {return (b == 0) ? a : PGCD (b,a%b);}
static int PPCM (int a, int b) {return (a*b) / PGCD (a,b);}

// Takes the size of host buffer and user buffer : returns the number of frames needed for buffer adaptation
static int Pa_ASIO_CalcFrameShift (int M, int N)
{
        int res = 0;
        for (int i = M; i < PPCM (M,N) ; i+=M) { res = max (res, i%N); }
        return res;
}

// We have the following relation :
// Pa_ASIO_CalcFrameShift (M,N) + M = Pa_ASIO_CalcFrameShift (N,M) + N
                        
/* ASIO sample type to PortAudio sample type conversion */
static PaSampleFormat Pa_ASIO_Convert_SampleFormat(ASIOSampleType type) 
{
        switch (type) {
        
                case ASIOSTInt16MSB:
                case ASIOSTInt16LSB:
                case ASIOSTInt32MSB16:
                case ASIOSTInt32LSB16:
                        return paInt16;
                
                case ASIOSTFloat32MSB:
                case ASIOSTFloat32LSB:
                case ASIOSTFloat64MSB:
                case ASIOSTFloat64LSB:
                        return paFloat32;
                
                case ASIOSTInt32MSB:
                case ASIOSTInt32LSB:
                case ASIOSTInt32MSB18:          
                case ASIOSTInt32MSB20:          
                case ASIOSTInt32MSB24:          
                case ASIOSTInt32LSB18:          
                case ASIOSTInt32LSB20:          
                case ASIOSTInt32LSB24:          
                        return paInt32;
                        
                case ASIOSTInt24MSB:
                case ASIOSTInt24LSB:
                        return paInt24;
                        
                default:
                        return paCustomFormat;
        }
}



//--------------------------------------------------------------------------------------------------------------------
static void PaHost_CalcBufferOffset(internalPortAudioStream   *past)
{
	 if (asioDriverInfo.past_FramesPerHostBuffer > past->past_FramesPerUserBuffer){
            // Computes the MINIMUM value of null frames shift for the output buffer alignement
            asioDriverInfo.pahsc_OutputBufferOffset = Pa_ASIO_CalcFrameShift (asioDriverInfo.past_FramesPerHostBuffer,past->past_FramesPerUserBuffer);
            asioDriverInfo.pahsc_InputBufferOffset = 0;
            DBUG(("PaHost_CalcBufferOffset : Minimum BufferOffset for Output = %d\n", asioDriverInfo.pahsc_OutputBufferOffset));
    }else{
    
            //Computes the MINIMUM value of null frames shift for the input buffer alignement
            asioDriverInfo.pahsc_InputBufferOffset = Pa_ASIO_CalcFrameShift (asioDriverInfo.past_FramesPerHostBuffer,past->past_FramesPerUserBuffer);
            asioDriverInfo.pahsc_OutputBufferOffset = 0;
            DBUG(("PaHost_CalcBufferOffset : Minimum BufferOffset for Input = %d\n", asioDriverInfo.pahsc_InputBufferOffset));
    }
}

//--------------------------------------------------------------------------------------------------------------------
/* Allocate ASIO buffers, initialise channels */
static ASIOError Pa_ASIO_CreateBuffers (PaHostSoundControl *asioDriverInfo, long InputChannels,
                                                                          long OutputChannels, long framesPerBuffer)
{
        ASIOError  err;
        int i;
        
        ASIOBufferInfo *info = asioDriverInfo->bufferInfos;
        
        // Check parameters
        if ((InputChannels > kMaxInputChannels) || (OutputChannels > kMaxOutputChannels)) return ASE_InvalidParameter;
        
        for(i = 0; i < InputChannels; i++, info++){
                info->isInput = ASIOTrue;
                info->channelNum = i;
                info->buffers[0] = info->buffers[1] = 0;
        }
        
        for(i = 0; i < OutputChannels; i++, info++){
                info->isInput = ASIOFalse;
                info->channelNum = i;
                info->buffers[0] = info->buffers[1] = 0;
        }
        
        // Set up the asioCallback structure and create the ASIO data buffer
        asioDriverInfo->pahsc_asioCallbacks.bufferSwitch = &bufferSwitch;
        asioDriverInfo->pahsc_asioCallbacks.sampleRateDidChange = &sampleRateChanged;
        asioDriverInfo->pahsc_asioCallbacks.asioMessage = &asioMessages;
        asioDriverInfo->pahsc_asioCallbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfo;
        
        DBUG(("Pa_ASIO_CreateBuffers : ASIOCreateBuffers with inputChannels = %ld \n", InputChannels));
        DBUG(("Pa_ASIO_CreateBuffers : ASIOCreateBuffers with OutputChannels = %ld \n", OutputChannels));
        DBUG(("Pa_ASIO_CreateBuffers : ASIOCreateBuffers with size = %ld \n", framesPerBuffer));
     
        err =  ASIOCreateBuffers( asioDriverInfo->bufferInfos, InputChannels+OutputChannels,
                                  framesPerBuffer, &asioDriverInfo->pahsc_asioCallbacks);
        if (err != ASE_OK) return err;
        
        // Initialise buffers
        for (i = 0; i < InputChannels + OutputChannels; i++)
        {
                asioDriverInfo->pahsc_channelInfos[i].channel = asioDriverInfo->bufferInfos[i].channelNum;
                asioDriverInfo->pahsc_channelInfos[i].isInput = asioDriverInfo->bufferInfos[i].isInput;
                err = ASIOGetChannelInfo(&asioDriverInfo->pahsc_channelInfos[i]);
                if (err != ASE_OK) break;
        }

        err = ASIOGetLatencies(&asioDriverInfo->pahsc_inputLatency, &asioDriverInfo->pahsc_outputLatency);
        
        DBUG(("Pa_ASIO_CreateBuffers : InputLatency = %ld latency = %ld msec \n", 
                asioDriverInfo->pahsc_inputLatency,  
                (long)((asioDriverInfo->pahsc_inputLatency*1000)/ asioDriverInfo->past->past_SampleRate)));
        DBUG(("Pa_ASIO_CreateBuffers : OuputLatency = %ld latency = %ld msec \n", 
                asioDriverInfo->pahsc_outputLatency,
                (long)((asioDriverInfo->pahsc_outputLatency*1000)/ asioDriverInfo->past->past_SampleRate)));
        
        return err;
}


/*
 Query ASIO driver info :
 
 First we get all available ASIO drivers located in the ASIO folder,
 then try to load each one. For each loaded driver, get all needed informations.
*/
static PaError Pa_ASIO_QueryDeviceInfo( internalPortAudioDevice * ipad )
{

#define NUM_STANDARDSAMPLINGRATES   3   /* 11.025, 22.05, 44.1 */
#define NUM_CUSTOMSAMPLINGRATES     9   /* must be the same number of elements as in the array below */
#define MAX_NUMSAMPLINGRATES  (NUM_STANDARDSAMPLINGRATES+NUM_CUSTOMSAMPLINGRATES)

        ASIOSampleRate possibleSampleRates[] 
                = {8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, 44100.0, 48000.0, 88200.0, 96000.0};
                
        ASIOChannelInfo channelInfos;
        long InputChannels,OutputChannels;
        double *sampleRates;
        char* names[PA_MAX_DEVICE_INFO] ;
        PaDeviceInfo *dev;
        int           i;
        int           numDrivers;
		ASIOError     asioError;
		
	   /* Allocate names */
        for (i = 0 ; i < PA_MAX_DEVICE_INFO ; i++) {
        	names[i] = (char*)PaHost_AllocateFastMemory(32);
        	/* check memory */
        	if(!names[i]) return paInsufficientMemory;
        }
        
        /* MUST BE CHECKED : to force fragments loading on Mac */
        Pa_ASIO_loadAsioDriver("dummy");
        
        /* Get names of all available ASIO drivers */
        asioDrivers->getDriverNames(names,PA_MAX_DEVICE_INFO);
        
        /* Check all available ASIO drivers */
#if MAC
        numDrivers = asioDrivers->getNumFragments();
#elif WINDOWS
        numDrivers = asioDrivers->asioGetNumDev();
#endif

        DBUG(("PaASIO_QueryDeviceInfo: number of installed drivers = %d\n", numDrivers ));

        for (int driver = 0 ; driver < numDrivers ; driver++)
        {

            #if WINDOWS
                    asioDriverInfo.pahsc_driverInfo.asioVersion = 2; // FIXME - is this right? PLB
                    asioDriverInfo.pahsc_driverInfo.sysRef = GetDesktopWindow(); // FIXME - is this right? PLB
            #endif
            
            DBUG(("---------------------------------------\n"));
            
            DBUG(("PaASIO_QueryDeviceInfo: Driver name = %s\n", names[driver]));
  
            /* If the driver can be loaded : */
            if ( !Pa_ASIO_loadAsioDriver(names[driver]) ){
                     DBUG(("PaASIO_QueryDeviceInfo could not loadAsioDriver %s\n", names[driver]));
            } else {
            
                    DBUG(("PaASIO_QueryDeviceInfo: loadAsioDriver OK\n"));
                    
                    if((asioError = ASIOInit(&asioDriverInfo.pahsc_driverInfo)) != ASE_OK){
                    
                         DBUG(("PaASIO_QueryDeviceInfo: ASIOInit returned %d for %s\n", asioError, names[driver]));
                         
                    }else {
                    
                    	 DBUG(("PaASIO_QueryDeviceInfo: ASIOInit OK \n"));
                    	 
                    	 if(ASIOGetChannels(&InputChannels, &OutputChannels) != ASE_OK){
                    	 
                            DBUG(("PaASIO_QueryDeviceInfo could not ASIOGetChannels for %s\n", names[driver]));
                            
                         }else {
                            
                            DBUG(("PaASIO_QueryDeviceInfo: ASIOGetChannels OK \n"));
                                
                            /* Gets the name */
                            dev = &(ipad[sNumDevices].pad_Info);
                            dev->name = names[driver];
                            names[driver] = 0;
                            
                            /* Gets Input and Output channels number */
                            dev->maxInputChannels = InputChannels;
                            dev->maxOutputChannels = OutputChannels;
                            
                            DBUG(("PaASIO_QueryDeviceInfo: InputChannels = %d\n", InputChannels ));
                            DBUG(("PaASIO_QueryDeviceInfo: OutputChannels = %d\n", OutputChannels ));
                            
                            /* Make room in case device supports all rates. */
                            sampleRates = (double*)PaHost_AllocateFastMemory(MAX_NUMSAMPLINGRATES * sizeof(double));
                            /* check memory */
                            if (!sampleRates) {
                                ASIOExit();
                                return paInsufficientMemory;
                            }

⌨️ 快捷键说明

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