Проекты GitHub SourceForge |
MT32 /
PatchКак описание Patch'а переводится в значения регистров LA32Wave GeneratorStructure of PartialСогласно www.polynominal.com у MT-32 имеется 13 возможных вариантов использования partials. В firmware v1.0.7 описание Partial Structure находится в массиве uint16_t, находящимся по адресу 669Eh. Вот так он выглядит в двоичном представлении.
Каждый байт отвечает за один partial: LSB - за partial1, MSB - за partial2. Назначение полей в этих байтах совпадают. [7:6] - WG mode extension: 00 - SYN, 10 - PCM with Ring Modulation, 11 - PCM; Partial Structure отвечает за:
Биты [7:6] в PCM режиме напрямую копируются в регистр WG_SETUP синтезатора LA32. По какой-то причине, для partial2 при включенном Ring Modulation их значения должны быть 0b10 вместо 0b11. PCMЧто используется
На что влияют
SynthЧто используется
На что влияют
WG_PULSE_WIDTH = USAT8( ((VELOCITY - 64) * (WG_PW_VELO_SENS - 7)) + MAP_PULSE_WIDTH[WG_PULSE_WIDTH] ) USAT8(a, b) - насыщение в uint8_t. PitchЧто используется
pitch_note = (NOTE + 12) / 12 pitch_octave = (NOTE + 12) % 12 epitch_base = MAP_PITCH[pitch_note]; // высота тона epitch_base += pitch_octave * 0x1'000; // каждая октава удваивает частоту тона (см. примечание) epitch_base += 0x6'000; // какая-то коррекция epitch_base = (epitch_base * MAP_KEYFOLLOW[WG_PITCH_KEYFOLLOW] / (2 * 0x1000); epitch_base += MAP_COARSE[WG_PITCH_COARSE]; // грубая подстройка тона в настройках Partial (полутоны) epitch_base += MAP_FINE[WG_PITCH_FINE]; // тонкая подстройка тона в настройках Partial (центы) epitch_base += MAP_COARSE[KEY_SHIFT + 12] epitch_base += MAP_FINE[FINE_TUNE] PCM
epitch_base += MAP_PCM_TUNE[WG_PCM_WAVE] SYNTH
SYNTH SQUAREepitch_base += 0x9'10d SYNTH SAWepitch_base += 0x9'10d - 0x0'010 На что влияют
Следует отметить, что частота задается в виде дробного десятичного числа с фиксированной запятой в формате 0xI'FFF, где I - целая часть, а FFF - дробная. Само значение является показателем степени 2 (экпонентой) частоты генератора в килогерцах. Например, базовой частотой для большинства PCM сэмплов является 0x5'000, что равняется 2^5.000 = 32.000КГц. Для синтеза синусоиды (режим SYNTH SQUARE) расчет значения epitch_base выглядит так: epitch_base = LOG2(FREQ * 2 * 1.024) * 4096 То есть, частота генератора в два раза выше частоты звука. Более того, в килогерце считается не 1000Гц, а 1024Гц, то есть 2^10Гц. Возможно, это связано с тем, что LA32 тактируется генератором с частотой 16384КГц (2^14КГц). Таблица MAP_PITCH[12], если перевести ее значения в обычные дроби, содержит в себе значения от 0 до 1: (n / 12), где n = 0..12. 12 - это количество полутонов в октаве. Таблица MAP_KEYFOLLOW[17] содержит дробные коэффиценты, позволяющие линейно растянуть или сжать частоты тонов по нотам. По какой-то причине (видимо, чтобы повысить точность вычислений) эти коэффициенты удвоены. Поэтому, после умножения чисел с фиксированной запятой, помимо обычной коррекции разряда (деление на 1000h в нашем случае), результат еще и делится на 2. Значение параметров по умолчанию:WG_PITCH_KEYFOLLOW = 1; MAP_KEYFOLLOW[WG_PITCH_KEYFOLLOW] = 0x2000 TVAЧто используетсяНа что влияютTVFЧто используется
В общем виде, расчет значения регистра TVF_FREQ выглядит так: tvf_freq = TVF_CUTOFF_FREQ - 50.0 REG_TVF_FREQ = TO_INT(tvf_freq - 125.5) Как это ни странно, частота фильтра не зависит от частоты ноты. По всей видимости, фильть здесь не совсем фильтр, а коэффициент похожести сигнала на синусоиду. Подробней нужно смотреть в исходниках MUNT или в выходе LA32.
Дальше, в расчет вводятся TVF Key Follow и TVF Bias Point: // TVF Key Follow tvf_freq += MAP_TVF_KEYFOLLOW[TVF_KEY_FOLLOW] - MAP_TVF_KEYFOLLOW[WG_PITCH_KEYFOLLOW] // TVF Bias Point if (TVF_BIAS_POINT_DIR >= 64) { // >A1..>C7 // TVF_BIAS_POINT_DIR(64..127) to MIDI_NOTE_A1..MIDI_NOTE_C7 tvf_bias_note = TVF_BIAS_POINT_DIR - 64 + MIDI_NOTE_A1 if (midi_note >= tvf_bias_note) { tvf_freq += tvf_bias_note * MAP_TVF_BIAS_LEVEL[TVF_BIAS_LEVEL] } } else { // <A1..<C7 // TVF_BIAS_POINT_DIR(0..63) to MIDI_NOTE_A1..MIDI_NOTE_C7 tvf_bias_note = TVF_BIAS_POINT_DIR + MIDI_NOTE_A1 if (g_midi_note < tvf_bias_note) { tvf_freq -= tvf_bias_note * MAP_TVF_BIAS_LEVEL[TVF_BIAS_LEVEL] } } TVF_RES = tvf_resonance + ((INT(tvf_resonance) / 4) * 32) На что влияют
|