Files
-
blinds / hardware_design / pcb / blinds_v60.brd
-
blinds / hardware_design / pcb / blinds_v60.sch
-
braids / hardware_design / pcb / braids_v50.brd
-
braids / hardware_design / pcb / braids_v50.sch
-
branches / hardware_design / pcb / branches_v40.brd
-
branches / hardware_design / pcb / branches_v40.sch
-
clouds / hardware_design / pcb / clouds_v30.brd
-
clouds / hardware_design / pcb / clouds_v30.sch
-
ears / hardware_design / panel / ears_panel_v30.brd
-
ears / hardware_design / panel / ears_panel_v30.sch
-
ears / hardware_design / pcb / ears_v40.brd
-
ears / hardware_design / pcb / ears_v40.sch
-
edges / hardware_design / pcb / edges_expander_v01.brd
-
edges / hardware_design / pcb / edges_expander_v01.sch
-
edges / hardware_design / pcb / edges_v20.brd
-
edges / hardware_design / pcb / edges_v20.sch
-
elements / hardware_design / pcb / elements_v02.brd
-
elements / hardware_design / pcb / elements_v02.sch
-
frames / hardware_design / pcb / frames_v03.brd
-
frames / hardware_design / pcb / frames_v03.sch
-
grids / hardware_design / pcb / grids_v02.brd
-
grids / hardware_design / pcb / grids_v02.sch
-
kinks / hardware_design / pcb / kinks_v41.brd
-
kinks / hardware_design / pcb / kinks_v41.sch
-
links / hardware_design / pcb / links_v40.brd
-
links / hardware_design / pcb / links_v40.sch
-
marbles / hardware_design / pcb / marbles_v70.brd
-
marbles / hardware_design / pcb / marbles_v70.sch
-
peaks / hardware_design / pcb / peaks_v30.brd
-
peaks / hardware_design / pcb / peaks_v30.sch
-
plaits / hardware_design / pcb / plaits_v50.brd
-
plaits / hardware_design / pcb / plaits_v50.sch
-
rings / hardware_design / pcb / rings_v30.brd
-
rings / hardware_design / pcb / rings_v30.sch
-
ripples / hardware_design / pcb / ripples_v40.brd
-
ripples / hardware_design / pcb / ripples_v40.sch
-
shades / hardware_design / pcb / shades_v30.brd
-
shades / hardware_design / pcb / shades_v30.sch
-
shelves / hardware_design / pcb / shelves_expander_v10.brd
-
shelves / hardware_design / pcb / shelves_expander_v10.sch
-
shelves / hardware_design / pcb / shelves_v05.brd
-
shelves / hardware_design / pcb / shelves_v05.sch
-
stages / hardware_design / pcb / stages_v70.brd
-
stages / hardware_design / pcb / stages_v70.sch
-
streams / hardware_design / pcb / streams_v02_bargraph.brd
-
streams / hardware_design / pcb / streams_v02_bargraph.sch
-
streams / hardware_design / pcb / streams_v05.brd
-
streams / hardware_design / pcb / streams_v05.sch
-
tides / hardware_design / pcb / tides_v40.brd
-
tides / hardware_design / pcb / tides_v40.sch
-
veils / hardware_design / pcb / veils_v40.brd
-
veils / hardware_design / pcb / veils_v40.sch
-
volts / hardware_design / pcb / volts_v01.brd
-
volts / hardware_design / pcb / volts_v01.sch
-
warps / hardware_design / pcb / warps_v30.brd
-
warps / hardware_design / pcb / warps_v30.sch
-
yarns / hardware_design / pcb / yarns_v03.brd
-
yarns / hardware_design / pcb / yarns_v03.sch
Last update 6 years 3 months
by
Olivier Gillet
voice_allocator.cc// Copyright 2011 Olivier Gillet. // // Author: Olivier Gillet (ol.gillet@gmail.com) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // // ----------------------------------------------------------------------------- // // Polyphonic voice allocator. #include "edges/voice_allocator.h" #include <string.h> namespace edges { void VoiceAllocator::Clear() { ClearNotes(); for (uint8_t i = 0; i < kMaxPolyphony; ++i) { lru_[i] = kMaxPolyphony - i - 1; } } void VoiceAllocator::ClearNotes() { memset(&pool_, 0, sizeof(pool_)); } uint8_t VoiceAllocator::NoteOn(uint8_t note) { if (size_ == 0) { return 0xff; } // First, check if there is a voice currently playing this note. In this case // This voice will be responsible for retriggering this note. // Hint: if you're more into string instruments than keyboard instruments, // you can safely comment those lines. uint8_t voice = Find(note); // Then, try to find the least recently touched, currently inactive voice. if (voice == 0xff) { for (uint8_t i = 0; i < kMaxPolyphony; ++i) { if (lru_[i] < size_ && !(pool_[lru_[i]] & 0x80)) { voice = lru_[i]; } } } // If all voices are active, use the least recently played note. if (voice == 0xff) { for (uint8_t i = 0; i < kMaxPolyphony; ++i) { if (lru_[i] < size_) { voice = lru_[i]; } } } pool_[voice] = 0x80 | note; Touch(voice); return voice; } uint8_t VoiceAllocator::Find(uint8_t note) const { for (uint8_t i = 0; i < size_; ++i) { if ((pool_[i] & 0x7f) == note) { return i; } } return 0xff; } uint8_t VoiceAllocator::NoteOff(uint8_t note) { uint8_t voice = Find(note); if (voice != 0xff) { pool_[voice] &= 0x7f; Touch(voice); } return voice; } void VoiceAllocator::Touch(uint8_t voice) { int8_t source = kMaxPolyphony - 1; int8_t destination = kMaxPolyphony - 1; while (source >= 0) { if (lru_[source] != voice) { lru_[destination--] = lru_[source]; } --source; } lru_[0] = voice; } } // namespace edges