у тебя есть адрес в сэмпле 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
Sayman (20.05.2021)
При формировании формулы, пользовался этой документацией.
Код: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.
Sayman (21.05.2021)
Это задача интерполяции. У вас есть исходный сэмпл - таблица значений некоторой функции, выбранных с равным шагом по горизонтальной оси. Вам нужно получить значения этой же функции на другом шаге по горизонтальной оси.
Хотя в математике существует много разных методов интерполяции, в случае звука правильным методом интерполяции является только один - это "Band-limited interpolation", также известная как "Nyquist interpolation". В русском языке встречается термин "Интерполяция по Котельникову". Есть теорема Котельникова, согласно которой, для записи полосно-ограниченного сигнала без потерь достаточно взять дискретные отсчёты этого сигнала через равные промежутки времени. Ну и соответствующая формула, позволяющая восстановить непрерывный во времени сигнал по этим дискретным отсчётам.
Грубо говоря, при воспроизведении мод-файла надо по сэмплу восстановить непрерывный во времени сигнал, а потом снова его дискретизировать, уже на другом интервале взятия отсчётов.
К сожалению, точная интерполяция по Котельникову на практике неосуществима, поэтому обычно используются более или менее точные её приближения.
Одним из таких приближений (очень грубым) является подстановка ближайшего слева соседнего отсчёта исходного сэмпла. Это и соответствует пропуску и дублированию значений сэмпла, о которых вы писали. Конечно, такой подход привносит в выходной сигнал значительные искажения. Даже линейная интерполяция намного лучше.
Тема очень объёмная. В случае мод-файлов задача усложняется тем, что соотношения между исходной и целевой частотой дискретизации не являются обыкновенными дробями с малым числителем и знаменателем.
На практике обычно выбирают некоторый компромисс между точностью (величиной искажений) и вычислительными затратами. Рекомендую гуглить на темы "Resampling". Вот ещё хорошая статья на тему: "Polynomial Interpolators for High-Quality Resampling of Oversampled Audio".
Последний раз редактировалось Barmaley_m; 22.05.2021 в 13:21.
С любовью к вам, Yandex.Direct
Размещение рекламы на форуме способствует его дальнейшему развитию
Barmaley_m, все эти высокие математики это очень хорошо и полезно, где-то в отдельных областях. Но у нас Z80, нам бы что более приземлённое. Кобровские плеера без этих математик играют очень хорошо. от сюда и вопрос - как?! Ещё есть пара плееров. для Сэм Копа и Энтерпрайза, но там повсеместно самомодифицирующийся код. отследить что-то сложнова-то малость...
На Z80 нормальную интерполяцию не сделать. Как следствие - никогда не получится на Z80 без аппаратной поддержки сделать высококачественный проигрыватель модов. Учитывая это, я считаю, что Z80 просто не предназначен, не приспособлен для решения данной задачи в реальном времени. Все попытки реализации такого проигрывателя на Z80 дадут результаты вида "конфетка из г...". Напрасная потеря времени, с учётом качества результата.
Если уж делать проигрыватель модов - то хороший, а значит, нужно нормальное железо - например, цифровой сигнальный процессор или хотя бы STM32F4xx. Тогда затраты на вылизывание и оптимизацию программы окупятся сторицей - в виде повышения качества звука. Ещё памяти надо хотя бы пару мегабайт, чтобы туда влезли тяжёлые моды.
Если так уж сильно хочется пользоваться интерполяцией методом "ближайшего соседа" и терпеть сопутствующие искажения - то рекомендую расковырять спектрумовские проигрыватели "цифровой" музыки на AY или Covox. Помню, дизассемблировал "цифровые" плееры из демок группы Flash за авторством Amadeus Wakson (впоследствии переименовался в Voxon) - "Alexgift", "Ball dreams 2". Вполне понятный, красивый код.
Последний раз редактировалось Barmaley_m; 22.05.2021 в 23:20.
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/
Последний раз редактировалось Manwe; 27.05.2021 в 22:15.
manwe.pdp-11.ru
krotan (27.05.2021)
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)