Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.04.2020, 17:29   #1
7in
(aka Jin X) !RTFM!
Форумчанин
 
Аватар для 7in
 
Регистрация: 14.12.2014
Сообщений: 295
По умолчанию PC Speaker + ШИМ aka RealSound

Друзья!
Кто выводил семплы (WAV'ки) через спикер ШИМом (под DOS)? Делитесь опытом! :D
Причём, нужен опыт тех, кто копал глубоко.

Итак, стандартный код инициализации таймера:
Код:
	mov al,0B0h
	out 43h,al	; set mode 0 for counter 2
	mov al,1
	out 42h,al	; write low byte (1)
	dec ax
	out 42h,al	; write high byte (0)
	in al,61h
	or al,3
	out 61h,al	; enable speaker
	mov al,90h
	out 43h,al	; prepare to write low bytes to counter 2
Тут всё понятно, вопросов нет.

Далее настраиваем таймер 0 (который генерит IRQ0) на нужную частоту дискретизации и в обработчике шпарим out 42h,al (пишем младшие байты в счётчик 2).

А теперь самое интересное!


1. По логике, отправляемое в порт 42h значение не должно быть больше счётчика, на которое настроен таймер 0 (т.е. если мы выводим звук с частотой 22050 Гц, значит 1193182/22050 = 54), назовём это значение PIT0_CNT.
Ведь как это работает? Когда мы пишем в этот порт, на спикер подаётся 0, а по истечении тиков счётчика – 1. Вот и весь ШИМ. Т.е. если семпл (мы берём беззнаковые, разумеется) имеет значение 85 (33%), значит при PIT0_CNT = 54 мы подаём 18, и треть промежутка времени между двумя соседними семплами на спикере будет 0, 2/3 времени – 1.

Я пересмотрел кучу исходников (в частности, отсюда: https://pascal.sources.ru/sound/index.htm, не все, конечно, но прилично).
И везде вот такая таблица:
Код:
	; al = sample
	mov bx,sine_table
	xlatb		; al = sample translated to range 1..75

sine_table:
	db	1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2
	db	2,2,2,3,3,3,3,3,3,3,3,3,3,3,4,4
	db	4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5
	db	5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6
	db	6,6,6,7,7,7,7,7,7,7,7,7,7,7,8,8
	db	8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9
	db	9,9,10,10,10,10,11,11,12,12,13,14,14,15,16,17
	db	17,18,19,20,21,22,23,24,26,27,28,29,30,31,33,34
	db	35,36,38,39,40,41,43,44,45,46,48,49,50,51,52,53
	db	54,55,57,58,58,59,60,61,62,63,64,64,65,66,66,67
	db	67,67,67,67,67,68,68,68,68,68,68,68,68,68,68,68
	db	68,68,69,69,69,69,69,69,69,69,69,69,69,70,70,70
	db	70,70,70,70,70,70,70,70,70,70,71,71,71,71,71,71
	db	71,71,71,71,71,72,72,72,72,72,72,72,72,72,72,72
	db	72,72,73,73,73,73,73,73,73,73,73,73,73,74,74,74
	db	74,74,74,74,74,74,74,74,74,74,75,75,75,75,75,75
Очевидно, что она настроена на частоту ≈ 16 кГц (1193182/75 ≈ 15909).
Но почему же она используется в плеерах ДЛЯ ЛЮБЫХ частот дискретизации? И для 11 кГц, и для 22 кГц.
Неужели все авторы так жёстко тупят?


2. Почему используется такая синусоидальная таблица, а не линейное значение? Типа:
Код:
	; al = sample
	mov ah,75
	mul ah
	mov al,ah	; al = sample translated to range 1..75
Здесь меня интересует теоретическая база.
И каким образом такая таблица получена? Я хочу генерить такую таблицу в зависимости от частоты дискретизации.
Я забил в Excel'е такую формулу: =ЦЕЛОЕ((-COS(A1/256*ПИ())+1)/2*256). Она выдаёт значения от 0 до 255 (да, от 0, т.к. при нуле, как я понимаю, можно просто ничего не писать в 42-й порт, там как была 1, так и останется... верно?)
Но! В этом случае мы получаем много 0-й в начале, затем чуть меньше единиц... в конце много 254 и чуть больше 255. Здесь же значений 1 и 75 меньше, чем 2 и 74. Какая-то странная таблица, по мне.

А может, эта таблица должна вообще состоять из логарифмических значений (снизу значения растут быстро, сверху – медленно) или...?
Есть ли у кого-то подробное описание технологии RealSound ?


3. По идее, при настройке таймера, первые 5 строк (до in al,61h) можно убрать, т.к. когда мы пишем младший байт, таймер начинает работать любопытным образом: младший и старший байты уменьшаются почти синхронно, т.е. результирующий эффект такой же, как и при обнулении старшего байта (я пробовал это в реальном DOS, в VMware, в DOSBox, в QEMU, в Bochs – везде это так). Это безопасно или всё же с этим могут возникнуть проблемы?


4. Как я понимаю, оптимальная частота дискретизации ≈ 16 кГц. Сильно ниже – появляется писк, сильно выше – "разрядность" ШИМа становится недостаточной для более или менее точной его настройки, появляется излишне много помех. Тем не менее, может быть кто-то экспериментировал и может подсказать, где та граница качества/шума, на которую лучше не заступать? Т.е. оптимальный диапазон частот дискретизации (может быть, от 16 до 24 или до 32 кГц?)
В DOSBox ещё, зараза, спикер работает не так, как в реальной системе. В нём писка вообще нет! И нормально работают как раз значения от 1 до 75. Пишешь меньше (даже при более высокой частоте дискретизации) – звук становится тише, пишешь больше (даже при низкой частоте дискретизации) – начинает хрипеть :-/
Делаю лабы на Asm/Delphi/C++/Python/VBA(Excel): asmlabs.ru
7in вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
pascal + Speaker arnold Паскаль, Turbo Pascal, PascalABC.NET 4 16.02.2013 10:39
PC Speaker и midi(mod) Hacker19_90 Мультимедиа в Delphi 6 17.04.2012 11:00
Проигрывание MIDI мелодии через Speaker IvaD Мультимедиа в Delphi 2 23.01.2012 12:01
pc speaker IceBreaker Общие вопросы C/C++ 8 27.01.2011 18:44