VR
Virtual Reality On-line   Журнал
Новости   |     Журнал    |    Хаkер    |     Магазин   |   Проекты
[   Вход    ]
[Kарта сайтa]

[ Download  ]
[  Конкурс  ]
[ Анекдоты  ]
[  Ссылки   ]
[  Реклама  ]
[ Почтальон ]
[ О проекте ]






TopList
Программирование звука.
Функции записи звука
:
Logo

Эту рубрику я так же давно уже не делал. Сегодня я собрался решил, что пора тебе рассказать про функции записи звука. Итак читай и юзай. Только в 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;

На этом всё. Алгоритм работы записи идентичен воспроизведению, поэтому смотри исходник и разбирайся. Если ты читал статьи про воспроизведение, то у тебя не будет проблем.

На этом всё. Удачи!!!

 Исходники примера забирай здесь

Внимание!!! Примерчик немного недоработан, потому что сляпан на быструю руку. Главное, чтобы ты понял алгоритм записи данных.


Design by FMk group ©
Copyright©: Horrific aka Флёнов Михаил ©