ATMEGA328を搭載した Arduino Duemilanove 互換機で音をPWM D/A変換出力するシンセサイザーライブラリです。
Revision | 3c6fdeedb6f0127f4fa8ced72842e82e8be5716d (tree) |
---|---|
Time | 2020-04-18 23:56:21 |
Author | Akiyoshi Kamide <kamide@yk.r...> |
Commiter | Akiyoshi Kamide |
Doc/keywords update, and macro refactored
@@ -1,5 +1,5 @@ | ||
1 | 1 | // |
2 | -// PWM DAC Synthesizer ver.20200413 | |
2 | +// PWM DAC Synthesizer ver.20200418 | |
3 | 3 | // by Akiyoshi Kamide (Twitter: @akiyoshi_kamide) |
4 | 4 | // http://kamide.b.osdn.me/pwmdac_synth_lib/ |
5 | 5 | // https://osdn.jp/users/kamide/pf/PWMDAC_Synth/ |
@@ -16,17 +16,7 @@ | ||
16 | 16 | #define cbi16(sfr, bit) (_SFR_WORD(sfr) &= ~_BV(bit)) |
17 | 17 | #define sbi16(sfr, bit) (_SFR_WORD(sfr) |= _BV(bit)) |
18 | 18 | |
19 | -// Function-to-array generator | |
20 | -#define FX2(f,x) f(x), f(x + 1) | |
21 | -#define FX4(f,x) FX2(f,x), FX2(f,x + 2) | |
22 | -#define FX8(f,x) FX4(f,x), FX4(f,x + 4) | |
23 | -#define FX16(f,x) FX8(f,x), FX8(f,x + 8) | |
24 | -#define FX32(f,x) FX16(f,x),FX16(f,x + 16) | |
25 | -#define FX64(f,x) FX32(f,x),FX32(f,x + 32) | |
26 | -#define FX128(f,x) FX64(f,x),FX64(f,x + 64) | |
27 | -#define ARRAY128(f) {FX128(f,0)} | |
28 | -#define ARRAY256(f) {FX128(f,0),FX128(f,128)} | |
29 | - | |
19 | +// Default parameter | |
30 | 20 | #ifndef PWMDAC_OUTPUT_PIN |
31 | 21 | #define PWMDAC_OUTPUT_PIN 3 |
32 | 22 | #endif |
@@ -37,7 +27,8 @@ | ||
37 | 27 | #define PWMDAC_POLYPHONY 6 |
38 | 28 | #endif |
39 | 29 | |
40 | -// Built-in wavetable generator | |
30 | +// | |
31 | +// Built-in wavetable functions | |
41 | 32 | // x = Phase angle : 0x00...0x80(PI_radian)...0xFF |
42 | 33 | // f(x) = Wave voltage at the x : 0x00(min)...0x80(center)...0xFF(max) |
43 | 34 | #define PWMDAC_SQUARE_WAVE(x) (((x) < 0x80 ? 0x00 : 0xFF) / PWMDAC_POLYPHONY) |
@@ -46,17 +37,26 @@ | ||
46 | 37 | #define PWMDAC_MAX_VOLUME_SINE_WAVE(x) ((byte)( 0x80 * (1 + sin(PI * (x) / 0x80)) )) |
47 | 38 | #define PWMDAC_SINE_WAVE(x) ((byte)( 0x80 * (1 + sin(PI * (x) / 0x80)) / PWMDAC_POLYPHONY )) |
48 | 39 | #define PWMDAC_SHEPARD_TONE(x) ((byte)( 0x80 * (8 \ |
49 | - +sin(PI * (x) / 0x80) \ | |
50 | - +sin(PI * (x) / 0x40) \ | |
51 | - +sin(PI * (x) / 0x20) \ | |
52 | - +sin(PI * (x) / 0x10) \ | |
53 | - +sin(PI * (x) / 0x08) \ | |
54 | - +sin(PI * (x) / 0x04) \ | |
55 | - +sin(PI * (x) / 0x02) \ | |
56 | - +sin(PI * (x) / 0x01) \ | |
57 | - ) / (8 * PWMDAC_POLYPHONY) )) | |
40 | + +sin(PI * (x) / 0x80) \ | |
41 | + +sin(PI * (x) / 0x40) \ | |
42 | + +sin(PI * (x) / 0x20) \ | |
43 | + +sin(PI * (x) / 0x10) \ | |
44 | + +sin(PI * (x) / 0x08) \ | |
45 | + +sin(PI * (x) / 0x04) \ | |
46 | + +sin(PI * (x) / 0x02) \ | |
47 | + +sin(PI * (x) / 0x01) \ | |
48 | + ) / (8 * PWMDAC_POLYPHONY) )) | |
49 | + | |
50 | +#define FX2(f,x) f(x), f(x + 1) | |
51 | +#define FX4(f,x) FX2(f,x), FX2(f,x + 2) | |
52 | +#define FX8(f,x) FX4(f,x), FX4(f,x + 4) | |
53 | +#define FX16(f,x) FX8(f,x), FX8(f,x + 8) | |
54 | +#define FX32(f,x) FX16(f,x), FX16(f,x + 16) | |
55 | +#define FX64(f,x) FX32(f,x), FX32(f,x + 32) | |
56 | +#define FX128(f,x) FX64(f,x), FX64(f,x + 64) | |
57 | +#define FX256(f,x) FX128(f,x), FX128(f,x + 128) | |
58 | 58 | |
59 | -#define PWMDAC_CREATE_WAVETABLE(table, function) PROGMEM const byte table[] = ARRAY256(function) | |
59 | +#define PWMDAC_CREATE_WAVETABLE(table, func) PROGMEM const byte table[] = { FX256(func,0) } | |
60 | 60 | |
61 | 61 | // [Phase-correct PWM dual-slope] |
62 | 62 | // TCNTn value changes to: |
@@ -277,7 +277,7 @@ class PWMDACSynth { | ||
277 | 277 | wavetable = this->channel->wavetable; |
278 | 278 | envelope = this->channel->envelope; |
279 | 279 | modulation = &(this->channel->modulation); |
280 | - static PROGMEM const unsigned long phase_speed_table[] = ARRAY128(PHASE_SPEED_OF); | |
280 | + static PROGMEM const unsigned long phase_speed_table[] = { FX128(PHASE_SPEED_OF,0) }; | |
281 | 281 | dphase32_original = pgm_read_dword(phase_speed_table + (this->note = note)); |
282 | 282 | dphase32_bended = this->channel->bendedPitchOf(dphase32_original); |
283 | 283 | dphase32_real = dphase32_bended + dphase32_moffset; |
@@ -1,17 +1,17 @@ | ||
1 | 1 | |
2 | 2 | [PWMDAC_Synth - PWM DAC synthesizer library for Arduino] |
3 | 3 | |
4 | -ver.20200405 | |
4 | +ver.20200418 | |
5 | 5 | |
6 | 6 | https://osdn.jp/users/kamide/pf/PWMDAC_Synth/wiki/FrontPage |
7 | 7 | |
8 | -ArduinoÅ®ì·éÈÕVZTCUCuÅ·B | |
9 | 8 | |
10 | 9 | ±êÍACAmiDion |
11 | 10 | |
12 | 11 | http://www.yk.rim.or.jp/~kamide/music/chordhelper/hardware/ |
13 | 12 | |
14 | -ÌQ@È~ÅÀµ½¹¹ðCu»µ½àÌÅ·B | |
13 | +ÌQ@È~ÅÀµ½¹¹ðCuƵÄƧ³¹½A | |
14 | +ArduinoÝ·@pÌPWMVZTCUCuÅ·B | |
15 | 15 | |
16 | 16 | |
17 | 17 | ArduinoÅyíðìë¤ÆµÄA±ñÈâèÉÔ¿½Á½±ÆÍ èܹñ©H |
@@ -52,6 +52,8 @@ Arduino | ||
52 | 52 | î{IÈg¢ûðºLɦµÜ·BȨAm[gIAm[gItÈÇA¹ÌoµûÉ¢ÄÍ |
53 | 53 | Arduino IDE Ìj [©ç½ÇêéuXPb`ÌávðQlɵľ³¢B |
54 | 54 | |
55 | + yTvR[hz | |
56 | + // | |
55 | 57 | // KvɶAPWMDAC_Synth.h ðCN[h·éOÉ #define źLðwèÅ«Ü·B |
56 | 58 | // |
57 | 59 | #define PWMDAC_OUTPUT_PIN 3 // PWMoÍsÔiȪÂFºLuoÍs(PWM)vQÆj |
@@ -101,9 +103,14 @@ Arduino | ||
101 | 103 | ftHgÍ6da¹Å·B |
102 | 104 | PWMDAC_POLYPHONY ÉlðÝèµÄRpCµ¼·±ÆŸÂ\Å·B |
103 | 105 | |
104 | - ¯¹ðâ·ÆA»ÌªAèÝ ISR() ÌÀsÉÔª©©èÜ·B | |
105 | - èÝÈOÌðs¤½ßÌÔI]TªÈÈÁ½_Å®ìµÈÈèÜ·B | |
106 | - »¤Èé¡OªAÀã̯¹ÌãÀÅ·B | |
106 | + ¦ ¯¹ðâµÄ¢ÆA»Ìª | |
107 | + ISR() (Interrupt Service Routine: èÝT[rX[`)ɨ¯é | |
108 | + [vñª¦A½ZÉÈÁÄ«Ü·B ÜèɽZ᪎ loop() ðÀs·é | |
109 | + ɪÈÈéÆA®ìs\É×èÜ·B»¤Èé¡OªA¯¹ÌÀãÌãÀÅ·B | |
110 | + | |
111 | + ¦ ISR() ÈÇÅ®ì¬xªv³êé½ßAPWMDAC_Synth.h ÉÍ | |
112 | + #pragma GCC optimize ("-O3") | |
113 | + ªwè³êĢܷBRpCÌÅK»îðA±ÌCu¾¯¬xDæÉ·é½ßÅ·B | |
107 | 114 | |
108 | 115 | ÁèÌMIDI`lÉε{CXATCÌDæxðã°é±ÆàÅ«Ü·B |
109 | 116 | ãqÌu`lDæxwèvðQÆB |
@@ -126,27 +133,23 @@ Arduino | ||
126 | 133 | |
127 | 134 | MIDI`lì |
128 | 135 | |
129 | - PWM_SYNTH Ì\bhÅA | |
136 | + PWMDACSynth::getChannel() Å | |
130 | 137 | |
131 | 138 | MIDI`lÔ(1`16) Ì MIDI`lÖÌ|C^ |
132 | 139 | |
133 | - ðÝÏ·Å«Ü·B | |
134 | - | |
135 | - MidiChannel *getChannel(char channel) | |
136 | - char getChannel(MidiChannel *cp) | |
137 | - | |
138 | - MIDI`lÖÌ|C^ðîµÄ`lPÊɽ¹é | |
139 | - p[^ðìÅ«Ü·B | |
140 | + ðÝÏ·Å«Ü·BMIDI`lÖÌ|C^ðîµÄA | |
141 | + `lPÊɽ¹ép[^ðìÅ«Ü·B | |
142 | + iìû@É¢ÄÍ PWMDAC_Synth.h ðQÆj | |
140 | 143 | |
141 | 144 | ȨAm[gIAm[gItAsb`xhÈÇA¡oÄ¢é¹ |
142 | - iATC³êÄ¢é{CXjɦÀɽf³¹éÉÍA | |
143 | - MidiChannel ÅÍÈ PWMDACSynth ÌoÖðÄÑo·Kvª èÜ·B | |
145 | + iATC³êÄ¢é{CXjɦÀɽf³¹éÉÍAPWMDACSynth Ì٤Š| |
146 | + pӵĢéoÖðÄÑoµA`lÆ{CXð¯ÉXV·éKvª èÜ·B | |
144 | 147 | |
145 | 148 | |
146 | 149 | MIDIÖ |
147 | 150 | |
148 | - PWM_SYNTH ÃIIuWFNgÉÍAMIDICuÌ MIDI.setHandleXxxx() É | |
149 | - ¼ÚwèÅ«éæ¤AøÌâ^ðí¹½Öð¢Â©pӵĢܷB | |
151 | + PWMDACSynth Åè`³ê½¢Â©Ì static IuWFNgÍA | |
152 | + MIDICuÌ MIDI.setHandleXxxx() ɼÚwèÅ«é`®ÉÈÁĢܷB | |
150 | 153 | |
151 | 154 | ½¾µAÚ±èÌMIDIfoCXÉæÁÄÍANOTE OFF ÌãíèÉ |
152 | 155 | velocity=0 Ì NOTE ON ðÁÄé±Æª éÌÅA»Ì꾯 |
@@ -158,39 +161,29 @@ Arduino | ||
158 | 161 | |
159 | 162 | ¹FÏX |
160 | 163 | |
161 | - g`ÆGx[vp[^iADSRjð MidiChannel NXÌ | |
162 | - wavetable Æ env_param Éwè·é±ÆÅA¹FðÏXÅ«Ü·B | |
163 | - | |
164 | - ADSRÌÝèÍ EnvelopeParam NXðîµÄs¢Ü·B | |
165 | - RXgN^ÅÌlðwèµÄú»Å«Ü·B | |
166 | - | |
167 | - Eattack_time - A^bNÔiå«¢ÙÇm[gI¼ã̧¿ãªèªäÁèj | |
168 | - Edecay_time - fBPCÔiå«¢ÙÇm[gIã̸ªäÁèj | |
169 | - Esustain_level - TXeBxi¸ª~ÜÁ½ ÆÛ·é¹Êj | |
170 | - Erelease_time - [XÔiå«¢ÙÇm[gItã̸ªäÁèj | |
171 | - | |
172 | - lÌÍÍÍ sustain_level ª 0`255A»êÈOÍ 0`15 Å·B | |
173 | - ÀÔÍ loop() àÅ update() ðÄÑo·pxÉæÁÄÏíèÜ·B | |
164 | + g`e[uÆADSRGx[vp[^ðA»ê¼ê MidiChannel NXÌ | |
165 | + wavetable Æ envelope[] Éwè·é±ÆÅA¹FðÏXÅ«Ü·B | |
174 | 166 | |
175 | - eADSRp[^lÖÌ|C^Í getParam() \bhÅæ¾Å«Ü·B | |
167 | + ܽAInstrument \¢ÌèðvOÌæÉìèA»êð | |
168 | + programChange() Éwè·é¾¯ÅAg`ÆGx[vðêxÉÝèÅ«Ü·B | |
169 | + MIDIÌvO`FWðÀ·éÆ«ÉÖÅ·B | |
176 | 170 | |
171 | + yg`z wavetable | |
177 | 172 | g`e[uÍAvf256Ìbyte^PROGMEMzñƵĶ¬µÜ·B |
178 | 173 | »êð wavetable Éwè·é±ÆÅAg`ðØèÖ¦é±ÆªÅ«Ü·B |
179 | - | |
180 | - g`e[uzñ̶¬ÍAPWMDAC_Synth.h ãÅè`³ê½ | |
181 | - }Nðg¢AKvÈg`e[u¾¯ð¶¬µÄ¾³¢B | |
182 | - | |
183 | - ±Ì}NÍA¯¹ª¦ÄàMxª255ð´¦Ä¹ê¹¸A | |
184 | - ©ÂÅå¹ÊÌoéæ¤ÈvZ®ÉÈÁĢܷB | |
185 | - ±êÉKÁÄ©ªÅg`ðè`·êÎA»êðwèµÄ | |
186 | - Ʃ̹Fð¶Ýo·±ÆàÂ\Å·B | |
187 | - | |
188 | - vOÌæÉ Instrument \¢ÌèðìÁÄA | |
189 | - »êðwè·é±ÆŹFðÏX·é±ÆàÅ«Ü·B | |
190 | - MIDIÌvO`FWÌÀÉͱÌû@ª¨··ßÅ·B | |
191 | - »ÝÌo[WÅÍAvO`FWÎɺ¢A | |
192 | - Gx[vÌú»É Instrument \¢Ìèðg¤C^[tF[XÉ | |
193 | - µÄRAMÖÌWJðŬÀÉ}¦çêéæ¤ÉµÜµ½B | |
174 | + g`ÖÌ}Nð PWMDAC_CREATE_WAVETABLE() }NÉwè·é©A | |
175 | + ܽͻêÉÈçÁÄ©ªÅzñðè`·é±ÆÅACÓÌg`𶬷é±ÆªÂ\Å·B | |
176 | + | |
177 | + ¦ gÍi255¯¹FftHg6da¹ÌÆ«42jð´¦È¢æ¤ÉµÄ¾³¢B | |
178 | + ¯¹¢ÁÏ¢ÉÂ絽ƫÉÅå¹Ê255ð´¦ÄI[o[t[µAmCYª | |
179 | + ¶·é°êª èÜ·B | |
180 | + | |
181 | + yADSRGx[vz envelope[] | |
182 | + ADSR_ATTACK_VALUE - A^bNÔi0`15Aå«¢ÙÇm[gI¼ã̧¿ãªèªäÁèj | |
183 | + ADSR_DECAY_VALUE - fBPCÔi0`15Aå«¢ÙÇm[gIã̸ªäÁèj | |
184 | + ADSR_SUSTAIN_VALUE - TXeBxi0`255A¸ª~ÜÁ½ ÆÛ·é¹Êj | |
185 | + ADSR_RELEASE_VALUE - [XÔi0`15Aå«¢ÙÇm[gItã̸ªäÁèj | |
186 | + ÀÔÍ loop() àÅ update() ðÄÑo·pxÉæÁÄÏíèÜ·B | |
194 | 187 | |
195 | 188 | |
196 | 189 | `lDæxwè |
@@ -217,10 +210,6 @@ Arduino | ||
217 | 210 | ½da¹´ª¸íêé±Æª èÜ·ÌÅAKX²®µÄ¾³¢B |
218 | 211 | |
219 | 212 | |
220 | -»Ì¼ÌÖ | |
221 | - | |
222 | - »Ì¼ApÅ«éÖÉ¢ÄÍ\[XR[hÌwb_ PWMDAC_Synth.h ðQÆB | |
223 | - | |
224 | 213 | |
225 | 214 | ìÒF«æµ - Akiyoshi Kamide |
226 | 215 | http://www.yk.rim.or.jp/~kamide/ |
@@ -6,10 +6,8 @@ | ||
6 | 6 | # Datatypes (KEYWORD1) |
7 | 7 | ####################################### |
8 | 8 | |
9 | -EnvelopeParam KEYWORD1 | |
10 | 9 | Instrument KEYWORD1 |
11 | 10 | MidiChannel KEYWORD1 |
12 | -VoiceStatus KEYWORD1 | |
13 | 11 | PWMDACSynth KEYWORD1 |
14 | 12 | |
15 | 13 | ####################################### |
@@ -24,7 +22,6 @@ pitchBend KEYWORD2 | ||
24 | 22 | controlChange KEYWORD2 |
25 | 23 | systemReset KEYWORD2 |
26 | 24 | getChannel KEYWORD2 |
27 | -setEnvelope KEYWORD2 | |
28 | 25 | setPriority KEYWORD2 |
29 | 26 | |
30 | 27 | ####################################### |
@@ -35,3 +32,4 @@ PWMDAC_NOTE_A_FREQUENCY LITERAL1 | ||
35 | 32 | PWMDAC_POLYPHONY LITERAL1 |
36 | 33 | PWMDAC_OUTPUT_PIN LITERAL1 |
37 | 34 | PWMDAC_CHANNEL_PRIORITY_SUPPORT LITERAL1 |
35 | + |