none
AVStream. Unexpected reset to the minimum sample rate after running of the Sound Control Panel. RRS feed

  • Question

  • Hi All.

    I create the audio driver on the basis of AVStream model (I'm usse Windows 7/8).

    The driver supports some discrete sample rates of audio (for example 44100 and 48000 Hz). All these sample rates are initialized in two descriptors of KSDATARANGE_AUDIO, for example:


    KSDATARANGE_AUDIO dataRange44100;
    ZERO_STRUCT(dataRange44100);
    
    ...
    dataRange44100.MinimumSampleFrequency = 44100;
    dataRange44100.MaximumSampleFrequency= 44100;
    ...
    
    KSDATARANGE_AUDIO dataRange48000;
    ZERO_STRUCT(dataRange48000);
    
    ...
    dataRange48000.MinimumSampleFrequency = 48000;
    dataRange48000.MaximumSampleFrequency= 48000;
    ...

      But I can reproduce the strange feature:

    1. Run "ControlPanel->Sound->MyDevice->Properties->Advanced" and setup 48000 Hz, click on "Apply" button. I look my log from the driver, see that is called the SetDataFormat() callback with an correct format which an nSamplePerSec == 48000 Hz. All excellent..
    2. I close the "Properties" dialog (e.g. click on "Ok" button).
    3. Again I select my device from the active window of "Sound" application and again I click to the "Properties" button.
    4. And here begins the strange things... I look my log from the driver and see that called the SetDataFormat() callback which has a wrong sample rate nSamplePerSec == 44100 Hz!!! I.e. "Sound" application compulsorily dropped my previous setup from 48000 Hz to the minimal 44100 Hz.


    In case change of KSDATARANGE_AUDIO arrays to the 48000 and 96000 Hz, then start of the "Sound->Properties" will drop my sample rate to the 48000 Hz.

    I.e. any new start "Sound->Properties" drops my sample rate to the minimum possible...


    Why it happened? Whether someone can explain me this strange behavior of  the "Sound" application? Or, maybe, I didn't consider/missed something and there are any undocumented features of AVStream of model?


    Best regards, Denis.







    • Edited by kuzulis Monday, November 18, 2013 9:47 AM
    Monday, November 18, 2013 9:43 AM

All replies

  • Can someone help me? Because I don't know why it happened..

    Here my code..

    DispatchSetFormat() handler:

    NTSTATUS
    RenderPin::DispatchSetFormat(
        KSPIN *pin,
        KSDATAFORMAT *oldFormat,
        KSMULTIPLE_ITEM *oldAttributeList,
        const KSDATARANGE *dataRange, 
        const KSATTRIBUTE_LIST *attributeRange
        )
    {
        PAGED_CODE();
        DENTER();
        ASSERT(pin);
        ASSERT(pin->Context);
        ASSERT(pin->ConnectionFormat);
        ASSERT(dataRange);
    
        if (oldFormat) {
            DOUT(DBG_PRINT, ("*** oldFormat ***"));
        }
        if (oldAttributeList) {
            DOUT(DBG_PRINT, ("*** oldAttributeList ***"));
        }
    
        if (dataRange->FormatSize < sizeof(KSDATARANGE_AUDIO)) {
            // invalid length
            DOUT(DBG_ERROR, ("invalid dataRange length got: %u expected: %u ]", 
                dataRange->FormatSize, sizeof(KSDATARANGE_AUDIO)));
            return STATUS_NO_MATCH;
        }
    
        if (NULL == pin) {
            DOUT(DBG_ERROR, ("pin is NULL ]"));
            return STATUS_INVALID_PARAMETER;
        }
    
        if (NULL == pin->ConnectionFormat) {
            DOUT(DBG_ERROR, ("ConnectionFormat is NULL ]"));
            return STATUS_INVALID_PARAMETER;
        }
    
        if (NULL == dataRange) {
            DOUT(DBG_ERROR, ("dataRange is NULL ]"));
            return STATUS_INVALID_PARAMETER;
        }
    
        KSDATARANGE_AUDIO* data_range = (KSDATARANGE_AUDIO*)dataRange; //lint !e826
        KSDATAFORMAT* data_format = pin->ConnectionFormat;
    
    
        // check the request, we are requested outside of the range!!!
        if (!IsEqualGUID(data_format->Specifier, data_range->DataRange.Specifier) ||
            data_format->FormatSize < sizeof(KSDATAFORMAT_WAVEFORMATEX)) {
            // invalid Specifier
            DOUT(DBG_ERROR, ("invalid Specifier or format size ]"));
            return STATUS_NO_MATCH;
        }
    
        // typecast it
        KSDATAFORMAT_WAVEFORMATEX* format_ext = (KSDATAFORMAT_WAVEFORMATEX*) data_format; //lint !e826
        WAVEFORMATEX& wave_format_ex = format_ext->WaveFormatEx;
    
        DOUT(DBG_PRINT, ("wFormatTag:%lu", wave_format_ex.wFormatTag));
        DOUT(DBG_PRINT, ("nChannels:%lu", wave_format_ex.nChannels));
        DOUT(DBG_PRINT, ("nSamplesPerSec:%lu", wave_format_ex.nSamplesPerSec));
        DOUT(DBG_PRINT, ("nAvgBytesPerSec:%lu", wave_format_ex.nAvgBytesPerSec));
        DOUT(DBG_PRINT, ("nBlockAlign:%lu", wave_format_ex.nBlockAlign));
        DOUT(DBG_PRINT, ("wBitsPerSample:%lu", wave_format_ex.wBitsPerSample));
        DOUT(DBG_PRINT, ("cbSize:%lu", wave_format_ex.cbSize));
    
        // check if it meets the requirements, allow only one data range
        if (data_range->MaximumBitsPerSample < wave_format_ex.wBitsPerSample ||
            data_range->MinimumBitsPerSample > wave_format_ex.wBitsPerSample) {
            // invalid format
            DOUT(DBG_ERROR, ("invalid BitsPerSample: %u ]", wave_format_ex.wBitsPerSample));
            return STATUS_NO_MATCH;
        }
    
        // check if it meets the requirements, allow only one data range
        if (data_range->MaximumChannels < wave_format_ex.nChannels || wave_format_ex.nChannels <= 0) {
            // invalid number of channels
            DOUT(DBG_ERROR, ("invalid number of channels %u ]", wave_format_ex.nChannels));
            return STATUS_NO_MATCH;
        }
    
        ULONG sample_size = wave_format_ex.nBlockAlign/wave_format_ex.nChannels;
        DOUT(DBG_PRINT, ("SampleSize %d, BitsPerSample %d ", sample_size, wave_format_ex.wBitsPerSample));
    
        // check format
        switch (wave_format_ex.wFormatTag) {
            case WAVE_FORMAT_PCM:
                // is supported
                 break;
    
            case WAVE_FORMAT_EXTENSIBLE:
                {
                    ASSERT(format_ext->WaveFormatEx.cbSize >= (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)));
                    WAVEFORMATEXTENSIBLE* waveFormatExtensible = (WAVEFORMATEXTENSIBLE*)(&format_ext->WaveFormatEx);
    
                    if (IsEqualGUID(waveFormatExtensible->SubFormat,KSDATAFORMAT_SUBTYPE_PCM)) {
                        // valid format
                        break;
                    }
    
                    // invalid format
                    DOUT(DBG_ERROR, ("invalid SubFormat:  ]"));
                    return STATUS_NO_MATCH;
                }
    
            default:
                 DOUT(DBG_ERROR, ("invalid wFormatTag: %u ]", wave_format_ex.wFormatTag));
                return STATUS_NO_MATCH;
        }
    
        NTSTATUS status = STATUS_SUCCESS;
    
        m_sampeRate =  wave_format_ex.nSamplesPerSec;
    
        DOUT(DBG_PRINT, ("status:%lu", status));
        DLEAVE();
        return status;
    }


    IntersectHandler() handler:

    NTSTATUS
    RenderPin::IntersectHandler(
        KSFILTER *filter,
        IRP *irp,
        KSP_PIN *pinInstance,
        KSDATARANGE *callerDataRange,
        KSDATARANGE *descriptorDataRange,
        ULONG bufferSize,
        VOID *data,
        ULONG *dataSize
        )
    {
        PAGED_CODE();
        DENTER();
    
        ASSERT(pinInstance);
        ASSERT(callerDataRange);
        ASSERT(descriptorDataRange);
        ASSERT(dataSize);
        UNREFERENCED_PARAMETER(pinInstance);
    
        if (descriptorDataRange->FormatSize < sizeof(KSDATARANGE_AUDIO)) {
            // invalid length
            DOUT(DBG_ERROR, ("invalid descriptorDataRange length got: %u expected: %u ]",
                descriptorDataRange->FormatSize, sizeof(KSDATARANGE_AUDIO)));
            return STATUS_NO_MATCH;
        }
    
        //
        // Descriptor data range must be WAVEFORMATEX.
        //
        KSDATARANGE_AUDIO* descriptor_data_range = (KSDATARANGE_AUDIO*)descriptorDataRange; //lint !e826
    
        KSDATARANGE_AUDIO* caller_data_range = NULL;
    
        //
        // Caller data range may be wildcard or WAVEFORMATEX.
        //
        if (IsEqualGUID(callerDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)) {
            //
            // Wildcard.  Do not try to look at the specifier.
            //
            caller_data_range = NULL;
        } else {
            //
            // WAVEFORMATEX.  Validate the specifier ranges.
            //
    
            if (callerDataRange->FormatSize < sizeof(KSDATARANGE_AUDIO)) {
                // invalid length
                DOUT(DBG_ERROR, ("invalid callerDataRange length got: %u expected: %u ]",
                    callerDataRange->FormatSize, sizeof(KSDATARANGE_AUDIO)));
                return STATUS_NO_MATCH;
            }
    
            caller_data_range = (KSDATARANGE_AUDIO*)callerDataRange; //lint !e826
    
            if ((caller_data_range->MaximumSampleFrequency < descriptor_data_range->MinimumSampleFrequency) ||
            (descriptor_data_range->MaximumSampleFrequency < caller_data_range->MinimumSampleFrequency)) {
                // invalid sample rate
                DOUT(DBG_ERROR, ("invalid sample rate caller: %u-%u descriptor: %u-%u ]",
                    caller_data_range->MinimumSampleFrequency, caller_data_range->MaximumSampleFrequency,
                    descriptor_data_range->MinimumSampleFrequency, descriptor_data_range->MaximumSampleFrequency));
                return STATUS_NO_MATCH;
            }
    
            if ((caller_data_range->MaximumBitsPerSample < descriptor_data_range->MinimumBitsPerSample) ||
            (descriptor_data_range->MaximumBitsPerSample < caller_data_range->MinimumBitsPerSample)) {
                // invalid bits per sample
                DOUT(DBG_ERROR, ("invalid bits per sample caller: %u-%u descriptor: %u-%u ]",
                    caller_data_range->MinimumBitsPerSample, caller_data_range->MaximumBitsPerSample,
                    descriptor_data_range->MinimumBitsPerSample, descriptor_data_range->MaximumBitsPerSample));
                return STATUS_NO_MATCH;
            }
    
    
            if ((LONG(descriptor_data_range->MaximumChannels) < LONG(caller_data_range->MaximumChannels)) ||
            ((LONG(descriptor_data_range->MaximumChannels) == 2) && ((LONG(caller_data_range->MaximumChannels) != 2) && (LONG(caller_data_range->MaximumChannels) != -1)))) {
                // invalid MaximumChannels
                DOUT(DBG_ERROR, ("invalid MaximumChannels caller: %u desc: %u ]",
                    caller_data_range->MaximumChannels, descriptor_data_range->MaximumChannels));
                return STATUS_NO_MATCH;
            }
        }
    
        unsigned int data_format_size = sizeof(KSDATAFORMAT);
    
        if (bufferSize == 0) {
            //
            // Size query - return the size.
            //
            *dataSize = data_format_size;
            DOUT(DBG_ERROR, ("STATUS_BUFFER_OVERFLOW ]"));
            return STATUS_BUFFER_OVERFLOW;
        }
    
        if (bufferSize < data_format_size) {
            //
            // Buffer is too small.
            //
            DOUT(DBG_ERROR, ("STATUS_BUFFER_TOO_SMALL ]"));
            return STATUS_BUFFER_TOO_SMALL;
        }
    
        if (NULL == data) {
            //
            // Data buffer is NULL.
            //
            DOUT(DBG_ERROR, ("Data buffer is null ]"));
            return STATUS_INVALID_PARAMETER;
        }
    
        if (NULL == dataSize) {
            //
            // Data size buffer is NULL.
            //
            DOUT(DBG_ERROR, ("Data size buffer is null ]"));
            return STATUS_INVALID_PARAMETER;
        }
    
        KSDATAFORMAT* ks_data_format = (KSDATAFORMAT *)(data);
    
        //
        // Gotta build the format.
        //
        *dataSize = data_format_size;
    
        //
        // All the guids are in the descriptor's data range.
        //
        RtlCopyMemory(
            ks_data_format,
            descriptorDataRange,
            sizeof(KSDATAFORMAT)
            );
    
        ///  wave_format_ex->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
    
        WORD number_of_channels;
        if (caller_data_range) {
            number_of_channels = (WORD)min(caller_data_range->MaximumChannels, descriptor_data_range->MaximumChannels);
        } else {
            number_of_channels = (WORD)descriptor_data_range->MaximumChannels;
        }
    
        ks_data_format->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
        ks_data_format->FormatSize = data_format_size;
        ks_data_format->SampleSize = SAMPLE_SIZE * number_of_channels; ///wave_format_ex->Format.nBlockAlign;
    
        DOUT(DBG_PRINT, ("status:%lu", STATUS_SUCCESS));
        DLEAVE();
    
        return STATUS_SUCCESS;
    }

    Discrete descriptor DataRange arrays:

    static
    const
    KSDATARANGE_AUDIO
    ksAudioStreamFormat44100 = {
    
        { // KSDATARANGE
          sizeof(KSDATARANGE_AUDIO),             // FormatSize
          0,                                      // Flags
          0,                                      // SampleSize
          0,                                      // Reserved
          STATIC_KSDATAFORMAT_TYPE_AUDIO,             // Media type
          STATIC_KSDATAFORMAT_SUBTYPE_PCM,            // Media subtype
          STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX, // Media format specifier
        },
    
        2,                                      // MaximumChannels
        16,                                     // MinimumBitsPerSample
        32,                                     // MaximumBitsPerSample
        44100,                                // MinimumSampleFrequency
        44100                                // MaximumSampleFrequency
    };
    
    static
    const
    KSDATARANGE_AUDIO
    ksAudioStreamFormat48000 = {
    
        { // KSDATARANGE
          sizeof(KSDATARANGE_AUDIO),             // FormatSize
          0,                                      // Flags
          0,                                      // SampleSize
          0,                                      // Reserved
          STATIC_KSDATAFORMAT_TYPE_AUDIO,             // Media type
          STATIC_KSDATAFORMAT_SUBTYPE_PCM,            // Media subtype
          STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX, // Media format specifier
        },
    
        2,                                      // MaximumChannels
        16,                                     // MinimumBitsPerSample
        32,                                     // MaximumBitsPerSample
        48000,                                // MinimumSampleFrequency
        48000                                // MaximumSampleFrequency
    };
    
    static
    const
    KSDATARANGE_AUDIO
    ksAudioStreamFormat88200 = {
    
        { // KSDATARANGE
          sizeof(KSDATARANGE_AUDIO),             // FormatSize
          0,                                      // Flags
          0,                                      // SampleSize
          0,                                      // Reserved
          STATIC_KSDATAFORMAT_TYPE_AUDIO,             // Media type
          STATIC_KSDATAFORMAT_SUBTYPE_PCM,            // Media subtype
          STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX, // Media format specifier
        },
    
        2,                                      // MaximumChannels
        16,                                     // MinimumBitsPerSample
        32,                                     // MaximumBitsPerSample
        88200,                                // MinimumSampleFrequency
        88200                                // MaximumSampleFrequency
    };
    
    static
    const
    KSDATARANGE_AUDIO
    ksAudioStreamFormat96000 = {
    
        { // KSDATARANGE
          sizeof(KSDATARANGE_AUDIO),             // FormatSize
          0,                                      // Flags
          0,                                      // SampleSize
          0,                                      // Reserved
          STATIC_KSDATAFORMAT_TYPE_AUDIO,             // Media type
          STATIC_KSDATAFORMAT_SUBTYPE_PCM,            // Media subtype
          STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX, // Media format specifier
        },
    
        2,                                      // MaximumChannels
        16,                                     // MinimumBitsPerSample
        32,                                     // MaximumBitsPerSample
        96000,                                // MinimumSampleFrequency
        96000                                // MaximumSampleFrequency
    };
    
    const
    PKSDATARANGE
    ksAudioPinDataRanges[4] = {
        PKSDATARANGE(&ksAudioStreamFormat44100),
        PKSDATARANGE(&ksAudioStreamFormat48000),
        PKSDATARANGE(&ksAudioStreamFormat88200),
        PKSDATARANGE(&ksAudioStreamFormat96000)
    };


    1) In attempt to establish 96000Hz from the "ControlPanel->Sound->MySpeakers->Properties->Advanced" everything it is fine, I see from log:

    MyKs:RenderPin::DispatchSetFormat[
    MyKs:wFormatTag:65534 
    MyKs:nChannels:2 
    MyKs:nSamplesPerSec:96000 
    MyKs:nAvgBytesPerSec:384000 
    MyKs:nBlockAlign:4 
    MyKs:wBitsPerSample:16 
    MyKs:cbSize:22 
    MyKs:SampleSize 2, BitsPerSample 16  
    MyKs:status:0 
    MyKs:RenderPin::DispatchSetFormat]
    

    2) Click to "OK" button to close the sound device properties dialog.

    3) Again select my device "MySpeakers" from an Sound dialog and click to the "Properties" button. Now I see a mystical thing from the log, where invoked a SetDataFormat() with the 44100Hz:

    MyKs:RenderPin::DispatchSetFormat[
    MyKs:wFormatTag:65534 
    MyKs:nChannels:2 
    MyKs:nSamplesPerSec:44100 
    MyKs:nAvgBytesPerSec:176400 
    MyKs:nBlockAlign:4 
    MyKs:wBitsPerSample:16 
    MyKs:cbSize:22 
    MyKs:SampleSize 2, BitsPerSample 16  
    MyKs:status:0 
    MyKs:RenderPin::DispatchSetFormat]
    

    Somebody can explain for me (or comment) a such behavior?

    Wednesday, November 20, 2013 8:47 AM