Есть задачи для программистов для НГС

NeoGS software and hardware

Postby Grey » 24 Sep 2018, 23:42

так для ясности. Я имел в виду что буфера 16 битные 256 отсчетов = 512 байт, но плеер сэмплы в них пишет 8 битные со знаком, а после аппаратного умножения на громкость результаты прибавляются к этому буферу. Пишет все каналы через один и тот же порт, в старшем разряде номер ячейки буфера. Громкости хотелось бы две, что бы результат в оба буфера прописывался. т.е. два умножения и сложения потребуется.

а ДМА для чего при такой схеме ? Сразу со счетчиком масштабирования ? Что бы вместо цикла, который я в примере написал, запускать ДМА последовательно для каждого канала ? Это конечно круто. ДМА хоть 100 каналов сложит :-) . не знаю - считать надо. Процессор конечно сильно разгрузит (даже ImpulsTracker можно успеть обсчитать), но подъемно ли это для альтеры ? ДМА же вообще из не подключенных страниц сможет читать? красота. Только два режима ДМА - сложения с буфером и сложения с 32768 для обнуления первого канала.
Grey
 
Posts: 89
Joined: 01 Mar 2011, 21:07
Group: Registered users

Postby lvd » 25 Sep 2018, 00:06

Я тут подумал, что если 1 блок памяти заюзать для хранения регистров ДМА типа адреса и счётчика, то можно ДМАчить столько каналов, сколько их в тот блок памяти помещается: контроллер читает состояние очередной дма машинки, выполняет 1 байт передачи, пишет взад и идёт следующую машинку обрабатывать. Примерно каналов 64 так можно прокачать, вот только останется ли процессору время. Зато логика не будет использоваться.

Всего в альтере 6 памятей по 512 байт каждая, одна просрана для хранения регистров отсчётов обычного ГС (ага, 4-8 байт из 512 :), другие две в текущей наработке на ДМА мп3 и сдкарты. Ещё две грохнем на 16битные буфера вывода в ЦАП, останется 2. Из них одну на ДМА-машинки.
Можно конечно дма-машинки сложить вместе с регистрами отсчётов, и увеличить за счёт этого буфера семплов до 4х512 байт (512 отсчётов на канал: левый и правый)
Многого нет здесь: http://lvd.nedopc.com
Image
User avatar
lvd
 
Posts: 1678
Joined: 07 Apr 2007, 22:28
Group: Registered users

Postby lvd » 25 Sep 2018, 00:10

С умножением кстати там сейчас жопа (умножаются отсчёты на громкости), т.к. умножителей в acexе нету, просто так грохать логику на разлапистый умножитель нельзя, остаётся умножать столбиком, такт на бит результата.
Многого нет здесь: http://lvd.nedopc.com
Image
User avatar
lvd
 
Posts: 1678
Joined: 07 Apr 2007, 22:28
Group: Registered users

Postby Grey » 25 Sep 2018, 00:44

что даст такая ДМА машина? То что сразу заполнил очередь для всех каналов и не надо запускать ДМА и ждать его завершения для каждого канала в отдельности? Я правильно понял?
Если так то думаю что и 2-х буферов хватит. Не забыть статус что бы можно было определить, какая половина буфера играет (регистр счетчика на чтение).
Тогда на 37.500 кгц - 128 тиков - это примерно 1/5 экрана (сори привык загрузку процесора в частях фрейма считать). На 20 мгц это не так уж и мало. Если с умом распределять нагрузку ( не каждый же пол буфера нужно строку патерна просчитывать).
С двумя громкостями на канал очень хотелось бы. Лучше 32 канала с панингом чем 64 левый/правый. Канал то можно два раза запустить но времени больше на чтение потратится. Кстати раз одно и тоже число сэмпла на 2 громкости умножается, может можно как то в алгоритме сэкономить - двигать же его один раз а результат писать в две ячейки в зависимости от битов множетелей?
Для счетчика коэффициента достаточно 2 байта . - 4 бита целая 12 дробная ( но можно и 3 байта - как легче считать ), для адреса в памяти 3 байта, для дробного части адреса - 2 байта и 2 байта громкости - 10 байт на канал округлим на тех нужды до 16 байт - вот 32 канала с панингом в буфере дма машинки займут 512 байт
Grey
 
Posts: 89
Joined: 01 Mar 2011, 21:07
Group: Registered users

Postby Grey » 25 Sep 2018, 01:12

Стоп.
Подумал - прямо так в лоб нельзя через ДМА машинку заполнять буфер.
За раз будет передаваться сразу 128 отсчетов сэмпла.
Но дело в том, что один цикл скорости воспроизведения может быть (и зачастую) не кратен 128.
Т.е передав в буфер например 75 отсчетов нужно поменять периоды, громкости для команд и спецэфектов или вообще строку патерна, ноту или инструмент поменять.
При программном цикле в DUP 128 делается джамп на нужную ротацию (например в 75-ю), по окончании меняются подготовленные периоды, сэмплы, громкости, и делает джамп внутрь цикла 53-ю позицию (128-75=53) .

Значит нужно что бы для ДМА задавалось количество отсчетов, которые нужно передать, Поменять все параметры, и запустить ещё раз ДМА уже указав количество отсчетов равное 128 минус длинна первой пересылки.

И второе - когда сам в цикле считаешь и к адресу прибавляешь коэффициент, то в конце процедуры, адрес, где остановились - известен. Значит нужно, что бы эти адреса после окончания работы ДМА были доступны для чтения, что бы можно было определить - на каком байте сэмпла остановилась передача. Эти данные нужны для определения конца сэмпла, для определения границы loop-а , перезапуска лупа с начала. Аппаратно же их не будешь проверять и менять.
Grey
 
Posts: 89
Joined: 01 Mar 2011, 21:07
Group: Registered users

Postby lvd » 25 Sep 2018, 20:41

Grey wrote:что даст такая ДМА машина? То что сразу заполнил очередь для всех каналов и не надо запускать ДМА и ждать его завершения для каждого канала в отдельности? Я правильно понял?

Можно запустить все ДМА-каналы и ждать их завершения одновременно.

Если так то думаю что и 2-х буферов хватит. Не забыть статус что бы можно было определить, какая половина буфера играет (регистр счетчика на чтение).
Тогда на 37.500 кгц - 128 тиков - это примерно 1/5 экрана (сори привык загрузку процесора в частях фрейма считать). На 20 мгц это не так уж и мало. Если с умом распределять нагрузку ( не каждый же пол буфера нужно строку патерна просчитывать).

1. считать можно сразу на частоту 24мгц -- на ней Z80 работает вполне стабильно, остальное тоже
2. 37500 на 24мгц это 640 тактов.
3. Основной тормоз в аппаратном микшировании это умножение. Оно будет примерно тактов 10 (вместе со считыванием старого значения и записью нового). Таким образом, грубая оценка: 640/10 = 64, за 1 выходной семпл можно замикшировать 64 канала (отдельно левые и правые), или 32 с пэнниннгом.

Кстати раз одно и тоже число сэмпла на 2 громкости умножается, может можно как то в алгоритме сэкономить - двигать же его один раз а результат писать в две ячейки в зависимости от битов множетелей?

Можно множить одновременно 2 громкости на 1 отсчёт -- х1.5 примерно железо умножителей, а тактов столько же.
Многого нет здесь: http://lvd.nedopc.com
Image
User avatar
lvd
 
Posts: 1678
Joined: 07 Apr 2007, 22:28
Group: Registered users

Postby lvd » 25 Sep 2018, 20:53

Grey wrote:Т.е передав в буфер например 75 отсчетов нужно поменять периоды, громкости для команд и спецэфектов или вообще строку патерна, ноту или инструмент поменять.

Мысли такие:
1. как там в моде или с3ме или ит задана нота канала? И как её пересчитывать в период для частоты дискретизации 37500?
2. Насколько я знаю, в прошивке ГС текущей изменения семплов происходят примерно 50 раз в секунду (точно задаётся величиной BPM), всё остальное время семплы тупо играются с постоянной скоростью (с учётом лупов наверное). Да и на амиге так же --
3. В амиге низкие частоты дискретизации играются напрямую (т.е. частота хоть и низкая, но ее период задан с точностью сотен наносекунд), а в прошивке ГС текущей вроде как медленные семплы интерполируются (интерполяция это +2 умножения на отсчёт, грубо говоря, или + целый блок памяти на таблицы). Что тут должно быть, с учётом того что частота дискретизации фиксированная?

Остальное: ну можно задать в блочке памяти все параметры, типа шага, адреса и т.д., но можно же и длину цикла задать? А потом эту длину просто вычесть из адреса, вот и луп. правда это 4 байта: позиция в цикле и длина.
У меня получается так:
3 байта -- адрес
1 байт -- управляющий
2 байта -- счётчик лупа
2 байта -- размер лупа
1 байт -- сумматор периода, дробная часть (целая часть -- адрес)
2 байта -- период
1 байт -- громкость

итого 12 байт на канал. 42 каналов макс (левые+правые), или 21 с пеннингом.

Если точно известна битность счётчика лупа и периода то можно наверное сэкономить 1 управляющий байт, распихав по другим байтам, или наоборот в какой-нибудь 1 байт старшие части нескольких величин вытеснить.
Многого нет здесь: http://lvd.nedopc.com
Image
User avatar
lvd
 
Posts: 1678
Joined: 07 Apr 2007, 22:28
Group: Registered users

Postby Grey » 26 Sep 2018, 01:07

По моему не надо DMA заставлять отслеживать лупы и конец сэмпла. это дело проигрывателя. Аппаратно там можно накосячить при малых размерах цикла и большом периоде сэмпла. Но если уверен что получиться, то конечно было бы удобно. А программно можно все эти нюансы обработать. В сэмпле просто в конце лупа копируются ещё 256 (512 в зависимости от размера буфера) байт сэмпла от начала лупа, что бы при выборке когда перскочит конец лупа, то данные были как в начале лупа. А в конце заполенния буфера проигрыватель проверят, на сколько пересокчил луп и вычитает из адреса конеци прибавляет к началу лупа - получется та же точка в сэмпле.
Нота задается периодом, но при делении её на частоту дескритезации и умножении на частоту сэмпла получается целая и дробная часть - коэффициент масштабирования. в идеале и для простоты расчетов 1 байт целая и 2 байт дробная часть. Но можно всего 2 байта, и тогда 4 бита целая и 12 бит дробная. Как удобнее аппаратно прибавлять.
Вот ДМА должен просто прибавлять к адресу семпла целую и дробную часть, получившуюся дробную часть запоминать для следющего прибавления, сэмпл выбирать естественно по целой части адреса.
В конце выборку должна быть возможность прочитать , на каком адресе остановилась выборка.

По поводу скорости - - она задается двумя параметрами - темп и скорость. От темпа расчитывается ,сколько раз в секунду будут изменятся данные, а скорость - это сколько таких отсчетов приходится на одну ноту.
При стандартном темпе для трекров 125 ударов - на частоте 37500 один цикл будет каждые 1/50 = это 37500/50 = 750 байт. Но тем часто бывает другой и там будут совсем не ровные значения.
Поэтому и нужно что бы можно было указать, сколько DMA байт передать байт. 5 раз передаем полные буфер 128 байт, а на 6-ой нужно передать 110, и пересчитать каналы и передать 18 байт до полного буфера , а дальше опять по 128 байт.
Grey
 
Posts: 89
Joined: 01 Mar 2011, 21:07
Group: Registered users

Postby Grey » 26 Sep 2018, 03:09

я ешё раз все обдумал. Если действительно сможешь сделать что бы ДМА сам следил за циклом и за концом сэмпла, то тогда подход немного измениться и упростится, тогда не нужен доступ для чтения ячеек с адресами ДМА машины, где она остановилась. Пускай сама продолжает с того места где остановилась при запуске следующей порции. А где поменялись данные - туда записываем новые данные.
Но что тогда нужно .

Нужно что бы можно было указать ДМА , сколько байт сэмпла передать в буфер. Это обязательно для точного совпадения скорости в модулях. Если просто привязывается к размеру половины буфера - 128 байт, то во многих модулях скорость будет сильно отличаться от оригинала и оцифровки уплывут.

Тут три варианта.
ПЕРВЫЙ Если ДМА сможет сам следить, в какой буфер писать и ждать пока он проиграет - это самый оптимистичный вариант. Тогда логика работы такая.
в ДМА задается 2 байта - сколько отсчетов проиграть. потому как это может быть и 100 и 10000. в зависимости от заданного темпа. поэтому пусть будет от 1 до 65535. Но в стандартных условиях это 750 байт.
Буфер 2*512 байт - 2 канала по 256 16-битных слов.- половина буфера - 128 отсчетов.
Значит ДМА сам определяет какой буфер играется и заполняет 128 байт второй половины буфера, останавливается, ждет пока проиграет первая половина и продолжает заполнять вторую и так по кругу, пока не передаст всю заданную ему в начале длинну. После этого z80 быстро записывает в ДМА новые параметры сэмплов и запускает ДМА дальше указав опять, сколько байт передать в буфер (если темп не менялся то столько же как и в первый раз ) - но ДМА должен начать заполнение буфера с того места, где остановился а не с начала !!! (Или лучше будет возможность указать - с какого адреса буфера начать заполнение)
Так как ДМА складывает сам каналы, то он может даже ориентироваться не по половине буфера по проигранному байту. Т.е. заполняет до проигрываемого сейчас байта и останавливается и потом все время идет как бы следом за воспроизведением. А при следующем запуске начинает строго с того места где остановился (лучше возможность указать от куда начать заполнение) и опять догоняет буфер и опять за ним медленно ползет до следующей остановки. Этот вариант возможен если ДМА складывает все каналы параллельно. т.е. перебрал и сложил все каналы, перешел к следующей ячейке буфера.

ВТОРОЙ Если ДМА не будет сам следить за заполнением буфера. тогда это должен делать z80. Но все равно должна быть возможность запустить пересылку столько байт, сколько нужно, но не более размера буфера - т.е от 1 до 256 (или от 0 до 255). Тогда z80 говорит ДМА с какого адреса буфер начать заполнять и сколько байт. Синхронизируется при этом читая статус - какая ячейка буфера сейчас воспроизводится, надеясь что ДМА все успеет сделать.
Этот вариант менее удобный но тоже вполне работоспособен.

Ну и ТРЕТИЙ вариант - самый плачевный, если ДМА четко привязан к размеры буфера. т.е. передает только по 128 байт и по другому не умеет, потом в другую половину буфера 128 байт. При этом варианте точность плеера немного пострадает. 750/128 = 5,86 . Допустим сделаем 6 циклов ДМА и в какой то момент 5 - примерно как то попадем. Кому слон на ухо наступил - не заметит. Но жизнь это осложнит , и времени для расчетов заметно меньше будет.

Это было только описание взаимодействия ДМА с буфером воспроизведения.

Теперь о ДМА машине

Что должно быть обязательно.
ДМА при запись первого канала должен делать сложение не с буфером а с 32768.
карта ДМА машины будет такая.
2 байта - адрес сэмпла - предлагаю для экономии выравнивать начало сэмплов до 256 байт (или 64 - биты позволяют но смысла нет)
2 байта - длинна сэмпла - при достижении ДМА должен или остановится или начать с лупа
2 байта - смещение начала лупа - если равен длине или больше то ДМА останавливается, если меньше - то запуск с лупа, только с учетом остатка (дробной части адреса).
2 байта - счетчик адреса воспроизведения (прибавляется к стартовому адресу, проверяется на конец длинны)
2 байта - остаток или дробная часть счетчика адреса сэмпла (12 бит)
2 байта - (условно - период) коэффициент масштабирования сэмпла (4 бита целая 12 бит дробная часть) - то что в цикле прибавляется к адресу сэмпла и к остатку. Это период уже помноженный на частоту сэмпла и поделенный на частоту дискретизации.
1 байт громкость
Получается минимум 13 байт . и без управляющего байта, правда остаются свободные 2 бита в адресе сэмпла, 4 бита в дробной части адреса сэмпла и 2 бита в громкости.
Можно сэкономить 1 байт, если отвести по 12 байт на 40 каналов - 480 байт, а оставшиеся 32 байта = 6 бит*40 - использовать как громкости - Да - не удобно считать, но громкость не так критично. Еще в в свободных битах 2 бита отвести - правый/левый канал, или в оба сразу.
объединить 4 свободных бита в дробной части счетчике и 4 бита в старшей части периода. тогда будет всего 3 байта - период и остаток

(в предложенной тобой карте почти тоже самое , только про начало лупа забыл, только счетчик и длинна. И 1 байт -- сумматор периода - мало, минимум 12 бит , я как раз у себя это учитываю 4+12 целая+дробная . )

Круто, если луп будет двух видов, с начала или вперед назад. Если нет - то можно и программно сэмпл разворачивается в обратную сторону - но тогда длинна может не поместиться в 64к.

Для ровного счета - 40 каналов, только без четкой привязки к правому или к левому, пусть битом в громкости задается - в правый или в левый канал складывать, ( а если возможно то и в два сразу вот и почти панинг, а если возможно, то в один складывать а в другой вычитать - вот тебе и суроунд для ImpulsTracker-a. ).

и получится крутотень.

В сам буфер z80 писать ничего не будет. Будет писать в память ДМА машины через два порта. В старшем разряде адреса- номер ячейки памяти ДМА машины, так как их 512 то два разных младших адреса порта нужно.
Читать - какая ячейка буфера проигрывается - 0-255 , и какой байт или отсчет ДМА складывает, либо просто статус ДМА - закончил или нет. (при параллельной обработке каналов ДМА можно какой отсчет , если будет выбрана последовательная схема записи в буфер, то просто закончил или нет)
Last edited by Grey on 26 Sep 2018, 11:20, edited 1 time in total.
Grey
 
Posts: 89
Joined: 01 Mar 2011, 21:07
Group: Registered users

Postby Grey » 26 Sep 2018, 03:19

По поводу низких частот. Она будет получатся при коэффициенте, когда целая часть 0 а дробная - маленькая.
Тогда при чтении сэмлпа ДМА несколько раз будет читаться один и тот же байт, пока сложения адреса и периоада неперевалят за один целый адрес.
Ну да - будет ступенька, но она и в оригинале и в МОД и в s3m и в it есть, и автор пишет слыша её и делая где нужно ресамплинг. В impulstracker-r конечно можно включить линейную интерполяцию, но там и 16 бит сэмплы есть. А стоит ли это делать в 8 битном компьютере? - не уверен, хотя было бы красиво.
Grey
 
Posts: 89
Joined: 01 Mar 2011, 21:07
Group: Registered users

PreviousNext

Return to NeoGS - софт и железо

Who is online

Users browsing this forum: No registered users and 1 guest

cron