Автор работы: Пользователь скрыл имя, 25 Ноября 2011 в 07:49, курсовая работа
Целью моей работы является программирование в среде Windows XP АЦП и ЦАП стандартного звукового адаптера. Обе задачи реализуются на языке Borland Delphi 7.0 Enterprise в одной программе, алгоритмы и блоки которой в дальнейшем могут быть использованы в качестве основы для написания программы цифрового осциллографа либо обмена данными между ПК и радиотехническим прибором.
Введение………………………………………………………………...2
Краткие сведения об устройстве звукового адаптера………….…3
Основные понятия и возможности звукового интерфейса………5
Потоковая модель…………………...…………………………………………....5
Звуковой буфер……………………………………………………………………5
Синхронные и асинхронные устройства……………………………………....6
Полу- и полнодуплексные звуковые устройства……………………………...6
Уведомление о завершении обработки буфера………………………………..7
Подготовка буферов……………………………………………………………..7
Способы кодирования цифрового звука……………………………………….7
Формат потока…………………………………………………………………...8
Структура потока………………………………………………………………..9
Паузы, сброс и зацикливание………………………………………………….10
Поддержка нескольких процессов…………………………………………....10
Служба переназначения устройств и форматов………………………………11
Номера звуковых устройств…………………………………………………...11
Идентификаторы (ключи) открытых устройств……………………………...12
Низкоуровневое программирование звука в Windows……………………..13
Общая схема взаимодействия программы и звуковой подсистемы……...14
Структуры, используемые в звуковом интерфейсе………………………...16
Структура WAVEFORMATEX………………………………………………..16
Структуры WAVEINCAPS и WAVEOUTCAPS………………………….….18
Структура WAVEHDR………………………………………………………...19
Заключение…………………………………………………………………...….21
Дождавшись завершения обработки очередного буфера или получив его в результате уведомления от драйвера, программа обрабатывает записанные данные, определяя их размер по полю dwBytesRecorded в заголовке буфера. Затем освобожденный буфер может быть вновь передан драйверу функцией AddBuffer.
Цикл воспроизведения начинается с заполнения одного или нескольких буферов звуковыми данными, после чего они передаются драйверу устройства вывода функцией Write. После получения первого же буфера драйвер запускает ЦАП адаптера, который начинает извлекать звуковые отсчеты. Драйвер всегда воспроизводит каждый буфер полностью, в соответствии со значением поля dwBufferLength в его заголовке. После возврата отработанных буферов приложению они вновь заполняются данными и опять передаются драйверу.
При
необходимости приостановить
Для устройств вывода, поддерживающих расширенные функции управления, программа может регулировать громкость звука функцией SetVolume, а также изменять высоту тона и скорость воспроизведения функциями SetPitch/SetPlaybackRate. Более общим способом регулировки громкости является обращение к микшеру (mixer), который является устройством класса Aux.
Для
аварийного прерывания обработки потока
используется функция Reset, немедленно
останавливающая процесс записи
или воспроизведения и
После завершения использования буферов их необходимо освободить от фиксации в памяти функциями Unprepare, после чего буферы могут быть возвращены в пул динамической памяти (heap).
При полном завершении работы с устройством оно закрывается функцией Close.
Как правило, при передаче указателей на структуры в параметрах интерфейсных функций передаются также размеры этих структур. Это делается для того, чтобы звуковая подсистема могла отслеживать версию интерфейса, используемую программой, - 16- или 32-разрядный, ASCII или UNICODE.
tWAVEFORMATEX = packed record
wFormatTag: Word;
nChannels: Word;
nSamplesPerSec: DWORD;
nAvgBytesPerSec: DWORD;
nBlockAlign: Word;
wBitsPerSample: Word;
cbSize: Word;
end;
wFormatTag - код группы форматов, отражающий способ кодирования звука. Константы, представляющие различные группы, имеют имена вида WAVE_FORMAT_x, где x — название группы. В подключаемом модуле Delphi MMSYSTEM определена только одна константа из этой серии - WAVE_FORMAT_PCM.
nChannels - количество каналов. Обычно этот параметр имеет значение 1 или 2.
nSamplesPerSec - частота дискретизации (количество отсчетов одного канала в секунду).
nAvgBytesPerSec - примерное количество байтов в секунду (скорость звукового потока). Формально требуется, чтобы для форматов PCM это поле было равно произведению nSamplesPerSec и nBlockAlign, однако на практике драйверы обычно не проверяют этого условия.
nBlockAlign - количество байтов, занимаемое одним блоком звукового потока. Формально для форматов PCM это поле должно быть равно произведению nChannels и wBitsPerSample, деленному на 8, однако это правило устанавливалось в то время, когда применялись только 8- и 16-разрядные отсчеты. Таким образом, для правильного вычисления произведение перед делением необходимо округлить в большую сторону до ближайшего кратного восьми:
nBlockAlign = (nChannels * wBitsPerSample + 7) / 8
Поскольку для «больших» отсчетов могут использоваться как 24-, так и 32-разрядные слова, то однозначной связи между разрядностью отсчета и размером блока может не быть.
wBitsPerSample - разрядность отсчета.
cbSize - размер дополнительной информации о формате, расположенной непосредственно за концом структуры. Если дополнительной информации нет, поле должно быть нулевым. Для форматов PCM это поле игнорируется.
Описывают свойства и характеристики звукового устройства. Все поля структур заполняются только звуковой подсистемой и драйвером. Структуры WAVEINCAPS и WAVEOUTCAPS практически одинаковы; WAVEINCAPS имеет следующий вид:
tagWAVEOUTCAPSA = record
wMid: Word;
wPid: Word;
vDriverVersion: MMVERSION;
szPname: array[0..MAXPNAMELEN-1] of AnsiChar;
dwFormats: DWORD;
wChannels: Word;
dwSupport: DWORD;
end;
wMid, wPid - идентификаторы разработчика (Manufacturer) и самого драйвера (Product).
vDriverVersion - версия драйвера, представленная младшим словом (тип MMVERSION эквивалентен типу UINT, который в Win32 является 32-разрядным). Старший байт слова представляет основной номер версии, а младший байт - номер подверсии, отражающей непринципиальные изменения драйвера. Для выделения каждого номера можно использовать стандартные макросы HIBYTE и LOBYTE.
szPname - имя устройства в виде строки ASCIIZ.
dwFormats - множество поддерживаемых устройством типовых форматов в виде битовой комбинации. Константы для отдельных битов имеют названия вида WAVE_FORMAT_fcbb, где f - старшая цифра частоты дискретизации (1, 2 или 4), c - количество каналов (S - стерео или M - моно), а bb - разрядность отсчета (08 или 16). Например: WAVE_FORMAT_1M08 - 11025 Гц, 8 бит, моно, а WAVE_FORMAT_2S16 - 22050 Гц, 16 бит, стерео.
wChannels - максимальное количество каналов, поддерживаемых устройством. Большинство адаптеров поддерживает два канала (стереорежим).
wReserved1 - служебное поле.
Структура
WAVEOUTCAPS полностью аналогична WAVEINCAPS,
за исключением того, что содержит дополнительное
поле dwSupport - битовую комбинацию режимов
вывода, поддерживаемых устройством.
Структура WAVEHDR
Называется заголовком звукового буфера и описывает буфер как хранилище данных и как элемент очереди драйвера. Изначально заполняется приложением, впоследствии отдельные поля модифицируются драйвером.
wavehdr_tag = record
lpData: PChar;
dwBufferLength: DWORD;
dwBytesRecorded: DWORD;
dwUser: DWORD;
dwFlags: DWORD;
dwLoops: DWORD;
lpNext: PWaveHdr;
reserved: DWORD;
end;
lpData - указатель звукового буфера (тип char *). Устанавливается приложением, драйвером не изменяется.
dwBufferLength - размер буфера в байтах. Устанавливается приложением, драйвером не изменяется.
dwBytesRecorded - количество байтов, записанных устройством в буфер. Устанавливается драйвером, имеет значение только после завершения обработки данного буфера.
dwUser - поле пользователя, в которое программа может занести любое угодное ей значение, например ссылку на внутренний описатель устройства. Устанавливается приложением, драйвером не используется и не изменяется.
dwFlags
- флаги состояния буфера. Устанавливаются
приложением, модифицируются драйвером.
|
dwLoops — количество проигрываний цикла для устройств вывода. Имеет значение только в первом буфере цикла. В обычном режиме (без циклов) поле должно быть нулевым. Устанавливается приложением, драйвером не изменяется.
lpNext — указатель заголовка следующего в очереди буфера. Управляется только драйвером.
reserved —
служебное поле. Управляется только драйвером.
Заключение.
В ходе проделанной работы написана программа, в которой реализовано решение двух изначально поставленных задач: программирование АЦП и ЦАП стандартной звуковой карты в среде Windows XP.
Программа состоит из двух блоков – генератора звуковых синусоидальных колебаний заданной частоты и амплитуды и анализатора поступающего сигнала. Таким образом, выходной сигнал может быть использован как источник регулируемого переменного гармонического напряжения малой амплитуды (порядка 1 В) для подключаемого устройства. Если для нормальной работы устройства необходим гармонический сигнал большей амплитуды, то к выходу звуковой карты может быть подключен усилитель переменного напряжения. Немного изменив программный код, на выходе можно получить произвольный сигнал, амплитуда которого в каждый момент времени будет удовлетворять функции A=f(t), определяющей данную зависимость. В своей программе я ограничился лишь получением синусоидальных колебаний, описываемых функциональной зависимостью , где - максимальное значение амплитуды (уровень сигнала), fr – частота колебания в герцах, time – переменная, характеризующая виртуальное время.
Прием данных (оцифровка сигнала) осуществляется в реальном времени вторым блоком программы – анализатором импульсов. При этом допустим как выборочный анализ сигнала (с линейного входа, микрофона и т.д.), так общий анализ всех сигналов одновременно, включая воспроизведение звуковых файлов. Выбор линии ввода осуществляется с помощью стандартного компонента Windows XP – регулятора громкости. Поступающие сигналы преобразуются в набор (буфер - динамический массив) отсчетов с заданными параметрами потока и далее могут быть использованы для любых целей. В моей программе из этого набора строится графическая зависимость отсчетов поступающих данных от времени.
К
сожалению, звуковая карта (из-за специфики
своего принципа действия) не может
быть использована в качестве генератора
или анализатора постоянного
напряжения. Однако эта проблема легко
решается путем использования