Сообщений 2    Оценка 125        Оценить  
Система Orphus

Подсистема сжатия звука в Windows

Автор: Евгений Музыченко
Источник: Журнал Компьютер Пресс #7-2000
Опубликовано: 10.07.2003
Исправлено: 10.12.2016
Версия текста: 1.0

Введение
Основные принципы работы подсистемы сжатия
Драйверы, преобразователи, кодеки, фильтры
Постоянные и временные драйверы
Разрешенные и запрещенные драйверы
Глобальные и локальные драйверы
Приоритет поиска драйвера
Аппаратная поддержка драйверов
Синхронные и асинхронные драйверы
Уведомление приложений о выполнении операций
Типы фильтров и форматов
Стандартные фильтры и форматы
Порции и буферы преобразуемых данных
Потоки преобразования
Независимые участки в потоках
Ключи объектов
Версии ACM и драйверов
Пресеты
Программирование ACM
Типовые схемы применения средств ACM
Запрос сведений о заданном фильтре или формате
Перебор доступных типов и стандартных фильтров/форматов
Выбор фильтра/формата при помощи стандартного диалога
Выбор наиболее подходящего формата
Обработка потока данных
Поиск звукового устройства, аппаратно поддерживающего сжатый формат
Типы и структуры, используемые в ACM
Тип FOURCC
Структура WAVEFORMATEX
Структура WAVEFILTER
Структура ACMDRIVERDETAILS
Структуры ACMFILTERTAGDETAILS / ACMFORMATTAGDETAILS
Структуры ACMFILTERDETAILS / ACMFORMATDETAILS
Структуры ACMFILTERCHOOSE и ACMFORMATCHOOSE
Структура ACMSTREAMHEADER
Функции ACM
Классы функций интерфейса ACM
Возвращаемые значения
Информационные функции
acmGetVersion - запрос версии ACM
acmMetrics - запрос параметров компонент ACM
Функции работы с драйверами
acmDriverAdd - добавление нового драйвера
acmDriverRemove - удаление установленного драйвера
acmDriverEnum - перебор установленных драйверов
acmDriverID - запрос идентификатора драйвера
acmDriverOpen - открывание драйвера
acmDriverClose - закрывание открытого драйвера
acmDriverMessage - передача сообщения драйверу
acmDriverPriority - изменение приоритета драйвера
acmDriverDetails - запрос описания драйвера
Функции работы с фильтрами и форматами
acmFilterTagDetails / acmFormatTagDetails - запрос описания типа
acmFilterDetails / acmFormatDetails - запрос параметров фильтра/формата
Функции перебора типов и стандартных фильтров/форматов
acmFilterChoose / acmFormatChoose - вывод диалога выбора фильтра/формата
acmFormatSuggest - запрос рекомендуемого для преобразования формата
Функции работы с потоками преобразования
acmStreamOpen - открывание потока преобразования
acmStreamClose - закрывание потока
acmStreamSize - запрос рекомендуемого размера порции преобразования
acmStreamPrepareHeader - подготовка заголовка к преобразованию
acmStreamUnprepareHeader - отмена действий по подготовке заголовка
acmStreamConvert - запрос преобразования очередной порции звуковых данных
acmStreamReset - прерывание обработки потока
acmStreamMessage - посылка сообщения драйверу потока
Функции, определяемые приложением
DriverEnumCallback - функция поддержки перебора драйверов
Функции поддержки перебора типов и стандартных фильтров/форматов
Функция перехвата сообщений диалога выбора фильтра/формата
Функция уведомления приложения о завершении операции с потоком
DriverProc - функция пользовательского драйвера ACM
Существующие драйверы подсистемы сжатия
Установка и удаление постоянных драйверов ACM
Использование драйвера фильтров MSFilter
Фильтр Volume
Фильтр Echo
Недостатки подсистемы сжатия
Пример программы, использующей ACM

Демонстрационный проект - RTCompress

Введение

Подсистема сжатия звука (Audio Compression Manager - ACM, диспетчер сжатия звука) первоначально была введена в расширении Video For Windows (VFW) для Windows 3.x, вместе с подсистемой сжатия изображения (Video Compression Manager - VCM). Целью введения этих подсистем было создание удобного, универсального и гибкого интерфейса для работы со звуковыми и видеопотоками. Позднее ACM и VCM были включены в состав стандартной звуковой подсистемы для платформ Win32. Таким образом, для работы с ACM необходима либо платформа Windows 3.x с расширением VFW, либо платформа Win32.

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

ПРИМЕЧАНИЕ

В отличие от базовой звуковой подсистемы (MME/Wave), подсистема сжатия в Win32 выполнена полностью 32-разрядной и не содержит внутренних переходов между 32- и 16-разрядным кодом. Некоторые драйверы существуют и в 16-разрядных вариантах, обеспечивая сервис ACM для приложений Win16.

Подсистема сжатия тесно связана со службой переназначения (Wave Mapper) звуковой подсистемы. При открывании Wave–устройства может быть задан режим прозрачного преобразования форматов, при котором Wave Mapper при помощи ACM находит подходящее сочетание звукового устройства и кодека, обеспечивающее ввод или вывод звука в запрошенном формате. При этом приложение может считать, что запрошенный формат поддерживается непосредственно звуковым адаптером.

Основные принципы работы подсистемы сжатия

По структуре и принципу работы подсистема ACM очень похожа на базовую звуковую подсистему MME/Wave, описанную в статье "Низкоуровневое программирование звука в Windows". Остановлюсь лишь на основных особенностях и отличиях подсистемы сжатия:

Драйверы, преобразователи, кодеки, фильтры

В ACM существует два вида обработки звука:

Модули драйверов ACM, реализующие функции преобразования форматов, называют преобразователями формата (format convertors). Модули, реализующие функции фильтрования, называются фильтрами (filters). Один и тот же подключаемый драйвер может совмещать в себе различные функции, а также - содержать более одного преобразователя или фильтра.

Преобразование форматов, при котором меняется тип (tag) формата, обычно сопровождается изменением объема звуковых данных. Такие виды преобразования называются сжатием (compression) или восстановлением (decompression). Сжатию обычно подвергаются данные в формате PCM, а при восстановлении формат PCM обычно имеет результат операции. Преобразователи формата, реализующие сжатие/восстановление, называются кодеками (codec - coder/decoder или compressor/decompressor).

Постоянные и временные драйверы

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

Разрешенные и запрещенные драйверы

По умолчанию все драйверы ACM разрешены для использования. Однако служба ACM - по требованию пользователя или приложения - может запретить включение в работу отдельных драйверов. Например, таким образом можно предотвратить автоматическое подключение неэффективного драйвера, когда имеется более подходящий, или на время исключить из работы драйвер, содержащий ошибки. Для запрещенного драйвера можно только узнать его параметры; все остальные операции с драйвером невозможны до тех пор, пока он не будет снова разрешен для работы.

Глобальные и локальные драйверы

Первоначально, на платформе Windows 3.x, драйверы подразделялись на глобальные и локальные. Глобальный драйвер был доступен всем приложениям Windows, локальный - только установившему его приложению. Соответственно, все постоянные драйверы являлись глобальными.

В Win32 поведение системы было изменено - теперь всем приложениям доступны только постоянные драйверы, а атрибут "локальный" или "глобальный" используется для определения приоритета при автоматическом поиске драйвера.

Приоритет поиска драйвера

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

Аппаратная поддержка драйверов

Большинство драйверов ACM являются программными - они используют для своей работы только ресурсы центрального процессора, и не нуждаются в каких-либо дополнительных аппаратных средствах. Для успешной работы программного драйвера необходим лишь достаточно мощный центральный процессор и необходимое количество основной памяти.

При наличии в системе DSP (Digital Signal Processor - цифровой сигнальный процессор), который может обрабатывать звук практически без участия центрального процессора, для него может быть разработан драйвер ACM, выполняющий обработку звука средствами этого DSP. Сам DSP при этом может быть как встроен в системную плату, так и находиться на одной из плат расширения. В этом случае говорят, что драйвер ACM имеет аппаратную поддержку.

Некоторые звуковые устройства поддерживают аппаратное преобразование форматов в реальном времени при вводе/выводе звука - например, они могут выдавать записываемый звук сразу в формате ADPCM, сжимая его "на ходу" при помощи встроенного DSP. Несмотря на то, что такие устройства бесполезны для полнофункционального драйвера ACM и полностью поддерживаются базовой звуковой подсистемой MME/Wave, ACM предоставляет некоторые удобства в отношении и таких устройств. ACM содержит средства поиска и выбора форматов по различным критериям, и одним из таких критериев является аппаратная поддержка формата одним из звуковых адаптеров - при вводе и/или при выводе.

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

Синхронные и асинхронные драйверы

Как и драйверы звуковых адаптеров, драйверы ACM также могут быть синхронными и асинхронными. Практически все программные драйверы являются синхронными; драйверы с аппаратной поддержкой обычно делаются асинхронными. Для асинхронных драйверов предусмотрена очередь входных заданий и механизм уведомления приложения о завершении ранее запрошенных операций; синхронные драйверы не возвращают приложению управления до тех пор, пока не будет завершена запрошенная операция.

Уведомление приложений о выполнении операций

ACM поддерживает два вида уведомления приложения: о выполнении запрошенных операций над потоком преобразования, и об изменении приоритетов и состояний глобальных драйверов ACM.

Механизм уведомления о выполнении операций над потоками полностью аналогичен базовой звуковой подсистеме MME/Wave, за одним исключением - по непонятной причине не поддерживаются сообщения задаче (thread). Таким образом, для уведомления может быть либо активизирован объект события (event), либо вызвана функция приложения, либо отправлено сообщение одному из окон приложения. Приложение уведомляется о наступлении каждого из трех событий потока: успешное завершение функций открывания и закрывания потока, завершение операции преобразования. Вид уведомления задается при открывании потока функцией acmStreamOpen.

Для уведомления об изменении приоритетов и состояний драйверов заданному окну приложения посылается заданное сообщение Windows. Окно и сообщение задаются подобно установке нового драйвера - функцией acmDriverAdd. Окно, получающее такие сообщения, называется окномуведомления (notification window).

Типы фильтров и форматов

Основной характеристикой фильтра или формата является его тип - способ обработки данных в фильтре (эхо, усиление/ослабление) или способ представления данных в формате (PCM, ADPCM, MPEG и т.п.).

Конкретные форматы и фильтры внутри каждого типа отличаются только параметрами: частотой дискретизации, разрядностью отсчета, тонкостями кодирования - для форматов, степенью усиления/ослабления сигнала, величиной задержки - для фильтров. Основные характеристики - способ представления и вид обработки - в пределах одного типа остаются неизменными.

Каждому типу фильтров и форматов присвоен свой уникальный код (tag), который однозначно идентифицирует его в подсистеме сжатия. Коды типов имеют неизменные числовые значения и для обеспечения уникальности должны быть зарегистрированы в Microsoft. Наряду с кодами типов ACM использует также индексы (внутренние номера) типов фильтров/форматов, поддерживаемых каждым из драйверов. Индексы не имеют ничего общего с кодами и отражают лишь порядковые номера фильтров/форматов различного типа в служебных списках драйвера. При помощи индексов удобно последовательно перебирать все типы фильтров/форматов, поддерживаемые заданным драйвером.

Стандартные фильтры и форматы

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

Однако количество допустимых фильтров или форматов любого типа не ограничивается списком стандартных; остальные могут быть получены изменением второстепенных параметров (частоты дискретизации, разрядности отсчета, количества каналов, громкости, задержки и т.п.). Стандартные фильтры/форматы являются всего лишь фиксированными сочетаниями различных параметров фильтра/формата внутри каждого типа.

Порции и буферы преобразуемых данных

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

Для каждого потока преобразования создаются два буфера: входной - для порции исходных данных, и выходной - для порции данных результата. Размер преобразуемой порции не может превышать выбранного размера буфера.

Потоки преобразования

Как и основная звуковая подсистема MME/Wave, ACM обрабатывает звуковые данные потоками. Это означает, что приложение не может обрабатывать звуковые данные в произвольной последовательности, а только последовательно, от начала к концу потока. Такое ограничение связано с тем, что как преобразование форматов, так и фильтрование может потребовать информации о предшествовании - например, относительное кодирование амплитуд в формате ADPCM или формирование эффекта эха в фильтре Echo. Поэтому обработка звукового потока в ACM включает в себя три стадии:

Поток преобразования ACM фактически состоит из двух звуковых потоков - исходного (source) и результирующего (destination). Данные исходного потока существуют до начала обработки и не изменяются после ее завершения; данные результирующего потока создаются в процессе обработки.

Независимые участки в потоках

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

Ключи объектов

Как и в остальных подсистемах Windows, объекты ACM, с которыми работает приложение, идентифицируются специальными ключами, которые ACM возвращает приложению в ответ на запрос доступа к объекту. В ACM имеется три вида объектов:

Каждый из объектов имеет свой тип ключа - HACMDRIVERID, HACMDRIVER, HACMSTREAM. Кроме этого, имеется универсальный тип HACMOBJ, предназначенный для использования в функциях, работающих с объектами различного типа.

Версии ACM и драйверов

Номера версий, используемый в ACM, имеют тип DWORD и состоят из трех компонент:

Для разбора полученного двойного слова удобно использовать стандартные макросы Windows:

DWORD x = acmGetVersion ();
Major = HIBYTE (HIWORD (x));
Minor = LOBYTE (HIWORD (x));
Build = LOWORD (x);

Пресеты

ACM позволяет присваивать отдельным стандартным фильтрам/форматам произвольные пользовательские названия (пресеты), которые затем сохраняются в базе данных ACM в виде отдельного списка. Диалог выбора фильтра/формата, выводимый функциями выбора, содержит в верхней части список пресетов, из которого можно быстро выбрать требуемый.

Программирование ACM

Для программирования ACM необходим любой стандартный Win32 SDK, содержащий файлы заголовков MMSYSTEM.H, MSACM.H, MMREG.H и библиотек WINMM.LIB, MSACM32.LIB. Такой SDK имеется в составе всех известных компиляторов, поддерживающих платформу Win32.

Типовые схемы применения средств ACM

Запрос сведений о заданном фильтре или формате

Для имеющегося описателя фильтра или описателя формата выполняются функции acmFilterTagDetails, acmFilterDetails или acmFormatTagDetails, acmFormatDetails, возвращающие сведения либо о типе, к которому принадлежит указанный фильтр/формат, либо о самом фильтре/формате. В частности, полученные сведения могут использоваться для вывода информации пользователю.

Перебор доступных типов и стандартных фильтров/форматов

Для имеющегося набора условий, которым должен удовлетворять искомый тип или стандартный фильтр/формат, выполняются функции перебора фильтров/форматов - acmFilterTagEnum, acmFilterEnum, acmFormatTagEnum, acmFormatEnum. В результате для каждого подходящего типа, или каждого подходящего стандартного фильтра/формата вызывается соответствующая функция поддержки перебора. В результате поиск может быть прерван при обнаружении подходящего объекта, или может быть составлен список объектов, предлагаемый затем пользователю для ручного выбора.

Выбор фильтра/формата при помощи стандартного диалога

Для имеющегося набора условий, которым должен удовлетворять искомый тип или стандартный фильтр/формат, формируется структура ACMFILTERCHOOSE / ACMFORMATCHOOSE и выполняется функция выбора acmFilterChoose / acmFormatChoose. В результате ACM выводит пользователю стандартный диалог, содержащий списки подходящих типов и стандартных фильтров/форматов. После выбора пользователем нужного фильтра/формата ACM возвращает его описатель и дополнительные сведения.

Выбор наиболее подходящего формата

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

Обработка потока данных

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

Исходный звуковой поток может быть взят как из файла, так и получен в реальном времени - от любого звукового устройства, по сети, или другим путем. Результирующий поток также может быть записан в файл, выведен в реальном времени на звуковое устройство, передан по сети и т.п.

Поиск звукового устройства, аппаратно поддерживающего сжатый формат

При наличии звукового потока в заданном сжатом формате приложение может выполнить поиск звукового устройства, аппаратно поддерживающего ввод и/или вывод в таком формате. Для этого вначале при помощи функции acmFormatEnum выполняется перебор форматов, эквивалентных заданному, а в слове флагов перебора устанавливается HARDWARE. В результате, при успешном поиске, будет обнаружен драйвер, "знающий" о существовании звукового устройства с аппаратной поддержкой заданного формата; в слове режимов и возможностей которого будет установлен флаг HARDWARE. Опросив этот драйвер функцией acmMetrics с параметрами HARDWARE_WAVE_INPUT или HARDWARE_WAVE_OUTPUT, можно получить идентификатор звукового устройства, по которому оно может быть открыто функциями waveInOpen или waveOutOpen.

Типы и структуры, используемые в ACM

Большинство структур имеет в своем составе поле cbStruct, в которое приложение должно занести размер области памяти, где размещена структура. Интерфейсные функции используют это поле двояким образом: когда информация из структуры является исходной - поле показывает, какой ее объем реально присутствует в указанной области памяти; когда функция заполняет поля структуры возвращаемой информацией - поле cbStruct ограничивает размер заполняемой области. В зависимости от выбранной функции и режимов ее работы существуют различные ограничения на размер области памяти: она может включать либо только часть полей описанной структуры, либо всю структуру целиком, либо иметь резервную область непосредственно за концом структуры. В последнем случае резервная область может использоваться для дополнительных данных, не вошедших в основные поля описанной структуры.

Когда ACM заполняет структуру, содержащую поле cbStruct, в него заносится реальный размер возвращенной информации. Если какие-то поля структуры являются необязательными, приложение может определить, какая часть структуры была заполнена ACM.

При обращении к ACM вместе со структурой часто передается сопровождающий набор флагов, показывающих, какие из полей структуры несут осмысленную информацию. Несмотря на то, что такие поля анализируются лишь при наличии соответствующих флагов, многие функции являются "привередливыми" и требуют, чтобы неиспользуемые входные поля имели нулевые значения. Чтобы гарантировать успешную работу функций, необходимо перед обращением к ним либо обнулить все неиспользуемые входные поля, либо обнулить всю структуру до заполнения ее полей осмысленной информацией.

Тип FOURCC

Описывает коды, используемых в формате RIFF (Resource Interchange File Format - формат файлов обмена ресурсами). Файлы формата RIFF широко используются для представления звуковых и видеоданных (расширения WAV, AVI, ANI, RMI, SBK и т.п.) и Windows предоставляет для работы с ними специальный интерфейс MMIO (MultiMedia Input/Output - мультимедийный ввод/вывод). В MMIO определены стандартные коды RIFF, которые используются для идентификации драйверов ACM.

Тип FOURCC (Four-Character Code - четырехсимвольный код) представляет собой двойное слово (DWORD), содержащее слово из 1..4 ASCII–символов - "RIFF", "wave", "fmt" и т.п. Слова короче четырех символов дополняются справа пробелами.

Порядок символов в двоичном представлении типа FOURCC тот же, что и в файле: первый символ представляется младшим байтом, а последний - старшим. Поэтому простое присваивание символьной константы (например, 'fmt ') даст обратное расположение байтов в двойном слове. Для корректного формирования значения можно использовать макросы MAKEFOURCC и mmioFOURCC.

Структура WAVEFORMATEX

Полностью описывает параметры формата. Описание структуры приведено в предыдущей статье - "Низкоуровневое программирование звука в Windows".

Структура WAVEFILTER

Полностью описывает параметры фильтра.

DWORD  cbStruct;
DWORD  dwFilterTag;
DWORD  fdwFilter;
DWORD  dwReserved [5];

Структура ACMDRIVERDETAILS

Описывает параметры и свойства драйвера ACM. Кроме cbStruct, поля структуры заполняются ACM.

DWORD  cbStruct;
FOURCC  fccType;
FOURCC  fccComp;
WORD  wMid;
WORD  wPid;
DWORD  vdwACM;
DWORD  vdwDriver;
DWORD  fdwSupport;
DWORD  cFormatTags;
DWORD  cFilterTags;
HICON  hicon;
char  szShortName [ACMDRIVERDETAILS_SHORTNAME_CHARS];
char  szLongName [ACMDRIVERDETAILS_LONGNAME_CHARS];
char  szCopyright [ACMDRIVERDETAILS_COPYRIGHT_CHARS];
char  szLicensing [ACMDRIVERDETAILS_LICENSING_CHARS];
char  szFeatures [ACMDRIVERDETAILS_FEATURES_CHARS];
CONVERTER Драйвер содержит преобразователи формата.
CODEC Драйвер содержит кодеки.
FILTER Драйвер содержит фильтры.
DISABLED Драйвер запрещен.
ASYNC Драйвер является асинхронным.
HARDWARE Драйвер связан со звуковым адаптером, аппаратно поддерживающим ввод/вывод звука в сжатом формате. Для получения идентификатора звукового устройства необходимо использовать функцию acmMetrics.
LOCAL Драйвер является локальным

Структуры ACMFILTERTAGDETAILS / ACMFORMATTAGDETAILS

Описывают параметры типа фильтров/форматов, и различаются только именами полей. Поля структур заполняются ACM, если не оговорено иначе.

Структура ACMFILTERTAGDETAILS:

DWORD  cbStruct; 
DWORD  dwFilterTagIndex; 
DWORD  dwFilterTag; 
DWORD  cbFilterSize; 
DWORD  fdwSupport; 
DWORD  cStandardFilters; 
char  szFilterTag [ACMFILTERTAGDETAILS_FILTERTAG_CHARS]; 

Структура ACMFFORMATTAGDETAILS:

DWORD  cbStruct;
DWORD  dwFormatTagIndex;
DWORD  dwFormatTag;
DWORD  cbFormatSize;
DWORD  fdwSupport;
DWORD  cStandardFormats;
char  szFormatTag [ACMFORMATTAGDETAILS_FORMATTAG_CHARS];

Структуры ACMFILTERDETAILS / ACMFORMATDETAILS

Описывают параметры конкретного фильтра/формата, и различаются только именами полей:

Структура ACMFILTERDETAILS:

DWORD  cbStruct; 
DWORD  dwFilterIndex; 
DWORD  dwFilterTag; 
DWORD  fdwSupport; 
LPWAVEFILTER  pwfltr; 
DWORD  cbwfltr; 
char  szFilter [ACMFILTERDETAILS_FILTER_CHARS]; 

Структура ACMFORMATDETAILS:

DWORD  cbStruct;
DWORD  dwFormatIndex;
DWORD  dwFormatTag;
DWORD  fdwSupport;
LPWAVEFORMATEX  pwfx;
DWORD  cbwfx;
char  szFormat [ACMFORMATDETAILS_FORMAT_CHARS];

Структуры ACMFILTERCHOOSE и ACMFORMATCHOOSE

Эти две очень похожие структуры описывают наборы данных, необходимые для вывода пользователю диалога, содержащего меню всех доступных или подходящих стандартных фильтров/форматов. Используются функциями acmFilterChoose и acmFormatChoose.

Структура ACMFILTERCHOOSE:

DWORD  cbStruct;
DWORD  fdwStyle;
HWND  hwndOwner;
LPWAVEFILTER  pwfltr;
DWORD  cbwfltr;
LPCSTR  pszTitle;
char  szFilterTag [ACMFILTERTAGDETAILS_FILTERTAG_CHARS];
char  szFilter [ACMFILTERDETAILS_FILTER_CHARS];
LPSTR  pszName;
DWORD  cchName;
DWORD  fdwEnum;
LPWAVEFILTER  pwfltrEnum;
HINSTANCE  hInstance;
LPCSTR  pszTemplateName;
LPARAM  lCustData;
ACMFILTERCHOOSEHOOKPROC  pfnHook;

Структура ACMFORMATCHOOSE:

DWORD  cbStruct;
DWORD  fdwStyle;
HWND  hwndOwner;
LPWAVEFORMATEX  pwfx;
DWORD  cbwfx;
LPCSTR  pszTitle;
char  szFormatTag [ACMFORMATTAGDETAILS_FORMATTAG_CHARS];
char  szFormat [ACMFORMATDETAILS_FORMAT_CHARS];
LPSTR  pszName;
DWORD  cchName;
DWORD  fdwEnum;
LPWAVEFORMATEX  pwfxEnum;
HINSTANCE  hInstance;
LPCSTR  pszTemplateName;
LPARAM  lCustData;
ACMFORMATCHOOSEHOOKPROC  pfnHook;
CONTEXTHELP В диалоге будет доступна контекстно-зависимая помощь. При запросе пользователем помощи ACM будет посылать окну-владельцу сообщения с кодами ACMHELPMSGCONTEXTMENU и ACMHELPMSGCONTEXTHELP, параметры wParam и lParam которых будут скопированы из исходных сообщений WM_CONTEXTMENU или WM_CONTEXTHELP. Коды сообщений ACM предварительно должны быть зарегистрированы в Windows посредством функции RegisterWindowMessage.
ENABLEHOOK Разрешает использование функции перехвата сообщений Windows, заданной полем pfnHook.
ENABLETEMPLATE Диалог будет создан из шаблона (template), описываемого полями hInstance и pszTemplateName.
ENABLETEMPLATEHANDLE Поле hInstance содержит ключ уже загруженного в память шаблона диалога. В этом случае поле pszTemplateName игнорируется.
INITTOFILTERSTRUCTINITTOWFXSTRUCT Начальные значения для типа и стандартного фильтра/формата в диалоге будут выбраны на основе описателя, указатель которого задан полем pwfltr / pwfx. В этом случае поле pwfltr/pwfx должно ссылаться на правильно заполненную структуру типа WAVEFILTER / WAVEFORMATEX.
SHOWHELP Диалог будет снабжен кнопкой запроса помощи (Help), при нажатии которой окну-владельцу будет посылаться сообщение ACM с кодом ACMHELPMSGSTRING. Это сообщение необходимо предварительно зарегистрировать в Windows посредством функции RegisterWindowMessage.

Структура ACMSTREAMHEADER

Описывает фрагмент преобразуемого звукового потока и называется заголовком потока.

DWORD  cbStruct; 
DWORD  fdwStatus; 
DWORD  dwUser; 
LPBYTE  pbSrc; 
DWORD  cbSrcLength; 
DWORD  cbSrcLengthUsed; 
DWORD  dwSrcUser; 
LPBYTE  pbDst; 
DWORD  cbDstLength; 
DWORD  cbDstLengthUsed; 
DWORD  dwDstUser; 
DWORD  dwReservedDriver [10]; 
DONE Преобразование завершено.
INQUEUE Заголовок находится в очереди драйвера.
PREPARED Заголовок подготовлен для передачи драйверу.

Функции ACM

Классы функций интерфейса ACM

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

Кроме этого, ACM сам может вызывать (callback) три типа функций приложения:

Информационные функции

acmGetVersion Запрос версии ACM
acmMetrics Запрос различных параметров ACM

Функции работы с драйверами

acmDriverAdd Установка собственного драйвера приложения или задание окна уведомления
acmDriverRemove Удаление собственного драйвера приложения
acmDriverOpen Открывание драйвера
acmDriverClose Закрывание драйвера
acmDriverDetails Запрос сведений о драйвере
acmDriverEnum Перебор доступных драйверов
acmDriverID Запрос идентификатора драйвера
acmDriverPriority Установка приоритета драйвера
acmDriverMessage Передача сообщения драйверу

Функции работы с фильтрами

acmFilterTagDetails Запрос сведений о типе фильтра
acmFilterDetails Запрос сведений о фильтре
acmFilterTagEnum Перебор доступных типов фильтров
acmFilterEnum Перебор доступных стандартных фильтров
acmFilterChoose Выбор фильтра при помощи стандартного диалога ACM

Функции работы с форматами

acmFormatTagDetails Запрос сведений о типе формата
acmFormatDetails Запрос сведений о формате
acmFormatTagEnum Перебор доступных типов форматов
acmFormatEnum Перебор доступных стандартных форматов
acmFormatChoose Выбор формата при помощи стандартного диалога ACM
acmFormatSuggest Запрос наиболее подходящего для преобразования формата

Функции работы с потоками

acmStreamOpen Открывание потока преобразования
acmStreamClose Закрывание потока
acmStreamSize Запрос размеров буферов потока
acmStreamPrepareHeader Подготовка буфера потока
acmStreamUnprepareHeader Отмена подготовки буфера потока
acmStreamConvert Преобразование очередной порции данных в потоке
acmStreamReset Сброс (уничтожение) потока
acmStreamMessage Передача сообщения драйверу потока

Функции, определяемые приложением

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

DriverProc Основная функция драйвера
ChooseHook Перехват сообщений диалога выбора фильтра/формата
DriverEnumCallback Поддержка перебора драйверов
FilterTagEnumCallback Поддержка перебора типов фильтров
FilterEnumCallback Поддержка перебора стандартных фильтров
FormatTagEnumCallback Поддержка перебора типов форматов
FormatEnumCallback Поддержка перебора стандартных форматов
StreamCallback Уведомление о завершении операции с потоком

Возвращаемые значения

Большинство функций ACM возвращает значения типа MMRESULT - универсальный код результата звуковой подсистемы Windows. В дополнение к стандартным кодам, константы для которых имеют префикс MMSYSERR_, для ACM определены константы с префиксами ACMERR_:

NOTPOSSIBLE Невозможно выполнить запрошенную операцию. Обычно эта ошибка возникает при невозможности использовать требуемое сочетание форматов, или когда объема заданного буфера недостаточно для записи всех затребованных данных.
BUSY Запрошенный драйвер в настоящее время используется, попытка закрыть поток с незавершенной асинхронной операцией, и т.п.
UNPREPARED Буфер преобразования не был подготовлен функцией acmStreamPrepareHeader.
CANCELED Пользователь закрыл кнопкой Cancel диалог, выведенный функцией выбора фильтра/формата.

Информационные функции

acmGetVersion - запрос версии ACM

DWORD acmGetVersion (void);

Возвращает версию ACM.

acmMetrics - запрос параметров компонент ACM

MMRESULT acmMetrics (
  HACMOBJ  Obj,
  UINT  MetricCode,
  void  *ForMetric
);
COUNT_DRIVERS, COUNT_LOCAL_DRIVERS Запрос количества разрешенных для работы драйверов ACM.
COUNT_DISABLED, COUNT_LOCAL_DISABLED Запрос количества запрещенных для работы драйверов ACM.
COUNT_CONVERTERS, COUNT_LOCAL_CONVERTERS Запрос количества установленных преобразователей формата.
COUNT_CODECS, COUNT_LOCAL_CODECS Запрос количества установленных кодеков.
COUNT_FILTERS, COUNT_LOCAL_FILTERS Запрос количества установленных фильтров.
COUNT_HARDWARE Запрос количества драйверов ACM, введенных для поддержки звуковых устройств с аппаратным преобразованием формата при вводе/выводе звука.
DRIVER_PRIORITY Запрос приоритета заданного драйвера.
DRIVER_SUPPORT Запрос флагов возможностей и режимов заданного драйвера.
HARDWARE_WAVE_INPUT Запрос идентификатора звукового устройства, аппаратно поддерживающего ввод (запись) звука в сжатом формате.
HARDWARE_WAVE_OUTPUT Запрос идентификатора звукового устройства, аппаратно поддерживающего вывод (воспроизведение) звука в сжатом формате.
MAX_SIZE_FILTER Запрос максимального размера структуры WAVEFILTER, необходимой для описания любого из фильтров, поддерживаемых заданным драйвером.
MAX_SIZE_FORMAT Запрос максимального размера структуры WAVEFORMATEX, необходимой для описания любого из форматов, поддерживаемых заданным драйвером.

Константы для кодов количества драйверов, содержащие в своих именах слово LOCAL, относятся к локальным драйверам ACM; варианты этих констант без слова LOCAL относятся к глобальным драйверам. Для определения общего количества установленных глобальных или локальных драйверов необходимо просуммировать возвращенные количества разрешенных и запрещенных для работы драйверов соответствующего типа.

В запросах количества драйверов параметр Obj должен быть нулевым. В запросах приоритета, флагов и связанного звукового устройства параметр Obj задает идентификатор опрашиваемого драйвера. В запросах максимальных размеров структур параметр Obj либо задает ключ или идентификатор драйвера, фильтры/форматы которого опрашиваются, либо равен NULL - в этом случае возвращается максимальное значение запрошенного параметра среди всех установленных драйверов.

ForMetric - указатель переменной, в которую возвращается запрашиваемый параметр. В описанной реализации все возвращаемые параметры имеют тип DWORD.

Функции работы с драйверами

acmDriverAdd - добавление нового драйвера

Функция устанавливает новый драйвер ACM, либо указывает окно уведомления, которому будут передаваться сообщения об изменении приоритета и состояния глобальных драйверов ACM.

MMRESULT acmDriverAdd (
  HACMDRIVERID  *ForId,
  HINSTANCE  ModuleInstance,
  LPARAM  Entry,
  DWORD  Message,
  DWORD  Flags
);
FUNCTION Параметр Entry является адресом функции драйвера, оформленной в соответствии с прототипом acmDriverProc.
NOTIFYHWND Параметр Entry является ключом окна, которое будет получать уведомление об изменении приоритетов и состояний глобальных драйверов ACM в системе. Код сообщения задается параметром Message.
GLOBAL Драйвер устанавливается как глобальный.
LOCAL Драйвер устанавливается как локальный.

Код сообщения Windows определяется приложением. Параметры wParam и lParam в получаемом окном сообщении не используются.

Флаги GLOBAL и LOCAL задаются только при установке драйверов; при задании окна уведомления они недопустимы.

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

acmDriverRemove - удаление установленного драйвера

Удаляет установленный драйвер из списка доступных для приложения драйверов.

MMRESULT acmDriverRemove (
  HACMDRIVERID  DrvId,
  DWORD  Reserved
);

acmDriverEnum - перебор установленных драйверов

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

MMRESULT acmDriverEnum (
  ACMDRIVERENUMCB  Callback,
  DWORD  Instance,
  DWORD  Flags
);
DISABLED В процесс перебора будут включены запрещенные драйверы. По умолчанию ACM перебирает только разрешенные драйверы.
NOLOCAL В процесс перебора будут включены только глобальные драйверы.

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

acmDriverID - запрос идентификатора драйвера

Запрашивает у ACM идентификатор драйвера по ключу открытого драйвера или потока.

MMRESULT acmDriverID (
  HACMOBJ  Obj,
  HACMDRIVERID  *ForId,
  DWORD  Reserved
);

acmDriverOpen - открывание драйвера

Открывает требуемый драйвер для последующей работы с ним.

MMRESULT acmDriverOpen (
  HACMDRIVER  *ForHandle, 
  HACMDRIVERID  DrvId,
  DWORD  Reserved
);

acmDriverClose - закрывание открытого драйвера

MMRESULT acmDriverClose (
  HACMDRIVER  Drv,
  DWORD  Reserved
);

acmDriverMessage - передача сообщения драйверу

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

LRESULT acmDriverMessage (
  HACMDRIVER  Drv,
  UINT  Msg, 
  LPARAM  Param1,
  LPARAM  Param2
);

Стандартное сообщение ACMDM_DRIVER_ABOUT требует от драйвера вывести диалог с кратким описанием и версией. Параметр Param1 должен содержать ключ окна-владельца диалога или быть нулевым, параметр Param2 не используется и должен быть нулевым.

Для того, чтобы узнать, поддерживает ли драйвер вывод диалога описания, параметр Param1 должен иметь значение -1L. Успешное завершение функции означает способность драйвера вывести диалог, в противном случае возвращается код ошибки MMSYSERR_NOTSUPPORTED.

acmDriverPriority - изменение приоритета драйвера

Изменяет приоритет выбранного драйвера. Дополнительно позволяет разрешить или запретить драйвер, а также отложить посылку уведомлений о смене состояния и приоритета.

MMRESULT acmDriverPriority (
  HACMDRIVERID  DrvId,
  DWORD  Priority,
  DWORD  Command
);
BEGIN Начало серии изменений состояний/приоритетов драйверов. Предписывает ACM отложить посылку сообщений окнам уведомления приложений до того, пока она не будет явно разрешена командой END.
END Завершение серии изменений состояний/приоритетов драйверов. Предписывает ACM возобновить посылку сообщений окнам уведомления приложений.
DISABLE Запрещает разрешенный драйвер. Если драйвер уже запрещен - не выполняет никаких действий.
ENABLE Разрешает запрещенный драйвер. Если драйвер уже разрешен - не выполняет никаких действий.

В случае команд BEGIN/END параметры DrvId и Priority должны иметь нулевые значения. Команда BEGIN должна сопровождаться командой END сразу же, как только будет завершено изменение приоритета/состояния всех требуемых драйверов.

Если необходима только смена приоритета, без изменения состояния драйвера - код команды должен быть нулевым.

acmDriverDetails - запрос описания драйвера

Заполняет заданную структуру параметрами указанного драйвера.

MMRESULT acmDriverDetails (
  HACMDRIVERID  DrvId,
  ACMDRIVERDETAILS  *Details,
  DWORD  Reserved
);

Функции работы с фильтрами и форматами

acmFilterTagDetails / acmFormatTagDetails - запрос описания типа

Возвращают описание заданного типа фильтров/форматов.

MMRESULT acmFilterTagDetails (
  HACMDRIVER  Drv,
  ACMFILTERTAGDETAILS  *Details,
  DWORD  RequestType
);
MMRESULT acmFormatTagDetails (
  HACMDRIVER  Drv,
  ACMFORMATTAGDETAILS  *Details,
  DWORD  RequestType
);
FILTERTAG / FORMATTAG Поле dwFiltertTag / dwFormatTag структуры Details содержит код типа фильтров/форматов, для которого запрашивается описание. Если ключ драйвера не задан, ACM опрашивает первый из драйверов, поддерживающих заданный тип.
INDEX Поле dwFilterTagIndex / dwFormatTagIndex структуры Details содержит индекс типа фильтров/форматов для драйвера, заданного параметром Drv, который в этом случае должен ссылаться на открытый драйвер.
LARGESTSIZE Запрашивается описание типа, для которого структура WAVEFILTER / WAVEFORMATEX имеет наибольший размер. Поле dwFiltertTag / dwFormatTag структуры Details при этом может либо задавать код типа, либо иметь значение WAVE_FILTER_UNKNOWN / WAVE_FORMAT_UNKNOWN. Если ключ драйвера не задан, ACM ищет драйвер, поддерживающий тип с наибольшим размером описателя фильтра/формата. При заданных ключе драйвера и коде типа этот запрос эквивалентен запросу FILTERTAG / FORMATTAG.

acmFilterDetails / acmFormatDetails - запрос параметров фильтра/формата

Возвращает описание заданного фильтра/формата.

MMRESULT acmFilterDetails (
  HACMDRIVER  Drv,
  ACMFILTERDETAILS  *Details,
  DWORD  RequestType
);
MMRESULT acmFormatDetails (
  HACMDRIVER  Drv,
  ACMFORMATDETAILS  *Details,
  DWORD  RequestType
);
FILTER / FORMAT Поле pwfltr / pwfx структуры Details содержит указатель описателя - структуры типа WAVEFILTER / WAVEFORMATEX, заполненной параметрами фильтра/формата, для которого запрашиваются дополнительные сведения. Код типа в описателе и в поле dwFiltertTag / dwFormatTag структуры Details должен совпадать. Если ключ драйвера не задан, ACM опрашивает первый из подходящих драйверов.
INDEX Поле dwFilterIndex / dwFormatIndex структуры Details содержит индекс стандартного фильтра/формата для драйвера, заданного параметром Drv, который в этом случае должен ссылаться на открытый драйвер.

Функции перебора типов и стандартных фильтров/форматов

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

MMRESULT acmFilterTagEnum (  // Перебор типов фильтров
  HACMDRIVER  Drv,
  ACMFILTERTAGDETAILS  *Details,
  ACMFILTERTAGENUMCB  Callback,
  DWORD  Instance, 
  DWORD  Flags
);
MMRESULT acmFilterEnum (  // Перебор стандартных фильтров
  HACMDRIVER  Drv,
  ACMFILTERDETAILS  *Details,
  ACMFILTERENUMCB  Callback,
  DWORD  Instance, 
  DWORD  Flags
);
MMRESULT acmFormatTagEnum (  // Перебор типов форматов
  HACMDRIVER  Drv,
  ACMFORMATTAGDETAILS  *Details,
  ACMFORMATTAGENUMCB  Callback,
  DWORD  Instance, 
  DWORD  Flags
);
MMRESULT acmFormatEnum (  // Перебор стандартных форматов
  HACMDRIVER  Drv,
  ACMFORMATDETAILS  *Details,
  ACMFORMATENUMCB  Callback,
  DWORD  Instance, 
  DWORD  Flags
);

Для функций перебора типов фильтров/форматов acmFilterTagEnum и acmFormatTagEnum флаги не определены; параметр Flags должен быть нулевым.

Для функции перебора стандартных фильтров acmFilterEnum определен один флаг, имя которого имеет префикс ACM_FILTERENUMF_:

DWFILTERTAG Поле dwFilterTag структуры типа WAVEFILTER, на которую ссылается указатель pwfltr структуры Details, содержит код типа перебираемых фильтров. Поле dwFilterTag структуры Details должно иметь то же самое значение.

Для функции перебора стандартных форматов acmFormatEnum определены следующие флаги, имена которых имеют префикс ACM_FORMATENUMF_:

HARDWARE Перебирать только форматы, которые аппаратно поддерживаются установленными звуковыми адаптерами. Вместе с этим флагом должна быть указана комбинация из флагов INPUT и OUTPUT.
INPUT Перебирать только форматы, в которых возможен ввод (запись).
OUTPUT Перебирать только форматы, в которых возможен вывод (воспроизведение).
WFORMATTAG Перебирать только форматы того же типа, что и заданный формат (поле wFormatTag описателя). Поле dwFormatTag структуры Details должно иметь то же самое значение кода типа.
NSAMPLESPERSEC Перебирать только форматы, имеющие ту же частоту дискретизации, что и заданный формат (поле nSamplesPerSec описателя).
NCHANNELS Перебирать только форматы, имеющие то же количество каналов, что и заданный формат (поле nChannels описателя).
WBITSPERSAMPLE Перебирать только форматы, имеющие ту же разрядность отсчета, что и заданный формат (поле wBitsPerSample описателя).
CONVERT Перебирать только форматы, в которые может быть преобразован заданный формат.
SUGGEST Перебирать только форматы, в которые рекомендуется преобразование из заданного формата. В отличие от функции acmFormatSuggest это позволяет выбрать наиболее подходящий из рекомендованных форматов. При успешном завершении операции поле dwFormatIndex структуры Details обнуляется.

Понятие "заданный формат" означает описатель формата типа WAVEFORMATEX, на который ссылается поле pwfx структуры Details. Соответствующие запросу поля описателя должны иметь осмысленные значения.

Для каждого подходящего объекта перебора вызывается функция поддержки перебора, которой передается описание объекта, а также заданное приложением произвольное значение Instance; например, это может быть описатель списка, в который функция поддержки будет заносить найденные объекты. Если функция поддержки возвращает TRUE - процесс перебора продолжается, в противном случае - прекращается.

Если в исходных данных нет ошибок - функция перебора завершается успешно, даже если не обнаружено ни одного подходящего объекта перебора.

acmFilterChoose / acmFormatChoose - вывод диалога выбора фильтра/формата

Эти две практически одинаковые функции выводят на экран диалог выбора фильтра/формата, содержащий списки отобранных по заданным условиям стандартных фильтров или форматов. Пользователь может выбрать желаемый фильтр или формат, в соответствии с которым ACM сформирует описатель в заданной области памяти.

MMRESULT acmFilterChoose (ACMFILTERCHOOSE  *Choose);
MMRESULT acmFormatChoose (ACMFORMATCHOOSE  *Choose);

Если в структуре Choose задана функция перехвата - она вызывается перед обработкой каждого сообщения, полученного оконной функцией диалога выбора.

При успешном завершении структура, на которую ссылается поле pwfltr / pwfx, заполняется параметрами выбранного фильтра/формата; одновременно ACM заполняет прочие информационные поля в структуре Choose. При отказе пользователя от выбора (кнопка Cancel/Отмена или закрытие диалога через системное меню) функция возвращает код ACMERR_CANCELED.

acmFormatSuggest - запрос рекомендуемого для преобразования формата

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

MMRESULT acmFormatSuggest (
  HACMDRIVER  Drv,
  WAVEFORMATEX  *SrcFmt,
  WAVEFORMATEX  *DstFmt,
  DWORD  DstFmtSize,
  DWORD  Flags
);
WFORMATTAG Искать только среди форматов заданного типа (совпадение полей wFormatTag).
NSAMPLESPERSEC Искать только среди форматов, имеющих заданную частоту дискретизации (совпадение полей nSamplesPerSec).
NCHANNELS Искать только среди форматов, имеющих заданное количество каналов (совпадение полей nChannels).
WBITSPERSAMPLE Искать только среди форматов, имеющих заданную разрядность отсчета (совпадение полей wBitsPerSample).

Функции работы с потоками преобразования

Все функции работы с потоками преобразования, кроме acmStreamOpen, получают в первом параметре Stream ключ открытого потока, над которым выполняется запрошенная операция.

acmStreamOpen - открывание потока преобразования

Открывает поток, в котором будет происходить обработка звука фильтром или преобразование формата.

MMRESULT acmStreamOpen (
  HACMSTREAM  *ForHandle,
  HACMDRIVER  Drv,
  WAVEFORMATEX  *SrcFmt,
  WAVEFORMATEX  *DstFmt,
  WAVEFILTER  *Filter,
  DWORD  Callback,
  DWORD  Instance,
  DWORD  Flags
);
ASYNC Запрашивается асинхронная обработка потока. В этом случае приложение будет получать уведомления о завершении операций открывания и закрывания потока, а также - операции преобразования порции данных.
NONREALTIME Обработка звука происходит не в реальном времени, и время обработки не является критическим ресурсом. По умолчанию ACM пытается обрабатывать звук как можно быстрее, чтобы преобразование могло происходить в реальном времени, по ходу записи/воспроизведения звука. Отказ от этого может способствовать более точной и качественной обработке.
QUERY Режим опроса допустимости заданных параметров потока. ACM делает все необходимые проверки, однако не выполняет действительного открывания потока. Успешное завершение функции означает, что операция действительного открывания будет выполнена успешно.

Имена констант способов уведомления имеют префикс CALLBACK_:

EVENT Параметр dwCallback является ключом объекта события (event handle).
FUNCTION Параметр dwCallback является адресом функции уведомления.
WINDOW Параметр dwCallback является ключом окна (window handle).

Если поток открыт асинхронно, то при наступлении каждого из трех событий потока выполняется действие, заданное способом уведомления:

acmStreamClose - закрывание потока

Закрывает открытый поток преобразования.

MMRESULT acmStreamClose (
  HACMSTREAM  Stream,
  DWORD  Reserved
);

acmStreamSize - запрос рекомендуемого размера порции преобразования

Запрашивает рекомендуемый размер буфера для порции данных исходного или результирующего звукового потока. Полученные размеры гарантируют их применимость в функции acmStreamConvert.

MMRESULT acmStreamSize (
  HACMSTREAM  Stream,
  DWORD  InSize,
  DWORD  *ForOutSize,
  DWORD  Type
);
SOURCE Задан размер буфера исходного потока, запрашивается размер буфера результирующего потока.
DESTINATION Задан размер буфера результирующего потока, запрашивается размер буфера исходного потока.

В случае ошибки в переменную по указателю ForOutSize заносится нулевое значение.

acmStreamPrepareHeader - подготовка заголовка к преобразованию

Подготавливает заголовок потока к преобразованию. Обычно задачей этой операции является проверка допустимости адресов и размеров буферов потока. Заголовок потока обязательно должен быть подготовлен перед применением функции преобразования acmStreamConvert.

MMRESULT acmStreamPrepareHeader (
  HACMSTREAM  Stream,
  ACMSTREAMHEADER  *Hdr,
  DWORD  Reserved
);

Нет необходимости выполнять подготовку заголовка каждый раз перед передачей заголовка ACM, как это рекомендовано делать для буферов основной звуковой подсистемы (Wave/MIDI). Заголовок может быть подготовлен только один раз, и затем сколько угодно раз использован в функции преобразования; единственное ограничение - размеры буферов потока не должны превышать тех значений, что были заданы перед подготовкой.

При успешном завершении операции подготовки в слове состояния заголовка (поле fdwStatus) устанавливается флаг PREPARED.

Операция подготовки может потребовать у ACM и драйвера выделения каких-либо ресурсов, закрепляемых за данным заголовком. Поэтому перед закрытием потока для каждого ранее подготовленного заголовка необходимо выполнить обратные действия при помощи функции acmStreamUnprepareHeader. Это гарантирует, что все выделенные ресурсы будут освобождены.

acmStreamUnprepareHeader - отмена действий по подготовке заголовка

Отменяет действия, ранее предпринятые ACM и драйвером при подготовке заголовка функцией acmStreamPrepareHeader.

MMRESULT acmStreamUnprepareHeader (
  HACMSTREAM  Stream,
  ACMSTREAMHEADER  *Hdr,
  DWORD  Reserved
);

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

Если размеры буферов потока, указанные в заголовке, были изменены после вызова функции подготовки acmStreamPrepareHeader - их значения должны быть восстановлены до обращения к функции acmStreamUnprepareHeader.

При успешном завершении операции подготовки в слове состояния заголовка (поле fdwStatus) сбрасывается флаг PREPARED. Это может происходить и при некоторых ошибках, когда функция возвращает ненулевое значение. Если выполнение функции завершилось с ошибкой, состояние этого флага показывает, смогла ли служба ACM действительно освободить заголовок. Если флаг сброшен, возвращенный код ошибки имеет чисто информационное значение, и повторного вызова функции не требуется.

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

acmStreamConvert - запрос преобразования очередной порции звуковых данных

Запрашивает у ACM обработку очередной порции данных исходного звукового потока.

MMRESULT acmStreamConvert (
  HACMSTREAM  Stream, 
  ACMSTREAMHEADER  *Hdr,
  DWORD  Flags
);
BLOCKALIGN Преобразуется только целое количество полных блоков звуковых данных. Здесь слово "блок" имеет специальный смысл - минимальный объем звуковых данных, который может быть подвергнут преобразованию. Например, кодек MPEG Layer 3 выполняет над данными преобразование Фурье, которое не может быть выполнено над отдельными отсчетами и требует накопления некоторого их количества.Этот флаг должен быть указан для всех операций преобразования, кроме последней, когда исходных данных недостаточно для заполнения последнего блока.
START Сообщает о начале очередного независимого участка потока. По этому флагу ACM устанавливает в исходное состояние внутренние служебные переменные, хранящие информацию о предшествовании. Например, фильтр, реализующий эффект эхо, очищает буфер задержанного звука.
END Сообщает о конце независимого участка потока. По этому флагу ACM начинает возвращать буферизованные выходные данные. Например, эхо-фильтр по этому флагу возвращает отголоски, сформированные из буфера задержанного звука, а кодек MPEG Layer 3 - остаток сжатого звука из внутреннего буфера. Если размер независимого участка не превышает одной порции звуковых данных, флаги START и END указываются вместе.

Даже если исходный поток является однородным, состоящим из единственного участка, для корректной работы драйвера необходимо указание флага START при обработке первой порции данных, и флага END - при обработке последней. Для упрощения обработки в качестве последней порции можно передать драйверу один или несколько отсчетов тишины, специально сформированных в исходном буфере.

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

Если поток был открыт асинхронно (флаг ASYNC в слове режимов открывания потока) - заголовок вносится в очередь драйвера, при этом в его слове состояния сбрасывается флаг завершения DONE и устанавливается флаг присутствия в очереди INQUEUE. После завершения обработки драйвер изымает заголовок из очереди, сбрасывает флаг INQUEUE, устанавливает флаг DONE и уведомляет приложение о завершении операции одним из трех возможных способов, заданным при открывании потока.

Если поток был открыт синхронно - драйвер не возвращает управления до тех пор, пока не будет завершена обработка заданной порции данных. В этом случае флаги INQUEUE и DONE смысла не имеют.

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

Ситуация, когда драйвер возвращает нулевое значение в одном из указанных полей, в общем случае не является ошибочной. Нулевое значение поля cbSrcLengthUsed может означать, что драйвер не смог объединить исходные данные с накопленными внутри драйвера, и вернул результирующие данные лишь на основе накопленных. Нулевое значение поля cbDstLengthUsed означает, что исходных данных оказалось недостаточно для преобразования, и они были запомнены драйвером для последующих операций. Ошибочной является лишь ситуация, когда оба этих поля имеют нулевые значения, так как в этом случае невозможно дальнейшее продвижение по потоку. Рекомендуется отслеживать возникновение подобной ситуации, чтобы процесс преобразования не зацикливался.

acmStreamReset - прерывание обработки потока

Служит для аварийного прерывания обработки потока и возврата всех заголовков из очереди драйвера.

MMRESULT acmStreamReset (
  HACMSTREAM  Stream,
  DWORD  Reserved
);

Для асинхронного потока функция аварийно прерывает выполнение операций преобразования, запрошенных функциями acmStreamConvert. Для каждого заголовка, находящегося в очереди драйвера, выполняются те же действия, что и при успешном завершении операции преобразования. Узнать об аварийном завершении операции можно по нулевому значению полей cbSrcLengthUsed и cbDstLengthUsed в заголовке потока.

Для синхронного потока функция не выполняет никаких действий.

acmStreamMessage - посылка сообщения драйверу потока

Позволяет послать драйверу, обрабатывающему заданный поток, какое-либо специальное сообщение.

MMRESULT acmStreamMessage (
  HACMSTREAM  Stream,
  UINT  Msg, 
  LPARAM  Param1,
  LPARAM  Param2
);

Результатом функция является значение, возвращенное драйвером в ответ на переданное сообщение.

Функции, определяемые приложением

Эта группа функций определяется самим приложением для получения различных уведомлений от ACM. Имена функций в прототипах - условные, имя каждой функции полностью определяется приложением, а ACM получает только указатели этих функций.

Основную часть группы составляют функции поддержки перебора драйверов, типов фильтров/форматов и стандартных фильтров/форматов, вызываемые для каждого подходящего элемента соответствующего списка. Функции перебора содержат в своих условных именах слово Enum.

Каждая функция перебора должна возвратить значение TRUE для продолжения процесса перебора, и FALSE - для его завершения.

Функции перебора и уведомления не должны вызывать интерфейсных функций acmDriverAdd, acmDriverRemove, acmDriverPriority.

DriverEnumCallback - функция поддержки перебора драйверов

Вызывается для каждого драйвера, найденного в процессе выполнения функции перебора драйверов acmDriverEnum.

BOOL CALLBACK DriverEnumCallback (
  HACMDRIVERID  DrvId,
  DWORD  Instance,
  DWORD  Support
);

Функции поддержки перебора типов и стандартных фильтров/форматов

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

BOOL CALLBACK FilterTagEnumCallback (  // Поддержка перебора типов фильтров
  HACMDRIVERID  DrvId,
  ACMFILTERTAGDETAILS  *Details,
  DWORD  Instance,
  DWORD  Support
);
BOOL CALLBACK FilterEnumCallback (  // Поддержка перебора стандартных фильтров
  HACMDRIVERID  DrvId,
  ACMFILTERDETAILS  *Details,
  DWORD  Instance,
  DWORD  Support
);
BOOL CALLBACK FormatTagEnumCallback (  // Поддержка перебора типов форматов
  HACMDRIVERID  DrvId,
  ACMFORMATTAGDETAILS  *Details,
  DWORD  Instance,
  DWORD  Support
);
BOOL CALLBACK FormatEnumCallback (  // Поддержка перебора стандартных форматов
  HACMDRIVERID  DrvId,
  ACMFORMATDETAILS  *Details,
  DWORD  Instance,
  DWORD  Support
);

Функция перехвата сообщений диалога выбора фильтра/формата

Вызывается для каждого сообщения Windows, поступившего для обработки в оконную функцию диалога выбора фильтра/формата, сформированного функциями выбора acmFilterChoose / acmFormatChoose.

UINT CALLBACK acmChooseHookProc (
  HWND hwnd,
  UINT uMsg,	
  WPARAM wParam,
  LPARAM lParam
);

Параметры функции являются стандартными параметрами оконной функции Windows.

Если функция обрабатывает сообщение WM_CTLCOLOR, она должна возвратить ключ кисти, которая будет использоваться для отрисовки фона управляющих элементов (control background).

В дополнение к стандартным сообщениям Windows функции перехвата вызываются также со специальными сообщениями ACM в процессе формирования трех "выпадающих" списков (drop-down lists) диалога - названий пресетов (custom), названий типов (tag) и названий стандартных фильтров/форматов (filter/format). Вначале для каждого элемента, вносимого ACM в соответствующий список, функция перехвата вызывается с сообщением "проверка" (verify) и может разрешить или запретить включение элемента в список. После завершения формирования списков типов и стандартных фильтров/форматов функция перехвата для них вызывается с сообщением "добавление" (add). В ответ на это сообщение функция может добавить к спискам дополнительные типы или фильтры/форматы.

В качестве специального сообщения выступает код MM_ACM_FILTERCHOOSE / MM_ACM_FORMATCHOOSE, параметр wParam в котором задает тип списка и требуемую операцию. Имена констант для этих значений имеют вид objCHOOSE_list_op, где obj - объект выбора (FILTER или FORMAT), list - тип списка (CUSTOM, FILTERTAG, FILTER, FORMATTAG, FORMAT), op - операция (VERIFY или ADD).

Например: FILTERCHOOSE_CUSTOM_VERIFY - проверка возможности включения элемента в список пресетов диалога выбора фильтра, FORMATCHOOSE_FORMATTAG_ADD - запрос добавления нового элемента в список типов диалога выбора формата.

Для списка пресетов допустима только операция проверки, добавление в этот список запрещено.

Параметр lParam специального сообщения имеет различный смысл в зависимости от выполняемой операции:

При получении специального сообщения ACM функция перехвата должна вернуть значение TRUE, если сообщение воспринято и обработано, и FALSE, если сообщение игнорировано. Перед возвратом сообщения TRUE функция должна сообщить ACM результат обработки специального сообщения. Это делается при помощи стандартной функции Windows SetWindowLong:

SetWindowLong (hwnd, DWL_MSGRESULT, Result);

Параметр hwnd является ключом окна диалога, полученным от ACM, а Result - логическим значением TRUE/FALSE. Для операции проверки значение TRUE разрешает включение элемента в список, значение FALSE - запрещает. Для операции добавления значение TRUE запрашивает повторение операции добавления, значение FALSE свидетельствует о завершении процесса добавления. Если нет необходимости добавлять в списки новые значения, функция перехвата должна игнорировать специальные сообщения с кодами операций добавления.

Функция уведомления приложения о завершении операции с потоком

Вызывается при наступлении одного из событий потока.

        void CALLBACK acmStreamConvertCallback (
  HACMSTREAM Stream,
  UINT Msg,	
  DWORD Instance,
  LPARAM Param1,	
  LPARAM Param2
);
OPEN Поток успешно открыт функцией acmStreamOpen.
CLOSE Поток успешно закрыт функцией acmStreamClose. Ключ потока имеет только информационное значение - все операции с ключом потока в этот момент уже запрещены.
DONE Завершена операция преобразования, запрошенная функцией acmStreamConvert.

Параметр Param1 содержит указатель описателя заголовка потока.

Для вызова функции уведомления создается специальная задача (thread) с повышенным (ABOVE_NORMAL) приоритетом. Созданная задача используется для уведомления во всех потоках, и существует до завершения приложения.

Уведомления допустимы только для асинхронных потоков.

Формально функция не должна обращаться к другим функциям Windows, кроме PostMessage, timeGetSystemTime, timeGetTime, timeSetEvent, timeKillEvent, midiOutShortMsg, midiOutLongMsg, OutputDebugStr. Фактически же она работает в контексте собственной задачи, а не в контексте драйвера, так что на практике большинство функций Windows оказываются доступными.

DriverProc - функция пользовательского драйвера ACM

Вызывается ACM для обработки запросов, адресованных драйверу, после установки пользовательского драйвера функцией acmDriverAdd.

LRESULT CALLBACK DriverProc (
  DWORD dwID,
  HDRIVER hdrvr,
  UINT uMsg,	
  LPARAM lParam1,	
  LPARAM lParam2
);

Параметры функции драйвера и ее поведение описываются в Windows DDK (Driver Development Kit - набор для разработки драйверов).

Существующие драйверы подсистемы сжатия

В состав стандартной поставки Windows 95 и NT4 входят шесть драйверов ACM - Microsoft ADPCM, IMA ADPCM, Microsoft CCITT G.711 (форматы a-law/u-law), Microsoft GSM 6.10, Lernout & Hauspie CELP/SBC, DSP Group TrueSpeech. Форматы ADPCM, a-law, u-law ориентированы на произвольный звуковой сигнал, форматы GSM, CELP/SBC, TrueSpeech - на монофонический речевой сигнал.

Для оптимизации передачи звука в Интернет Microsoft разработан формат MSN Audio, драйвер которого поставляется в комплекте пакета NetShow.

В комплекте Internet Explorer 4 и Windows 98/2000 поставляются драйверы форматов G.723.1, VoxWare MetaSound, VivoActive/Siren, также ориентированные на передачу произвольного звука по сети, а также декодер Fraunhofer IIS для формата MPEG Layer 3.

В комплекте программного обеспечения звуковых карт Sound Blaster поставляются драйверы Creative ADPCM и Creative FastSpeech 10, ориентированные на речевой сигнал.

Институтом Fraunhofer IIS разработан профессиональный драйвер-кодек для формата MPEG Layer 3, работающий в реальном времени. Для сжатия стереофонического 16-разрядного сигнала PCM с частотой дискретизации 44.1 кГц в формат со скоростью потока 256 кбит/с необходим процессор Celeron 300A или более мощный.

Единственным известным мне драйвером-фильтром является разработанный Microsoft стандартный драйвер MSFilter, поставляемый в качестве примера в комплекте DDK для Windows 95/98 и NT/2000. Этот драйвер содержит два фильтра: Volume, изменяющий амплитуду сигнала в потоке, и Echo, реализующий эхо-эффект. Установочные файлы драйвера находятся в каталоге MSFilter.

Установка и удаление постоянных драйверов ACM

Драйверы ACM, входящие в стандартный комплект поставки Windows, устанавливаются при выборе пункта Audio Compression (Сжатие аудиоданных) в группе средств мультимедиа. Это можно сделать при установке Windows, если выбран режим выборочной установки (Custom Setup), либо в любое время при уже установленной системе, при помощи мастера установки/удаления программ.

Выборочную установку стандартных драйверов можно выполнить при помощи мастера установки оборудования в панели управления. Для этого нужно выбрать режим ручной установки, отказавшись от автоматического поиска оборудования, выбрать раздел звуковых, видео и игровых контроллеров, в списке производителей выбрать Microsoft Audio Codecs или DSP Group, а в списке продуктов - нужный драйвер.

Отдельно поставляемые драйверы имеют либо программу самоустановки (Setup.exe), либо INF–файл сценария установки. В последнем случае драйвер устанавливается подобно аппаратному адаптеру, тем же способом, что и выборочная установка стандартных драйверов, но после получения списка производителей и продуктов нужно выбрать установку с диска и ввести путь к каталогу установочных файлов.

Просмотреть список установленных драйверов ACM можно при помощи мастера мультимедиа в панели управления, открыв в закладке Advanced (Дополнительно) раздел Audio Compression codecs (Программы аудиосжатия). Открыв нужный драйвер, можно разрешить или запретить его, сменить приоритет поиска, изменить настройки, получить дополнительные сведения о драйвере, либо удалить драйвер из системы.

Использование драйвера фильтров MSFilter

Драйвер MSFilter, поддерживающий фильтры типов Volume и Echo, был предусмотрены Microsoft при проектировании подсистемы сжатия, поэтому все необходимые для его использования структуры и константы определены в файле MMREG.H. Однако по непонятной причине этот драйвер не был включен в стандартную поставку Windows, поэтому для работы с этими фильтрами необходимо установить драйвер в системе, используя мастер установки оборудования и файл сценария MSFILTER.INF.

Каждый из типов фильтров описывается собственной расширенной структурой, в основе которой лежит базовый описатель WAVEFILTER. Этот описатель является первым членом расширенной структуры описания каждого типа фильтра; по соглашению это поле имеет имя wfltr. Следом за базовым описателем располагаются собственные параметры фильтра данного типа.

Фильтры Volume и Echo работают только со звуковыми данными формата PCM.

По непонятной причине драйвер MSFilter считает, что он неспособен обрабатывать звук в реальном времени и в обязательном порядке требует наличия флага NONREALTIME при открывании потока преобразования.

Фильтр Volume

Предназначен для амплитудной обработки звукового сигнала - усиления или ослабления его амплитуды. Обработка производится путем умножения каждого отсчета сигнала на заданный коэффициент.

Уникальный код типа имеет значение WAVE_FILTER_VOLUME. Расширенная структура VOLUMEWAVEFILTER имеет вид:

WAVEFILTER  wfltr;
DWORD  dwVolume;

Фильтр Echo

Предназначен для временной обработки звукового сигнала - внесения эффекта задержки (эхо). Обработка производится путем задержки исходного сигнала на заданное время при помощи накопления отсчетов во вспомогательном буфере, с последующим суммированием задержанного сигнала с исходным. Перед суммированием задержанный сигнал умножается на заданный коэффициент, который для повышения правдоподобия эхо-эффекта выбирается меньше единицы, чтобы амплитуда задержанного сигнала ослаблялась.

Уникальный код типа имеет значение WAVE_FILTER_ECHO. Расширенная структура ECHOWAVEFILTER имеет вид:

WAVEFILTER  wfltr;
DWORD  dwVolume;
DWORD  dwDelay;

Недостатки подсистемы сжатия

Поскольку большинство драйверов ACM являются программными, они поддерживают только синхронную обработку потоков преобразования. Это создает неудобство при разработке многозадачных приложений, ориентированных на параллельную обработку данных. Впрочем, это ограничение легко обойти путем выноса алгоритмов работы с потоком в независимую задачу, которую затем можно запускать отдельно раз для каждого нового потока. Несмотря на то, что на однопроцессорной платформе такой параллелизм будет мнимым, и каждая задача все равно будет занимать центральный процессор такое же количество времени, обработка нескольких потоков будет "размазана" во времени, и те потоки, что требуют меньше процессорного времени для своей обработки, будут продвигаться быстрее. На многопроцессорных платформах задачи могут выполняться на разных процессорах, обеспечивая реальный, а не мнимый, параллелизм.

Несмотря на то, что ACM поддерживает для модулей обработки собственные наборы данных (instances) для каждого открытого потока, некоторые кодеки (например, Fraunhofer IIS Audio MPEG Layer 3) не позволяют открыть два и более параллельных потока преобразования в рамках одного процесса, даже если потоки открываются в разных задачах. Такое поведение кодека делает невозможным одновременное многоканальное преобразование звука. Обойти ограничение можно только путем запуска независимых параллельных процессов, организовав для них достаточно сложный алгоритм обмена данными.

Пример программы, использующей ACM

В качестве примера приведена программа RTCompress, записывающая звук с указанного устройства Wave In в формате PCM, в реальном времени преобразующая его в выбранный формат, и записывающая в стандартный файл RIFF Wave (.wav).



Фактически программа RTCompress переделана из программы Delay, представленной в качестве примера к статье "Низкоуровневое программирование звука в Windows".

Программа написана на языке C++, в среде Microsoft Visual C++ 4.2. Из возможностей C++ в основном использованы только "косметические" - более строгая проверка типов и возможность использовать имена структур в качестве имен типов. Единственное объектно-ориентированное средство языка, примененное в программе - наследование стандартной структуры WAVEFORMATEX для формирования расширенной структуры WaveFormat. Метод формирования расширенных структур форматов/фильтров, примененный в MMREG.H, рассчитан на совместимость с обычным языком C, и основан на включении базовой структуры первым элементом расширенной. Такой подход создает неудобства, заставляя выписывать лишние имена или преобразования типов, в то время как механизм наследования С++ совершенно естественным образом решает поставленную задачу - расширенная структура просто выводится из базовой, поскольку структуры в C++ являются классами с общим доступом.

Для работы с выходным файлом в программе использован интерфейс MMIO (функции с префиксом mmio), специально ориентированный на работу со звуковыми и видеофайлами. Этот интерфейс будет описан в одном из следующих выпусков журнала.

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

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

В качестве последней порции исходного сигнала, снабженной пометкой завершения участка, формируется один блок отсчетов тишины (значения 0x80 для 8-разрядных отсчетов, и нулевые - для всех остальных).

Поскольку программа работает с элементами управления диалогов (Common Controls), базовой звуковой подсистемой MME/Wave и подсистемой сжатия ACM - при построении используются библиотеки comctl32, winmm и msacm32.


Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.
    Сообщений 2    Оценка 125        Оценить