Звук
Эта программа увеличивает громкость выбранного канала на 1000.
Code: |
uses MMSystem;
procedure TForm1.Button1Click(Sender: TObject); var vol: longint; LVol, RVol: integer; begin AuxGetVolume(ListBox1.ItemIndex, @Vol); LVol := Vol shr 16; if LVol < MaxWord - 1000 then LVol := LVol + 1000 else LVol := MaxWord; RVol := (Vol shl 16) shr 16; if RVol < MaxWord - 1000 then RVol := RVol + 1000 else RVol := MaxWord; AuxSetVolume(ListBox1.ItemIndex, LVol shl 16 + RVol); end;
procedure TForm1.FormCreate(Sender: TObject); var i: integer; cap: TAuxCaps; begin for i := 0 to auxGetNumDevs - 1 do begin auxGetDevCaps(i, Addr(cap), SizeOf(cap)); ListBox1.Items.Add(cap.szPname) end; end; |
Второй вариант:
Code: |
uses mmsystem;
function GetWaveVolume: DWord; var Woc : TWAVEOUTCAPS; Volume : DWord; begin result:=0; if WaveOutGetDevCaps(WAVE_MAPPER, @Woc, sizeof(Woc)) = MMSYSERR_NOERROR then if Woc.dwSupport and WAVECAPS_VOLUME = WAVECAPS_VOLUME then begin WaveOutGetVolume(WAVE_MAPPER, @Volume); Result := Volume; end; end;
procedure SetWaveVolume(const AVolume: DWord); var Woc : TWAVEOUTCAPS; begin if WaveOutGetDevCaps(WAVE_MAPPER, @Woc, sizeof(Woc)) = MMSYSERR_NOERROR then if Woc.dwSupport and WAVECAPS_VOLUME = WAVECAPS_VOLUME then WaveOutSetVolume(WAVE_MAPPER, AVolume); end;
procedure TForm1.Button1Click(Sender: TObject); begin Beep; end;
procedure TForm1.Button2Click(Sender: TObject); var LeftVolume: Word; RightVolume: Word; begin LeftVolume := StrToInt(Edit1.Text); RightVolume := StrToInt(Edit2.Text); SetWaveVolume(MakeLong(LeftVolume, RightVolume)); end;
procedure TForm1.Button3Click(Sender: TObject); begin Caption := IntToStr(GetWaveVolume); end; |
Автор MMM
Прислал: Ненашев Илья Николаевич
Под WinNT/2000/XP вы можете использовать Beep(Tone, Duration) (задавать тон и продолжительность звучания). А под 9.x/Me эта функция не реализована, но можно командовать железом через порты, и сделать универсальную:
Code: |
unit BeepUnit;
procedure Beep(Tone, Duration: Word); // универсальная - версию виндовса проверяет
procedure Sound(Freq : Word); procedure NoSound;
procedure SetPort(address, Value:Word); function GetPort(address:word):word;
implementation
procedure SetPort(address, Value:Word); var bValue: byte; begin bValue := trunc(Value and 255); asm mov dx, address mov al, bValue out dx, al end; end;
function GetPort(address:word):word; var bValue: byte; begin asm mov dx, address in al, dx mov bValue, al end; GetPort := bValue; end;
procedure Sound(Freq : Word); var B : Byte; begin if Freq > 18 then begin Freq := Word(1193181 div LongInt(Freq)); B := Byte(GetPort($61)); if (B and 3) = 0 then begin SetPort($61, Word(B or 3)); SetPort($43, $B6); end; SetPort($42, Freq); SetPort($42, Freq shr 8); end; end;
procedure NoSound; var Value: Word; begin Value := GetPort($61) and $FC; SetPort($61, Value); end;
procedure Beep(Tone, Duration: Word); begin if SysUtils.Win32Platform = VER_PLATFORM_WIN32_NT then Windows.Beep(Tone, Duration) else begin Sound(Tone); Windows.Sleep(Duration); NoSound; end; end;
end. |
Взято из forum.sources.ru
Вот мой старый способ, которым я извлекал звуки в Visual Basic (это было много времени назад) с помощью функций API. Ниже приведена функция, требующая на входе два параметра: тон и длительность воспроизведения. (Примечание: функции Windows API требуют гораздо большее количество параметров, но вам нужно беспокоиться только о тех, которые изменяются от вызова до вызова... т.е. только о тоне и длительности.)
Code: |
procedure MakeSound(note, duration: integer); { Цель: Проигрывание звуков на динамике PC. Параметры: note = шаг тона (правильный диапазон с 1 по 84 (1
самый низкий тон и 84 самый высокий) duration = продолжительность звучания (допустимый диапазон с 1 по 128... но это мои догадки... чем меньше значение тем короче продолжительность) } var result: integer; begin {проверка на правильность величины... должно быть 1-84} if (note < 1) or (note > 84) then exit; {проверка на правильность величины... по моим догадкам, должно быть в диапазоне от 1 до 128} if (duration < 1) or (duration > 128) then exit; {открываем звуковой канал} result := OpenSound; {устанавливаем размер звуковой очереди (не очищайте это! Я думаю что каждая нота требует 6 байт.)} result := SetVoiceQueueSize(1, 6); {устанавливаем звуковую ноту (и ее длительность)} result := SetVoiceNote(1, note, duration, 1); {проигрываем ноту} result := StartSound; {ожидаем окончания звучания} result := WaitSoundState(S_QUEUEEMPTY); {закрываем звуковой канал} CloseSound; end; |
Затем можно вызвать эту функцию следующим образом...
MakeSound(1,1);
MakeSound(32,10);
Эти две строчки заставят динамик вашего PC зазвучать сначала в низком диапазоне (продолжительностью в секунду или две), и затем немного дольше в более высоком диапазоне.
Автор: Steve Keyser
Взято с delphiworld.narod.ru
Если Вам не нужен компонент MediaPlayer, а сыграть звук, например, при нажатии на кнопку, нужно, воспользуйтесь функцией PlaySound. Одна из ее возможностей – сыграть wav-файл.
Code: |
uses MMsystem;
procedure TForm1.Button1Click(Sender: TObject); begin if OpenDialog1.Execute then PlaySound(PChar(OpenDialog1.FileName), 0, SND_FILENAME); end; |
Автор советов: Даниил Карапетян
e-mail: Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.
Автор справки: Алексей Денисов
e-mail: Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.
Sound Blaster воспроизводит как синтезированный звук так и оцифровые звуки.
В этом файле будет расмотрено программирование воспроизведения цифровых
выборок через Sound Blaster DSP.
+-------------------------------------+-------------------------------------
| Порты ввода/вывода SoundBlaster DSP |
+=====================================+
Чип DSP ( Цифровой Звуковой Процессор ) программируется через пять портов,
которые определяются через базовый адрес Sound Blaster:
2x6h - DSP Сброс
2xAh - DSP Чтение
2xCh - DSP Запись (команды/данные) ,
состояние буфера записи DSP( Бит 7 )
2xEh - Состояние буфер чтения DSP ( Бит 7 ),
подтверждение прерывания DSP
Пятый порт только для Sound Blaster 16
2xFh - подтверждение прерывания DSP с 16 битами
Где x = 1 для базового адреса 210h.
x = 2 для базового адреса 220h.
.
.
x = 6 для базового адреса 260h.
+-----------+----------------------------------------------------------------
| Сброс DSP |
+===========+
Необходимо сбросить DSP прежде, чем начать работу с ним. Сброс осуществляется
по следующему алгоритму:
1) Запишите 1 в порт сброса (2x6)
2) Ждите 3 микросекунды
3) Запишите 0 в порт сброса (2x6)
4) Читайте порт состояния буфера чтения (2xE) пока бит 7 = 1
5) Опрашивайте порт данных чтения (2xA) пока вы не получите AAh.
Для сброса DSP требуется около 100 мкс. Если после этого вы не получили
AAh. Значит, либо нет звуковой платы, или задан был неверный базовый
адрес.
Пример:
#define MAX_BASE_SB 5
int bases[MAX_BASE_SB]={ 0x220, 0x230, 0x240, 0x250, 0x260 };
int baseAddrSB=0x220;
// Прочитать
unsigned char pascal ReadSB
(void)
{
unsigned int value;
while (!(inp((baseAddrSB+0xE)) & 0x80));
value = inp((baseAddrSB+0xA));
return value;
}
// Проверить наличие
char pascal CheckSB
( void )
{
int i, j;
for ( j=0; j 23 KHz. Затем младший
байт длины, потом старший.
WriteSB(DMA_8_BIT_DAC);
WriteSB(lo(len));
WriteSB(hi(len));
24h - Включение записи с ADC 8 Бит 4KHz - > 23 KHz
74h - Включение вывода на DAC 4 Бит ADPCM 4KHz - > 12 KHz
75h - Включение вывода на DAC 4 Бит ADPCM с 4KHz - > 12 KHz с байтом ссылки
76h - Включение вывода на DAC 2.6 Бит ADPCM 4KHz - > 13 KHz
77h - Включение вывода на DAC 2.6 Бит ADPCM с 4KHz - > 13 KHz с байтом ссылки
16h - Включение вывода на DAC 2 Бит ADPCM 4KHz - > 11 KHz
17h - Включение вывода на DAC 2 Бит ADPCM с 4KHz - > 11 KHz с байтом ссылки
ADPCM ( Адаптивная Импульсно-кодовая Модуляция) - это звуковая методика
сжатия, где различие между последовательными выборками сохраняется скорее
чем их фактические значения. В режимах с байтами ссылки, первый байт -
фактическое начальное значение. Наличие режимов с и без байтов ссылки значит
что вы можете выводить последовательные блоки без наличия байта ссылки.
Bxh - программмирование режима DMA с 16 битным цифровым звуком.
( Только для SB16 )
Командная последовательность:
Команда, Режим, Lo(Length-1), Hi(Length-1):
Первый байт команды состоит:
D7 D6 D5 D4 D3 D2 D1 D0
--+--+--+--+---+----+-----+--
1 0 1 1 A/D A/I FIFO 0
---------------+----+-----+--
0=D/A 0=SC 0=off
1=A/D 1=AI 1=on
Общие команды:
B8 - одиночный цикл с 16-битной записи звука
B0 - одиночного цикла с 16-битным воспроизведением
BE - автоинициализируемая 16-битная запись
B6 - автоинициализируемое 16-битной воспроизведение
Режим:
D7 D6 D5 D4 D3 D2 D1 D0
---+--+-------+-----+--+--+--+--
0 0 Стерео Знак 0 0 0 0
0-Моно 0-без
1-Стерео 1-со знаком
Cxh - программирование режим DMA с 8-битным цифровым звуком.
( Только для SB16 )
Те же самые команды, что для 16-бит.
C8 - одиночный цикл с 8-битной записи звука
C0 - одиночного цикла с 8-битным воспроизведением
CE - автоинициализируемая 8-битная запись
C6 - автоинициализируемое 8-битной воспроизведение
FIFO используется чтобы удалять несогласованности в тот период выборки,
когда звуковая плата не способна получить DMA, когда это требуется.
Без FIFO плата делает попытку захвата DMA в точно тот момент, когда
требуется выборка. Если другое устройство с более высоким приоритетом
обращается к DMA, звуковая плата ожидает и скорость выборки может
уменьшаться. FIFO позволяет во время выборки с DMA быть более гибким DSP
без потери звукового качества. FIFO очищается всякий раз, когда команда
посылается DSP. В режиме одиночного цикла, DSP постоянно перепрограммируется.
С FIFO DSP может еще содержать данные, который не были выданы, когда
команда очистила DAC. Чтобы избежать этого, FIFO должен быть переключен
в режим с одиночным циклом. Затем, снова переведен в автоинициализируемый
режим, когда DSP не перепрограммируется.
1Ch - Включение вывода на DAC 8 Бит 4KHz - > 23 KHz с автоинциализацией
90h - Включение вывода на DAC 8 бит 4kHz - > 44 KHz с автоинициализацией
48h - Установить длину блока на пересылку перед посылкой 91h, 99h
сначала младший байт затем старший длину.
91h - Включение вывода на DAC 8 бит 4kHz - > 44 KHz стерео
99h - Включение записи с ADC 8 бит 4kHz - > 44 KHz стерео
WriteSB(SET_LEN_DMA_8_BIT);
WriteSB(lo(len));
WriteSB(hi(len));
WriteSB(DMA_8_BIT_DAC_HI);
D0h - остановить 8-битный DMA
D4h - возобновить 8-битный DMA
D5h - остановить 16-битный DMA
D6h - возобновить 16-битный DMA
Эти команды пригодны как и для автоинциализированного режима,
так и для одиночных циклов.
D9h - Выход из авто инициализируемого режима DMA с 16 битами
после окончания текущего блока.
DAh - Выход из авто инициализируемого режима DMA с 8 битами
после окончания текущего блока.
E1h - Получить номер версии DSP. После посылки этой команды, прочитайте
из DSP два байта. Первый байт - главный номер версии и второй
байт - малый номер версии. Версия 4.00 - это SB16.
Версия | Стерео | Частота | FIFO | 16 бит
--------+--------+----------+------+--------
< 2.00 | - | до 21379 | - | -
>= 2.00 | - | до 21379 | + | -
>= 2.01 | - | до 43478 | + | -
>= 3.00 | + | до 43478 | + | -
>= 3.01 | + | до 43478 | + | +
Пример определения версии:
int pascal VersionSB
( void )
{
char ch, ch1;
WriteSB(0xE1);
ch=ReadSB();
ch1=ReadSB();
verSB=ch<<8 | ch1;
if ( verSB>=0x200 )
Fifo=1;
if ( verSB>=0x201 )
MaxFrequency=1;
if ( verSB>=0x300 )
Stereo=1;
if ( verSB>=0x301 )
SixteenBit=1;
return verSB;
}
+----------------------+----------------------------------------------------
| Программирование DMA |
+======================+
Контроллер DMA (Прямого Доступа В память) управляет пересылками данных
между устройствами ввода/вывода и памятью без использования центрального
процессора. IBM совместимая ЭВМ имеет два контроллера DMA один для
пересылок с 8 битами и другой для пересылок с 16 битами. Контроллер DMA,
вместе с внешним регистром страницы, способен на перемещение блоков по 64 КБ.
Ниже приведена информация по программированию DMA.
Адреса портов для адреса DMA и регистров счета.
Контроллер | Адрес | Функция
---------------+---------+-----------------
DMA 1 | 00 | Канал 0 адреса
c 8 битами | 01 | Канал 0 счета
Подчиненный | 02 | Канал 1 адрес
| 03 | Канал 1 счета
| 04 | Канал 2 адреса
| 05 | Канал 2 счета
| 06 | Канал 3 адреса
| 07 | Канал 3 счета
--------------+---------+------------------
DMA 2 | C0 | Канал 4 адреса
с 16 битами | C2 | Канал 4 счета
Ведущий | C4 | Канал 5 адреса
| C6 | Канал 5 счета
| C8 | Канал 6 адреса
| CA | Канал 6 счета
| CC | Канал 7 адреса
| CE | Канал 7 счета
Адреса портов для регистров управления
Адрес | Операция| Функция
DMAC1 DMAC2 | |
------------+---------+-----------------------------------
0A D4 | Запись | регистр маски
0B D6 | Запись | регистр режима
0C D8 | Запись | регистр сброс байта flip-flop
Адреса портов для младших регистров страницы
Адрес | Функция
--------+-----------------------------------
81 | 2 Канал DMA с 8 битами
82 | 3 Канал DMA с 8 битами
83 | 1 Канал DMA с 8 битами
87 | 0 Канал DMA с 8 битами
89 | 6 Канал DMA с 16 битами
8A | 7 Канал DMA с 16 битами
8B | 5 Канал DMA с 16 битами
Бита регистра режима
БИТ | Функция
---------+----------------------------------
Биты 7:6 | Биты выбора Режима
00 | Выбранный Режим запроса
01 | Одиночный выбранный режим
10 | Выбранный блочный режим
11 | Каскадный выбранный режим
---------+----------------------------------
Бит 5 | Бит приращения / декремента Адреса
1 | Выбранный Декремент адреса
0 | Выбранное Приращение адреса
---------+----------------------------------
Бит 4 | Авто инициализация
1 | Автоинициализация включена
0 | Одиночный
---------+----------------------------------
Биты 3:2 | Биты Пересылки
00 | Проверите пересылку
01 | Запишите пересылку ( К памяти )
10 | Читайте пересылку ( Из памяти )
11 | Запрещенный
** | Игнорируется если биты 7:6 = 11
---------+----------------------------------
Биты 1:0 | Биты выбора Канала
00 | Выберите канал 0 (4)
01 | Выберите канал 1 (5)
10 | Выберите канал 2 (6)
11 | Выберите канал 3 (7)
Биты маски записи
БИТ | Функция
----------+-----------------------------------
Биты 7:3 | Неиспользуемый ( Набор к 0 )
|
Бит 2 | Установить/сбросить бит маски
1 | Установить бит маски ( Отключите канал )
0 | Сбросить бит маски ( Доступен канал )
----------+------------------------------------
Биты 1:0 | Биты выбора Канала
00 | канал 0 (4)
01 | канал 1 (5)
10 | канал 2 (6)
11 | канал 3 (7)
DMAC2 используется для работы с 16 битами и DMAC1 используется для
работы с 8 битами. Вот пример программирования DMA:
1) Вычислите абсолютный линейный адрес вашего буфера
LinearAddr = MK_SEG( Buf ) * 16L + MK_OFF ( Buf );
2) Отключите канал DMA звуковой платы установкой бита маски
outp(MaskPort, 1 + ( DMAChannel % 4 ));
3) Очистите указатель байта flip-flop
outp(ClrPort, DMAChannel );
4) Запишите режим DMA для пересылки
Биты выбора режима должны устанавливаться в 00h для режима запроса.
Адрес бита +/- должен устанавливаться в 0 для приращения адреса.
Бит автоинициализации должен устанавливаться соответственно.
Биты пересылки должны устанавливаться в 10h для воспроизведения и
01h для записи. Выбор канала должен устанавливаться так же как и на
канал DMA звуковой платы.
outp(ModePort, Mode + ( DMAChannel % 4 ));
Некоторые часто используемые режимы:
48h + Канал - одиночный цикл воспроизведение
58h + Канал - автоинициализируемое воспроизведение
44h + Канал - запись одиночного цикла
54h + Канал - автоинициализируемая запись
5) Запишите смещение буфера, младший байт затем старший байт. Для
шестнадцати разрядных данных, смещение должно быть в словах от начала
128k-байтной страницы, для 8-битных от 64K. Самый простой метод для
вычисления смещения с 16 битами - это разделить линейный адрес на
два перед вычислением смещения.
#define lo(value) (unsigned char)((value) & 0x00FF)
#define hi(value) (unsigned char)((value) >> 8)
if ( SixteenBit==1 )
BufOffset= ( LinearAddr / 2 ) % 65536;
else BufOffset= LinearAddr % 65536;
outp(BaseAddrPort, lo(BufOffset));
outp(BaseAddrPort, hi(BufOffset));
6) Запишите длину пересылки в соответствующий порт счета, младший
байт затем старший байт. Для пересылки с 8 битами, запишите
длину в байтах минус единица. Для пересылки с 16 битами, запишите
номер длину в словах минус единица.
if ( SixteenBit==1 )
TransferLength/=2;
outp(CountPort, lo(TransferLength-1));
outp(CountPort, hi(TransferLength-1));
7) Запишите страницу буфера в регистр страницы DMA.
outp(PagePort, ( LinearAddr / 65536));
8) Включите DMA звуковой платы очистив соответствующий бит маски
outp(MaskPort, DMAChannel % 4);
Пример :
int MaskPort, ClrPort, ModePort, ModeDMA, CountPort, PagePort,
BaseAddrPort;
int pageports[4]={ 0x87, 0x83, 0x81, 0x82 };
MaskPort=0x0A; ClrPort=0xC; ModePort=0xB;
ModeDMA=0x48+DMAChannel;
CountPort=1+DMAChannel*2;
BaseAddrPort=DMAChannel*2;
PagePort=pageports[DMAChannel];
outportb(MaskPort, 4 + DMAChannel);
outportb(ClrPort, DMAChannel );
outportb(ModePort, ModeDMA );
outportb(BaseAddrPort,lo(aligned_physical));
outportb(BaseAddrPort,hi(aligned_physical));
outportb(PagePort,(unsigned char)((aligned_physical>>16)&0xFF));
outportb(CountPort,lo(len-1));
outportb(CountPort,hi(len-1));
outportb(MaskPort, DMAChannel );
+---------------------------+------------------------------------------------
| Установка частоты выборки |
+===========================+
Для версии Sound Blaster ниже 4.00 установка частоты выборки выполняется
посылкой DSP команды 40h. При этом частота преобразуется к константе времени
по формуле:
4KHz - > 23 KHz:
Time Constant = 256 - (1,000,000 / sampling rate)
= 256 - (1,000,000 / 8,000 )
= 131
4KHz - > 44 KHz:
Time Constant = (MSByte of) 65536 - (256,000,000 / sampling rate)
= (MSByte of) 65536 - (256,000,000 / 44,100)
= (MSByte of) 59731
= (MSByte of) 0E953h
= 0E9h
void pascal RateSB
( unsigned int rate )
{
unsigned char tc;
if ( MaxFrequency==0 )
{
if ( rate<5000 ) rate=5000;
if ( rate>22528 ) rate=22528;
tc = (unsigned char)(256 - (1000000/rate));
}
else
{
if ( rate<5000 ) rate=5000;
if ( rate>45056 ) rate=45056;
tc = (unsigned char)(hi((unsigned int)(65536-(256000000L/rate))));
}
WriteSB(TIME_CONSTANT);
WriteSB(tc);
}
В отличие от этого SB16 программируется фактической частотой выборки.
Команда 41h используется для воспроизведения, а 42h используется для записи.
if ( Play==1 )
WriteSB ( 0x41 );
else WriteSB ( 0x42 );
WriteSB ( hi( frequency ) );
WriteSB ( lo( frequency ) );
+---------------------------------------+------------------------------------
| Алгоритм цифрового ввода/вывода звука |
+=======================================+
Чтобы записывать или воспроизводить звук, вы должны использовать следующую
последовательность:
1) Распределите буфер который не пересекает границу 64 Kb
2) Установите программу обработки прерывания.
3) Запрограммируйте контроллер DMA для фоновой пересылки
4) Установите частоту выборки
5) Запишите команду I/O в DSP
6) Запишите режим пересылки I/O в DSP
7) Запишите размер блока в DSP ( Младший байт/Старший байт )
После этого сразу начнется запись или воспроизведение звука.
Выделение памяти под буфер DMA:
data=(char far *)farmalloc(131000L);
if ( data==NULL )
{
printf("Нет места под буфер DMA\n");
return 0;
}
physical=((unsigned long)FP_OFF(data))+(((unsigned long)FP_SEG(data))<<4);
aligned_physical=physical+0x0FFFFL;
aligned_physical&=0xF0000L;
aligned=MK_FP((unsigned )((aligned_physical >> 4) & 0xFFFF),0);
Ниже приведены примеры последовательностей для программирования SB
с помощью DMA.
Нормальная частота, воспроизведение:
1) Записать D1h в 2xCh
2) Установить обработчик прерывания
3) Записать 40h в 2xCh
4) Записать константы времени в 2xCh
5) Запрограммировать DMA
6) Записать 14h в 2xCh
7) Записать длину выборки
8) Обслуживать прерывания, до окончания выборки
9) Восстановить старый обработчик
10) Записать D3h в 2xCh
При этом можно записывать любые команды в DSP, пока идет воспроизведение.
Повышенная частота, воспроизведение:
1) Записать D1h в 2xCh
2) Установить обработчик прерывания
3) Записать 40h в 2xCh
4) Записать константы времени в 2xCh
5) Запрограммировать DMA
6) Записать 48h в 2xCh
7) Записать длину выборки
8) Записать 91h в 2xCh
9) Обслуживать прерывания, до окончания выборки
10) Восстановить старый обработчик
11) Записать D3h в 2xCh
Нормальная частота, запись звука:
1) Установить обработчик прерывания
2) Записать 40h в 2xCh
3) Записать константы времени в 2xCh
4) Запрограммировать DMA
5) Записать 24h в 2xCh
6) Записать длину выборки
7) Обслуживать прерывания, до окончания выборки
8) Восстановить старый обработчик
При этом можно посылать любые команды в DSP, пока идет запись.
Повышенная частота, запись:
1) Установить обработчик прерывания
2) Записать 40h в 2xCh
3) Записать константы времени в 2xCh
4) Запрограммировать DMA
5) Записать 48h в 2xCh
6) Записать длину выборки
7) Записать 99h в 2xCh
8) Обслуживать прерывания, до окончания выборки
9) Восстановить старый обработчик
+------------------------------------+--------------------------------------
| Конец цифрового ввода/вывода звука |
+====================================+
Когда пересылка закончена генерируется прерывание. Фактический номер
прерывания зависит от установки IRQ на плате Sound Blaster:
IRQ | Прерывание
-----+------------
2 | 0Ah
3 | 0Bh
5 | 0Dh
7 | 0Fh
Для обслуживания прерывания необходимо выполнить:
1) подтвердите прием прерывания от DSP прочитав порт (2xEh) один раз для
8-битного звука, или порт 2xF для 16-битного звука.
2) Вывод следующего буфера, если есть.
3) Выведите значение 20h ( EOI ) в порт контроллера прерывания 20h,
а если IRQ8-15(прерывания 70h-77h), то записать 20h в A0h.
Установка прерывания :
DMA_complete = 0;
disable();
OldIRQ = getvect(0x08 + SbIRQ);
setvect(0x08 + SbIRQ,SBHandler);
enable();
Обработчик прерывания :
static void far interrupt SBHandler( void )
{
enable();
DMA_complete = 1;
// подтведить
inportb(baseAddrSB+0xE);
outportb(0x20,0x20);
}
Инициализация обработчика :
DMA_complete = 0;
im = inportb(0x21);
tm = ~(1 << SbIRQ);
outportb(0x21,im & tm);
enable();
Сброс обработчика :
disable();
setvect(0x08 + SbIRQ,OldIRQ);
i = inportb(0x21);
outportb(0x21, i | (1 << SbIRQ));
enable();
Воспроизведение файла выборки:
f = fopen(argv[1],"rb");
raw = ( char far * ) farmalloc(32000L);
if ( f == 0 || raw==0 )
{
printf("Не могу открыть файл выборки - %s\n",argv[1]);
printf("Нет памяти\n",argv[1]);
ResetSB();
return;
}
printf("Воспроизведение выборки ...\n");
WriteSB(ON_SOUND_SB);
RateSB(22222);
len=fread(raw,1,32000,f);
while ( 1 )
{
if ( len==0 ) break;
PlaySB(raw,len);
len=fread(raw,1,32000,f);
while ( StatePlaySB()==0 )
if ( kbhit() ) { getch(); goto Fin; }
}
Fin:
if ( f!=0 ) fclose(f);
if ( raw!=0 ) farfree(raw);
ResetSB();
+-------------+-------------------------------------------------------------
| Стерео звук |
+=============+
При воспроизведении стерео звуков необходимо посылать 2 байта DSP, первый
для левого канала, второй для правого. Необходимо так же указать SB,
что вы воспроизводите стерео звук, через регистры миксера.
+----------------------+----------------------------------------------------
| Миксер Sound Blaster |
+======================+
Ниже приведена информация для SbPro.
Порт 2x4h - индексный порт миксера, 2x5h - порт данных (чтения/записи).
void pascal WriteMixerSB
( char index, char val )
{
outportb(baseAddrSB+4,index);
outportb(baseAddrSB+5,val);
}
char pascal ReadMixerSB
( char index )
{
outportb(baseAddrSB+4,index);
return inportb(baseAddrSB+5);
}
Регистр Сброса Данных используется для инициализации миксера. Установите
этот регистр в 0 перед изменением любого из других регистров миксера.
void pascal ResetMixerSB
( void )
{
WriteMixerSB(0,0); // RESET
}
Регистр записи определяет источник звука и тип фильтра.
Индекс = 0Ch
7 6 5 4 3 2 1 0
--------+-------+---+---+----
+---+---+ +-+-+
+---+ |
| |
В Фильтре ADC Источник
000 - Низкие 00 - Микрофон 1
001 - Высокие 01 - CD
010 - Нет Фильтра 10 - Микрофон 2
11 - Линейный вход
#define SOURCE_MIC1 0
#define SOURCE_CD 1
#define SOURCE_MIC2 2
#define SOURCE_LINE 3
void pascal InputMixerSB
( char sou, char filtr )
{
char val;
val=(sou<<1)&0x6;
val|=(filtr<<3)&0x38;
WriteMixerSB(0xC,val);
}
Регистр воспроизведения служит для установки фильтра и стерео звука.
Индекс = 0Eh
7 6 5 4 3 2 1 0
--------+---------------+----
| |
| |
0 - Использовать фильтр 0 - моно
1 - Без фильтра 1 - Stereo
#define MONO 0
#define STEREO 1
#define USE_FILTER 0
#define BYPASS_FILTER 1
void pascal OutputMixerSB
( char st, char filtr )
{
char val;
val=(st==1)?2:0;
val|=(filtr==1)?0x20:0;
WriteMixerSB(0xE,val);
}
Регистр общей громкости:
Индекс = 22h
7 6 5 4 3 2 1 0
+-----------+---+-----------+
+-----+-----+ +-----+-----+
| |
Громкость Громкость
Лево Право
void pascal MasterVolumeSB
( char left, char right )
{
char val;
val=right&0xf;
val|=(left<<4)&0xf0;
WriteMixerSB(0x22,val);
}
Регистр громкости DSP:
Индекс = 04h
7 6 5 4 3 2 1 0
+-----------+---+-----------+
+-----+-----+ +-----+-----+
| |
Громкость Громкость
Лево Право
void pascal VoiceVolumeSB
( char left, char right )
{
char val;
val=right&0xf;
val|=(left<<4)&0xf0;
WriteMixerSB(0x04,val);
}
Регистр громкости FM синтезатора:
Индекс= 26h
7 6 5 4 3 2 1 0
+-----------+---+-----------+
+-----+-----+ +-----+-----+
| |
Громкость Громкость
Лево Право
void pascal FMVolumeSB
( char left, char right )
{
char val;
val=right&0xf;
val|=(left<<4)&0xf0;
WriteMixerSB(0x26,val);
}
Регистр громкости CD:
Индекс = 28h
7 6 5 4 3 2 1 0
+-----------+---+-----------+
+-----+-----+ +-----+-----+
| |
Громкость Громкость
Лево Право
void pascal CDVolumeSB
( char left, char right )
{
char val;
val=right&0xf;
val|=(left<<4)&0xf0;
WriteMixerSB(0x28,val);
}
Регистр громкости линейного входа:
Индекс = 2Eh
7 6 5 4 3 2 1 0
+-----------+---+-----------+
+-----+-----+ +-----+-----+
| |
Громкость Громкость
Лево Право
void pascal LineVolumeSB
( char left, char right )
{
char val;
val=right&0xf;
val|=(left<<4)&0xf0;
WriteMixerSB(0x2E,val);
}
Регистр громкости микрофона:
Индекс = 0Ah
7 6 5 4 3 2 1 0
--------------------+-------+
+---+---+
|
Громкость микрофона.
void pascal MicVolumeSB
( char vol )
{
char val;
val=vol&0x7;
WriteMixerSB(0xA,val);
}
+------------+--------------------------------------------------------------
| Примечание:|
+============+
Данный документ составлен Анисимовым С.Ю. 08/1995. г. К-Чепецк,
Кировской обл. Россия. v1.( и последняя )
Данными для составления этого документа послужила информация
из различных источников. Поэтому автор не несет ответственность
за неверную информацию, и за повреждения техники и тел при
использовании этого документа.
С наилучшими пожеланиями, для всех любителей программировать Sound Blaster !
Vale !
Взято с Vingrad.ru https://forum.vingrad.ru
Страница 2 из 2