📄 wavepdd.c
字号:
//------------------------------------------------------------------------------------------------------------
// Function: private_WaveInStop
//
// Purpose: stop recording immediately
//-------------------------------------------------------------------------------------------------------------
VOID
private_WaveInStop(
PWAVEHDR pwh
)
{
FUNC_WPDD("+PDD_WaveInStop");
v_fMoreData[WAPI_IN] = FALSE;
StopDmac(gInputSrc);
AudioInMute(TRUE);
FUNC_WPDD("-PDD_WaveInStop");
}
//------------------------------------------------------------------------------------------------------------
// Function: PowerDownUnit
//
// Purpose: power up or power down a dac, adc, or other devices
//-------------------------------------------------------------------------------------------------------------
void PowerDownUnit(unsigned short int Unit,BOOL ShutDown)
{
//TODO Do we need to wait some time before powering on or off the unit?
unsigned short int PowerDownCtrlStat=0;
if( !ShadowReadAC97( POWERDOWN_CTRL_STAT, &PowerDownCtrlStat, DEV_AUDIO) ) // Enable Variable Rate Audio
DEBUGMSG(ZONE_ERROR, (TEXT( "-- read of PwrDnCtrl failed \r\n") ) );
if (ShutDown)
PowerDownCtrlStat |= Unit;
else
PowerDownCtrlStat &= ~Unit;
if( !ShadowWriteAC97( POWERDOWN_CTRL_STAT, PowerDownCtrlStat , DEV_AUDIO) ) // Enable Variable Rate Audio
DEBUGMSG(ZONE_ERROR, (TEXT( "-- Bad VRA Value \r\n") ) );
}
//------------------------------------------------------------------------------------------------------------
// Function: private_WaveStandby
//
// Purpose: instruct the audio PDD to put the audio circuitry in standby mode.
// According to the documentation this function "This message should turn off as much of the audio circuit
// as possible. When this message is called again, the audio circuitry should be turned on as quickly as
// possibly [sic]. This message is sent between playback of sounds to minimize audio circuit power drain.
//-------------------------------------------------------------------------------------------------------------
VOID
private_WaveStandby(
WAPI_INOUT apidir
)
{
static BOOL PowerDownIn=TRUE;
static BOOL PowerDownOut=TRUE;
//TODO: this function doesn't seem to get called under PB 3.0
switch(apidir)
{
case WAPI_IN:
DEBUGMSG(ZONE_TEST,(TEXT("wavestandby PowerDownIn: %x WAPI_INOUT: %x\r\n"),PowerDownIn,apidir));
PowerDownUnit(PWR_PR0_ADC,PowerDownIn); //turn
PowerDownIn=!PowerDownIn;
break;
case WAPI_OUT:
DEBUGMSG(ZONE_TEST,(TEXT("wavestandby PowerDownOut: %x WAPI_INOUT: %x\r\n"),PowerDownOut,apidir));
PowerDownUnit(PWR_PR1_DAC,PowerDownOut); //turn
PowerDownOut=!PowerDownOut;
break;
default:
DEBUGMSG(ZONE_TEST,(TEXT("bad param in wavestandby\r\n")));
DEBUGCHK(FALSE);
}
}
//------------------------------------------------------------------------------------------------------------
// Function: private_WaveGetDevCaps
//
// Purpose: return the capabilities of the audio hardware
//-------------------------------------------------------------------------------------------------------------
MMRESULT
private_WaveGetDevCaps(
WAPI_INOUT apidir,
PVOID pCaps,
UINT wSize
)
{
PWAVEINCAPS pwic = pCaps;
PWAVEOUTCAPS pwoc = pCaps;
MMRESULT mmRet = MMSYSERR_NOERROR;
FUNC_WPDD("+PDD_WaveGetDevCaps");
if (pCaps == NULL) {
//
// If pCaps == NULL, we are requesting if the driver PDD is capable of
// this mode at all. In other words, if APIDIR == WAPI_IN, we return
// no error if input is supported, and MMSYSERR_NOTSUPPORTED otherwise.
// Since UCB1400 has both, we return MMSYSERR_NOERROR regardless.
//
if( WAPI_IN == apidir)
return( MMSYSERR_NOERROR );
else // ( WAPI_OUT == apidir)
return( MMSYSERR_NOERROR );
}
//
// Fill in the DevCaps here.
//
if (apidir == WAPI_OUT)
{
DEBUGMSG(ZONE_VERBOSE, (TEXT("API_OUT\r\n" )) );
pwoc->wMid = MM_MICROSOFT; //TODO: this says microsoft wrote this driver, change to intel
pwoc->wPid = (apidir == WAPI_OUT ? 24 : 23); // generic in or out...
pwoc->vDriverVersion = 0x0001;
wsprintf (pwoc->szPname, TEXT("AC '97 Stereo (%hs)"), __DATE__);
pwoc->dwFormats = WAVE_FORMAT_1M08 |
WAVE_FORMAT_1M16 |
WAVE_FORMAT_1S08 |
WAVE_FORMAT_1S16 |
WAVE_FORMAT_2M08 |
WAVE_FORMAT_2M16 |
WAVE_FORMAT_2S08 |
WAVE_FORMAT_2S16 |
WAVE_FORMAT_4M08 |
WAVE_FORMAT_4M16 |
WAVE_FORMAT_4S08 |
WAVE_FORMAT_4S16;
pwoc->wChannels = 2;
//pwoc->dwSupport = WAVECAPS_VOLUME | WAVECAPS_SYNC ;
}
else
{
DEBUGMSG(ZONE_VERBOSE, (TEXT("API_IN\r\n" )) );
pwic->wMid = MM_MICROSOFT; //TODO: this says microsoft wrote this driver, change to intel
pwic->wPid = (apidir == WAPI_OUT ? 24 : 23); // generic in or out...
pwic->vDriverVersion = 0x0001;
wsprintf (pwoc->szPname, TEXT("AC '97 Stereo (%hs)"), __DATE__);
pwic->dwFormats = WAVE_FORMAT_1M08 |
WAVE_FORMAT_1M16 |
WAVE_FORMAT_1S08 |
WAVE_FORMAT_1S16 |
WAVE_FORMAT_2M08 |
WAVE_FORMAT_2M16 |
WAVE_FORMAT_2S08 |
WAVE_FORMAT_2S16 |
WAVE_FORMAT_4M08 |
WAVE_FORMAT_4M16 |
WAVE_FORMAT_4S08 |
WAVE_FORMAT_4S16;
pwic->wChannels = 2;
//pwic->dwSupport = WAVECAPS_VOLUME | WAVECAPS_SYNC ;
}
FUNC_WPDD("-PDD_WaveGetDevCaps");;
return(mmRet);
}
//------------------------------------------------------------------------------------------------------------
// Function: private_WaveOpen
//
// Purpose: prepare to either send or receive audio data (based on WAPI_INOUT direction flag)
//-------------------------------------------------------------------------------------------------------------
MMRESULT
private_WaveOpen(
WAPI_INOUT apidir,
LPWAVEFORMATEX lpFormat,
BOOL fQueryFormatOnly
)
{
MMRESULT mmRet = MMSYSERR_NOERROR;
FUNC_VERBOSE("+PDD_WaveOpen");
switch (CodecType)
{
case UCB14002A:
if ((lpFormat->wFormatTag != WAVE_FORMAT_PCM) ||
( lpFormat->nChannels != 1 &&
lpFormat->nChannels != 2) ||
( lpFormat->nSamplesPerSec != KHZ08_000 &&
lpFormat->nSamplesPerSec != KHZ11_025 &&
lpFormat->nSamplesPerSec != KHZ12_000 &&
lpFormat->nSamplesPerSec != KHZ22_050 &&
lpFormat->nSamplesPerSec != KHZ24_000 &&
lpFormat->nSamplesPerSec != KHZ32_000 &&
lpFormat->nSamplesPerSec != KHZ44_100 &&
lpFormat->nSamplesPerSec != KHZ48_000
) ||
( lpFormat->wBitsPerSample != 16 &&
lpFormat->wBitsPerSample != 8))
{
DEBUGMSG(ZONE_ERROR, (TEXT( "return bad format\r\n" )) );
return WAVERR_BADFORMAT;
}
break;
case UCB14001B:
default:
if ((lpFormat->wFormatTag != WAVE_FORMAT_PCM) ||
( lpFormat->nChannels != 1 &&
lpFormat->nChannels != 2) ||
( lpFormat->nSamplesPerSec != KHZ08_000 &&
lpFormat->nSamplesPerSec != KHZ11_025 &&
lpFormat->nSamplesPerSec != KHZ16_000 &&
lpFormat->nSamplesPerSec != KHZ22_050 &&
lpFormat->nSamplesPerSec != KHZ32_000 &&
lpFormat->nSamplesPerSec != KHZ44_100 &&
lpFormat->nSamplesPerSec != KHZ48_000
) ||
( lpFormat->wBitsPerSample != 16 &&
lpFormat->wBitsPerSample != 8))
{
DEBUGMSG(ZONE_ERROR, (TEXT( "return bad format\r\n " )) );
return WAVERR_BADFORMAT;
}
} // end switch
//if they only want a query format, then we can return success.
if (fQueryFormatOnly) {
DEBUGMSG( ZONE_VERBOSE, (TEXT( "Format Query\r\n " )) );
return MMSYSERR_NOERROR;
}
if (g_fInUse[apidir]) {
DEBUGMSG(ZONE_ERROR, (TEXT("\r\n")));
return MMSYSERR_ALLOCATED;
}
if (apidir < NUM_API_DIRS) g_fInUse[apidir] = TRUE;
//ENABLE VRA
if( !ShadowWriteAC97( EXTENDED_AUDIO_CTRL, VRA_ENABLED_MASK , DEV_AUDIO) ) // Enable Variable Rate Audio
DEBUGMSG(ZONE_ERROR, (TEXT( "-- Bad VRA Value \r\n") ) );
//set the sample rate
if (AC97SetSampleRate((unsigned short int)lpFormat->nSamplesPerSec,apidir) == FALSE)
{
DEBUGMSG( 1, (TEXT( "return bad sample rate:\r\n " )) );
return MMSYSERR_NOTSUPPORTED;
}
if (apidir < NUM_API_DIRS) g_sample_size[apidir] = lpFormat->nBlockAlign;
if (apidir == WAPI_OUT) {
if (lpFormat->wBitsPerSample == 8) {
if (lpFormat->nChannels == 1) {
g_pfnFillBuffer = FillBufferM08;
}
else {
g_pfnFillBuffer = FillBufferS08;
}
}
else {
if (lpFormat->nChannels == 1) {
g_pfnFillBuffer = FillBufferM16;
}
else {
g_pfnFillBuffer = FillBufferS16;
}
}
}
else {
if (lpFormat->wBitsPerSample == 8) {
if (lpFormat->nChannels == 1) {
g_pfnGetBuffer = GetBufferM08;
}
else {
g_pfnGetBuffer = GetBufferS08;
}
}
else {
if (lpFormat->nChannels == 1) {
g_pfnGetBuffer = GetBufferM16;
}
else {
g_pfnGetBuffer = GetBufferS16;
}
}
// Support Low-latency Capture
// Adjust the effective DMA buffer size, based on the requested sample rate.
// The idea is that we want our DMA capture buffers to represent a fixed amount of time,
// regardless of the sample rate.
// This means that if the application buffers are small (as is the case with VoIP or DirectSoundCapture)
// then we still can return the buffer very soon after we have enough captured data to fill it.
// The way this used to work (fixed-size capture buffers) meant that at low sample rates
// we would wait for hundreds of milliseconds, then turn around and discover that the application
// had only given us 80 milliseconds of wave headers, so we would be forced to drop samples on the floor.
g_capture_buffer_size = sizeof(DWORD) * g_capture_latency * lpFormat->nSamplesPerSec / 1000;
if (g_capture_buffer_size > g_dma_buffer_size) {
g_capture_buffer_size = g_dma_buffer_size;
}
v_pAudioRcvA_Virtual->dcmd = (v_pAudioRcvA_Virtual->dcmd & ~0x1fff) | g_capture_buffer_size;
v_pAudioRcvB_Virtual->dcmd = (v_pAudioRcvB_Virtual->dcmd & ~0x1fff) | g_capture_buffer_size;
}
ResetAC97Controller(); // this flushes the fifos and freezes AC-Link - workaround for B-Stepping problem.
FUNC_VERBOSE("-PDD_WaveOpen");
return MMSYSERR_NOERROR;
}
//------------------------------------------------------------------------------------------------------------
// Function: PDD_WaveProc
//
// Purpose: process WPDM_xxx messages from the MDD. This is the main message handler for the PDD.
//-------------------------------------------------------------------------------------------------------------
MMRESULT
PDD_WaveProc(
WAPI_INOUT apidir,
DWORD dwCode,
DWORD dwParam1,
DWORD dwParam2
)
{
MMRESULT mmRet = MMSYSERR_NOERROR;
DEBUGMSG( ZONE_VERBOSE, (TEXT( "PDD_WaveProc: " )) );
switch (dwCode) {
case WPDM_CLOSE:
if (apidir == WAPI_IN && g_fInUse[apidir]) {
// if app never send WODM_RESET, the capture DMA is still running. Stop it now.
private_WaveInStop(NULL);
}
if (apidir < NUM_API_DIRS) g_fInUse[apidir] = FALSE;
DEBUGMSG( ZONE_VERBOSE, (TEXT( "....close %s\r\n" ),(apidir == WAPI_IN)?"i n ":"o u t ") );
break;
case WPDM_CONTINUE:
DEBUGMSG( ZONE_VERBOSE, (TEXT( "....continue %s\r\n" ),(apidir == WAPI_IN)?"i n ":"o u t ") );
if (apidir == WAPI_IN)
private_WaveInContinue((PWAVEHDR) dwParam1);
else
private_WaveOutContinue((PWAVEHDR) dwParam1);
break;
case WPDM_GETDEVCAPS:
DEBUGMSG( ZONE_VERBOSE, (TEXT( "....getdevcaps\r\n" )) );
mmRet = private_WaveGetDevCaps(apidir, (PVOID) dwParam1, (UINT) dwParam2);
break;
case WPDM_OPEN:
DEBUGMSG( ZONE_VERBOSE, (TEXT( "....open %s\r\n" ),(apidir == WAPI_IN)?"i n ":"o u t ") );
mmRet = private_WaveOpe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -