Эту рубрику я так же давно уже не делал. Сегодня я собрался решил, что пора тебе рассказать про функции записи звука. Итак читай и юзай. Только в VR-online (я действительно ещё нигде в инете не видел описания этих функций на русском языке).
В принципе, вся работа с записью идентична воспроизведению. Только имена функций немного изменились и появилось несколько новых. Даже парамеры многих функций одинаковы.
Как и при воспроизведении, так и при записи в системе может быть несколько устройств позволяющих выполнять такие функции. Если ты хочешь узнать о характеристиках устройства записи, то можно воспользоватся функцией waveInGetDevCaps (если ты помнишь, то же самое выполняет waveOutGetDevCaps для устройств воспроизведения).
Для С/С++
MMRESULT waveInGetDevCaps(
UINT uDeviceID, //Указатель на устройство записи
LPWAVEINCAPS pwoc,//Структура, куда будут записаны данные
UINT cbwoc //Размер структуры
);
Для Delphi
function waveInGetDevCaps(
uDeviceID: UINT; //Указатель на устройство записи
lpCaps: PWaveInCaps; //Структура, куда будут записаны данные
uSize: UINT //Размер структуры
): MMRESULT; stdcall;
Второй параметр - структура WAVEOUTCAPS. Она выглядит так:
Для С/С++
typedef struct {
WORD wMid; //Идентификатор производителя
WORD wPid; //Идентификатор устройства
MMVERSION vDriverVersion; //Версия драйвера
CHAR szPname[MAXPNAMELEN];//Название устройства
DWORD dwFormats; //Поддерживаемые форматы
WORD wChannels; //Количество каналов
DWORD dwSupport; //Свойства
} WAVEINCAPS;
Для Delphi
PWaveInCapsA = ^TWaveInCapsA;
PWaveInCapsW = ^TWaveInCapsW;
PWaveInCaps = PWaveInCapsA;
{$EXTERNALSYM tagWAVEINCAPSA}
tagWAVEINCAPSA = record
wMid: Word; //Идентификатор производителя
wPid: Word; //Идентификатор устройства
vDriverVersion: MMVERSION; //Версия драйвера
szPname: array[0..MAXPNAMELEN-1] of AnsiChar; //Название устройства
dwFormats: DWORD; //Поддерживаемые форматы
wChannels: Word; //Количество каналов
dwSupport: DWORD; //Свойства
end;
В принципе, всё то же самое, что и при воспроизведении, только теперь указатели и идентификаторы относятся к устройству записи.
Чтобы узнать количество установленных устройств записи используется функция waveInGetNumDevs:
Для С++
UINT waveInGetNumDevs(VOID);
Для Delphi
function waveInGetNumDevs: UINT; stdcall;
Как и при воспроизведении, здесь так же нужно сначала открыть устройство записи. При открытии, ты получаешь указатель устройства, который потом используешь при вызови остальных функций.
Для С++
MMRESULT waveInOpen(
LPHWAVEIN phwi, //Сюда будет помещён указатель на устройство
UINT uDeviceID, //Идентификатор устройства
LPWAVEFORMATEX pwfx,//Адрес струтуры WAVEFORMATEX
DWORD dwCallback, //Функция, которая будет вызыватся на все сообщения
DWORD dwCallbackInstance, //Произвольный параметр
DWORD fdwOpen //Флаги открытия устройства.
);
Для Delphi
function waveInOpen(
lphWaveIn: PHWAVEIN; //Сюда будет помещён указатель на устройство
uDeviceID: UINT; //Идентификатор устройства
lpFormatEx: PWaveFormatEx; //Адрес струтуры WAVEFORMATEX
dwCallback, //Функция, которая будет вызыватся на все сообщения
dwInstance, //Произвольный параметр
dwFlags: DWORD //Флаги открытия устройства.
): MMRESULT;
Параметр uDeviceID (идентификатор устройства) - может принимать значение WAVE_MAPPER. В этом случае будет использоватся устройство записи по умолчанию.
Структуру WAVEFORMATEX мы уже использовали при воспроизведении. Она не изменилась и используется звесь в том же виде и описывает параметры записываемого звука. В зависимости от занесённых сюда данных, будет зависить качество записываемого звука. Ты обязательно должен указать параметры звука, который хочешь получить в результате записи.
Параметр dwFlag может принимать следующие значения:
CALLBACK_EVENT - в dwCallback находится событие THandle, через которое будет происходить информирования о ходе воспроизведения.
CALLBACK_THREAD - в dwCallback находится идентификатор потока
CALLBACK_FUNCTION - в dwCallback находится указатель на функцию.
CALLBACK_WINDOW - в dwCallback указатель на окно, которому будут посылаться сообщения.
CALLBACK_NULL - в dwCallback ничего нет.
WAVE_ALLOWSYNC - можно открыть устройство в синхронном режиме.
WAVE_FORMAT_DIRECT - запрещается преобразование данных с помощью ACM драйвера.
WAVE_FORMAT_QUERY - Если ты установишь этот параметр, то реального открытия звуковухи не произойдёт. Функция проверит возможность открытия с заданными тобой параметрами, и если всё ничтяк, то вернёт тебе MMSYSERR_NOERROR. Если твои параметры недопустимы, то вернётся код ошибки. В любом случае реального открытия устройства не произойдёт. Этот флаг можно использовать как тест на допустимость настроек.
С остальными параметрами и так всё ясно по комментариям. Тем более, что они схожи с параметрами функции открытия устройства воспроизведения.
После окончания использования устройства, оно должно быть освобождено. Для этого есть функция waveInClose:
Для С++
MMRESULT waveInClose(HWAVEIN hwi);
Для Delphi
function waveInClose(hWaveIn: HWAVEIN): MMRESULT; stdcall;
Параметр только один - указатель на открытое устройство, полученный при выполнении функции waveInOpen.
Для записи так же используются блоки данных, которые надо подготавливать и уничтожать. Для подготовки блока данных используется функция waveInPrepareHeader:
Для С++
MMRESULT waveInPrepareHeader(
HWAVEIN hwi, //Указатель на уже открытое устройство
LPWAVEHDR pwh, //Адрес структуры WAVEHDR
UINT cbwh //Размер структуры
);
Для Delphi
function waveInPrepareHeader(
hWaveIn: HWAVEIN; //Указатель на уже открытое устройство
lpWaveInHdr: PWaveHdr;//Адрес структуры WAVEHDR
uSize: UINT //Размер структуры
): MMRESULT; stdcall;
Структура WAVEHDR уже была описана мной в февральском номере. Здесь она же и ничем не отличается.
Когда блок данных уже не нужен, его надо уничтожить. Для этого используется функция waveInUnPrepareHeader:
Для С++
MMRESULT waveInUnprepareHeader(
HWAVEIN hwi, //Указатель на уже открытое устройство
LPWAVEHDR pwh, //Адрес структуры WAVEHDR
UINT cbwh //Размер структуры
);
Для Delphi
function waveInUnprepareHeader(
hWaveIn: HWAVEIN; //Указатель на уже открытое устройство
lpWaveInHdr: PWaveHdr;//Адрес структуры WAVEHDR
uSize: UINT //Размер структуры
): MMRESULT; stdcall;
После того, как блок данных подготовлен, он должен быть подключён к устройству записи. Для этого используется функция waveInAddBuffer. С помощью этой функции блок данных помещается в очередь записи.
Для С++
MMRESULT waveInAddBuffer(
HWAVEIN hwi, //Указатель на уже открытое устройство
LPWAVEHDR pwh, //Адрес структуры WAVEHDR
UINT cbwh //Размер структуры
);
Для Delphi
function waveInAddBuffer(
hWaveIn: HWAVEIN; //Указатель на уже открытое устройство
lpWaveInHdr: PWaveHdr;//Адрес структуры WAVEHDR
uSize: UINT //Размер структуры
): MMRESULT; stdcall;
Параметры те же самые, что и при подготовке блока данных.
Всё. Устройство открыто, блоки подготовлены и поставлены в очередь записи. Теперь можно и приступить к записи звуковых данных. Для этого используется функция waveInStart:
Для С++
MMRESULT waveInStart(
HWAVEIN hwi
);
Для Delphi
function waveInStart(
hWaveIn: HWAVEIN
): MMRESULT; stdcall;
Единственный параметр - указатель на открытое устройство. Внимание!!! Запись начнётся только если в очереди есть хотя бы один блок данных. Второй блок может быть подключён после начала записи. Если ты начнёшь запись без блоков данных, то данные потеряются, потому что им некуда будет сохраняться.
Для окончания записи может использоватя функция waveInReset
Для С++
MMRESULT waveInReset(
HWAVEIN hwi
);
Для Delphi
function waveInReset(
hWaveIn: HWAVEIN
): MMRESULT; stdcall;
Параметр тот же. После вызова этой функции запись прекращается, все блоки данных возвращаются из очереди и позиция записи устанавливается в ноль.
Для прекращения записи есть ещё одна функция - waveInStop. Она так же останавливает запись, но если в очереди есть хотя бы один блок данных, он останется в очереди. При последующем старте, запись будет происходить в этот блок.
Для С++
MMRESULT waveInStop(
HWAVEIN hwi
);
Для Delphi
function waveInStop(
hWaveIn: HWAVEIN
): MMRESULT; stdcall;
Есть ещё две интересные функции используемые при записи. Первая из них - waveInGetErrorText. С помощью этой функции можно узнать текст сообщения о происшедшей ошибке при записи.
Для С++
MMRESULT waveInGetErrorText(
MMRESULT mmrError, //Код ошибки полученный при записи
LPSTR pszText, //Сюда поместят текст соответствующий коду
UINT cchText //Размер буфера pszText отведённого под текст
);
Для Delphi
function waveInGetErrorText(
mmrError: MMRESULT; //Код ошибки полученный при записи
lpText: PChar; //Сюда поместят текст соответствующий коду
uSize: UINT //Размер буфера pszText отведённого под текст
): MMRESULT; stdcall;
и последняя на сегодня функция - waveInGetPosition. Эта функция возвращает текущую позицию записи.
Для С++
MMRESULT waveInGetPosition(
HWAVEIN hwi, //Указатель на открытое устройство
LPMMTIME pmmt, //Структура MMTIME, в которую поместят результат
UINT cbmmt //Размер структуры MMTIME
);
Для Delphi
function waveInGetPosition(
hWaveIn: HWAVEIN; //Указатель на открытое устройство
lpInfo: PMMTime; //Структура MMTIME, в которую поместят результат
uSize: UINT //Размер структуры MMTIME
): MMRESULT; stdcall;
На этом всё. Алгоритм работы записи идентичен воспроизведению, поэтому смотри исходник и разбирайся. Если ты читал статьи про воспроизведение, то у тебя не будет проблем.