Просмотр полной версии : перемещение по семплу
Приветствую. Возникла необходимость загрузить и проиграть MOD файл на Спринтере. Скачал несколько мануалов по формату этого файла. В целом, формат понятен, есть пара моментов, но не страшно. Вопросы возникают на следующих моментах:
1. Для проигрывания сэмпла на какой то ноте на амиге используются периоды которые, как я понимаю, используются для Паулы. На машинах без Паулы используют формулу для преобразования периода в частоты, которые и дают те самые ноты. Если я верно понимаю, то для проигрывания сэмпла с более высокой нотой (частотой) производится выборка данных с пропуском скольких-то байт. Для проигрывания на более низких нотах, наоборот, байты дублируются. Хотелось бы понимать, как эти периоды и частоты преобразовать в алгоритм выборки данных. Т.е. когда некая частота и надо брать данные из сэмпла с пропуском или без. В общем, как корректно перемещаться по сэмплу для получения нужных нот.
2. У мод файла есть 2 параметра - темп и кол-во ударов в минуту (BPM). При стандартных параметрах 6/125 получается ровно 50гц. хорошо. а как быть с параметрами вроде 3/125 и другими вариантами? а ещё скорость может меняться командами на каждом шаге. как корректно отслеживать эти скорости и "исполнять" трек на заданных скоростях?
Много читал, но ответов на эти вопросы не смог найти. Может не там искал?
Касательно проигрывания цифры на спринтере: для этого можно использовать CBL - Covox BLaster. Данный девайс умеет работать в одном из нескольких режимов, который можно настроить. Частоты от 8кгц до 96кгц, моно или стерео, 8бит или 16бит. У CBL есть своё FIFO и прерывания которые возникают по мере опустошения этого FIFO. его размер 128/256 байт, в зависимости от выбранного режима. Заполнять буфер можно через акселератор, т.е. очень быстро. Поскольку есть этот девайс, то проигрывать MOD файлы можно асинхронным методом, без привязок к таймингам машины.
Может кто-нибудть помочь в данном вопросе? Спасибо!
посмотри в сторону исходников прошивки GeneralSound
я видел исходники в формате тасма, а из тасма экспорт работает с ошибками. несколько раз экспортил, всегда мусор получал. а ковыряться в тасме занятие не из приятных (как и в аласме). и если честно, в этих исходниках мне буыло трудно разбираться. особенно если учесть, что с цифрой ранее не работал...
Через CBL не получится т.к. тебе ещё семплы складывать надо на разных скоростях - по идее самый разумный способ это на ходу складывать и играть в ковокс побайтно
Я лично хотел под Спринтер написать STM-плеер, но сначала сеть :)
Темп имеет отношение к плавно изменяющимся характеристикам звука, например громкости, тона...
На самом деле эти характеристики меняются ступенчато, а тон означает сколько ступенек между соседними строками.
Например громкость понижается при темпе 6. Это значит, что при переходе от одной строчке к следующей громкость будет ступенчато понижена 6 раз.
Через CBL не получится т.к. тебе ещё семплы складывать надо на разных скоростях - по идее самый разумный способ это на ходу складывать и играть в ковокс побайтно
Я лично хотел под Спринтер написать STM-плеер, но сначала сеть :)
всё в точности наоборот - у нас достаточно мощей для проигрывания мода в асинхронном режиме. для синхронного как раз все мощности улетят в трубу при подгонке таймингов, аля пентагоны. оно мне надо?
такты и так, и эдак считать придётся
такты и так, и эдак считать придётся
для чего? подгонка нужна для синхронного метода, чтобы задержки подогнать (если есть что подгонять). ГСка при её 12мгц умудряется ещё и интерполяцией заниматься нешуточной. нам доступно чуть больше. задержки и подгонки не нужны. нужен промежуточный буфер для создания wave данных и по приходу CBL прерывания сбрасывать их в фифо. если останется свободное время, его можно отдать под микшер, интерполяцию и блэт джек с дефками...
этот буфер слишком маленький
и кстати интерполяцию тоже синхронно можно делать
этот буфер слишком маленький
и кстати интерполяцию тоже синхронно можно делать
как понять маленький буфер? промежуточный буфер для накопления wave данных, которые потом будут улетать в FIFO, его хоть 1кб, хоть 16кб. это уже экспериментально можно будет определить его размерность. а делать интерполяцию в синхронном режиме - это боль и унижение. нет желания заморачиваться с синхронным режимом. когда доступна фишка с асинхронным благодаря которому куча времени освобождается.
можно было бы пойти альтернативным путём и запилить аналог ГСки под ИСУ, но я не паяльщик, а вы там все суперзаняты какими-то своими делами.
Темп имеет отношение к плавно изменяющимся характеристикам звука, например громкости, тона...
На самом деле эти характеристики меняются ступенчато, а тон означает сколько ступенек между соседними строками.
Например громкость понижается при темпе 6. Это значит, что при переходе от одной строчке к следующей громкость будет ступенчато понижена 6 раз.
а что на счёт семпла? как ноты играть? как двигаться по семплу в зависимости от ноты (периода или частоты)?
я видел исходники в формате тасма, а из тасма экспорт работает с ошибками. несколько раз экспортил, всегда мусор получал. а ковыряться в тасме занятие не из приятных (как и в аласме). и если честно, в этих исходниках мне буыло трудно разбираться. особенно если учесть, что с цифрой ранее не работал...
https://github.com/psbhlw/gs-firmware
https://github.com/psbhlw/gs-firmware
тут я понял ещё меньше, чем в исходниках плеера для Enterprise 128.
Hacker Grey
20.05.2021, 18:55
у тебя есть адрес в сэмпле 16 бит и целая часть и 16 бит дробная часть (для масштабирования).
ты по формулам вычисляешь период приращение. 16 бит целая часть ( 0 если проигрывать медленнее и обычно не более 15) и дробная часть.
На каждой выборке ты прибавляешь к указателю дробную и целую часть периода приращение и получаешь новый адрес смещения.
Вот в моих исходниках как я это делал, заполнение 256 байт буфера.
SAMPLBUFF
DUP 256 // повторить фрагмент до EDUP - 256 раз
add hl,bc // складываем дробные части
exx // переключаем набор регистров
adc hl,bc // складываем целые части, с учетом переноса от сложения дробной части
ld a,(hl) // читаем байт сэмпла
ld (de),a // кладем в буфер
inc e // увеличиваем адрес буфера на 1
exx // переключаем набор регистров
EDUP //
ret
сами исходники в теме выложены
Hacker Grey
20.05.2021, 21:33
При формировании формулы, пользовался этой документацией.
Finetuning (C2SPD) is actually the frequency in herz for
the note C4. Why is it C2SPD? Well, originally in ST2
the middle note was C2 and the name stuck. Later in ST3
the middle note was raised to C4 for more octaves... So
actually C2SPD should be called C4SPD...
Table for note frequencies used by ST3:
note: C C# D D# E F F# G G# A A# B
period: 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016, 0960,0907
middle octave is 4.
8363 * 16 * ( period(NOTE) >> octave(NOTE) )
note_st3period = --------------------------------------------
middle_c_finetunevalue(INSTRUMENT)
note_amigaperiod = note_st3period / 4
note_herz=14317056 / note_st3period
Note that ST3 uses period values that are 4 times larger than the
amiga to allow for extra fine slides (which are 4 times finer
than normal fine slides).
How ST3 mixes:
1) volumetable is created in the following way:
> volumetable[volume][sampledata]=volume*(sampledata-128)/64;
NOTE: sampledata in memory is unsigned in ST3, so the -128 in the
formula converts it so that the volumetable output is signed.
2) postprocessing table is created with this pseudocode:
> z=mastervol&127;
> if(z<0x10) z=0x10;
> c=2048*16/z;
> a=(2048-c)/2;
> b=a+c;
> { 0 , if x < a
> posttable[x+1024] = { (x-a)*256/(b-a) , if a <= x < b
> { 255 , if x > b
3) mixing the samples
output=1024
for i=0 to number of channels
output+=volumetable[volume*globalvolume/64][sampledata];
next
realoutput=posttable[output]
This is how the mixing is done in theory. In practice it's a bit
different for speed reasons, but the result is the same.
Barmaley_m
22.05.2021, 13:12
Если я верно понимаю, то для проигрывания сэмпла с более высокой нотой (частотой) производится выборка данных с пропуском скольких-то байт. Для проигрывания на более низких нотах, наоборот, байты дублируются. Хотелось бы понимать, как эти периоды и частоты преобразовать в алгоритм выборки данных. Т.е. когда некая частота и надо брать данные из сэмпла с пропуском или без. В общем, как корректно перемещаться по сэмплу для получения нужных нот.
Это задача интерполяции. У вас есть исходный сэмпл - таблица значений некоторой функции, выбранных с равным шагом по горизонтальной оси. Вам нужно получить значения этой же функции на другом шаге по горизонтальной оси.
Хотя в математике существует много разных методов интерполяции, в случае звука правильным методом интерполяции является только один - это "Band-limited interpolation", также известная как "Nyquist interpolation". В русском языке встречается термин "Интерполяция по Котельникову". Есть теорема Котельникова, согласно которой, для записи полосно-ограниченного сигнала без потерь достаточно взять дискретные отсчёты этого сигнала через равные промежутки времени. Ну и соответствующая формула, позволяющая восстановить непрерывный во времени сигнал по этим дискретным отсчётам.
Грубо говоря, при воспроизведении мод-файла надо по сэмплу восстановить непрерывный во времени сигнал, а потом снова его дискретизировать, уже на другом интервале взятия отсчётов.
К сожалению, точная интерполяция по Котельникову на практике неосуществима, поэтому обычно используются более или менее точные её приближения.
Одним из таких приближений (очень грубым) является подстановка ближайшего слева соседнего отсчёта исходного сэмпла. Это и соответствует пропуску и дублированию значений сэмпла, о которых вы писали. Конечно, такой подход привносит в выходной сигнал значительные искажения. Даже линейная интерполяция намного лучше.
Тема очень объёмная. В случае мод-файлов задача усложняется тем, что соотношения между исходной и целевой частотой дискретизации не являются обыкновенными дробями с малым числителем и знаменателем.
На практике обычно выбирают некоторый компромисс между точностью (величиной искажений) и вычислительными затратами. Рекомендую гуглить на темы "Resampling". Вот ещё хорошая статья на тему: "Polynomial Interpolators for High-Quality Resampling of Oversampled Audio (http://yehar.com/blog/wp-content/uploads/2009/08/deip.pdf)".
Barmaley_m, все эти высокие математики это очень хорошо и полезно, где-то в отдельных областях. Но у нас Z80, нам бы что более приземлённое. Кобровские плеера без этих математик играют очень хорошо. от сюда и вопрос - как?! Ещё есть пара плееров. для Сэм Копа и Энтерпрайза, но там повсеместно самомодифицирующийся код. отследить что-то сложнова-то малость...
Barmaley_m
22.05.2021, 23:12
Barmaley_m, все эти высокие математики это очень хорошо и полезно, где-то в отдельных областях. Но у нас Z80, нам бы что более приземлённое.
На Z80 нормальную интерполяцию не сделать. Как следствие - никогда не получится на Z80 без аппаратной поддержки сделать высококачественный проигрыватель модов. Учитывая это, я считаю, что Z80 просто не предназначен, не приспособлен для решения данной задачи в реальном времени. Все попытки реализации такого проигрывателя на Z80 дадут результаты вида "конфетка из г...". Напрасная потеря времени, с учётом качества результата.
Если уж делать проигрыватель модов - то хороший, а значит, нужно нормальное железо - например, цифровой сигнальный процессор или хотя бы STM32F4xx. Тогда затраты на вылизывание и оптимизацию программы окупятся сторицей - в виде повышения качества звука. Ещё памяти надо хотя бы пару мегабайт, чтобы туда влезли тяжёлые моды.
Ещё есть пара плееров. для Сэм Копа и Энтерпрайза, но там повсеместно самомодифицирующийся код. отследить что-то сложнова-то малость...
Если так уж сильно хочется пользоваться интерполяцией методом "ближайшего соседа" и терпеть сопутствующие искажения - то рекомендую расковырять спектрумовские проигрыватели "цифровой" музыки на AY или Covox. Помню, дизассемблировал "цифровые" плееры из демок группы Flash за авторством Amadeus Wakson (впоследствии переименовался в Voxon) - "Alexgift", "Ball dreams 2". Вполне понятный, красивый код.
6/125 – это ticks и bpm.
Ticks – грубо говоря сколько времени (сколько базовых временных отрезков) удерживать каждую строку паттерна перед переходом на следующую строку. Каждый tick (кроме первого) нужно применять эффект, прописанный для данной ноты на данной строке. Например, эффект понижения громкости при ticks=6 применится 6-1=5 раз, а при ticks=3 только 3-1=2 раза (то есть громкость опустится на вдвое меньшую величину). Ну и на следующую строку надо переходить вдвое быстрей.
BPM – удары в минуту. Всё время забываю – при ticks=6 «ударом» считается то ли каждая 4-я строка паттерна, то ли каждая 8-я.
Движение по сэмплу делается так: указатель – не целое число, а вещественное (можно с фиксированной точкой, можно с плавающей). Обычно заводят таблицу приращений для каждой ноты. Приращение прибавляется к указателю на каждом шаге обработки (то есть 11025 раз в секунду при частоте микширования 11,025 КГц).
Если интересно, вот исходники моего проигрывателя S3M для БК 0011: http://thesands.ru/bk0010/st0/
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot