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

📄 basewave.cpp

📁 在微软例子下实现的虚拟声卡,实现了各种接口,是学习的一个好例子
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1997-2000  Microsoft Corporation All Rights Reserved

Module Name:

    basewave.cpp

Abstract:

    Implementation of wavecyclic miniport.

--*/

#include <msvad.h>
#include "common.h"
#include "basewave.h"

//=============================================================================
// CMiniportWaveCyclicMSVAD
//=============================================================================

//=============================================================================
#pragma code_seg("PAGE")
CMiniportWaveCyclicMSVAD::CMiniportWaveCyclicMSVAD
(
    void
)
/*++

Routine Description:

  Constructor for wavecyclic miniport.

Arguments:

Return Value:

--*/
{
    PAGED_CODE();

    DPF_ENTER(("[CMiniportWaveCyclicMSVAD::CMiniportWaveCyclicMSVAD]"));

    // Initialize members.
    //
    m_AdapterCommon = NULL;
    m_Port = NULL;
    m_FilterDescriptor = NULL;

    m_NotificationInterval = 0;
    m_SamplingFrequency = 0;

    m_ServiceGroup = NULL;
    m_MaxDmaBufferSize = DMA_BUFFER_SIZE;

    m_MaxOutputStreams = 0;
    m_MaxInputStreams = 0;
    m_MaxTotalStreams = 0;

    m_MinChannels = 0;
    m_MaxChannelsPcm = 0;
    m_MinBitsPerSamplePcm = 0;
    m_MaxBitsPerSamplePcm = 0;
    m_MinSampleRatePcm = 0;
    m_MaxSampleRatePcm = 0;
} // CMiniportWaveCyclicMSVAD

//=============================================================================
CMiniportWaveCyclicMSVAD::~CMiniportWaveCyclicMSVAD
(
    void
)
/*++

Routine Description:

  Destructor for wavecyclic miniport

Arguments:

Return Value:

--*/
{
    PAGED_CODE();

    DPF_ENTER(("[CMiniportWaveCyclicMSVAD::~CMiniportWaveCyclicMSVAD]"));

    if (m_Port)
    {
        m_Port->Release();
    }

    if (m_ServiceGroup)
    {
        m_ServiceGroup->Release();
    }

    if (m_AdapterCommon)
    {
        m_AdapterCommon->Release();
    }
} // ~CMiniportWaveCyclicMSVAD

//=============================================================================
STDMETHODIMP
CMiniportWaveCyclicMSVAD::GetDescription
(
    OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
)
/*++

Routine Description:

    The GetDescription function gets a pointer to a filter description.
    The descriptor is defined in wavtable.h for each MSVAD sample.

Arguments:

  OutFilterDescriptor - Pointer to the filter description

Return Value:

  NT status code.

--*/
{
    PAGED_CODE();

    ASSERT(OutFilterDescriptor);

    DPF_ENTER(("[CMiniportWaveCyclicMSVAD::GetDescription]"));

    *OutFilterDescriptor = m_FilterDescriptor;

    return (STATUS_SUCCESS);
} // GetDescription

//=============================================================================
STDMETHODIMP
CMiniportWaveCyclicMSVAD::Init
(
    IN  PUNKNOWN                UnknownAdapter_,
    IN  PRESOURCELIST           ResourceList_,
    IN  PPORTWAVECYCLIC         Port_
)
/*++

Routine Description:

Arguments:

  UnknownAdapter_ - pointer to adapter common.

  ResourceList_ - resource list. MSVAD does not use resources.

  Port_ - pointer to the port

Return Value:

  NT status code.

--*/
{
    PAGED_CODE();

    ASSERT(UnknownAdapter_);
    ASSERT(Port_);

    DPF_ENTER(("[CMiniportWaveCyclicMSVAD::Init]"));

    // AddRef() is required because we are keeping this pointer.
    //
    m_Port = Port_;
    m_Port->AddRef();

    // We want the IAdapterCommon interface on the adapter common object,
    // which is given to us as a IUnknown.  The QueryInterface call gives us
    // an AddRefed pointer to the interface we want.
    //
    NTSTATUS ntStatus =
        UnknownAdapter_->QueryInterface
        (
            IID_IAdapterCommon,
            (PVOID *) &m_AdapterCommon
        );

    if (NT_SUCCESS(ntStatus))
    {
        KeInitializeMutex(&m_SampleRateSync, 1);
        ntStatus = PcNewServiceGroup(&m_ServiceGroup, NULL);

        if (NT_SUCCESS(ntStatus))
        {
            m_AdapterCommon->SetWaveServiceGroup(m_ServiceGroup);
        }
    }

    if (!NT_SUCCESS(ntStatus))
    {
        // clean up AdapterCommon
        //
        if (m_AdapterCommon)
        {
            // clean up the service group
            //
            if (m_ServiceGroup)
            {
                m_AdapterCommon->SetWaveServiceGroup(NULL);
                m_ServiceGroup->Release();
                m_ServiceGroup = NULL;
            }

            m_AdapterCommon->Release();
            m_AdapterCommon = NULL;
        }

        // release the port
        //
        m_Port->Release();
        m_Port = NULL;
    }

    return ntStatus;
} // Init

//=============================================================================
NTSTATUS
CMiniportWaveCyclicMSVAD::PropertyHandlerCpuResources
(
    IN  PPCPROPERTY_REQUEST     PropertyRequest
)
/*++

Routine Description:

  Processes KSPROPERTY_AUDIO_CPURESOURCES

Arguments:

  PropertyRequest - property request structure

Return Value:

  NT status code.

--*/
{
    PAGED_CODE();

    ASSERT(PropertyRequest);

    DPF_ENTER(("[CMiniportWaveCyclicMSVAD::PropertyHandlerCpuResources]"));

    NTSTATUS                    ntStatus = STATUS_INVALID_DEVICE_REQUEST;

    if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
    {
        ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(LONG), 0);
        if (NT_SUCCESS(ntStatus))
        {
            *(PLONG(PropertyRequest->Value)) = KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU;
            PropertyRequest->ValueSize = sizeof(LONG);
            ntStatus = STATUS_SUCCESS;
        }
    }
    else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
    {
        ntStatus =
            PropertyHandler_BasicSupport
            (
                PropertyRequest,
                KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
                VT_I4
            );
    }

    return ntStatus;
} // PropertyHandlerCpuResources

//=============================================================================
NTSTATUS
CMiniportWaveCyclicMSVAD::PropertyHandlerGeneric
(
    IN  PPCPROPERTY_REQUEST     PropertyRequest
)
/*++

Routine Description:

  Handles all properties for this miniport.

Arguments:

  PropertyRequest - property request structure

Return Value:

  NT status code.

--*/
{
    PAGED_CODE();

    ASSERT(PropertyRequest);
    ASSERT(PropertyRequest->PropertyItem);

    NTSTATUS                    ntStatus = STATUS_INVALID_DEVICE_REQUEST;

    switch (PropertyRequest->PropertyItem->Id)
    {
        case KSPROPERTY_AUDIO_CPU_RESOURCES:
            ntStatus = PropertyHandlerCpuResources(PropertyRequest);
            break;

        default:
            DPF(D_TERSE, ("[PropertyHandlerGeneric: Invalid Device Request]"));
            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
    }

    return ntStatus;
} // PropertyHandlerGeneric

//=============================================================================
NTSTATUS
CMiniportWaveCyclicMSVAD::ValidateFormat
(
    IN  PKSDATAFORMAT           pDataFormat
)
/*++

Routine Description:

  Validates that the given dataformat is valid.
  This version of the driver only supports PCM.

Arguments:

  pDataFormat - The dataformat for validation.

Return Value:

  NT status code.

--*/
{
    PAGED_CODE();

    ASSERT(pDataFormat);

    DPF_ENTER(("[CMiniportWaveCyclicMSVAD::ValidateFormat]"));

    NTSTATUS                    ntStatus = STATUS_INVALID_PARAMETER;
    PWAVEFORMATEX               pwfx;

    pwfx = GetWaveFormatEx(pDataFormat);
    if (pwfx)
    {
        if (IS_VALID_WAVEFORMATEX_GUID(&pDataFormat->SubFormat))
        {
            USHORT wfxID = EXTRACT_WAVEFORMATEX_ID(&pDataFormat->SubFormat);

            switch (wfxID)
            {
                case WAVE_FORMAT_PCM:
                {
                    switch (pwfx->wFormatTag)
                    {
                        case WAVE_FORMAT_PCM:
                        {
                            ntStatus = ValidatePcm(pwfx);
                            break;
                        }
                    }
                    break;
                }

                default:
                    DPF(D_TERSE, ("Invalid format EXTRACT_WAVEFORMATEX_ID!"));
                    break;
            }
        }
        else
        {
            DPF(D_TERSE, ("Invalid pDataFormat->SubFormat!") );
        }
    }

    return ntStatus;
} // ValidateFormat

//-----------------------------------------------------------------------------
NTSTATUS
CMiniportWaveCyclicMSVAD::ValidatePcm
(
    IN  PWAVEFORMATEX           pWfx
)
/*++

Routine Description:

  Given a waveformatex and format size validates that the format is in device
  datarange.

Arguments:

  pWfx - wave format structure.

Return Value:

    NT status code.

--*/
{
    PAGED_CODE();

    DPF_ENTER(("CMiniportWaveCyclicMSVAD::ValidatePcm"));

    if
    (
        pWfx                                                &&
        (pWfx->cbSize == 0)                                 &&
        (pWfx->nChannels >= m_MinChannels)                  &&
        (pWfx->nChannels <= m_MaxChannelsPcm)               &&
        (pWfx->nSamplesPerSec >= m_MinSampleRatePcm)        &&
        (pWfx->nSamplesPerSec <= m_MaxSampleRatePcm)        &&
        (pWfx->wBitsPerSample >= m_MinBitsPerSamplePcm)     &&
        (pWfx->wBitsPerSample <= m_MaxBitsPerSamplePcm)
    )
    {
        return STATUS_SUCCESS;
    }

    DPF(D_TERSE, ("Invalid PCM format"));

    return STATUS_INVALID_PARAMETER;
} // ValidatePcm

//=============================================================================
// CMiniportWaveCyclicStreamMSVAD
//=============================================================================

CMiniportWaveCyclicStreamMSVAD::CMiniportWaveCyclicStreamMSVAD
(
    void
)
{
    m_pMiniport = NULL;
    m_fCapture = FALSE;
    m_fFormat16Bit = FALSE;
    m_fFormatStereo = FALSE;
    m_ksState = KSSTATE_STOP;
    m_ulPin = (ULONG)-1;

    m_pDpc = NULL;
    m_pTimer = NULL;

    m_fDmaActive = FALSE;
    m_ulDmaPosition = 0;
    m_pvDmaBuffer = NULL;
    m_ulDmaBufferSize = 0;
    m_ulDmaMovementRate = 0;    
    m_ullDmaTimeStamp = 0;
}

//=============================================================================
CMiniportWaveCyclicStreamMSVAD::~CMiniportWaveCyclicStreamMSVAD
(
    void
)
/*++

Routine Description:

  Destructor for wavecyclic stream

Arguments:

  void

Return Value:

--*/
{
    PAGED_CODE();

    DPF_ENTER(("[CMiniportWaveCyclicStreamMS::~CMiniportWaveCyclicStreamMS]"));

    if (m_pTimer)
    {
        KeCancelTimer(m_pTimer);
        ExFreePool(m_pTimer);
    }

    if (m_pDpc)
    {
        ExFreePool( m_pDpc );
    }

    // Free the DMA buffer
    //
    FreeBuffer();
} // ~CMiniportWaveCyclicStreamMSVAD

//=============================================================================
NTSTATUS
CMiniportWaveCyclicStreamMSVAD::Init
(
    IN  PCMiniportWaveCyclicMSVAD Miniport_,
    IN  ULONG                   Pin_,
    IN  BOOLEAN                 Capture_,
    IN  PKSDATAFORMAT           DataFormat_
)
/*++

Routine Description:

  Initializes the stream object. Allocate a DMA buffer, timer and DPC

⌨️ 快捷键说明

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