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

📄 pa_asio.cpp

📁 ppciaxclient softphone
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                            dev->sampleRates = sampleRates;
                            dev->numSampleRates = 0;
                            
                            /* Loop through the possible sampling rates and check each to see if the device supports it. */
                            for (int index = 0; index < MAX_NUMSAMPLINGRATES; index++) {
                                    if (ASIOCanSampleRate(possibleSampleRates[index]) != ASE_NoClock) {
                                            DBUG(("PaASIO_QueryDeviceInfo: possible sample rate = %d\n", (long)possibleSampleRates[index]));
                                            dev->numSampleRates += 1;
                                            *sampleRates = possibleSampleRates[index];
                                            sampleRates++;
                                    }
                            }
                            
                            /* We assume that all channels have the same SampleType, so check the first */
                            channelInfos.channel = 0;
                            channelInfos.isInput = 1;
                           
                            if ((asioError = ASIOGetChannelInfo(&channelInfos)) == ASE_NotPresent) {
                            	DBUG(("PaASIO_QueryDeviceInfo: ASIOGetChannelInfo returned %d \n",asioError)); 
                            }
                            
                            dev->nativeSampleFormats = Pa_ASIO_Convert_SampleFormat(channelInfos.type);
                            
                            /* unload the driver */
                            if ((asioError = ASIOExit()) != ASE_OK) {
                            	DBUG(("PaASIO_QueryDeviceInfo: ASIOExit returned %d \n",asioError)); 
                            }
                            
                            sNumDevices++;
                        }
		                   
                    }
               }
        }
                    
        /* free only unused names */
        for (i = 0 ; i < PA_MAX_DEVICE_INFO ; i++) if (names[i]) PaHost_FreeFastMemory(names[i],32);
        
        return paNoError;
}

//----------------------------------------------------------------------------------
// TAKEN FROM THE ASIO SDK: 
void sampleRateChanged(ASIOSampleRate sRate)
{
        // do whatever you need to do if the sample rate changed
        // usually this only happens during external sync.
        // Audio processing is not stopped by the driver, actual sample rate
        // might not have even changed, maybe only the sample rate status of an
        // AES/EBU or S/PDIF digital input at the audio device.
        // You might have to update time/sample related conversion routines, etc.
}

//----------------------------------------------------------------------------------
// TAKEN FROM THE ASIO SDK: 
long asioMessages(long selector, long value, void* message, double* opt)
{
        // currently the parameters "value", "message" and "opt" are not used.
        long ret = 0;
        switch(selector)
        {
                case kAsioSelectorSupported:
                        if(value == kAsioResetRequest
                        || value == kAsioEngineVersion
                        || value == kAsioResyncRequest
                        || value == kAsioLatenciesChanged
                        // the following three were added for ASIO 2.0, you don't necessarily have to support them
                        || value == kAsioSupportsTimeInfo
                        || value == kAsioSupportsTimeCode
                        || value == kAsioSupportsInputMonitor)
                                ret = 1L;
                        break;
                        
                case kAsioBufferSizeChange:
                        //printf("kAsioBufferSizeChange \n");
                        break;
                        
                case kAsioResetRequest:
                        // defer the task and perform the reset of the driver during the next "safe" situation
                        // You cannot reset the driver right now, as this code is called from the driver.
                        // Reset the driver is done by completely destruct is. I.e. ASIOStop(), ASIODisposeBuffers(), Destruction
                        // Afterwards you initialize the driver again.
                        asioDriverInfo.stopped;  // In this sample the processing will just stop
                        ret = 1L;
                        break;
                case kAsioResyncRequest:
                        // This informs the application, that the driver encountered some non fatal data loss.
                        // It is used for synchronization purposes of different media.
                        // Added mainly to work around the Win16Mutex problems in Windows 95/98 with the
                        // Windows Multimedia system, which could loose data because the Mutex was hold too long
                        // by another thread.
                        // However a driver can issue it in other situations, too.
                        ret = 1L;
                        break;
                case kAsioLatenciesChanged:
                        // This will inform the host application that the drivers were latencies changed.
                        // Beware, it this does not mean that the buffer sizes have changed!
                        // You might need to update internal delay data.
                        ret = 1L;
                        //printf("kAsioLatenciesChanged \n");
                        break;
                case kAsioEngineVersion:
                        // return the supported ASIO version of the host application
                        // If a host applications does not implement this selector, ASIO 1.0 is assumed
                        // by the driver
                        ret = 2L;
                        break;
                case kAsioSupportsTimeInfo:
                        // informs the driver wether the asioCallbacks.bufferSwitchTimeInfo() callback
                        // is supported.
                        // For compatibility with ASIO 1.0 drivers the host application should always support
                        // the "old" bufferSwitch method, too.
                        ret = 1;
                        break;
                case kAsioSupportsTimeCode:
                        // informs the driver wether application is interested in time code info.
                        // If an application does not need to know about time code, the driver has less work
                        // to do.
                        ret = 0;
                        break;
        }
        return ret;
}


//----------------------------------------------------------------------------------
// conversion from 64 bit ASIOSample/ASIOTimeStamp to double float
#if NATIVE_INT64
        #define ASIO64toDouble(a)  (a)
#else
        const double twoRaisedTo32 = 4294967296.;
        #define ASIO64toDouble(a)  ((a).lo + (a).hi * twoRaisedTo32)
#endif


static ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow)
{       
        // the actual processing callback.
        // Beware that this is normally in a seperate thread, hence be sure that you take care
        // about thread synchronization. This is omitted here for simplicity.
        
        // store the timeInfo for later use
        asioDriverInfo.tInfo = *timeInfo;

        // get the time stamp of the buffer, not necessary if no
        // synchronization to other media is required
        
        if (timeInfo->timeInfo.flags & kSystemTimeValid)
                asioDriverInfo.nanoSeconds = ASIO64toDouble(timeInfo->timeInfo.systemTime);
        else
                asioDriverInfo.nanoSeconds = 0;

        if (timeInfo->timeInfo.flags & kSamplePositionValid)
                asioDriverInfo.samples = ASIO64toDouble(timeInfo->timeInfo.samplePosition);
        else
                asioDriverInfo.samples = 0;

        if (timeInfo->timeCode.flags & kTcValid)
                asioDriverInfo.tcSamples = ASIO64toDouble(timeInfo->timeCode.timeCodeSamples);
        else
                asioDriverInfo.tcSamples = 0;

        // get the system reference time
        asioDriverInfo.sysRefTime = get_sys_reference_time();

#if 0
        // a few debug messages for the Windows device driver developer
        // tells you the time when driver got its interrupt and the delay until the app receives
        // the event notification.
        static double last_samples = 0;
        char tmp[128];
        sprintf (tmp, "diff: %d / %d ms / %d ms / %d samples                 \n", asioDriverInfo.sysRefTime - (long)(asioDriverInfo.nanoSeconds / 1000000.0), asioDriverInfo.sysRefTime, (long)(asioDriverInfo.nanoSeconds / 1000000.0), (long)(asioDriverInfo.samples - last_samples));
        OutputDebugString (tmp);
        last_samples = asioDriverInfo.samples;
#endif

        // To avoid the callback accessing a desallocated stream
        if (asioDriverInfo.past == NULL) return 0L;
        
        // Keep sample position
	    asioDriverInfo.pahsc_NumFramesDone = timeInfo->timeInfo.samplePosition.lo;
        
        // Reentrancy control
        if( ++asioDriverInfo.reenterCount) {
        	asioDriverInfo.reenterError++;
        	DBUG(("bufferSwitchTimeInfo : reentrancy detection = %d\n", asioDriverInfo.reenterError));
       		return 0L;
        }
		
		do {

           	/*  Has a user callback returned '1' to indicate finished at the last ASIO callback? */
	        if( asioDriverInfo.past->past_StopSoon ) {
	        
	                Pa_ASIO_Clear_Output(asioDriverInfo.bufferInfos, 
	                        asioDriverInfo.pahsc_channelInfos[0].type,
	                        asioDriverInfo.pahsc_NumInputChannels ,
	                        asioDriverInfo.pahsc_NumOutputChannels,
	                        index, 
	                        0, 
	                        asioDriverInfo.past_FramesPerHostBuffer);
	                
	                asioDriverInfo.past->past_IsActive = 0; 
	                
	                // Finally if the driver supports the ASIOOutputReady() optimization, do it here, all data are in place
	                if (asioDriverInfo.pahsc_postOutput) ASIOOutputReady();
	       
	        }else {
	                
	                /* CPU usage */
	                Pa_StartUsageCalculation(asioDriverInfo.past);
	                
	                Pa_ASIO_Callback_Input(index);
	                         
	                // Finally if the driver supports the ASIOOutputReady() optimization, do it here, all data are in place
	                if (asioDriverInfo.pahsc_postOutput) ASIOOutputReady();
	                
	                Pa_ASIO_Callback_End();
	                        
	                /* CPU usage */
	                Pa_EndUsageCalculation(asioDriverInfo.past);
	        }
        
       	} while(asioDriverInfo.reenterCount--);
        
        return 0L;
}


//----------------------------------------------------------------------------------
void bufferSwitch(long index, ASIOBool processNow)
{       
        // the actual processing callback.
        // Beware that this is normally in a seperate thread, hence be sure that you take care
        // about thread synchronization. This is omitted here for simplicity.

        // as this is a "back door" into the bufferSwitchTimeInfo a timeInfo needs to be created
        // though it will only set the timeInfo.samplePosition and timeInfo.systemTime fields and the according flags
        
        ASIOTime  timeInfo;
        memset (&timeInfo, 0, sizeof (timeInfo));

        // get the time stamp of the buffer, not necessary if no
        // synchronization to other media is required
        if(ASIOGetSamplePosition(&timeInfo.timeInfo.samplePosition, &timeInfo.timeInfo.systemTime) == ASE_OK)
                timeInfo.timeInfo.flags = kSystemTimeValid | kSamplePositionValid;
                
        // Call the real callback
        bufferSwitchTimeInfo (&timeInfo, index, processNow);
}

//----------------------------------------------------------------------------------
unsigned long get_sys_reference_time()
{       
        // get the system reference time
        #if WINDOWS
                return timeGetTime();
	     #elif MAC
                static const double twoRaisedTo32 = 4294967296.;
                UnsignedWide ys;
                Microseconds(&ys);
                double r = ((double)ys.hi * twoRaisedTo32 + (double)ys.lo);
                return (unsigned long)(r / 1000.);
        #endif
}


/*************************************************************
** Calculate 2 LSB dither signal with a triangular distribution.
** Ranged properly for adding to a 32 bit integer prior to >>15.
*/
#define DITHER_BITS   (15)
#define DITHER_SCALE  (1.0f / ((1<<DITHER_BITS)-1))

⌨️ 快捷键说明

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