• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

電子楽器CAmiDionのArduinoスケッチ(C++)です。回路図も置いてあります。


コミットメタ情報

リビジョン6fbad073fea6a57891f9e1ed3e4c93b89b56c4f0 (tree)
日時2019-08-16 12:14:22
作者Akiyoshi Kamide <kamide@yk.r...>
コミッターAkiyoshi Kamide

ログメッセージ

Program Change sending feature added, refactored, and webpage URL updated

変更サマリ

差分

--- a/CAmiDion.ino
+++ b/CAmiDion.ino
@@ -1,9 +1,9 @@
11 //
22 // CAmiDion - Musical Chord Instrument
3-// ver.20160429
3+// ver.20190816
44 // by Akiyoshi Kamide (Twitter: @akiyoshi_kamide)
5-// http://kamide.b.osdn.me/camidion/
6-// http://osdn.jp/users/kamide/pf/CAmiDion/
5+// http://camidion.wordpress.com/camidion/
6+// http://osdn.net/users/kamide/pf/CAmiDion/
77 // http://www.yk.rim.or.jp/~kamide/music/chordhelper/hardware/
88 //
99
@@ -71,7 +71,8 @@ PROGMEM const Instrument DRUM_INSTRUMENT = {randomWavetable, {5, 0, 5, 0}};
7171
7272 class WaveSelecter {
7373 protected:
74- byte current_midi_channel; // 1==CH1, ...
74+ byte current_midi_channel; // 1==CH1
75+ byte programs[0x10]; // 0[0]==Prog1[CH1]
7576 public:
7677 WaveSelecter() {
7778 PWMDACSynth::getChannel(DRUM_MIDI_CHANNEL)->programChange(&DRUM_INSTRUMENT);
@@ -79,9 +80,10 @@ class WaveSelecter {
7980 #ifdef USE_LED
8081 led_ctrl.setMidiChannel(0);
8182 #endif
83+ memset(programs, 0, sizeof(programs));
8284 }
8385 #ifdef USE_LCD
84- void showWaveform(char delimiter) {
86+ void showWaveform(const char delimiter) {
8587 lcd.printWaveform(
8688 current_midi_channel,
8789 PWMDACSynth::getChannel(current_midi_channel)->wavetable,
@@ -93,7 +95,7 @@ class WaveSelecter {
9395 }
9496 #endif
9597 byte getCurrentMidiChannel() { return current_midi_channel; }
96- void changeCurrentMidiChannel(char offset) {
98+ void changeCurrentMidiChannel(const char offset) {
9799 char ch0 = current_midi_channel + offset - 1;
98100 current_midi_channel = (ch0 &= 0xF) + 1;
99101 #ifdef USE_LED
@@ -104,7 +106,7 @@ class WaveSelecter {
104106 showEnvelope();
105107 #endif
106108 }
107- void changeWaveform(char offset) {
109+ void changeWaveform(const char offset) {
108110 if( ! offset ) return;
109111 MidiChannel *cp = PWMDACSynth::getChannel(current_midi_channel);
110112 for( char i = 0; i < NumberOf(WAVETABLE_LIST); i++ ) {
@@ -118,7 +120,7 @@ class WaveSelecter {
118120 return;
119121 }
120122 }
121- void changeEnvelope(AdsrStatus adsr, char offset) {
123+ void changeEnvelope(const AdsrStatus adsr, const char offset) {
122124 byte *p = PWMDACSynth::getChannel(current_midi_channel)->envelope.getParam(adsr);
123125 if( adsr == ADSR_SUSTAIN ) *p += offset * 0x10; // 0..F -> 0..FF
124126 else { *p += offset; *p &= 0xF; }
@@ -126,6 +128,25 @@ class WaveSelecter {
126128 showEnvelope();
127129 #endif
128130 }
131+ byte getProgram(const byte channel) { return programs[channel - 1]; }
132+ byte getProgram() { return getProgram(current_midi_channel); }
133+ void programChange(const byte channel, const byte program) {
134+ if( channel == DRUM_MIDI_CHANNEL ) return;
135+ byte *pp = programs + channel - 1;
136+ *pp = program & 0x7F;
137+#ifdef USE_LCD
138+ if( channel == current_midi_channel ) lcd.printProgram(*pp);
139+#endif
140+#if defined(OCTAVE_ANALOG_PIN)
141+ PWMDACSynth::getChannel(channel)->programChange(INSTRUMENTS + *pp);
142+#endif
143+#ifdef USE_MIDI_OUT
144+ MIDI.sendProgramChange(*pp, channel);
145+#endif
146+ }
147+ void programChange(const byte program) {
148+ programChange(current_midi_channel, program);
149+ }
129150 };
130151
131152 WaveSelecter wave_selecter;
@@ -151,8 +172,7 @@ void HandleNoteOn(byte channel, byte pitch, byte velocity) {
151172
152173 #if defined(OCTAVE_ANALOG_PIN)
153174 void HandleProgramChange(byte channel, byte number) {
154- if( channel == DRUM_MIDI_CHANNEL ) return;
155- PWMDACSynth::getChannel(channel)->programChange(INSTRUMENTS + number);
175+ wave_selecter.programChange(channel, number);
156176 }
157177 #endif
158178
@@ -636,6 +656,9 @@ class MyButtonHandler : public ButtonHandler {
636656 if( button_input.isOn(MIDI_CH_BUTTON) ) {
637657 if(y == 0) {
638658 if( x >= -1 && x <= 1 ) wave_selecter.changeCurrentMidiChannel(x);
659+#ifdef USE_LCD
660+ else if( x == -2 ) lcd.printProgram(wave_selecter.getProgram());
661+#endif
639662 return;
640663 }
641664 switch(x) {
@@ -644,6 +667,8 @@ class MyButtonHandler : public ButtonHandler {
644667 case 2: wave_selecter.changeEnvelope(ADSR_DECAY, y); break;
645668 case 3: wave_selecter.changeEnvelope(ADSR_SUSTAIN, y); break;
646669 case 4: wave_selecter.changeEnvelope(ADSR_RELEASE, y); break;
670+ case -1: wave_selecter.programChange(wave_selecter.getProgram() + y); break;
671+ case -2: wave_selecter.programChange(wave_selecter.getProgram() + y*8); break;
647672 }
648673 return;
649674 }
--- a/CAmiDionLCD.h
+++ b/CAmiDionLCD.h
@@ -52,9 +52,22 @@ class CAmiDionLCD : public LCD_PARENT_CLASS {
5252 memcpy( bufp, str, len ); bufp += len;
5353 }
5454 void setString(char *str) { setString(str,strlen(str)); }
55- void setHex(byte value) {
55+ void setSingleHex(byte value) {
5656 *bufp++ = value + (value < 10 ?'0':'A'-10);
5757 }
58+ void setDecimal(byte value) {
59+ byte d100 = value / 100;
60+ if( d100 ) {
61+ *bufp++ = d100 + '0';
62+ value -= d100 * 100;
63+ }
64+ byte d10 = value / 10;
65+ if( d100 || d10 ) {
66+ *bufp++ = d10 + '0';
67+ value -= d10 * 10;
68+ }
69+ *bufp++ = value + '0';
70+ }
5871 public:
5972 CAmiDionLCD() : LCD_PARENT_CLASS( LCD_CONSTRUCTOR_ARGS ) {
6073 current_chord = MusicalChord();
@@ -115,7 +128,7 @@ class CAmiDionLCD : public LCD_PARENT_CLASS {
115128 setCursor(0,0);
116129 printLineBuffer();
117130 }
118- void printTempo(unsigned int bpm, char delimiter) {
131+ void printTempo(const unsigned int bpm, const char delimiter) {
119132 #if LCD_COLS >= 15
120133 setString("Tempo",5);
121134 #else
@@ -126,15 +139,21 @@ class CAmiDionLCD : public LCD_PARENT_CLASS {
126139 printLineBuffer();
127140 clearChord();
128141 }
129- void printEnvelope(EnvelopeParam *ep) {
130- *bufp++ = 'a'; setHex(*(ep->getParam(ADSR_ATTACK)));
131- *bufp++ = 'd'; setHex(*(ep->getParam(ADSR_DECAY)));
132- *bufp++ = 's'; setHex(*(ep->getParam(ADSR_SUSTAIN)) >> 4);
133- *bufp++ = 'r'; setHex(*(ep->getParam(ADSR_RELEASE)));
142+ void printProgram(byte program) { // program = 0..127
143+ setString("Prog:");
144+ setDecimal(++program);
134145 setCursor(0,1);
135146 printLineBuffer();
136147 }
137- void printWaveform(byte midi_channel, PROGMEM const byte wavetable[], char delimiter = ':') {
148+ void printEnvelope(EnvelopeParam* const ep) {
149+ *bufp++ = 'a'; setSingleHex(*(ep->getParam(ADSR_ATTACK)));
150+ *bufp++ = 'd'; setSingleHex(*(ep->getParam(ADSR_DECAY)));
151+ *bufp++ = 's'; setSingleHex(*(ep->getParam(ADSR_SUSTAIN)) >> 4);
152+ *bufp++ = 'r'; setSingleHex(*(ep->getParam(ADSR_RELEASE)));
153+ setCursor(0,1);
154+ printLineBuffer();
155+ }
156+ void printWaveform(const byte midi_channel, PROGMEM const byte wavetable[], const char delimiter = ':') {
138157 PROGMEM static const uint8_t random_pattern[] = {
139158 B10101,
140159 B01010,
@@ -224,10 +243,7 @@ class CAmiDionLCD : public LCD_PARENT_CLASS {
224243 static const char wavename_guitar[] PROGMEM = "Guitar";
225244 #endif
226245 setString("Ch",2);
227- if( midi_channel >= 10 ) {
228- *bufp++ = '1'; midi_channel -= 10;
229- }
230- *bufp++ = midi_channel + '0';
246+ setDecimal(midi_channel);
231247 *bufp++ = delimiter;
232248 const char PROGMEM *wavename;
233249 if( wavetable == shepardToneSineWavetable ) {