使用自定义类型实现类似枚举的功能

时间:2017-08-13 11:48:09

标签: enums arduino hashtable teensy

我正在使用Teensy处理USB MIDI控制器。控制器是一排7个按钮,每个按钮是一个渐进度,7个按钮构成和弦进程。按下时,设备发送MIDI音符开/关信息以播放和弦。

在我的代码中,我intervals存储了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;

我也有一个chords数组,如下所示:

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 }
  }
};

我想以与enum间隔类似的方式访问和弦,这样我就可以做这样的事情(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);

我知道它不可能有一个自定义类型的枚举,但有什么方法可以接近这个?我考虑过使用HashTable,但是我必须从头开始实现它,如果我能帮助它,我不会想到它。

1 个答案:

答案 0 :(得分:5)

枚举的重点在于您创建的新类型只能使用固定的值集。为你的间隔使用枚举是合适的,因为在实际使用中只有这么多的间隔,并且因为创建一个新类型比在这里使用整数常量更方便。

你的和弦的故事是不同的。你已经有了和弦的类型,所以将它们包装在另一个枚举类型中是没有用的。而且,和弦的数量远不如有限。我手边的和弦图表显示了22个形状,但不包括反转。你的和弦结构比用枚举人工限制和弦更合适。

C还有另外两种机制来创建除枚举之外的“常量”:预处理器定义和静态变量。

使用预处理器指令,我们可以定义Chord文字。 IIRC结构文字是C99的东西,以前只能有初始化文字。

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

使用静态变量,您可以在标题中声明一个对象:

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

请注意,C没有像::这样的名称空间运算符。相反,您必须自己为任何可能的冲突标识符添加前缀。 C ++确实有名称空间,但这不会影响这个答案中的要点。