Простейшее цифровое эхо
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.