Средства разработки приложений


Листинг 1. Простейшее цифровое эхо


program echo; uses dsp_dma,getsbinf; {Ввод звука - 16 бит со знаком, вывод - 8 бит со знаком.} const BufSize = 2*1024; { размер буфера DMA } TimeConst = 156; { 156 - примерно 10 кГц } HalfBufToFill : integer = 0; { которая половина буфера DMA свободна } BothBuf : byte = 0; { индикатор заполнения обоих буферов } type RecBufType = array[0..BufSize-1]of integer; { для буфера DMA записи } PlayBufType = array[0..BufSize-1]of shortint; { для буфера DMA воспроизведения } var RecBuf : ^RecBufType; { буфер DMA для записи} PlayBuf : ^PlayBufType;{буфер DMA для воспроизведения} inpage, outpage : word; {страницы для буферов DMA} inoffset, outoffset : word; {смещения для буферов DMA} {$F+} procedure SBint;interrupt; {обработчик прерывания от звуковой платы} var intstat : integer; i : integer; begin Port[base + $04] := $82; {проверяем, по какому каналу пришло прерывание} intstat := Port[base + $05] and 3; BothBuf := BothBuf or intstat; if (intstat and 2 <> 0) then begin {16-битовый канал} i := Port[base + $0F]; end; if (intstat and 1 <> 0) then begin {8-битовый канал} i := Port[base + $0E]; end; if BothBuf = 3 then begin {если прошли прерывания от обоих каналов} for i := 0 to BufSize div 2 - 1 do PlayBuf^[HalfBufToFill*BufSize div 2 + i] := hi(RecBuf^[HalfBufToFill*BufSize div 2 + i]); write(HalfBufToFill,#8); {выводим на экран номер половинки буфера} HalfBufToFill := HalfBufToFill xor 1; BothBuf := 0; end; if (irq > 8) then {для IRQ 10, посылаем сигнал EOI во второй контроллер} Port[$A0] := $20; Port[$20] := $20; { посылаем EOI в первый контроллер} end; {$F-} var SkipLength : longint; {размер памяти до границы 64-Кбайт страницы} SkipBlock : pointer; begin writeln(' Эхо - Sound Blaster 16 в ', 'режиме full duplex'); writeln(' для завершения работы ', 'нажмите Enter'); GetBlasterInfo; {определяем характеристики карты} if (cardtype <> 6) then begin {Проверка, что на плате возможен full duplex} writeln(cardtype); writeln( 'Для работы программы необходим Sound Blaster 16.'); halt; end; if (dma8 = dma16) then begin writeln('Ошибка: совпадение 8-битового и ', '16-битового каналов DMA.'); halt; end; SetMixer; {сброс DMAC и установки микшера} getmem(SkipBlock,16); {проверка, чтобы буферы не пересекали границу 64К} SkipLength := $10000 - (seg(SkipBlock^) shl 4) - ofs(SkipBlock^); freemem(SkipBlock,16); if SkipLength > 3*BufSize then getmem(SkipBlock,SkipLength); getmem(RecBuf,2*BufSize); {выделение памяти для буфера записи} inpage := ((longint(seg(RecBuf^)) * 16) + ofs(RecBuf^)) div $10000; inoffset := ((longint(seg(RecBuf^)) * 16) + ofs(RecBuf^)) and $FFFF; getmem(PlayBuf,BufSize); {выделение памяти для буфера воспроизведения} outpage := ((longint(seg(PlayBuf^)) * 16) + ofs(PlayBuf^)) div $10000; outoffset := ((longint(seg(PlayBuf^)) * 16) + ofs(PlayBuf^)) and $FFFF; fillchar(PlayBuf^,BufSize,0); {очистка буфера воспроизведения} EnableInterrupt( @SBint); SetupDMA(dma16,inpage,inoffset,BufSize, $54); {DMA на ввод} SetupDSP($BE,$10,BufSize div 2,TimeConst); {16 бит со знаком FIFO моно} SetupDMA(dma8,outpage,outoffset,BufSize, $58); {DMA на вывод} SetupDSP($C6,$10,BufSize div 2,TimeConst); {8 бит со знаком FIFO моно} readln; dspout($D5); {приостанавливаем 16-битовый ввод-вывод} dspout($D0); {приостанавливаем 8-битовый ввод-вывод} DisableInterrupt; freemem(PlayBuf,BufSize); freemem(RecBuf,2*BufSize); if SkipLength < 3*BufSize then freemem(SkipBlock,SkipLength); end.

Сначала необходимо убедиться, что звуковая плата способна работать в режиме full duplex. Проще (и безопаснее) всего это сделать с помощью переменной окружения 'BLASTER'. Подобным способом следует определить и базовый адрес порта ввода-вывода, а также номера используемых IRQ и канала DMA. Программа, выполняющая разбор переменной окружения, приведена в листинге 2. Плата должна быть 6-го типа, а номера 8- и 16-разрядного каналов DMA - различаться.


Начало  Назад  Вперед



Книжный магазин