📄 minwave.cpp
字号:
DmaChannel16 = NULL;
//
// 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 *) &AdapterCommon
);
//
// We need a service group for notifications. We will bind all the
// streams that are created to this single service group. All interrupt
// notifications ask for service on this group, so all streams will get
// serviced. The PcNewServiceGroup() call returns an AddRefed pointer.
// The adapter needs a copy of the service group since it is doing the
// ISR.
//
if (NT_SUCCESS(ntStatus))
{
KeInitializeMutex(&SampleRateSync,1);
ntStatus = PcNewServiceGroup(&ServiceGroup,NULL);
}
if (NT_SUCCESS(ntStatus))
{
AdapterCommon->SetWaveMiniport ((PWAVEMINIPORTSB16)this);
ntStatus = ProcessResources(ResourceList);
}
//
// In case of failure object gets destroyed and destructor cleans up.
//
return ntStatus;
}
/*****************************************************************************
* PinDataRangesStream
*****************************************************************************
* Structures indicating range of valid format values for streaming pins.
*/
static
KSDATARANGE_AUDIO PinDataRangesStream[] =
{
{
{
sizeof(KSDATARANGE_AUDIO),
0,
0,
0,
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM),
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
},
2, // Max number of channels.
8, // Minimum number of bits per sample.
16, // Maximum number of bits per channel.
5000, // Minimum rate.
44100 // Maximum rate.
}
};
/*****************************************************************************
* PinDataRangePointersStream
*****************************************************************************
* List of pointers to structures indicating range of valid format values
* for streaming pins.
*/
static
PKSDATARANGE PinDataRangePointersStream[] =
{
PKSDATARANGE(&PinDataRangesStream[0])
};
/*****************************************************************************
* PinDataRangesBridge
*****************************************************************************
* Structures indicating range of valid format values for bridge pins.
*/
static
KSDATARANGE PinDataRangesBridge[] =
{
{
sizeof(KSDATARANGE),
0,
0,
0,
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
}
};
/*****************************************************************************
* PinDataRangePointersBridge
*****************************************************************************
* List of pointers to structures indicating range of valid format values
* for bridge pins.
*/
static
PKSDATARANGE PinDataRangePointersBridge[] =
{
&PinDataRangesBridge[0]
};
/*****************************************************************************
* MiniportPins
*****************************************************************************
* List of pins.
*/
static
PCPIN_DESCRIPTOR
MiniportPins[] =
{
// Wave In Streaming Pin (Capture)
{
1,1,0,
NULL,
{
0,
NULL,
0,
NULL,
SIZEOF_ARRAY(PinDataRangePointersStream),
PinDataRangePointersStream,
KSPIN_DATAFLOW_OUT,
KSPIN_COMMUNICATION_SINK,
(GUID *) &PINNAME_CAPTURE,
&KSAUDFNAME_RECORDING_CONTROL, // this name shows up as the recording panel name in SoundVol.
0
}
},
// Wave In Bridge Pin (Capture - From Topology)
{
0,0,0,
NULL,
{
0,
NULL,
0,
NULL,
SIZEOF_ARRAY(PinDataRangePointersBridge),
PinDataRangePointersBridge,
KSPIN_DATAFLOW_IN,
KSPIN_COMMUNICATION_NONE,
(GUID *) &KSCATEGORY_AUDIO,
NULL,
0
}
},
// Wave Out Streaming Pin (Renderer)
{
1,1,0,
NULL,
{
0,
NULL,
0,
NULL,
SIZEOF_ARRAY(PinDataRangePointersStream),
PinDataRangePointersStream,
KSPIN_DATAFLOW_IN,
KSPIN_COMMUNICATION_SINK,
(GUID *) &KSCATEGORY_AUDIO,
NULL,
0
}
},
// Wave Out Bridge Pin (Renderer)
{
0,0,0,
NULL,
{
0,
NULL,
0,
NULL,
SIZEOF_ARRAY(PinDataRangePointersBridge),
PinDataRangePointersBridge,
KSPIN_DATAFLOW_OUT,
KSPIN_COMMUNICATION_NONE,
(GUID *) &KSCATEGORY_AUDIO,
NULL,
0
}
}
};
/*****************************************************************************
* TopologyNodes
*****************************************************************************
* List of nodes.
*/
static
PCNODE_DESCRIPTOR MiniportNodes[] =
{
{
0, // Flags
NULL, // AutomationTable
&KSNODETYPE_ADC, // Type
NULL // Name
},
{
0, // Flags
NULL, // AutomationTable
&KSNODETYPE_DAC, // Type
NULL // Name
}
};
/*****************************************************************************
* MiniportConnections
*****************************************************************************
* List of connections.
*/
static
PCCONNECTION_DESCRIPTOR MiniportConnections[] =
{
{ PCFILTER_NODE, 1, 0, 1 }, // Bridge in to ADC.
{ 0, 0, PCFILTER_NODE, 0 }, // ADC to stream pin (capture).
{ PCFILTER_NODE, 2, 1, 1 }, // Stream in to DAC.
{ 1, 0, PCFILTER_NODE, 3 } // DAC to Bridge.
};
/*****************************************************************************
* MiniportFilterDescriptor
*****************************************************************************
* Complete miniport description.
*/
static
PCFILTER_DESCRIPTOR
MiniportFilterDescriptor =
{
0, // Version
&AutomationFilter, // AutomationTable
sizeof(PCPIN_DESCRIPTOR), // PinSize
SIZEOF_ARRAY(MiniportPins), // PinCount
MiniportPins, // Pins
sizeof(PCNODE_DESCRIPTOR), // NodeSize
SIZEOF_ARRAY(MiniportNodes), // NodeCount
MiniportNodes, // Nodes
SIZEOF_ARRAY(MiniportConnections), // ConnectionCount
MiniportConnections, // Connections
0, // CategoryCount
NULL // Categories - use the default categories (audio, render, capture)
};
/*****************************************************************************
* CMiniportWaveCyclicSB16::GetDescription()
*****************************************************************************
* Gets the topology.
*/
STDMETHODIMP
CMiniportWaveCyclicSB16::
GetDescription
(
OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
)
{
PAGED_CODE();
ASSERT(OutFilterDescriptor);
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicSB16::GetDescription]"));
*OutFilterDescriptor = &MiniportFilterDescriptor;
return STATUS_SUCCESS;
}
/*****************************************************************************
* CMiniportWaveCyclicSB16::DataRangeIntersection()
*****************************************************************************
* Tests a data range intersection.
*/
STDMETHODIMP
CMiniportWaveCyclicSB16::
DataRangeIntersection
(
IN ULONG PinId,
IN PKSDATARANGE ClientDataRange,
IN PKSDATARANGE MyDataRange,
IN ULONG OutputBufferLength,
OUT PVOID ResultantFormat,
OUT PULONG ResultantFormatLength
)
{
PAGED_CODE();
BOOLEAN DigitalAudio;
NTSTATUS Status;
ULONG RequiredSize;
ULONG SampleFrequency;
USHORT BitsPerSample;
//
// Let's do the complete work here.
//
if (!IsEqualGUIDAligned(ClientDataRange->Specifier,KSDATAFORMAT_SPECIFIER_NONE))
{
//
// The miniport did not resolve this format. If the dataformat
// is not PCM audio and requires a specifier, bail out.
//
if ( !IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_AUDIO )
|| !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_PCM ))
{
return STATUS_INVALID_PARAMETER;
}
DigitalAudio = TRUE;
//
// weird enough, the specifier here does not define the format of ClientDataRange
// but the format that is expected to be returned in ResultantFormat.
//
if (IsEqualGUIDAligned(ClientDataRange->Specifier,KSDATAFORMAT_SPECIFIER_DSOUND))
{
RequiredSize = sizeof(KSDATAFORMAT_DSOUND);
}
else
{
RequiredSize = sizeof(KSDATAFORMAT_WAVEFORMATEX);
}
}
else
{
DigitalAudio = FALSE;
RequiredSize = sizeof(KSDATAFORMAT);
}
//
// Validate return buffer size, if the request is only for the
// size of the resultant structure, return it now.
//
if (!OutputBufferLength)
{
*ResultantFormatLength = RequiredSize;
return STATUS_BUFFER_OVERFLOW;
}
else if (OutputBufferLength < RequiredSize)
{
return STATUS_BUFFER_TOO_SMALL;
}
// There was a specifier ...
if (DigitalAudio)
{
PKSDATARANGE_AUDIO AudioRange;
PWAVEFORMATEX WaveFormatEx;
AudioRange = (PKSDATARANGE_AUDIO) MyDataRange;
// Fill the structure
if (IsEqualGUIDAligned(ClientDataRange->Specifier,KSDATAFORMAT_SPECIFIER_DSOUND))
{
PKSDATAFORMAT_DSOUND DSoundFormat;
DSoundFormat = (PKSDATAFORMAT_DSOUND) ResultantFormat;
_DbgPrintF(DEBUGLVL_VERBOSE,("returning KSDATAFORMAT_DSOUND format intersection"));
DSoundFormat->BufferDesc.Flags = 0 ;
DSoundFormat->BufferDesc.Control = 0 ;
DSoundFormat->DataFormat = *ClientDataRange;
DSoundFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_DSOUND;
DSoundFormat->DataFormat.FormatSize = RequiredSize;
WaveFormatEx = &DSoundFormat->BufferDesc.WaveFormatEx;
*ResultantFormatLength = RequiredSize;
}
else
{
PKSDATAFORMAT_WAVEFORMATEX WaveFormat;
WaveFormat = (PKSDATAFORMAT_WAVEFORMATEX) ResultantFormat;
_DbgPrintF(DEBUGLVL_VERBOSE,("returning KSDATAFORMAT_WAVEFORMATEX format intersection") );
WaveFormat->DataFormat = *ClientDataRange;
WaveFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
WaveFormat->DataFormat.FormatSize = RequiredSize;
WaveFormatEx = &WaveFormat->WaveFormatEx;
*ResultantFormatLength = RequiredSize;
}
//
// Return a format that intersects the given audio range,
// using our maximum support as the "best" format.
//
WaveFormatEx->wFormatTag = WAVE_FORMAT_PCM;
WaveFormatEx->nChannels =
(USHORT) min( AudioRange->MaximumChannels,
((PKSDATARANGE_AUDIO) ClientDataRange)->MaximumChannels );
//
// Check if the pin is still free
//
if (!PinId)
{
if (AllocatedCapture)
{
return STATUS_NO_MATCH;
}
}
else
{
if (AllocatedRender)
{
return STATUS_NO_MATCH;
}
}
//
// Check if one pin is in use -> use same sample frequency.
//
if (AllocatedCapture || AllocatedRender)
{
SampleFrequency = SamplingFrequency;
if ( (SampleFrequency > ((PKSDATARANGE_AUDIO) ClientDataRange)->MaximumSampleFrequency)
|| (SampleFrequency < ((PKSDATARANGE_AUDIO) ClientDataRange)->MinimumSampleFrequency))
{
return STATUS_NO_MATCH;
}
}
else
{
SampleFrequency =
min( AudioRange->MaximumSampleFrequency,
((PKSDATARANGE_AUDIO) ClientDataRange)->MaximumSampleFrequency );
}
WaveFormatEx->nSamplesPerSec = SampleFrequency;
//
// Check if one pin is in use -> use other bits per sample.
//
if (AllocatedCapture || AllocatedRender)
{
if (Allocated8Bit)
{
BitsPerSample = 16;
}
else
{
BitsPerSample = 8;
}
if ((BitsPerSample > ((PKSDATARANGE_AUDIO) ClientDataRange)->MaximumBitsPerSample) ||
(BitsPerSample < ((PKSDATARANGE_AUDIO) ClientDataRange)->MinimumBitsPerSample))
{
return STATUS_NO_MATCH;
}
}
else
{
BitsPerSample =
(USHORT) min( AudioRange->MaximumBitsPerSample,
((PKSDATARANGE_AUDIO) ClientDataRange)->MaximumBitsPerSample );
}
WaveFormatEx->wBitsPerSample = BitsPerSample;
WaveFormatEx->nBlockAlign = (WaveFormatEx->wBitsPerSample * WaveFormatEx->nChannels) / 8;
WaveFormatEx->nAvgBytesPerSec = (WaveFormatEx->nSamplesPerSec * WaveFormatEx->nBlockAlign);
WaveFormatEx->cbSize = 0;
((PKSDATAFORMAT) ResultantFormat)->SampleSize = WaveFormatEx->nBlockAlign;
_DbgPrintF(DEBUGLVL_VERBOSE,("Channels = %d", WaveFormatEx->nChannels) );
_DbgPrintF(DEBUGLVL_VERBOSE,("Samples/sec = %d", WaveFormatEx->nSamplesPerSec) );
_DbgPrintF(DEBUGLVL_VERBOSE,("Bits/sample = %d", WaveFormatEx->wBitsPerSample) );
}
else
{
// There was no specifier. Return only the KSDATAFORMAT structure.
//
// Copy the data format structure.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -