2017-08-13 1 views
1

Je travaille sur un contrôleur MIDI USB utilisant un Teensy. Le contrôleur est une rangée de 7 boutons, chaque bouton est un degré de progression et les 7 boutons constituent une progression d'accords. Lorsqu'elle est pressée, l'appareil envoie un message d'activation/de désactivation de note MIDI pour jouer un accord.Implémentation d'une fonctionnalité de type enum avec des types personnalisés

Dans mon code je intervals stocké dans un enum:

/* 
* Intervals 
*/ 
typedef enum { 
    ROOT = 0, 
    UNISON = 0, 
    DIMINISHED_SECOND = 0, 
    MINOR_SECOND = 1, 
    AUGMENTED_UNISON = 1, 
    HALFSTEP = 1, 
    MAJOR_SECOND = 2, 
    DIMINISHED_THIRD = 2, 
    WHOLESTEP = 2, 
    MINOR_THIRD = 3, 
    AUGMENTED_SECOND = 3, 
    MAJOR_THIRD = 4, 
    DIMINISHED_FOURTH = 4, 
    PERFECT_FOURTH = 5, 
    AUGMENTED_THIRD = 5, 
    DIMINISHED_FIFTH = 6, 
    AUGMENTED_FOURTH = 6, 
    PERFECT_FIFTH = 7, 
    DIMINISHED_SIXTH = 7, 
    MINOR_SIXTH = 8, 
    AUGMENTED_FIFTH = 8, 
    MAJOR_SIXTH = 9, 
    DIMINISHED_SEVENTH = 9, 
    MINOR_SEVENTH = 10, 
    AUGMENTED_SIXTH = 10, 
    MAJOR_SEVENTH = 11, 
    DIMINISHED_OCTAVE = 11, 
    PERFECT_OCTAVE = 12, 
    AUGMENTED_SEVENTH = 12, 
    DIMISHED_NINTH = 12, 
    MINOR_NINTH = 13, 
    AUGMENTED_OCTAVE = 13, 
    MAJOR_NINTH = 14, 
    DIMINISHED_TENTH = 14, 
    MINOR_TENTH = 15, 
    AUGMENTED_NINTH = 15, 
    MAJOR_TENTH = 16, 
    DIMINISHED_ELEVENTH = 16, 
    PERFECT_ELEVENTH = 17, 
    AUGMENTED_TENTH = 17, 
    DIMINISHED_TWELFTH = 18, 
    AUGMENTED_ELEVENTH = 18, 
    PERFECT_TWELFTH = 19, 
    DIMINISHED_THIRTEENTH = 19, 
    MINOR_THIRTEENTH = 20, 
    AUGMENTED_TWELFTH = 20, 
    MAJOR_THIRTEENTH = 21, 
    DIMINISHED_FOURTEENTH = 21, 
    MINOR_FOURTEENTH = 22, 
    AUGMENTED_THIRTEENTH = 22, 
    MAJOR_FOURTEENTH = 23, 
    DIMINISHED_FIFTEENTH = 23, 
    PERFECT_FIFTEENTH = 24, 
    AUGMENTED_FOURTEENTH = 24, 
    AUGMENTED_FIFTEENTH = 25 
} INTERVAL; 

J'ai aussi un tableau de chords, comme ceci:

struct Chord { 
    String name; 
    int tones[7]; 
}; 

Chord chords[6] = { 
    { "maj", { 
    INTERVAL::UNISON, 
    INTERVAL::MAJOR_THIRD, 
    INTERVAL::PERFECT_FIFTH } 
    }, 
    { "min", { 
    INTERVAL::UNISON, 
    INTERVAL::MINOR_THIRD, 
    INTERVAL::PERFECT_FIFTH } 
    }, 
    { "maj7", { 
    INTERVAL::UNISON, 
    INTERVAL::MAJOR_THIRD, 
    INTERVAL::PERFECT_FIFTH, 
    INTERVAL::MAJOR_SEVENTH } 
    }, 
    { "min7", { 
    INTERVAL::UNISON, 
    INTERVAL::MINOR_THIRD, 
    INTERVAL::PERFECT_FIFTH, 
    INTERVAL::MINOR_SEVENTH } 
    }, 
    { "maj9", { 
    INTERVAL::UNISON, 
    INTERVAL::MAJOR_THIRD, 
    INTERVAL::PERFECT_FIFTH, 
    INTERVAL::MAJOR_SEVENTH, 
    INTERVAL::MAJOR_NINTH } 
    }, 
    { "min9", { 
    INTERVAL::UNISON, 
    INTERVAL::MINOR_THIRD, 
    INTERVAL::PERFECT_FIFTH, 
    INTERVAL::MINOR_SEVENTH, 
    INTERVAL::MINOR_NINTH } 
    } 
}; 

J'aimerais accéder aux accords dans un manière similaire à la enum d'intervalles de sorte que je peux faire quelque chose comme ça (psudeocode):

void playChord(Chord chord, int velocity, int channel) { 
    int i; 
    for(i=0; i<chord.length; i++) { 
     usbMIDI.sendNoteOn(chord[i], velocity, channel); 
    } 
} 

playChord(Chord::MAJOR, 127, 1); 

Je sais qu'il n'est pas possible d'avoir une énumération de types personnalisés, mais est-ce qu'il y a moyen de m'en rapprocher? J'ai envisagé d'utiliser un tableau de hachage, mais je devrais le mettre en œuvre à partir de zéro et je ne pense pas que si je peux l'aider.

Répondre

5

Le point d'un ENUM est que vous créez un nouveau type qui ne peut prendre un ensemble fixe de valeurs. Il est approprié d'utiliser une énumération pour vos intervalles car il y a seulement beaucoup d'intervalles dans l'utilisation réelle, et parce que la création d'un nouveau type est plus pratique que l'utilisation de constantes entières ici.

L'histoire est différente pour vos accords. Vous avez déjà un type pour vos accords, donc les envelopper dans un autre type enum n'est pas utile. De plus, le nombre d'accords est beaucoup moins fini. Un graphique d'accords que j'ai à portée de main montre 22 formes, mais cela n'inclut pas les inversions. Votre structure d'accords est beaucoup plus appropriée que de limiter artificiellement les accords avec une énumération.

C a deux autres mécanismes pour créer des "constantes" autres que enums: les variables de préprocesseur et les variables statiques. Avec une directive de préprocesseur, nous pouvons définir un littéral d'accord. Les littéraux de structure IIRC sont une chose C99, auparavant il ne pouvait y avoir que des littéraux d'initialisation.

#define CHORD_MAJOR ((Chord){"maj", {ROOT, MAJOR_THIRD, PERFECT_FIFTH}}) 

Avec une variable statique, vous déclarer un objet dans un en-tête:

static const Chord chord_major = {"maj", {ROOT, MAJOR_THIRD, PERFECT_FIFTH}}; 

Notez que C ne dispose pas d'un opérateur d'espace de noms comme ::. Au lieu de cela, vous devez préfixer vous-même tous les identifiants pouvant être en conflit. C++ a des espaces de noms, mais cela n'affecte pas les points créés dans cette réponse.