zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

NotePool.h (5092B)


      1 /*
      2   ZynAddSubFX - a software synthesizer
      3 
      4   NotePool.h - Pool of Synthesizer Engines And Note Instances
      5   Copyright (C) 2016 Mark McCurry
      6 
      7   This program is free software; you can redistribute it and/or
      8   modify it under the terms of the GNU General Public License
      9   as published by the Free Software Foundation; either version 2
     10   of the License, or (at your option) any later version.
     11 */
     12 #pragma once
     13 #include <stdint.h>
     14 #include <functional>
     15 #include "../globals.h"
     16 
     17 //Expected upper bound of synths given that max polyphony is hit
     18 #define EXPECTED_USAGE 3
     19 
     20 namespace zyn {
     21 
     22 typedef uint8_t note_t; //Global MIDI note definition
     23 
     24 struct LegatoParams;
     25 class PortamentoRealtime;
     26 class NotePool
     27 {
     28     public:
     29         //Currently this wastes a ton of bits due to the legatoMirror flag
     30         struct NoteDescriptor {
     31             //acceptable overlap after 2 minutes
     32             //run time at 48kHz 8 samples per buffer
     33             //19 bit minimum
     34             uint32_t age;
     35             note_t note;
     36             uint8_t sendto;
     37             //max of 16 kit elms and 3 kit items per
     38             uint8_t size;
     39             uint8_t status;
     40             bool    legatoMirror;
     41             PortamentoRealtime *portamentoRealtime;
     42             bool operator==(NoteDescriptor);
     43 
     44             //status checks
     45             bool playing(void) const;
     46             bool off(void) const;
     47             bool sustained(void) const;
     48             bool released(void) const;
     49             bool entombed(void) const;
     50             bool dying(void) const;
     51             bool latched(void) const;
     52 
     53             //status transitions
     54             void setStatus(uint8_t s);
     55             void doSustain(void);
     56 
     57             bool canSustain(void) const;
     58             void makeUnsustainable(void);
     59         };
     60 
     61         //To be pedantic this wastes 2 or 6 bytes per descriptor
     62         //depending on 32bit/64bit alignment rules
     63         struct SynthDescriptor {
     64             SynthNote *note;
     65             uint8_t type;
     66             uint8_t kit;
     67         };
     68 
     69 
     70         //Pool of notes
     71         NoteDescriptor   ndesc[POLYPHONY];
     72         SynthDescriptor  sdesc[POLYPHONY*EXPECTED_USAGE];
     73         bool             needs_cleaning;
     74 
     75 
     76         //Iterators
     77         struct activeNotesIter {
     78             SynthDescriptor *begin() {return _b;};
     79             SynthDescriptor *end() {return _e;};
     80             SynthDescriptor *_b;
     81             SynthDescriptor *_e;
     82         };
     83 
     84         struct activeDescIter {
     85             activeDescIter(NotePool &_np):np(_np)
     86             {
     87                 int off=0;
     88                 for(int i=0; i<POLYPHONY; ++i, ++off)
     89                     if(np.ndesc[i].status == 0)
     90                         break;
     91                 _end = np.ndesc+off;
     92             }
     93             NoteDescriptor *begin() {return np.ndesc;};
     94             NoteDescriptor *end() { return _end; };
     95             NoteDescriptor *_end;
     96             NotePool &np;
     97         };
     98 
     99         struct constActiveDescIter {
    100             constActiveDescIter(const NotePool &_np):np(_np)
    101             {
    102                 int off=0;
    103                 for(int i=0; i<POLYPHONY; ++i, ++off)
    104                     if(np.ndesc[i].status == 0)
    105                         break;
    106                 _end = np.ndesc+off;
    107             }
    108             const NoteDescriptor *begin() const {return np.ndesc;};
    109             const NoteDescriptor *end() const { return _end; };
    110             const NoteDescriptor *_end;
    111             const NotePool &np;
    112         };
    113 
    114         activeNotesIter activeNotes(NoteDescriptor &n);
    115 
    116         activeDescIter activeDesc(void);
    117         constActiveDescIter activeDesc(void) const;
    118 
    119         //Counts of descriptors used for tests
    120         int usedNoteDesc(void) const;
    121         int usedSynthDesc(void) const;
    122 
    123         NotePool(void);
    124 
    125         //Operations
    126         void insertNote(note_t note, uint8_t sendto, SynthDescriptor desc,
    127                         PortamentoRealtime *portamento_realtime=NULL, bool legato=false);
    128         void insertLegatoNote(NoteDescriptor desc, SynthDescriptor sdesc);
    129 
    130         void upgradeToLegato(void);
    131         void applyLegato(note_t note, const LegatoParams &par, PortamentoRealtime *portamento_realtime=NULL);
    132 
    133         void makeUnsustainable(note_t note);
    134 
    135         void releaseLatched();
    136 
    137         bool full(void) const;
    138         bool synthFull(int sdesc_count) const;
    139 
    140         //Note that isn't KEY_PLAYING or KEY_RELEASED_AND_SUSTAINING
    141         bool existsRunningNote(void) const;
    142         int getRunningNotes(void) const;
    143         void enforceKeyLimit(int limit);
    144         int getRunningVoices(void) const;
    145         void enforceVoiceLimit(int limit, int preferred_note);
    146         void limitVoice(int preferred_note);
    147 
    148         void releasePlayingNotes(void);
    149         void releaseSustainingNotes(void);
    150         void releaseNote(note_t note);
    151         void release(NoteDescriptor &d);
    152         void latch(NoteDescriptor &d);
    153 
    154 
    155         void killAllNotes(void);
    156         void killNote(note_t note);
    157         void kill(NoteDescriptor &d);
    158         void kill(SynthDescriptor &s);
    159         void entomb(NoteDescriptor &d);
    160 
    161         void cleanup(void);
    162 
    163         void dump(void);
    164 };
    165 
    166 }