Рефераты. Программа воспроизведения произвольного звукового файла с использованием звукового адаптера (формат ...

                    AL=0 – от начала файла

     mov  cx,0     ; CX:DX - новое значение указателя

     mov  dx,38h   ; по этому адресу начинаются данные в tada.wav

     int  21h      ; переместим файловый указатель 

     mov ah,3Fh        ; Чтение из файла AH=3Fh

     mov  cx,27459  ; считать 27459 байтов в файле tada.wav

     push ds        ;заносим считанные данные в стек

     mov dx,ds     

     and  dx,0F000h ; выровняем буфер на границу 4K-страницы

     add  dx,1000h ; складываем dx и 1000h, необход. для DMA

     mov  ds,dx

     mov  dx,0     ; DS:DX - адрес буфера

     int  21h      ; чтение файла

     pop  ds         ; выгрузить из стека данные в ds

     ret

error_exit:        ; если не удалось открыть файл

     mov  ah,9     ; AH=09h

     mov  dx,offset notopenmsg    ; DS:DX = адрес сообщения об 

                                  ; ошибке

     int  21h      ; вывод строки на экран

     int  20h      ; конец программы

notopenmsg    db   'Could not open file',0Dh,0Ah    ; сообщение об    

                                                  ; ошибке

         db   'Exiting',0Dh,0Ah,'$'

open_file endp

Алгоритм и блок-схема

 


Считываем данные из файла

 
                                             

 


Компиляция

Для  компиляции будем использовать компилятор и линковщик Tasm и Tlink соответственно:

            tasm /m wavdma.asm

            tlink /t /x wavdma.obj


Код исходной  программы(начало)


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



FILESPEC equ 'C:\WINDOWS\MEDIA\TADA.WAV'

SBPORT   equ 220h

SBIRQ    equ 5         ; только IRQ0-IRQ7

     .model   tiny

     .code

     .186

     org  100h          ; COM-программа

start:

     call dsp_reset      ; инициализация DSP

     jc   no_blaster

     mov  bl,0D1h       ; команда 0D1h

     call dsp_write      ; включить звук

     call open_file      ; прочитать файл в буфер

     call hook_sbirq    ; перехватить прерывание

     mov  bl,40h        ; команда 40h

     call dsp_write      ; установка скорости передачи

     mov  bl,0B2h       ; константа для 11025Hz/Stereo

     call dsp_write

     call program_dma   ; начнём DMA-передачу данных


main_loop:              ; основной цикл

     cmp  byte ptr finished_flag,0


     je  main_loop      ; выход когда байт finished_flag = 1


     call restore_sbirq ; восстановить прерывание

no_blaster:

     ret


old_sbirq dd   ?         ; адрес старого обработчика

finished_flag db   0    ; флаг окончания работы

filename db   FILESPEC,0    ; имя файла


; обработчик прерывания звуковой карты

; устанавливает флаг finished_flag в 1

sbirq_handler proc far

     push ax

     mov  byte ptr cs:finished_flag,1 ; установить флаг

     mov  al,20h        ; послать команду EOI

Код исходной  программы(продолжение)


     out 20h,al        ; в контроллер прерываний

     pop  ax

     iret

sbirq_handler endp

; процедура dsp_reset

; сброс и инициализация DSP

dsp_reset proc near

     mov  dx,SBPORT+6 ; порт 226h - регистр сброса DSP

    

        mov  al,1 ; запись в него единицы запускает инициализацию

     out  dx,al

     mov  cx,40      ; небольшая пауза

dsploop:

     in   al,dx

     loop dsploop

     mov  al,0        ; запись нуля завершает инициализацию

     out  dx,al      ; теперь DSP готов к работе


     add  dx,8        ; порт 22Eh - бит 7 при чтении указывает на  

                        занятость

     mov  cx,100    ; буфера записи DSP

check_port:

     in   al,dx      ; прочитаем состояние буфера записи

     and  al,80h     ; если бит 7 ноль

     jz   port_not_ready     ; порт ещё не готов

     sub  dx,4        ; иначе: порт 22Ah - чтение данных из DSP

     in   al,dx

     add  dx,4        ; порт снова 22Eh

     cmp  al,0AAh    ; проверим, что DSP возвращает 0AAh при   

                      ; чтении -  это сигнал его готовности к   

                      ; работе

     je   good_reset

port_not_ready:

     loop check_port  ; повторить проверку на 0AAh 100 раз

bad_reset:

     stc             ; если Sound Blaster не откликается

     ret             ; вернуться с CF=1

good_reset:

     clc             ; если инициализация прошла успешно

     ret             ; вернуться с CF=0

dsp_reset endp


; процедура dsp_write

; посылает байт из BL в DSP

dsp_write proc near

     mov  dx,SBPORT+0Ch ; порт 22Ch - ввод данных/команд DSP

write_loop:          ; подождём готовности буфера записи DSP

     in   al,dx      ; прочитаем порт 22Ch

Код исходной  программы(продолжение)

    

     and al,80h     ; и проверим бит 7

     jnz  write_loop  ; если он не ноль - подождём ещё

     mov  al,bl      ; иначе:   


     out dx,al      ; пошлём данные

     ret

dsp_write endp


; процедура hook_sbirq

; перехватывает прерывание звуковой карты и разрешает его

hook_sbirq proc    near

     mov  ax,3508h+SBIRQ     ; AH=35h, AL=номер прерывания   

     int 21h      ; получим адрес старого обработчика

     mov  word ptr old_sbirq,bx   ; и сохраним его

     mov  word ptr old_sbirq+2,es

     mov  ax,2508h+SBIRQ     ; AH=25h, AL=номер прерывания

     mov  dx,offset sbirq_handler ; установим новый обработчик

     int  21h

     mov  cl,1

     shl  cl,SBIRQ

     not  cl       ; построим битовую маску

     in   al,21h        ; прочитаем OCW1

     and  al,cl         ; разрешим прерывание

     out  21h,al        ; запишем OCW1

     ret

hook_sbirq endp


; процедура restore_sbirq

; восстановим обработчик и запретим прерывание

restore_sbirq proc near

     mov  ax,3508h+SBIRQ     ; AH=25h AL=номер прерывания

     lds  dx,dword ptr old_sbirq

     int  21h      ; восстановим обработчик

     mov  cl,1

     shl  cl,SBIRQ ; построим битовую маску

     in   al,21h        ; прочитаем OCW1

     or   al,cl         ; запретим прерывание

     out 21h,al        ; запишем OCW1

     ret

restore_sbirq endp


; процедура open_file

; открывает файл filename и копирует звуковые данные из него, ;считая что  это - tada.wav, в буфер buffer

open_file proc near

     mov  ax,3D00h ; AH=3Dh AL=00

     mov  dx,offset filename ; DS:DX - ASCIZ-строка с именем файла

     int  21h      ; открыть файл для чтения

     jc   error_exit    ; если не удалось открыть файл - выйти

     mov  bx,ax         ; идентификатор файла в BX

Код исходной  программы(продолжение)

     mov ax,4200h ; AH=42h, AL=0

     mov  cx,0     ; CX:DX - новое значение указателя

     mov  dx,38h   ; по этому адресу начинаются данные в tada.wav

     int  21h      ; переместим файловый указатель 

     mov ah,3Fh        ; AH=3Fh

     mov  cx,27459  ; это - длина данных в файле tada.wav

     push ds

     mov dx,ds

     and  dx,0F000h ; выровняем буфер на границу 4K-страницы

     add  dx,1000h ; для DMA

     mov  ds,dx

     mov  dx,0     ; DS:DX - адрес буфера

     int  21h      ; чтение файла

     pop  ds

     ret

error_exit:        ; если не удалось открыть файл

     mov  ah,9     ; AH=09h

     mov  dx,offset notopenmsg    ; DS:DX = адрес сообщения об  

                                  ; ошибке

     int  21h      ; вывод строки на экран

     int  20h      ; конец программы

notopenmsg    db   'Could not open file',0Dh,0Ah    ; сообщение об     

                                                  ; ошибке

         db   'Exiting',0Dh,0Ah,'$'

open_file endp


; процедура program_dma

; настраивает канал 1 DMA

program_dma proc near

     mov  al,5      ; замаскируем канал 1

     out  0Ah,al

     xor  al,al    ; обнулим счётчик

     out  0Ch,al

     mov  al,49h   ; установим режим передачи

                   ; (используйте 59h для автоинициализации)

     out  0Bh,al


     push cs

     pop  dx

     and  dh,0F0h

     add  dh,10h   ; вычислим адрес буфера


     xor  ax,ax

     out  02h,al   ; запишем младшие 8 бит

     out  02h,al   ; запишем следующие 8 бит

     mov  al,dh

     shr  al,4

     out  83h,al   ; запишем старшие 4 бита


     mov  ax,27459 ; длина данных в tada.wav

     dec  ax       ; DMA требует длину-1

Код исходной  программы(заключение)

     out 03h,al   ; запишем младшие 8 бит длины

     mov  al,ah

     out  03h,al   ; запишем старшие 8 бит длины   

     mov al,1

     out  0Ah,al   ; снимем маску с канала 1 

     mov bl,14h   ; команда 14h

     call dsp_write ; 8-битное простое DMA-воспроизведение

     mov  bx,27459 ; размер данных в tada.wav

     dec  bx       ; минус 1

     call dsp_write ; запишем в DSP младшие 8 бит длины

     mov  bl,bh

     call dsp_write ; и старшие

     ret

program_dma endp

     end  start































Заключение


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



Литература


1)      Assembler для DOS, Windows и UNIX. – Зубков С.В. ”ДМК” Москва 2000г.

2)      Искусство программирования на Ассемблере. – Голубь Н.Г. ”DiaSoft” 2002г.

3)      Ассемблер для Windows. – Пирогов В.Ю. 2002г.

4)      Windows Assembly Language and Systems Programming.- Barry Kauler.  (перевод).

5)      Секреты системного программирования в Windows 98. - Мэтт Питрек.  К., 1996

6)      Сайт www.wasm.ru.  


Страницы: 1, 2, 3, 4



2012 © Все права защищены
При использовании материалов активная ссылка на источник обязательна.