The SysAudio system driver constructs an audio filter graph by connecting pairs of filter pins that support compatible audio data formats. SysAudio uses a technique called data intersection (short for data-range intersection) to negotiate a common format between two pins.
A pin factory specifies the set of formats that each pin supports as an array of data ranges, where each data range is a structure of type KSDATARANGE_AUDIO. A data range specifies a general format type, which can be KSDATAFORMAT_WAVEFORMATEX or KSDATAFORMAT_DSOUND. In addition, the data range specifies a range of values for each of the following parameters:
The KSDATARANGE_AUDIO structure specifies both minimum and maximum values for the bits-per-sample and sample-frequency ranges but only a maximum for the number-of-channels range. The minimum number of channels is implicitly one.
The job of negotiating a common data format for two pins consists of finding two data ranges—one from each pin—that intersect each other. A pair of data ranges intersect if:
As mentioned previously, the KSDATAFORMAT_AUDIO structure implies a hardware model in which the minimum number of channels supported by a pin is always one. According to this model, the number-of-channels ranges for any two pins should always overlap because both pins support at least one channel. Obviously, a hardware adapter with a minimum number of channels greater than one does not conform to this model, but the adapter driver can include a proprietary data-intersection handler to deal with issues like this (see the example in Proprietary Data-Intersection Handlers).
Once the handler finds a pair of intersecting data ranges for the two pins, a common data format can be selected from the region of intersection:
When negotiating a common format for an audio port driver's sink pin and the source pin of another filter (KMixer, for example), SysAudio first obtains the source pin's data-range array. SysAudio then sends a KSPROPERTY_DATA_INTERSECTION request to the sink pin and includes the source pin's data-range array with this request. The kernel-streaming layer intercepts the request and iteratively calls the port driver's data-intersection handler once for each successive element in the source pin's data-range array, beginning with the first element, until the handler succeeds in finding a data intersection.
With each call that SysAudio makes to the port driver's data-intersection handler, the handler first obtains the sink pin's data-range array from the miniport driver. It then iterates through the array, beginning with the first element, until it succeeds in finding an intersection between a sink-pin data range and the current source-pin data range. The handler selects a common format that lies within the intersection and outputs this format to the caller.
At each step in the iteration, the port driver calls the miniport driver's proprietary data-intersection handler with the two data ranges—one for each of the two pins. If at any step the proprietary handler declines to handle a data-intersection check between the two data ranges, the port driver's data-intersection handler performs the check instead.
To summarize, the search for an intersection between a source-pin data range and a sink-pin data range is an iterative process:
The search stops upon finding the first data intersection. This process tends to favor the elements toward the beginning of each pin's data-range array. When specifying an array of data ranges for a pin, an adapter driver should order the array elements by placing data ranges for preferred formats toward the beginning of the array.