📄 pa_dsound.c
字号:
{ int i; ERR_RPT(("Creation of requested Audio Capture device '%s' failed.\n", ((pad->pad_lpGUID == NULL) ? "Default" : pad->pad_Info.name) )); for( i=0; i<Pa_CountDevices(); i++ ) { pad = Pa_GetInternalDevice( i ); if( pad->pad_Info.maxInputChannels >= past->past_NumInputChannels ) { PRINT(("Try device '%s' instead.\n", pad->pad_Info.name )); hr = DirectSoundCaptureCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSoundCapture, NULL ); if( hr == DS_OK ) break; } } } if( hr != DS_OK ) { ERR_RPT(("PortAudio: DirectSoundCaptureCreate() failed!\n")); result = paHostError; sPaHostError = hr; goto error; } hr = DSW_InitInputBuffer( dsw, (unsigned long) (past->past_SampleRate + 0.5), past->past_NumInputChannels, numBytes ); DBUG(("DSW_InitInputBuffer() returns %x\n", hr)); if( hr != DS_OK ) { ERR_RPT(("PortAudio: DSW_InitInputBuffer() returns %x\n", hr)); result = paHostError; sPaHostError = hr; goto error; } }#endif /* SUPPORT_AUDIO_CAPTURE */ /* Calculate scalar used in CPULoad calculation. */ { LARGE_INTEGER frequency; if( QueryPerformanceFrequency( &frequency ) == 0 ) { pahsc->pahsc_InverseTicksPerUserBuffer = 0.0; } else { pahsc->pahsc_InverseTicksPerUserBuffer = past->past_SampleRate / ( (double)frequency.QuadPart * past->past_FramesPerUserBuffer ); DBUG(("pahsc_InverseTicksPerUserBuffer = %g\n", pahsc->pahsc_InverseTicksPerUserBuffer )); } } return result;error: PaHost_CloseStream( past ); return result;}/*************************************************************************/PaError PaHost_StartOutput( internalPortAudioStream *past ){ HRESULT hr; PaHostSoundControl *pahsc; PaError result = paNoError; pahsc = (PaHostSoundControl *) past->past_DeviceData; /* Give user callback a chance to pre-fill buffer. */ result = Pa_TimeSlice( past ); if( result != paNoError ) return result; // FIXME - what if finished? hr = DSW_StartOutput( &pahsc->pahsc_DSoundWrapper ); DBUG(("PaHost_StartOutput: DSW_StartOutput returned = 0x%X.\n", hr)); if( hr != DS_OK ) { result = paHostError; sPaHostError = hr; goto error; }error: return result;}/*************************************************************************/PaError PaHost_StartInput( internalPortAudioStream *past ){ PaError result = paNoError;#if SUPPORT_AUDIO_CAPTURE HRESULT hr; PaHostSoundControl *pahsc; pahsc = (PaHostSoundControl *) past->past_DeviceData; hr = DSW_StartInput( &pahsc->pahsc_DSoundWrapper ); DBUG(("Pa_StartStream: DSW_StartInput returned = 0x%X.\n", hr)); if( hr != DS_OK ) { result = paHostError; sPaHostError = hr; goto error; }error:#endif /* SUPPORT_AUDIO_CAPTURE */ return result;}/*************************************************************************/PaError PaHost_StartEngine( internalPortAudioStream *past ){ PaHostSoundControl *pahsc; PaError result = paNoError; pahsc = (PaHostSoundControl *) past->past_DeviceData; past->past_StopNow = 0; past->past_StopSoon = 0; past->past_IsActive = 1; /* Create timer that will wake us up so we can fill the DSound buffer. */ { int msecPerBuffer; int resolution; int bufsPerInterrupt; DBUG(("PaHost_StartEngine: past_NumUserBuffers = %d\n", past->past_NumUserBuffers)); /* Decide how often to wake up and fill the buffers. */ if( past->past_NumUserBuffers == 2 ) { /* Generate two timer interrupts per user buffer. */ msecPerBuffer = (500 * past->past_FramesPerUserBuffer) / (int) past->past_SampleRate; } else { if ( past->past_NumUserBuffers >= 16 ) bufsPerInterrupt = past->past_NumUserBuffers/8; else if ( past->past_NumUserBuffers >= 8 ) bufsPerInterrupt = 2; else bufsPerInterrupt = 1; msecPerBuffer = 1000 * (bufsPerInterrupt * past->past_FramesPerUserBuffer) / (int) past->past_SampleRate; DBUG(("PaHost_StartEngine: bufsPerInterrupt = %d\n", bufsPerInterrupt)); } DBUG(("PaHost_StartEngine: msecPerBuffer = %d\n", msecPerBuffer)); if( msecPerBuffer < 10 ) msecPerBuffer = 10; else if( msecPerBuffer > 100 ) msecPerBuffer = 100; DBUG(("PaHost_StartEngine: clipped msecPerBuffer = %d\n", msecPerBuffer)); resolution = msecPerBuffer/4; pahsc->pahsc_TimerID = timeSetEvent( msecPerBuffer, resolution, (LPTIMECALLBACK) Pa_TimerCallback, (DWORD) past, TIME_PERIODIC ); } if( pahsc->pahsc_TimerID == 0 ) { past->past_IsActive = 0; result = paHostError; sPaHostError = 0; goto error; }error: return result;}/*************************************************************************/PaError PaHost_StopEngine( internalPortAudioStream *past, int abort ){ int timeoutMsec; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; if( abort ) past->past_StopNow = 1; past->past_StopSoon = 1; /* Set timeout at 20% beyond maximum time we might wait. */ timeoutMsec = (int) (1200.0 * pahsc->pahsc_FramesPerDSBuffer / past->past_SampleRate); while( past->past_IsActive && (timeoutMsec > 0) ) { Sleep(10); timeoutMsec -= 10; } if( pahsc->pahsc_TimerID != 0 ) { timeKillEvent(pahsc->pahsc_TimerID); /* Stop callback timer. */ pahsc->pahsc_TimerID = 0; } return paNoError;}/*************************************************************************/PaError PaHost_StopInput( internalPortAudioStream *past, int abort ){#if SUPPORT_AUDIO_CAPTURE HRESULT hr; PaHostSoundControl *pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; (void) abort; hr = DSW_StopInput( &pahsc->pahsc_DSoundWrapper ); DBUG(("DSW_StopInput() result is %x\n", hr));#endif /* SUPPORT_AUDIO_CAPTURE */ return paNoError;}/*************************************************************************/PaError PaHost_StopOutput( internalPortAudioStream *past, int abort ){ HRESULT hr; PaHostSoundControl *pahsc; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; (void) abort; hr = DSW_StopOutput( &pahsc->pahsc_DSoundWrapper ); DBUG(("DSW_StopOutput() result is %x\n", hr)); return paNoError;}/*******************************************************************/PaError PaHost_CloseStream( internalPortAudioStream *past ){ PaHostSoundControl *pahsc; if( past == NULL ) return paBadStreamPtr; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paNoError; DSW_Term( &pahsc->pahsc_DSoundWrapper ); if( pahsc->pahsc_NativeBuffer ) { PaHost_FreeFastMemory( pahsc->pahsc_NativeBuffer, pahsc->pahsc_BytesPerBuffer ); /* MEM */ pahsc->pahsc_NativeBuffer = NULL; } PaHost_FreeFastMemory( pahsc, sizeof(PaHostSoundControl) ); /* MEM */ past->past_DeviceData = NULL; return paNoError;}/* Set minimal latency based on whether NT or Win95. * NT has higher latency. */static int PaHost_GetMinSystemLatency( void ){ int minLatencyMsec; /* Set minimal latency based on whether NT or other OS. * NT has higher latency. */ OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof( osvi ); GetVersionEx( &osvi ); DBUG(("PA - PlatformId = 0x%x\n", osvi.dwPlatformId )); DBUG(("PA - MajorVersion = 0x%x\n", osvi.dwMajorVersion )); DBUG(("PA - MinorVersion = 0x%x\n", osvi.dwMinorVersion )); /* Check for NT */ if( (osvi.dwMajorVersion == 4) && (osvi.dwPlatformId == 2) ) { minLatencyMsec = PA_WIN_NT_LATENCY; } else if(osvi.dwMajorVersion >= 5) { minLatencyMsec = PA_WIN_WDM_LATENCY; } else { minLatencyMsec = PA_WIN_9X_LATENCY; } return minLatencyMsec;}/*************************************************************************** Determine minimum number of buffers required for this host based** on minimum latency. Latency can be optionally set by user by setting** an environment variable. For example, to set latency to 200 msec, put:**** set PA_MIN_LATENCY_MSEC=200**** in the AUTOEXEC.BAT file and reboot.** If the environment variable is not set, then the latency will be determined** based on the OS. Windows NT has higher latency than Win95.*/#define PA_LATENCY_ENV_NAME ("PA_MIN_LATENCY_MSEC")int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate ){ char envbuf[PA_ENV_BUF_SIZE]; DWORD hresult; int minLatencyMsec = 0; double msecPerBuffer = (1000.0 * framesPerBuffer) / sampleRate; int minBuffers; /* Let user determine minimal latency by setting environment variable. */ hresult = GetEnvironmentVariable( PA_LATENCY_ENV_NAME, envbuf, PA_ENV_BUF_SIZE ); if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE) ) { minLatencyMsec = atoi( envbuf ); } else { minLatencyMsec = PaHost_GetMinSystemLatency();#if PA_USE_HIGH_LATENCY PRINT(("PA - Minimum Latency set to %d msec!\n", minLatencyMsec ));#endif } minBuffers = (int) (1.0 + ((double)minLatencyMsec / msecPerBuffer)); if( minBuffers < 2 ) minBuffers = 2; return minBuffers;}/*************************************************************************/PaError PaHost_Term( void ){ int i; /* Free names allocated during enumeration. */ for( i=0; i<sNumDevices; i++ ) { if( sDevices[i].pad_Info.name != NULL ) { free( (void *) sDevices[i].pad_Info.name ); sDevices[i].pad_Info.name = NULL; } } if( sDevices != NULL ) { PaHost_FreeFastMemory( sDevices, sNumDevices * sizeof(internalPortAudioDevice) ); /* MEM */ sDevices = NULL; sNumDevices = 0; } return 0;}void Pa_Sleep( long msec ){ Sleep( msec );}/************************************************************************* * Allocate memory that can be accessed in real-time. * This may need to be held in physical memory so that it is not * paged to virtual memory. * This call MUST be balanced with a call to PaHost_FreeFastMemory(). * Memory will be set to zero. */void *PaHost_AllocateFastMemory( long numBytes ){ void *addr = GlobalAlloc( GPTR, numBytes ); /* FIXME - do we need physical memory? Use VirtualLock() */ /* MEM */ return addr;}/************************************************************************* * Free memory that could be accessed in real-time. * This call MUST be balanced with a call to PaHost_AllocateFastMemory(). */void PaHost_FreeFastMemory( void *addr, long numBytes ){ if( addr != NULL ) GlobalFree( addr ); /* MEM */}/***********************************************************************/PaError PaHost_StreamActive( internalPortAudioStream *past ){ PaHostSoundControl *pahsc; if( past == NULL ) return paBadStreamPtr; pahsc = (PaHostSoundControl *) past->past_DeviceData; if( pahsc == NULL ) return paInternalError; return (PaError) (past->past_IsActive);}/*************************************************************************/PaTimestamp Pa_StreamTime( PortAudioStream *stream ){ DSoundWrapper *dsw; internalPortAudioStream *past = (internalPortAudioStream *) stream; PaHostSoundControl *pahsc; if( past == NULL ) return paBadStreamPtr; pahsc = (PaHostSoundControl *) past->past_DeviceData; dsw = &pahsc->pahsc_DSoundWrapper; return dsw->dsw_FramesPlayed;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -