GBA ASM - День 6: Простые звуковые эффекты — Архив WASM.RU
О звуковых каналах GBA
У GBA есть шесть звуковых каналов. Сегодня мы изучим только первые 4 (1-4), которые используются внутренним GBC GBA. Другие два канала - это прямые звуковые каналы, которые могут проигрывать сконвертированные звуковые файлы - о них мы сегодня говорить не будем. ПРИМЕЧАНИЕ: термин "direct sound" в данном контексте является не более чем полуофициальным названием 5 и 6 звуковых каналов GBA и никак не связан с DirectSound, который является частью мультимедийной библиотеки для Windows от Microsoft.
Чтобы мы могли воспользоваться определенными преимуществами, даруемые написанными мною самим макросами и константами, скачайте, пожалуйста, sound.h.
Сегодня мы узнаем, что нужно сделать, чтобы заставить выдать спикеры какой-нибудь звук. Чтобы заставить издать какой-нибудь звук каналы 1 или 2, нужно сделать следующее:
Шаги генерации звука
Включить поддержку звука (я предоставляю макрос SoundOn)
Включить требуемый звуковой канал (я предоставляю макрос Sx_Enable, где x - это нужный вам канал).
Загрузить REG_SOUNDxCNT_L правильным значением (вам придётся сделать это самим ).
Загрузить REG_SOUNDxCNT_H правильным значением (вам придётся сделать это самим).
Загрузить REG_SOUNDxCNT_X правильным значением (сами).
Вот и всё, и поверьте мне, это не так уж много, но может немного смутить.
Канал 1
Во-первых, я дам вам рабочую программу, которая генерирует звук через 1 канал.
Код (Text):
;-- Переписано на asm вручную с исходника на BELOGIC.COM с изменениями --; @include screen.h @include sound.h @include keypad.h @textarea SoundOn ; Шаг 1: мой макрос включает поддержку звука в REG_SOUNDCNT_X ; REG_SOUNDCNT_X контролирует всю звуковую систему. S1_Enable ; Шаг 2: мой макрос включает первый звуковой канал. ; S2_Enable включает канал... и так до 4. ldr r1,=REG_SOUND1CNT_L ; в этих двух строках я делаю шаги 3&4 за раз. ldr r0,=0xf7800056 str r0,[r1] ; сохраняем данные для шагов 3&4. ldr r1,=REG_SOUND1CNT_X ; Шаг 5: загружаем регистр. ldr r0,=0x8400 ; Этот регистр ответственен за что-то, связанное с str r0,[r1] ; тем, что будет делать канал. infin ; \ ; - наш типичный бесконечный цикл. b infin ; / ;-- Заканчивайте копировать здесь --;Я посмотрел, что написано о звуковых регистрах на BeLogic.Com и понял не всё. Основываясь на их списке регистров, у звуковых канало 2 и 4 нет REG_SOUNDxCNT_X, а их регистры REG_SOUNDxCNT_H и REG_SOUNDxCNT_L также 16-ти битны, но разделены 2 байтами, поэтому мы можем писать в них более простым образом и не должны делать шаги 3&4 за раз, а можем разделить загрузки для регистров CNT_L и CNT_H.
Похоже, что канал 3 служит для проигрывания сэмплов, поэтому я о нём больше не буду говорить.
Канал 1 - это очень приятный амплитудный звукогенератор. Поскольку я не очень хорошо понимаю уравнения, используемые на BeLogic, я не могу их объяснить (вообще). Для того, чтобы получить хоть какой-то звук мне пришлось повозиться с используемыми значениям, пока я не получил достаточно хороший эффект.
Канал 2
Канал 2 - это то же самое, что и канал 1, но генерируются только квадратные (square) волны, поэтому нам не нужен регистр REG_SOUND2CNT_X. Вот тот же самый код, подправленный для использования канала 2:
Код (Text):
;-- CONVERTED TO ASM BY HAND FROM BELOGIC.COM WITH MODIFICATIONS --; @include screen.h ; @include sound.h ; @include keypad.h ; @textarea SoundOn ; Шаг 1: мой макрос, который включает поддержку звука. S2_Enable ; Шаг 2: мой макрос, включающий второй звуковой канал. ldr r1,=REG_SOUND2CNT_L ; Шаг 3: в случае со вторым каналом на нужно ; объединять шаги 3 и 4 ldr r0,=0xff80 ; Регистры всё ещё 16-ти битны, но у нас в памяти ; есть пространство для манёвра str r0,[r1] ; сохраняем данные ldr r1,=REG_SOUND2CNT_H ; Шаг 4: ldr r0,=0xf400 ; я думаю, что для повторения звука на втором str r0,[r1] ; канале, вам необходимо инициализировать этот ; регистр снова, а если это не будет работать, то ; попробуйте проделать это с L и H. ; Шаг 5 не требуется для канала 2, так как у него нет регистра ; REG_SOUND2CNT_X. Канал 2 (и 4) не доставляют нам хлопоты, которые были у ; нас c каналом 1, так как дизайнеры системы памяти были так добры, что дали ; нам два лишних байта, дабы облегчить 32-х битное сохранение. infin ; \ ; - наш стандартный бесконечный цикл. b infin ; / ;-- STOP COPYING HERE --;Канал 4
Теперь давайте получим что-нибудь от канала 4. Это псевдослучайный генератор шума. В коде мы просто заменить все '2' в именах регистра на '4' и вперёд:
Код (Text):
;-- Сконвертировано из предыдущего примера --; ;-- Код должен работать, но заставить его это сделать у меня не получилось --; @include screen.h @include sound.h @include keypad.h @textarea SoundOn S4_Enable ldr r1,=REG_SOUND4CNT_L ldr r0,=0xf700 str r0,[r1] ldr r1,=REG_SOUND4CNT_H ldr r0,=0x8400 str r0,[r1] infin b infin ;-- Заканчивайте копировать здесь --;Я не знаю, почему этот код не заработал. Я пытался скомпилировать C-код на BeLogic, но тот код тоже на работает.
ОБНОВЛЕНИЕ: в качестве подарка на День благодарения 2002, код заработал.
Краткий итог
Обратите внимание, что я не объяснял, за что отвечает каждый бит каждого регистра. Я уже говорил, что не понимаю уравнения и определённо не понимаю даже половину содержимого на BeLogic.com. Чтобы добиться больше эффектов, поиграйтесь со значениями регистров - это единственный путь, если не смотреть мануалы на BeLogic.com. Я уже рассказал вам всё (или даже больше), что знаю о звуке в GBA, теперь идите и напишите демку с подпрыгивающими шарами (вверх и вниз) .
Спасибо,
- Mike H a.k.a GbaGuy- Нечто невозможное невозможно только до тех пор, пока оно не становится возможным.
- Jean-Luc Picard, Capt., USS EnterpriseЯ знаю, что уже использовал это изречение, но оно особенно подходит для программирования звука. © Mike H, пер. Aquila
GBA ASM - День 6: Простые звуковые эффекты
Дата публикации 21 авг 2003