Simple synthesizer for STM32F401RE/STMstation.
Dependencies: FastPWM mbed-dsp
This is a basic synthesizer to play music on the STM32F401RE Nucleo/STMstation development board:
Please see the API documentation for further details.
Here's a demo of the synthesizer at work in a music composing program on the STMstation. This one is "Miku" by Anamanaguchi.
STMstation_synth.h@0:c5ca205c0a80, 2017-07-03 (annotated)
- Committer:
- kkado
- Date:
- Mon Jul 03 08:16:42 2017 +0000
- Revision:
- 0:c5ca205c0a80
- Child:
- 1:db0c24aebb8a
Last commit before adding documentation
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kkado | 0:c5ca205c0a80 | 1 | #ifndef STMstation_synth_h |
kkado | 0:c5ca205c0a80 | 2 | #define STMstation_synth_h |
kkado | 0:c5ca205c0a80 | 3 | |
kkado | 0:c5ca205c0a80 | 4 | #include "mbed.h" |
kkado | 0:c5ca205c0a80 | 5 | #include "arm_math.h" |
kkado | 0:c5ca205c0a80 | 6 | #include "FastPWM.h" |
kkado | 0:c5ca205c0a80 | 7 | |
kkado | 0:c5ca205c0a80 | 8 | /** Basic synthesizer library for STM32F401RE Nucleo or STMstation P.1 development boards - may work with |
kkado | 0:c5ca205c0a80 | 9 | * other targets, but not tested yet. |
kkado | 0:c5ca205c0a80 | 10 | * |
kkado | 0:c5ca205c0a80 | 11 | * This is a multi-channel synthesizer, with sine, square, triangle, and noise waveform generation. Music is |
kkado | 0:c5ca205c0a80 | 12 | * stored as arrays in flash, but it is possible to use editable arrays in RAM. Standard number of channels is |
kkado | 0:c5ca205c0a80 | 13 | * 5, but additional channels can be added by changing the CHANNELS define. |
kkado | 0:c5ca205c0a80 | 14 | * |
kkado | 0:c5ca205c0a80 | 15 | * Audio signal is output as a PWM signal on PB_0, which MUST be fed into a 1-bit DAC to generate sound! |
kkado | 0:c5ca205c0a80 | 16 | * |
kkado | 0:c5ca205c0a80 | 17 | * Suggested setup: |
kkado | 0:c5ca205c0a80 | 18 | * @code |
kkado | 0:c5ca205c0a80 | 19 | * (PB_0)-----(R1)-----(C2) |
kkado | 0:c5ca205c0a80 | 20 | * | | |
kkado | 0:c5ca205c0a80 | 21 | * (C1) (SPEAKER) |
kkado | 0:c5ca205c0a80 | 22 | * | | |
kkado | 0:c5ca205c0a80 | 23 | * (GND) (GND) |
kkado | 0:c5ca205c0a80 | 24 | * |
kkado | 0:c5ca205c0a80 | 25 | * R1 = 150 Ohms, C1 = 47nF, C2 = 1uF, Speaker = 0.25W, 8 Ohms |
kkado | 0:c5ca205c0a80 | 26 | * @endcode |
kkado | 0:c5ca205c0a80 | 27 | */ |
kkado | 0:c5ca205c0a80 | 28 | |
kkado | 0:c5ca205c0a80 | 29 | #define AUDIO_PIN PB_0 |
kkado | 0:c5ca205c0a80 | 30 | #define CHANNELS 5 |
kkado | 0:c5ca205c0a80 | 31 | |
kkado | 0:c5ca205c0a80 | 32 | //Audio melody struct |
kkado | 0:c5ca205c0a80 | 33 | struct melody{ |
kkado | 0:c5ca205c0a80 | 34 | const uint8_t * notes[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 35 | const uint8_t * durations[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 36 | const uint8_t * AR[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 37 | const uint8_t * vol[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 38 | uint16_t max[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 39 | bool ended[CHANNELS], repeat[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 40 | uint8_t bpm; |
kkado | 0:c5ca205c0a80 | 41 | }; |
kkado | 0:c5ca205c0a80 | 42 | |
kkado | 0:c5ca205c0a80 | 43 | //Audio master struct |
kkado | 0:c5ca205c0a80 | 44 | struct master{ |
kkado | 0:c5ca205c0a80 | 45 | const uint8_t * notes[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 46 | const uint8_t * durations[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 47 | const uint8_t * AR[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 48 | const uint8_t * vol[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 49 | uint16_t index[CHANNELS], max[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 50 | float env[CHANNELS], sineCoef[CHANNELS], vSum, atkSlope[CHANNELS], relSlope[CHANNELS], relOffset[CHANNELS], volCoef[CHANNELS], halfPeriod[CHANNELS], triSlope[CHANNELS], noiseVal[CHANNELS], triVal[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 51 | uint32_t counter[CHANNELS], envAtkEnd[CHANNELS], envRelStart[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 52 | uint8_t val, timbre[CHANNELS], freqIndex[CHANNELS], bpm[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 53 | bool repeat[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 54 | bool* endptr[CHANNELS]; |
kkado | 0:c5ca205c0a80 | 55 | }; |
kkado | 0:c5ca205c0a80 | 56 | |
kkado | 0:c5ca205c0a80 | 57 | class STMstation_synth{ |
kkado | 0:c5ca205c0a80 | 58 | public: |
kkado | 0:c5ca205c0a80 | 59 | STMstation_synth(); |
kkado | 0:c5ca205c0a80 | 60 | |
kkado | 0:c5ca205c0a80 | 61 | void calc_coefs(int i); |
kkado | 0:c5ca205c0a80 | 62 | void calc_vSum2(); |
kkado | 0:c5ca205c0a80 | 63 | void calc_env(); |
kkado | 0:c5ca205c0a80 | 64 | int8_t square(float _halfperiod, uint16_t _counter); |
kkado | 0:c5ca205c0a80 | 65 | void calc_triangle(uint8_t _channel, float _halfperiod, float _trislope, uint32_t _counter); |
kkado | 0:c5ca205c0a80 | 66 | void calc_noise(uint8_t _channel, uint8_t _freq, uint32_t _counter); |
kkado | 0:c5ca205c0a80 | 67 | void calc_val2(); |
kkado | 0:c5ca205c0a80 | 68 | void clear_channel(uint8_t _channel); |
kkado | 0:c5ca205c0a80 | 69 | void stop_track(melody &newMelody); |
kkado | 0:c5ca205c0a80 | 70 | bool check_track(melody &newMelody); |
kkado | 0:c5ca205c0a80 | 71 | void check_end(); |
kkado | 0:c5ca205c0a80 | 72 | void check_start(); |
kkado | 0:c5ca205c0a80 | 73 | void note2(); |
kkado | 0:c5ca205c0a80 | 74 | void play(melody &newMelody, uint8_t refChannel = 0, uint16_t newIndex = 0); |
kkado | 0:c5ca205c0a80 | 75 | |
kkado | 0:c5ca205c0a80 | 76 | const uint16_t FSAMP; |
kkado | 0:c5ca205c0a80 | 77 | const float period; |
kkado | 0:c5ca205c0a80 | 78 | struct master Master; |
kkado | 0:c5ca205c0a80 | 79 | private: |
kkado | 0:c5ca205c0a80 | 80 | Ticker sample; |
kkado | 0:c5ca205c0a80 | 81 | FastPWM tone; |
kkado | 0:c5ca205c0a80 | 82 | }; |
kkado | 0:c5ca205c0a80 | 83 | |
kkado | 0:c5ca205c0a80 | 84 | #endif |