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

📄 drvrctxt.cpp

📁 此代码为WCE5.0下声卡的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// -----------------------------------------------------------------------------
//
//      THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//      ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//      THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//      PARTICULAR PURPOSE.
//  
// -----------------------------------------------------------------------------

#include "wavdrv.h"

/////////////////////////////////////////////////////////////////////////////
//
// CDriverContext Methods
//
/////////////////////////////////////////////////////////////////////////////
CDriverContext::CDriverContext (void)
{
    MYTHIS_CONSTRUCTOR;

    m_pDevice = NULL;
    m_ulVolume = 0xFFFFFFFF; // volume start off at max.
    m_pHead = NULL;         // list of open mixer handles
    m_pMxLineState = NULL;
    m_pMxControlState = NULL;

}

CDriverContext::~CDriverContext ()
{
    MYTHIS_CHECK;

    if (m_pDevice != NULL) {
        delete m_pDevice;
    }

    if (m_pMxLineState) {
        delete [] m_pMxLineState;
    }
    if (m_pMxControlState) {
        delete [] m_pMxControlState;
    }

    MYTHIS_DESTRUCTOR;
}

BOOL     
CDriverContext::Initialize (PCTSTR pszActiveKey)
{
    MYTHIS_CHECK;

    // set up convenient access to our registry key
    CRegKey regkey(pszActiveKey);

    m_pDevice = new CES1371;
    if (m_pDevice == NULL) {
        DEBUGMSG(ZONE_ERROR, (TEXT("Unable to allocate device object\r\n")));
        return FALSE;
    }

    if (! m_pDevice->MapDevice(&regkey)) {
        DEBUGMSG (ZONE_ERROR, (TEXT("Error mapping device\r\n")));
        return FALSE;
    }

    m_ulBufferSize = 16 * 1024;
    regkey.QueryDword(TEXT("BufferSize"), m_ulBufferSize);

    if (!m_pDevice->AudioInitialize(&regkey)) {
        DEBUGMSG(ZONE_ERROR, (TEXT("CDriverContext::Initialize - failed to initialize device\r\n")));
        return FALSE;
    }

    if (! InitializeMixerState ()) {
        DEBUGMSG(ZONE_ERROR, (TEXT("CDriverContext::Initialize - failed to initialize mixer interface\r\n")));
        return FALSE;
    }

    // find out what the hardware volume is set to so GetVolume returns an honest value
    USHORT usVolume = m_pDevice->ReadCodecRegister(AC97_PCMOUT_VOL);
    if (usVolume & 0x8000) {
        m_ulVolume = 0;
    }
    else {
        // AC97_PCMOUT_VOL has two five-bit fields, one for each stereo channel, indicating -Gain in 1.5dB steps
        // 0  = zero attenuation
        // 31 = 46.5 dB attenuation
        ULONG ulLeft  = 31 - ((usVolume & 0x1F00) >> 8);
        ULONG ulRight = 31 - (usVolume & 0x001F);

        // scale up from 5 to 16 bits
        ulLeft  <<= 11;
        ulRight <<= 11;

        // put into format expected by waveOutGetVolume (right high, left low)
        m_ulVolume = (ulRight << 16) | ulLeft;

    }

    return TRUE;
}

MMRESULT 
CDriverContext::GetCaps (ULONG msg, PWAVEOUTCAPS pCaps)
{
    MYTHIS_CHECK;

    pCaps->wMid = MM_MICROSOFT;
    if (msg == WIDM_GETDEVCAPS) {
        pCaps->wPid = MM_MSFT_WSS_WAVEIN; // generic in
    }
    else {
        pCaps->wPid = MM_MSFT_WSS_WAVEOUT;  // generic out...
    }
    pCaps->vDriverVersion = DRIVER_VERSION;

    wsprintf (pCaps->szPname, DEVICE_NAME);

    pCaps->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;                        

    pCaps->wChannels = 2;
    if (msg == WODM_GETDEVCAPS) {
        // only fill out dwSupport for output caps
        // this field is not present in the input caps
        pCaps->dwSupport = 
              WAVECAPS_VOLUME 
            | WAVECAPS_LRVOLUME 
            | WAVECAPS_PLAYBACKRATE
            | WAVECAPS_SAMPLEACCURATE
            | WAVECAPS_DIRECTSOUND          // supports Windows CE DirectSound Extensions
            ;
    }

    return MMSYSERR_NOERROR;
}


MMRESULT 
CDriverContext::GetExtCaps (PWAVEOUTEXTCAPS pCaps)
{
    pCaps->dwMaxHwStreams = 2;
    pCaps->dwFreeHwStreams = m_pDevice->GetNumFreeDMAChannels(DMADIR_OUT);
    pCaps->dwMinSampleRate = 100;
    pCaps->dwMaxSampleRate = 48000;

    // mixer stream parameters:
    // The driver can specify the sample rate, buffer size and count for the mixer stream.
    // This driver declines to state a preference by setting the values to zero.
    pCaps->dwSwMixerSampleRate = 0;
    pCaps->dwSwMixerBufferSize = 0;
    pCaps->dwSwMixerBufferCount = 0;
    return MMSYSERR_NOERROR;
}


MMRESULT 
CDriverContext::OpenStream (ULONG msg, HSTREAM * ppStream, LPWAVEOPENDESC pWOD, DWORD dwFlags)
{
    MYTHIS_CHECK;
    MMRESULT mr;

    if(    pWOD->lpFormat->wFormatTag != WAVE_FORMAT_PCM 
        || (pWOD->lpFormat->nChannels != 1 && pWOD->lpFormat->nChannels != 2)
        || (pWOD->lpFormat->wBitsPerSample != 8 && pWOD->lpFormat->wBitsPerSample != 16)
        || pWOD->lpFormat->nSamplesPerSec > 48000
        || pWOD->lpFormat->nSamplesPerSec < 100
        ) {
        DEBUGMSG(ZONE_ERROR,(TEXT("CDriverContext::OpenStream - format not supported\r\n")));
        return WAVERR_BADFORMAT;
    }

    if(    (pWOD->lpFormat->nBlockAlign != (pWOD->lpFormat->wBitsPerSample * pWOD->lpFormat->nChannels) / 8)
        || (pWOD->lpFormat->nAvgBytesPerSec != pWOD->lpFormat->nBlockAlign * pWOD->lpFormat->nSamplesPerSec)
        ) {
        DEBUGMSG(ZONE_ERROR,(TEXT("CDriverContext::OpenStream - ill-formed waveformat\r\n")));
        return MMSYSERR_INVALPARAM;
    }

    if (dwFlags & WAVE_FORMAT_QUERY) {
        // if this is just a query, we're done.
        return MMSYSERR_NOERROR;
    }

    // attempt to allocate a DMA channel
    ULONG ulChannelIndex;
    mr = m_pDevice->AllocDMAChannel( (msg==WODM_OPEN) ? DMADIR_OUT : DMADIR_IN, m_ulBufferSize, &ulChannelIndex);
    if (MMFAILED(mr)) {
        DEBUGMSG(ZONE_ERROR,(TEXT("CDriverContext::OpenStream - allocate DMA channel failed\r\n")));
        return mr;
    }

    // if that worked, allocate a stream context

    HSTREAM pStream;
    if (msg == WODM_OPEN) {
        pStream = new COutputStreamContext;
    }
    else {
        ASSERT(msg == WIDM_OPEN);
        pStream = new CInputStreamContext;
    }

    if (pStream == NULL) {
        DEBUGMSG(ZONE_ERROR, (TEXT("CDriverContext::OpenStream - CStreamContext::ctor failed\r\n")));
        m_pDevice->FreeDMAChannel(ulChannelIndex);
        return MMSYSERR_NOMEM;
    }


    mr = pStream->Initialize(m_pDevice, ulChannelIndex, pWOD);
    if (MMFAILED(mr)) {
        DEBUGMSG(ZONE_ERROR, (TEXT("CDriverContext::OpenStream - CStreamContext::Initialize failed\r\n")));
        delete pStream;
        return mr;
    }

    *ppStream = pStream;

    // we're done! it all worked
    return MMSYSERR_NOERROR;
}


MMRESULT 
CDriverContext::GetVolume (PULONG pulVolume)
{
    MYTHIS_CHECK;

    *pulVolume = m_ulVolume;

    return MMSYSERR_NOERROR;
}

MMRESULT 
CDriverContext::SetVolume (ULONG ulVolume)
{
    MYTHIS_CHECK;

    // Device-level SetVolume semantics: 
    // Set the "global" volume that affects all other streams uniformly
    // In the case of this device, that means the AC97_PCMOUT_VOL register.
    m_ulVolume = ulVolume; // keep track of what the nominal volume is

    USHORT usLeft = (USHORT)  ((m_ulVolume & 0x0000F800) >> 11);
    USHORT usRight = (USHORT) ((m_ulVolume & 0xF8000000) >> 27);
    
    USHORT usRegVal;
    if (usLeft == 0 && usRight == 0) {
        // if zero, just mute the output
        usRegVal = 0x8000;
    }

⌨️ 快捷键说明

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