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

📄 wavepdd.cpp

📁 此代码为WCE5.0下声卡的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    while ( (cbSrcBytes > 0) && (pwh != NULL)) {
        if (pwh->dwBytesRecorded >= pwh->dwBufferLength) {
            pwh = pwh->lpNext;
			continue;
        }

        // trasfer max(data_in_dma, room_in_buffer)
		ULONG cbDstBytes = pwh->dwBufferLength - pwh->dwBytesRecorded;
		ULONG cbTransferSize = min(cbSrcBytes, cbDstBytes);

        memcpy(pwh->lpData + pwh->dwBytesRecorded, pSrcBuffer, cbTransferSize);

        pwh->dwBytesRecorded += cbTransferSize;
		pSrcBuffer += cbTransferSize;
		cbSrcBytes -= cbTransferSize;
    }
}




// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
private_WaveStart (
    WAPI_INOUT apidir,
    PWAVEHDR pwh
    )
{

    FUNC_WPDD("+PDD_WaveStart");

	const ULONG ulInterruptPeriod = 5; // how often should we generate interrupts?

	PWAVEFORMATEX pFormat = g_pwfx[apidir];

    ULONG ulSamplesPerInterrupt = pFormat->nSamplesPerSec * ulInterruptPeriod / 1000;

	g_dmapos[apidir] = 0;

    if ( apidir == WAPI_OUT ) {
	    // for playback, pre-fill dma buffers with first bucket of data
        private_AudioFillBuffer(pwh, g_dma_buffer[WAPI_OUT], dma_buffer_size);
    }

    pCES1371->SetDMAChannelFormat( g_dmachannel[apidir],
                                   pFormat->nChannels,
                                   (pFormat->wBitsPerSample==8)?0:1,
                                   pFormat->nSamplesPerSec );

    // Initialize the DMA position to fire interrupt

    pCES1371->SetDMAChannelBuffer( g_dmachannel[apidir], dma_buffer_size, ulSamplesPerInterrupt);

    DEBUGMSG(ZONE_VERBOSE,(TEXT("ES1371: %s @ %s%02d %dHz, %d samples/interrupt\n\r"), 
		(apidir == WAPI_IN) ? TEXT("Recording") : TEXT("Playing"),
		(pFormat->nChannels == 1) ? TEXT("M") : TEXT("S"),
		pFormat->wBitsPerSample,
		pFormat->nSamplesPerSec,
		ulSamplesPerInterrupt
		));

    pCES1371->StartDMAChannel( g_dmachannel[apidir] );

    FUNC_WPDD("-PDD_WaveStart");
}


// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
private_WaveContinue (
    WAPI_INOUT apidir,
    PWAVEHDR pwh
    )
{
    FUNC_VERBOSE("+PDD_WaveContinue");

	ULONG size1, size2;

	ULONG newpos = pCES1371->GetDMAPosition(g_dmachannel[apidir]);
	ULONG lastpos = g_dmapos[apidir];
	g_dmapos[apidir] = newpos;

	// if dma position has wrapped past the end of the buffer,
	// we'll have to perform two transfers
	// otherwise, just transfer to the new position
	// note that we treat new==last as a full wrap - we transfer the entire buffer
	if (newpos <= lastpos) {
		size1 = dma_buffer_size - lastpos;
		size2 = newpos;
	}
	else {
		size1 = newpos - lastpos;
		size2 = 0;
	}


	g_pfnDmaTransfer[apidir](pwh, g_dma_buffer[apidir] + lastpos, size1);
	if (size2 > 0) {
		g_pfnDmaTransfer[apidir](pwh, g_dma_buffer[apidir], size2);
	}



    FUNC_VERBOSE("-PDD_WaveContinue");
}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID 
private_WaveStop(
    WAPI_INOUT apidir
    )
{
    FUNC_WPDD("+private_WaveStop");

    pCES1371->StopDMAChannel( g_dmachannel[apidir] );
    
    FUNC_WPDD("-private_WaveStop");
}


// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID 
private_WaveStandby(
    WAPI_INOUT apidir
    )
{
    //
    // We are going to be idle. so power off what we can.
    //
}


// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
MMRESULT
private_WaveOpen(
    WAPI_INOUT apidir,
    LPWAVEFORMATEX lpFormat,
    BOOL fQueryFormatOnly
    )
{
    MMRESULT mmRet = MMSYSERR_NOERROR;

    FUNC_WPDD("+PDD_WaveOpen");

    //
    // Allow PCM, mono or stereo, 8 or 16 bit at 11k or 22k Hz
    //
    if ((lpFormat->wFormatTag != WAVE_FORMAT_PCM) ||
        (lpFormat->nChannels  != 1 && lpFormat->nChannels != 2) ||
        (lpFormat->nSamplesPerSec < 4000 || lpFormat->nSamplesPerSec > 48000) ||
        (lpFormat->wBitsPerSample != 16 && lpFormat->wBitsPerSample != 8) )
    {
        mmRet = WAVERR_BADFORMAT;
        goto EXIT;
    }

    //
    // Only checking if format is supported
    //
    if (fQueryFormatOnly)
    {
        goto EXIT;
    }

    //
    // The hardware can support input and output at the sametime
    // but not multiple output and inputs return MMSYSERR_ALLOCATED 
    // if the input or output is alread in use.
    //
    if (g_fInUse[apidir]) 
    {
        mmRet = MMSYSERR_ALLOCATED;
        goto EXIT;
    }

    g_fInUse[apidir] = TRUE;

    // 
    // Save format the device was opened in  
    //
	g_pwfx[apidir] = lpFormat;
    g_silence = (lpFormat->wBitsPerSample == 8) ? 0x80 : 0;

EXIT:
    FUNC_WPDD("-PDD_WaveOpen");
    return mmRet;
}    


void private_waveOutGetVolume(PULONG pvol)
{
    *pvol = g_VolumeSettings.dwMasterVolume;
}

void private_waveOutSetVolume(ULONG vol)
{
    USHORT rvol,lvol;
    UCHAR  rindex,lindex;
    USHORT nVolume;

    lindex = (UCHAR)((0xF8000000 - (vol & 0xF8000000)) >> 27);
    rindex = (UCHAR)((0x0000F800 - (vol & 0x0000F800)) >> 11);

    lvol = volumeLUT[lindex] << 8;
    rvol = volumeLUT[rindex];

    nVolume = lvol | rvol; 
    g_VolumeSettings.dwMasterVolume = vol;

    g_VolumeSettings.fMasterMute = (vol == 0);

    if (vol == 0) {
        nVolume |= 0x8000; // bit 15 means mute. Use this to get total attenuation.
    }

    // write master volume
    pCES1371->WriteCodecRegister( AC97_MASTER_VOL_STEREO, nVolume );
}


void
SetMute (UCHAR reg, BOOL muted)
{
    USHORT vol;

    vol = pCES1371->ReadCodecRegister(reg);
    if (muted) {
        vol |=  0x8000; // set mute bit
    }
    else {
        vol &= ~0x8000; // clear mute bit
    }
    pCES1371->WriteCodecRegister(reg, vol);
}

void UpdateInputSelect(void)
{
    USHORT input_select;
    ULONG volume, regval;

    switch (g_VolumeSettings.dwInputSelect) {
        case WPDMX_LINE_MIC:
            input_select = AC97_RECMUX_MIC;
            if (g_VolumeSettings.fMicMute) {
                volume = 0;
            }
            else {
                volume = g_VolumeSettings.dwMicVolume & 0xffff;
                volume = volume | (volume << 16); // incoming volume is mono, cvt. to stereo
            }
            break;
        case WPDMX_LINE_IN:
            input_select = AC97_RECMUX_LINE;
            if (g_VolumeSettings.fLineInMute) {
                volume = 0;
            }
            else {
                volume = g_VolumeSettings.dwLineInVolume;
            }
            break;
        default:
            DEBUGMSG(ZONE_ERROR, (TEXT("UpdateInputSelect: illegal setting %04x\r\n"), g_VolumeSettings.dwInputSelect));
            return;
    }
    if (volume == 0) {
        regval = 0x8000;
    }
    else {
        regval = ((volume >> 20) & 0x0F00) | ((volume >> 12) & 0x000F);
    }
    DEBUGMSG(ZONE_VOLUME, (TEXT("UpdateInputSelect: sel=%04x vol=%04x\r\n"), input_select, regval));
    pCES1371->WriteCodecRegister(AC97_RECORD_SELECT, input_select);
    pCES1371->WriteCodecRegister(AC97_RECORD_GAIN, (USHORT) regval);
}


MMRESULT    
private_SetMixerValue(DWORD dwControl, DWORD dwSetting)
{
    DWORD dwControlType = dwSetting & WPDMX_CTL_MASK;
    DWORD dwLine = dwSetting & WPDMX_LINE_MASK;

    DEBUGMSG(ZONE_VOLUME, (TEXT("private_SetMixerValue(%04x, %08x)\r\n"), dwControl, dwSetting));

    switch (dwControl) {
        // volume controls
        case WPDMX_MASTER_VOL:
            private_waveOutSetVolume(dwSetting);
            break;
        case WPDMX_LINEIN_VOL:
            g_VolumeSettings.dwLineInVolume = dwSetting;
            UpdateInputSelect();
            break;
        case WPDMX_MIC_VOL:
            g_VolumeSettings.dwMicVolume = dwSetting;
            UpdateInputSelect();
            break;

        // Mute controls
        case WPDMX_MASTER_MUTE:
            g_VolumeSettings.fMasterMute = dwSetting;
            SetMute(AC97_MASTER_VOL_STEREO, g_VolumeSettings.fMasterMute);
            break;
        case WPDMX_LINEIN_MUTE:
            g_VolumeSettings.fLineInMute = dwSetting;
            UpdateInputSelect();
            break;
        case WPDMX_MIC_MUTE:
            g_VolumeSettings.fMicMute = dwSetting;
            UpdateInputSelect();
            break;
        // The input Mux
        case WPDMX_INPUT_MUX:
            g_VolumeSettings.dwInputSelect = dwSetting;
            UpdateInputSelect();
            break;
        default:
            DEBUGMSG(ZONE_ERROR, (TEXT("private_SetMixerValue: unsupported control %d\r\n"), dwControl));
            return MMSYSERR_NOTSUPPORTED;
    }
    return MMSYSERR_NOERROR;
}

MMRESULT  
private_GetMixerValue(DWORD dwControl, PDWORD pdwSetting)
{

    switch (dwControl) {
        case WPDMX_MASTER_VOL:
            private_waveOutGetVolume(pdwSetting);
            break;
        case WPDMX_MASTER_MUTE:
            *pdwSetting = g_VolumeSettings.fMasterMute;
            break;
        case WPDMX_LINEIN_VOL:
            *pdwSetting = g_VolumeSettings.dwLineInVolume;
            break;
        case WPDMX_LINEIN_MUTE:
            *pdwSetting = g_VolumeSettings.fLineInMute;
            break;
        case WPDMX_MIC_VOL:
            *pdwSetting = g_VolumeSettings.dwMicVolume;
            break;

⌨️ 快捷键说明

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