#include "tone.h" /** * Přidán attack - zmizí rušivé lupání, prodlouží se obsluha tónu. * */ extern "C" const short onePeriod[]; extern "C" const unsigned int midiTones[]; extern "C" const unsigned int attackTable[]; static constexpr unsigned defFall = 16u; static constexpr unsigned maxAttack = 127u; Tone::Tone() noexcept { ampl = 0; freq = 0; base = 0; atck = 0; fall = defFall; } void Tone::setAmpl (unsigned int a) { ampl = a; } void Tone::setFreq (unsigned int f) { freq = f; } void Tone::setMidiOn (unsigned int m) { freq = midiTones [m & 0x7F]; if (freq) atck = maxAttack; fall = 1; } void Tone::setMidiOff (void) { fall = defFall; /* base = 0; freq = 0; */ } void Tone::setFall (unsigned int f) { fall = f; } int Tone::step (void) { unsigned int k,t; int y; // Spočteme index x pro přístup do tabulky const unsigned x = (base >> 16) & 0xFF; y = onePeriod [x]; // vzorek vezmeme z tabulky // k je horní půlka amplitudy k = ampl >> 16; y *= k; // vzorek násobíme amplitudou (tedy tím vrškem) y >>= 12; // a vezmeme jen to, co potřebuje DAC k *= fall; // Konstanta fall určuje rychlost poklesu amplitudy, // čím více, tím je rychlejší. Pokud by bylo 1, pokles je 2^16 vzorků, což už je pomalé. base += freq; // časová základna pro další vzorek if (atck) { // přidán attack = náběh amplitudy t = attackTable [atck]; // z tabulky if (t > ampl) ampl = t; // prevence lupání - nemí být skok amplitudy atck -= 1; // dočasovat k nule } else ampl -= k; // exponenciální pokles amplitudy // a je to return y; }