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

📄 minwave.cpp

📁 C-Media8738/8768声卡驱动开发源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
#endif
				}
				break;
			case WAVE_FORMAT_DOLBY_AC3_SPDIF:
				if ((PinID != PIN_WAVE_AC3_RENDER_SINK) && (PinID != -1)) {
					return STATUS_INVALID_PARAMETER;
				}
				if ( ((waveFormat->wBitsPerSample >= MIN_BITS_PER_SAMPLE_AC3) && (waveFormat->wBitsPerSample <= MAX_BITS_PER_SAMPLE_AC3))
				  && ((waveFormat->nSamplesPerSec >= MIN_SAMPLE_RATE_AC3) && (waveFormat->nSamplesPerSec <= MAX_SAMPLE_RATE_AC3))
				  && (waveFormat->nChannels == MAX_CHANNELS_AC3) ) {
					return isFormatAllowed(waveFormat->nSamplesPerSec, FALSE, TRUE);
				}
				break;
		}
	}

	return STATUS_INVALID_PARAMETER;
}

// Tests a data range intersection
STDMETHODIMP CMiniportWaveCMI::DataRangeIntersection(ULONG PinId, PKSDATARANGE ClientDataRange, PKSDATARANGE MyDataRange, ULONG OutputBufferLength, PVOID ResultantFormat, PULONG ResultantFormatLength)
{
	PAGED_CODE();
	DBGPRINT(("CMiniportWaveCMI[%p]::DataRangeIntersection(%d, %p, %p, %d, %p, %p)", this, PinId, ClientDataRange, MyDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength));

	if (PinId == PIN_WAVE_AC3_RENDER_SINK) {
		bool isAC3Pin = true;
		// Under Windows 2000 and XP, the client's DataRange should be AC3 only.
		// The AC3 pin is the SPDIF pin in Windows Vista, so 2ch stereo is going to be allowed.

		if (!IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_AUDIO)
		  && !IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)) {
			return STATUS_NO_MATCH;
		}


		if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF)
		  && !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) {
			// check for Vista
			isAC3Pin = false;
			if (IoIsWdmVersionAvailable(0x06,0x00)) {
				if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_PCM)
				  && !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) {
					return STATUS_NO_MATCH;
				}
			} else {
				return STATUS_NO_MATCH;
			}
		}

		if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)
		 || IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)) {
			*ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX);
		} else
		if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
			*ResultantFormatLength = sizeof(KSDATAFORMAT_DSOUND);
		} else {
			return STATUS_NO_MATCH;
		}

		// Validate return buffer size, if the request is only for the
		// size of the resultant structure, return it now.
		if (!OutputBufferLength) {
			*ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX);
			return STATUS_BUFFER_OVERFLOW;
		} else
		if (OutputBufferLength < sizeof(KSDATAFORMAT_WAVEFORMATEX)) {
			return STATUS_BUFFER_TOO_SMALL;
		}

		PKSDATAFORMAT_WAVEFORMATEX  resultantFormatWFX = (PKSDATAFORMAT_WAVEFORMATEX) ResultantFormat;
		PWAVEFORMATEX               pWaveFormatEx;

		// Return the best (only) available format.
		resultantFormatWFX->DataFormat.FormatSize = *ResultantFormatLength;
		resultantFormatWFX->DataFormat.Flags      = 0;
		resultantFormatWFX->DataFormat.SampleSize = 4; // must match nBlockAlign
		resultantFormatWFX->DataFormat.Reserved	  = 0;

		resultantFormatWFX->DataFormat.MajorFormat  = KSDATAFORMAT_TYPE_AUDIO;
		INIT_WAVEFORMATEX_GUID(&resultantFormatWFX->DataFormat.SubFormat, WAVE_FORMAT_DOLBY_AC3_SPDIF);

		// Extra space for the DSound specifier
		if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {

			PKSDATAFORMAT_DSOUND  resultantFormatDSound = (PKSDATAFORMAT_DSOUND)ResultantFormat;

			resultantFormatDSound->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_DSOUND;

			// DSound format capabilities are not expressed
			// this way in KS, so we express no capabilities.
			resultantFormatDSound->BufferDesc.Flags   = 0 ;
			resultantFormatDSound->BufferDesc.Control = 0 ;

			pWaveFormatEx = &resultantFormatDSound->BufferDesc.WaveFormatEx;
		} else {
		// WAVEFORMATEX or WILDCARD (WAVEFORMATEX)
			resultantFormatWFX->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;

			pWaveFormatEx = (PWAVEFORMATEX)((PKSDATAFORMAT)resultantFormatWFX + 1);
		}

		pWaveFormatEx->nChannels	   = 2;
		pWaveFormatEx->wBitsPerSample  = 16; // SPDIF
		pWaveFormatEx->cbSize          = 0;
		if (isAC3Pin) {
			pWaveFormatEx->wFormatTag      = WAVE_FORMAT_DOLBY_AC3_SPDIF;
			pWaveFormatEx->nSamplesPerSec  = 48000;
		} else {
			pWaveFormatEx->wFormatTag      = WAVE_FORMAT_PCM;
			pWaveFormatEx->nSamplesPerSec  = min( ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency, MAX_SAMPLE_RATE);
		}
		pWaveFormatEx->nBlockAlign     = pWaveFormatEx->nChannels * pWaveFormatEx->wBitsPerSample / 8;
		pWaveFormatEx->nAvgBytesPerSec = pWaveFormatEx->nSamplesPerSec * pWaveFormatEx->nBlockAlign;

		return STATUS_SUCCESS;
	}
	if ((PinId == PIN_WAVE_RENDER_SINK) || (PinId == PIN_WAVE_CAPTURE_SINK)) {

		if (!IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_PCM) &&
          !IsEqualGUIDAligned(ClientDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD)) {
			return STATUS_NO_MATCH;
		}

		if (!IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_AUDIO) &&
          !IsEqualGUIDAligned(ClientDataRange->MajorFormat, KSDATAFORMAT_TYPE_WILDCARD)) {
			return STATUS_NO_MATCH;
		}

		if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ||
		  IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)) {
			*ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX);
		} else
		if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
			*ResultantFormatLength = sizeof(KSDATAFORMAT_DSOUND);
		} else {
			return STATUS_NO_MATCH;
		}


		ULONG sampleRate   = 0;
		ULONG nMaxChannels = min(((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels, requestedChannelCount);

		// check for Vista
		if (IoIsWdmVersionAvailable(6,0) && (PinId == PIN_WAVE_RENDER_SINK)) {
			nMaxChannels = ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels;
		}
		if (nMaxChannels & 0x01) {
			nMaxChannels--;
		}
		if (!nMaxChannels) {
			return STATUS_NO_MATCH;
		}

		if (isStreamRunning[PCM_OUT_STREAM]) {
			sampleRate = stream[PCM_OUT_STREAM]->currentSampleRate;
		} else
		if (isStreamRunning[PCM_IN_STREAM]) {
			sampleRate = stream[PCM_IN_STREAM]->currentSampleRate;
		}
		if (sampleRate == 0) {
			if ((nMaxChannels > 2) && (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency > MAX_SAMPLE_RATE_MULTI)) {
				sampleRate = MAX_SAMPLE_RATE_MULTI;
			} else
			if ((nMaxChannels == 2) && (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency > MAX_SAMPLE_RATE)) {
				sampleRate = MAX_SAMPLE_RATE;
			} else {
				sampleRate = ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency;
			}
		}

		if ((((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumSampleFrequency < sampleRate)
		  || (((PKSDATARANGE_AUDIO)ClientDataRange)->MinimumSampleFrequency > sampleRate)) {
			return STATUS_NO_MATCH;
		}

		if (PinId == PIN_WAVE_RENDER_SINK) {
			if (!OutputBufferLength) {
				*ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
				return STATUS_BUFFER_OVERFLOW;
			} else
			if (OutputBufferLength < sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX)) {
				return STATUS_BUFFER_TOO_SMALL;
			}

			if (((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels < 2) {
				DBGPRINT(("[[DataRangeIntersection] mono format not supported"));
				return STATUS_NO_MATCH;
			}

			PWAVEFORMATPCMEX WaveFormat = (PWAVEFORMATPCMEX)((PKSDATAFORMAT)ResultantFormat + 1);
    	    if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
				return STATUS_NOT_SUPPORTED;
			}
			*(PKSDATAFORMAT)ResultantFormat = *MyDataRange;
			((PKSDATAFORMAT)ResultantFormat)->FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);


			WaveFormat->Format.wFormatTag      = WAVE_FORMAT_EXTENSIBLE;
			WaveFormat->SubFormat              = KSDATAFORMAT_SUBTYPE_PCM;
			WaveFormat->Format.nChannels       = (WORD)nMaxChannels;
			WaveFormat->Format.wBitsPerSample  = 16;
			WaveFormat->Format.nBlockAlign     = (WaveFormat->Format.wBitsPerSample >> 3) * WaveFormat->Format.nChannels;
			WaveFormat->Format.nAvgBytesPerSec = WaveFormat->Format.nSamplesPerSec * WaveFormat->Format.nBlockAlign;
			WaveFormat->Format.cbSize          = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
			WaveFormat->Format.nSamplesPerSec  = sampleRate;
			WaveFormat->Samples.wValidBitsPerSample = WaveFormat->Format.wBitsPerSample;
			switch (nMaxChannels) {
				case 8: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_7POINT1; break;
				case 6: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_5POINT1; break;
				case 4: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_QUAD;    break;
				case 2: WaveFormat->dwChannelMask = KSAUDIO_SPEAKER_STEREO;  break;
			}
			if (nMaxChannels == requestedChannelCount) {
				WaveFormat->dwChannelMask = requestedChannelMask;
			}
			((PKSDATAFORMAT)ResultantFormat)->SampleSize = WaveFormat->Format.nBlockAlign;

			*ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
			DBGPRINT(("[DataRangeIntersection] MultiChannel Renderer: SampleRate: %d, ClientDataRange->MaxChans: %d, Channels: %d, BitPerSample: %d, BlockAlign: %d, AvgBytesPerSec: %d, ChannelMask: %08X", WaveFormat->Format.nSamplesPerSec, ((PKSDATARANGE_AUDIO)ClientDataRange)->MaximumChannels, WaveFormat->Format.nChannels, WaveFormat->Format.wBitsPerSample, WaveFormat->Format.nBlockAlign, WaveFormat->Format.nAvgBytesPerSec, WaveFormat->dwChannelMask));
		} else
		if (PinId == PIN_WAVE_CAPTURE_SINK) {
			PKSDATAFORMAT_WAVEFORMATEX  resultantFormatWFX;
			PWAVEFORMATEX               pWaveFormatEx;

			if (!OutputBufferLength) {
				*ResultantFormatLength = sizeof(KSDATAFORMAT_WAVEFORMATEX);
				return STATUS_BUFFER_OVERFLOW;
			} else
			if (OutputBufferLength < sizeof(KSDATAFORMAT_WAVEFORMATEX)) {
				return STATUS_BUFFER_TOO_SMALL;
			}

			if (nMaxChannels > 2) {
				nMaxChannels = 2;
			}

			resultantFormatWFX = (PKSDATAFORMAT_WAVEFORMATEX) ResultantFormat;
			resultantFormatWFX->DataFormat.FormatSize   = *ResultantFormatLength;
			resultantFormatWFX->DataFormat.Flags        = 0;
			resultantFormatWFX->DataFormat.SampleSize   = 4;
			resultantFormatWFX->DataFormat.Reserved     = 0;
			resultantFormatWFX->DataFormat.MajorFormat  = KSDATAFORMAT_TYPE_AUDIO;
			INIT_WAVEFORMATEX_GUID(&resultantFormatWFX->DataFormat.SubFormat, WAVE_FORMAT_PCM);

    	    if (IsEqualGUIDAligned(ClientDataRange->Specifier, KSDATAFORMAT_SPECIFIER_DSOUND)) {
				PKSDATAFORMAT_DSOUND resultantFormatDSound;
				resultantFormatDSound = (PKSDATAFORMAT_DSOUND)ResultantFormat;
				resultantFormatDSound->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_DSOUND;
				resultantFormatDSound->BufferDesc.Flags   = 0 ;
				resultantFormatDSound->BufferDesc.Control = 0 ;
				pWaveFormatEx = &resultantFormatDSound->BufferDesc.WaveFormatEx;
			} else {
				resultantFormatWFX->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
				pWaveFormatEx = (PWAVEFORMATEX)((PKSDATAFORMAT)resultantFormatWFX + 1);
			}
			pWaveFormatEx->wFormatTag      = WAVE_FORMAT_PCM;
			pWaveFormatEx->nChannels       = nMaxChannels;
			pWaveFormatEx->nSamplesPerSec  = sampleRate;
			pWaveFormatEx->wBitsPerSample  = 16;
			pWaveFormatEx->cbSize          = 0;
			pWaveFormatEx->nBlockAlign     = 4;
			pWaveFormatEx->nAvgBytesPerSec = 192000;
		}
		return STATUS_SUCCESS;
	}
	return STATUS_NO_MATCH;
}

//from IMiniportWaveCyclic::NewStream()
#ifdef WAVERT
STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVERTSTREAM *OutStream, PPORTWAVERTSTREAM OuterUnknown, ULONG PinID, BOOLEAN Capture, PKSDATAFORMAT DataFormat)
#else
STDMETHODIMP CMiniportWaveCMI::NewStream(PMINIPORTWAVECYCLICSTREAM *OutStream, PUNKNOWN OuterUnknown, POOL_TYPE PoolType, ULONG PinID, BOOLEAN Capture, PKSDATAFORMAT DataFormat, PDMACHANNEL* OutDmaChannel, PSERVICEGROUP* OutServiceGroup)
#endif
{
	PAGED_CODE();
	ASSERT(OutStream);
	ASSERT(DataFormat);
#ifdef WAVERT
	DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %d, %d, %p)", this, OutStream, OuterUnknown, PinID, Capture, DataFormat));
#else
	ASSERT(OutDmaChannel);
	ASSERT(OutServiceGroup);
	DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %p, %d, %d, %p, %p, %p)", this, OutStream, OuterUnknown, PoolType, PinID, Capture, DataFormat, OutDmaChannel, OutServiceGroup));
#endif

	NTSTATUS      ntStatus    = STATUS_SUCCESS;
	PWAVEFORMATEX waveFormat  = PWAVEFORMATEX(DataFormat + 1);
	UInt32        streamIndex = PCM_OUT_STREAM;

	ntStatus = validateFormat(DataFormat, PinID, Capture);
	if (!NT_SUCCESS(ntStatus)) {
		DBGPRINT(("invalid stream format"));
		return STATUS_UNSUCCESSFUL;
	}

	CMIAdapter->setUInt8Bit(REG_MIXER1, EN_SPDI2DAC);

	if (Capture) {
		streamIndex = PCM_IN_STREAM;
	} else if (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat)) {
		streamIndex = AC3_OUT_STREAM;
	}

	// make sure the hardware is not already in use
	if (isStreamRunning[streamIndex]) {
		DBGPRINT(("Stream %d running, exiting...", streamIndex));
   		return STATUS_UNSUCCESSFUL;
	}
	if ((streamIndex == AC3_OUT_STREAM) && isStreamRunning[PCM_OUT_STREAM]) {
   		stream[PCM_OUT_STREAM]->SetState(KSSTATE_STOP_AC3);
	}
	if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[AC3_OUT_STREAM]) {
   		return STATUS_UNSUCCESSFUL;
	}

	DBGPRINT(("---StreamNo: %d, Bits: %d, Sample Rate: %d, Channels: %d, AC3: %d", streamIndex,
		waveFormat->wBitsPerSample, waveFormat->nSamplesPerSec, waveFormat->nChannels,
		(WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&DataFormat->SubFormat))));

	// the DAC and ADC can only run at the same sample rate simultaneously
	if ((streamIndex == PCM_IN_STREAM) && isStreamRunning[PCM_OUT_STREAM]) {
   		if (waveFormat->nSamplesPerSec != stream[PCM_OUT_STREAM]->currentSampleRate) {
   			return STATUS_UNSUCCESSFUL;
		}
	}
	if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[PCM_IN_STREAM]) {
   		if (waveFormat->nSamplesPerSec != stream[PCM_IN_STREAM]->currentSampleRate) {
   			return STATUS_UNSUCCESSFUL;
		}
	}

	// instantiate a stream
#ifdef WAVERT
	ntStatus = CreateMiniportWaveStreamCMI(&stream[streamIndex], OuterUnknown, NonPagedPool);
#else
	ntStatus = CreateMiniportWaveStreamCMI(&stream[streamIndex], OuterUnknown, PoolType);
#endif
	if (!NT_SUCCESS (ntStatus)) {
		DBGPRINT(("Failed to create stream"));
		return ntStatus;
	}

	// initialize it
#ifdef WAVERT
	ntStatus = stream[streamIndex]->Init(this, streamIndex, Capture, DataFormat, OuterUnknown);
#else
	ntStatus = stream[streamIndex]->Init(this, streamIndex, Capture, DataFormat, DMAChannel[streamIndex], OutServiceGroup);
#endif
	if (!NT_SUCCESS(ntStatus)) {
		DBGPRINT(("Failed to init stream"));
		stream[streamIndex]->Release();
		stream[streamIndex] = NULL;
		*OutStream          = NULL;
#ifndef WAVERT
		*OutServiceGroup    = NULL;
		*OutDmaChannel      = NULL;
#endif
		return ntStatus;
	}

#ifdef WAVERT
//this has been referenced in CreateMiniportWaveStreamCMI() already
	*OutStream = (PMINIPORTWAVERTSTREAM)stream[streamIndex];
#else
	*OutDmaChannel = DMAChannel[streamIndex];
	DMAChannel[streamIndex]->AddRef();
	*OutStream = (PMINIPORTWAVECYCLICSTREAM)stream[streamIndex];
#endif

	return ntStatus;
}

static NTSTATUS PropertyHandler_ChannelConfig(PPCPROPERTY_REQUEST PropertyRequest)
{
	PAGED_CODE();
	ASSERT(PropertyRequest);
	DBGPRINT(("[PropertyHandler_ChannelConfig]"));

#ifdef WAVERT
	CMiniportWaveCMI *that = (CMiniportWaveCMI *) ((PMINIPORTWAVERT)PropertyRequest->MajorTarget);
#else
	CMiniportWaveCMI *that = (CMiniportWaveCMI *) ((PMINIPORTWAVECYCLIC)PropertyRequest->MajorTarget);
#endif

	if (PropertyRequest->Node == KSNODE_WAVE_DAC) {

		if (PropertyRequest->ValueSize == 0) {
			PropertyRequest->ValueSize = sizeof(LONG);
			return STATUS_BUFFER_OVERFLOW;
		} else if (PropertyRequest->ValueSize < sizeof (LONG)) {
			PropertyRequest->ValueSize = 0;
			return STATUS_BUFFER_TOO_SMALL;
		}

		if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) {
			*(PLONG)PropertyRequest->Value = that->requestedChannelMask;
			PropertyRequest->ValueSize = sizeof(ULONG);
			return STATUS_SUCCESS;
		} else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) {
			if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_7POINT1) {
				that->requestedChannelMask =  *(PLONG)PropertyRequest->Value;
				that->requestedChannelCount = 8;
				return STATUS_SUCCESS;
			}
			if (*(PLONG)PropertyRequest->Value == KSAUDIO_SPEAKER_5POINT1) {

⌨️ 快捷键说明

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