PC Speaker + ШИМ aka RealSound

Тема в разделе "WASM.AUDIO", создана пользователем Jin X, 22 апр 2020.

  1. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    369
    Адрес:
    Кольца Сатурна
    Друзья!
    Кто выводил семплы (WAV'ки) через спикер ШИМом (под DOS)? Делитесь опытом! :lol:
    Причём, нужен опыт тех, кто копал глубоко.

    Итак, стандартный код инициализации таймера:
    Код (ASM):
    1.     mov al,0B0h
    2.     out 43h,al    ; set mode 0 for counter 2
    3.     mov al,1
    4.     out 42h,al    ; write low byte (1)
    5.     dec ax
    6.     out 42h,al    ; write high byte (0)
    7.     in al,61h
    8.     or al,3
    9.     out 61h,al    ; enable speaker
    10.     mov al,90h
    11.     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, не все, конечно, но прилично).
    И везде вот такая таблица:
    Код (ASM):
    1.     ; al = sample
    2.     mov bx,sine_table
    3.     xlatb        ; al = sample translated to range 1..75
    4.  
    5. sine_table:
    6.     db    1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2
    7.     db    2,2,2,3,3,3,3,3,3,3,3,3,3,3,4,4
    8.     db    4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5
    9.     db    5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6
    10.     db    6,6,6,7,7,7,7,7,7,7,7,7,7,7,8,8
    11.     db    8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9
    12.     db    9,9,10,10,10,10,11,11,12,12,13,14,14,15,16,17
    13.     db    17,18,19,20,21,22,23,24,26,27,28,29,30,31,33,34
    14.     db    35,36,38,39,40,41,43,44,45,46,48,49,50,51,52,53
    15.     db    54,55,57,58,58,59,60,61,62,63,64,64,65,66,66,67
    16.     db    67,67,67,67,67,68,68,68,68,68,68,68,68,68,68,68
    17.     db    68,68,69,69,69,69,69,69,69,69,69,69,69,70,70,70
    18.     db    70,70,70,70,70,70,70,70,70,70,71,71,71,71,71,71
    19.     db    71,71,71,71,71,72,72,72,72,72,72,72,72,72,72,72
    20.     db    72,72,73,73,73,73,73,73,73,73,73,73,73,74,74,74
    21.     db    74,74,74,74,74,74,74,74,74,74,75,75,75,75,75,75
    Очевидно, что она настроена на частоту ≈ 16 кГц (1193182/75 ≈ 15909).
    Но почему же она используется в плеерах ДЛЯ ЛЮБЫХ частот дискретизации? И для 11 кГц, и для 22 кГц.
    Неужели все авторы так жёстко тупят?


    2. Почему используется такая синусоидальная таблица, а не линейное значение? Типа:
    Код (ASM):
    1.     ; al = sample
    2.     mov ah,75
    3.     mul ah
    4.     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. Пишешь меньше (даже при более высокой частоте дискретизации) – звук становится тише, пишешь больше (даже при низкой частоте дискретизации) – начинает хрипеть :facepalm:[/code]
     
  2. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    875
    А какая разница? Это же амплитуда.
    --- Сообщение объединено, 22 апр 2020 ---
    Это непонятно тоже, потому что обычно PWM как раз генерируется пилой (линейной). Я не работал с 8254 но работал с AVR, там через аппаратный PWM если передавать линейно, то все корректно:
    upload_2020-4-22_18-7-2.png
     
  3. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    369
    Адрес:
    Кольца Сатурна
    На спикере есть только + или - (1 или 0), какая амплитуда?
    Промежуток времени между семплами определяется частотой дискретизации. Соответственно, временнáя ширина импульса (внутри этого промежутка) для создания одной и той же "амплитуды" будет разной для разной частоты дискретизации. Мы же в 42-й порт пуляем фактически время, в течение которого на спикере будет 0, остальное время там будет 1.
    Я же привёл пример (см. про PIT0_CNT).

    А как же можно сделать пилу на спикере?
     
  4. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    875
    Это ширина импульса. Чем шире импульс тем больше амплитуда в ШИМ. Насколько я понимаю, из этой статьи, что для смены позиции динамику нужно около 60 микросекунд. Т.е. больше этого интервала нет смысла делать импульсы, независимо от частоты дискретизации. 75 как раз около 60 микросекунд получается.

    Ну ты ведь проигрываешь PCM, подавай просто семплы пилы.
     
  5. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Jin X,

    Какое отношение имеет шим к звуку ?

    Модуляция длительностью используется в эл. цепях, так как передаваемая порция энергии является интегральной по времени. Для звуковых колебаний совсем иные законы, частотная модуляция скорее(тк энергия функция частоты). При этом в ухе приёмник никак не керамический, который на давление реагирует.

    > Когда мы пишем в этот порт, на спикер подаётся 0, а по истечении тиков счётчика – 1.

    Тогда в паузе звука не будет, либо будет стабильная частота. Это похоже ЧМ, причём тут ШИ ?
    --- Сообщение объединено, 22 апр 2020 ---
    Jin X,

    > А как же можно сделать пилу на спикере?

    Пила используется в эл. что бы задать временной интервал по уровню(на компараторе). Тоесть время определяет напряжение. Но у тебя ведь прогр. цифровой таймер, а не аналоговый шим.. Но всё же можно - так как спикер не керамический пьез., а электромагнитный, те индуктивность. Реактивность есть функция частоты, чем выше частота, тем будет меньше амплитуда колебаний его мембраны; так же и по механическим причинам(инертность).
     
  6. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    875
    Кстати такая таблица скорее-всего объясняется нелинейностью движения мембраны спикера:
    upload_2020-4-22_20-1-26.png
     
  7. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    369
    Адрес:
    Кольца Сатурна
    Мы настраиваем 0-й таймер на частоту, скажем 22050 Гц (примерно), используя делитель 54 (1193182/54=22096).
    В обработчике IRQ пишем в 42-й порт, скажем, 18 (в режиме 0). И до следующего IRQ0 происходит следующее: на спикер подаётся 0 в течение 18 тиков счётчика (треть времени), затем идёт переключение в 1 в течение оставшихся 36 тиков (две трети времени).
    Никакой там частоты постоянной не будет. В 0-м режиме идёт переключение туда-сюда один раз. И дальше ничего не будет происходить, если мы снова не запишем что-то в 42-й порт. Но тут у нас снова срабатывает IRQ0.
    Если мы подадим значение > 54, то да, там будет тишина, т.к. туда подастся 0, а 1 не успеет, т.к. при следующем IRQ мы снова загрузим в 42-й порт новое значение (снова подадим 0).
    Чем не ШИМ?
    [​IMG]

    И как же я этим смогу управлять?
    У меня вообще к плате подключёны просто провода с выходом на джек, я слушаю через наушники, а не через динамик.
    Есть ещё и динамик, но вот такой:
    [​IMG]
    На разных динамиках будет разный эффект получается...

    Что-то я не улавливаю связи :)
    --- Сообщение объединено, 22 апр 2020 ---
    Надо было какой-то раздел выбрать, решил написать сюда. Поскольку всё-таки завязано на спикере и его таймерах.
     
    Последнее редактирование: 22 апр 2020
  8. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    369
    Адрес:
    Кольца Сатурна
    Короче, поступил ответ по поводу этой таблицы.
    Это таблица компандирования звука. Чтобы тихие звуки было лучше слышно.
    companding.jpg
    Так что, по идее, можно использовать и линию, если нужна экономия кода.
    --- Сообщение объединено, 23 апр 2020 ---
    Ну и чтоб динамику увеличить на основном диапазоне амплитуды.
     
  9. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    875
  10. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Jin X,

    > И как же я этим смогу управлять?

    Частотой, амплитуда мембраны есть в общем обратная функция частоты. Другое дело это нелинейная чувствительность органов к раздражителям, для звука пик на ~3khz(примерно), для света это зелёная часть спектра..

    Если частота приближается к частоте строчной развёртки(15khz) в старом тиви, это предел восприятия. Эта частота была выбрана как минимальная, что бы звук феррита не воспринимался. Модуляция выше этой частоты можно считать отсутствием звука, так же и мощность излучения упадёт(не на керамике, а на мех мембране), из за причин выше.

    Исходить и нужно из диаграмм чувствительности к звуку.
     
  11. _edge

    _edge Well-Known Member

    Публикаций:
    1
    Регистрация:
    29 окт 2004
    Сообщения:
    631
    Адрес:
    Russia
    Евгений,

    смотрю кризис действует на людей схоже - ударяются в ретро )

    еще по теме, вдруг чего полезного найдете, https://habr.com/ru/post/438448/

    и файл во вложении, поет песню (дос, досбокс)
     

    Вложения:

    • never.exe.txt
      Размер файла:
      22,5 КБ
      Просмотров:
      392
    Mikl___ нравится это.
  12. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    369
    Адрес:
    Кольца Сатурна
    _edge, я видел эту тему, но там несколько другое :)
    --- Сообщение объединено, 25 апр 2020 ---
    Never я помню, с приветом из 90-х :)
    --- Сообщение объединено, 25 апр 2020 ---
    Но в целом я более или менее определился с вопросами.
     
    Последнее редактирование: 25 апр 2020