Реализация IMediaObject::AllocateStreamingResources

[Функция, связанная с этой страницей, Медиаплеер Windows sdk, является устаревшей функцией. Он был заменен MediaPlayer. MediaPlayer оптимизирован для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует по возможности использовать MediaPlayer вместо пакета SDK для Медиаплеер Windows. Корпорация Майкрософт предлагает переписать существующий код, использующий устаревшие API, чтобы по возможности использовать новые API.]

В примере Echo метод AllocateStreamingResources создает буфер задержки . Для этого выполните следующие действия.

  1. Вычисление размера буфера, соответствующего заданному времени задержки для данного типа мультимедиа.
  2. Выделение новой памяти или перераспределение размера буфера, если он уже существует.
  3. Вызов метода, который заполняет буфер значениями, представляющими тишину.

Значение тишины зависит от глубины бита. Для 8-разрядного звука тишина представлена шестнадцатеричным значением 80; Для 16-разрядного звука тишина представлена нулем.

Вычисление размера буфера задержки

Чтобы вычислить размер, необходимый для буфера задержки, необходимо сначала получить структуру WAVEFORMATEX , содержащую сведения о звуковых данных. В следующем примере извлекается указатель на эту структуру из структуры входных DMO_MEDIA_TYPE :

// Get a pointer to the WAVEFORMATEX structure.
WAVEFORMATEX *pWave = ( WAVEFORMATEX * ) m_mtInput.pbFormat;
if (NULL == pWave)
{
    return E_FAIL;
}

После сохранения указателя на правильную структуру WAVEFORMATEX можно проверить его элементы и использовать их для вычисления требуемого размера буфера. Это демонстрируется в следующем примере кода:

// Get the size of the buffer required.
m_cbDelayBuffer = (m_dwDelayTime * pWave->nSamplesPerSec * pWave->nBlockAlign) / 1000;

Этот алгоритм вычисляет размер буфера, умножая время задержки в миллисекундах на количество выборок в миллисекундах, затем умножая результат на количество каналов, а затем умножая результат на количество байтов в выборке. Количество каналов и количество байтов в выборке не очевидны; они кодируются в члене nBlockAlign. При делении на 1000 значение nSamplesPerSec уменьшается до выборок в миллисекундах; миллисекунда является требуемой единицей, так как время задержки выражается в миллисекундах.

Выделение памяти буфера задержки

После вычисления требований к памяти можно выделить буфер. Возможно, потребуется удалить буфер, если он существует, например, когда пользователь вызывает страницу свойств для изменения значения времени задержки. В следующем коде показано выделение буфера задержки:

// Test whether a buffer exists.
if (m_pbDelayBuffer)
{
    // A buffer already exists.
    // Delete the delay buffer.
    delete m_pbDelayBuffer;
    m_pbDelayBuffer = NULL;
}

// Allocate the buffer.
m_pbDelayBuffer = new BYTE[m_cbDelayBuffer];

if (!m_pbDelayBuffer)
    return E_OUTOFMEMORY;

Если буфер успешно выделен, переместите перемещаемый указатель на головку буфера, как показано в следующем примере:

// Move the echo pointer to the head of the delay buffer.
m_pbDelayPointer = m_pbDelayBuffer;

Заполнение буфера задержки тишиной

Удобно написать метод для заполнения буфера задержки значениями, представляющими тишину. Метод должен получить указатель на допустимую структуру WAVEFORMATEX, а затем проверить член wBitsPerSample, чтобы определить, является ли звук 8-разрядным или более высоким. В следующем примере буфер задержки заполняется правильным значением для тишины:

void CEcho::FillBufferWithSilence(WAVEFORMATEX *pWfex)
{
    if (8 == pWfex->wBitsPerSample)
    {
    ::FillMemory(m_pbDelayBuffer, m_cbDelayBuffer, 0x80);
    }
    else
    ::ZeroMemory(m_pbDelayBuffer, m_cbDelayBuffer);
}

Не забудьте добавить объявление forward для функции в файл заголовка Echo.h в закрытом разделе:

void FillBufferWithSilence(WAVEFORMATEX *pWfex);

Необходимо добавить код в конце AllocateStreamingResources, чтобы вызывать этот метод при каждом создании или изменении размера буфера задержки. В следующем примере кода передается указатель WAVEFORMATEX с именем pWave в новый метод:

// Fill the buffer with values representing silence.
FillBufferWithSilence(pWave);

Перераспределение памяти буфера задержки

Когда пользователь изменяет время задержки с помощью страницы свойств, размер буфера задержки также должен измениться. Вы уже добавили код в AllocateStreamingResources для изменения размера буфера, но необходимо добавить строку кода в CEcho::p ut_delay, чтобы вызывать метод выделения ресурсов при каждом изменении значения свойства. Ниже приведен код:

// Reallocate the delay buffer.
AllocateStreamingResources();

Работа с ресурсами потоковой передачи