Simple synthesizer for STM32F401RE/STMstation.

Dependencies:   FastPWM mbed-dsp

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers STMstation_synth.h Source File

STMstation_synth.h

00001 #ifndef STMstation_synth_h
00002 #define STMstation_synth_h
00003 
00004 #include "mbed.h"
00005 #include "arm_math.h"
00006 #include "FastPWM.h"
00007 
00008 #define AUDIO_PIN   PB_0
00009 #define CHANNELS    5
00010 
00011 /** Stores data for a song or sound effect
00012  *  @param notes     Note frequency and timbre
00013  *  @param durations Duration (from 1/64th to 4 counts)
00014  *  @param AR        Attack/Release (bits 7:4 - attack, 3:0 - release)
00015  *  @param vol       Volume (0 - muted, 127 - 1x volume, 255 - 2x volume
00016  *  @param max       Max index of each channel
00017  *  @param ended     Has the channel completed playing?
00018  *  @param repeat    Should the channel repeat or stop?
00019  *  @param bpm       Tempo, in 1/4th counts per minute
00020  */
00021 struct melody{
00022     const uint8_t * notes[CHANNELS];
00023     const uint8_t * durations[CHANNELS]; 
00024     const uint8_t * AR[CHANNELS]; 
00025     const uint8_t * vol[CHANNELS];
00026     uint16_t max[CHANNELS];
00027     bool ended[CHANNELS], repeat[CHANNELS];
00028     uint8_t bpm;
00029 };
00030 
00031 /** Stores data that is currently being played. So many members! A lot of these are just coefficients for waveform synthesis.
00032  *  @param notes        (LOADED FROM MELODY) Note frequency and timbre
00033  *  @param durations    (LOADED FROM MELODY) Duration (from 1/64th to 4 counts)
00034  *  @param AR           (LOADED FROM MELODY) Attack/Release (bits 7:4 - attack, 3:0 - release)
00035  *  @param vol          (LOADED FROM MELODY) Volume (0 - muted, 127 - 1x volume, 255 - 2x volume
00036  *  @param index        Note currently being played
00037  *  @param max          (LOADED FROM MELODY) Max index of each channel
00038  *  @param env          (FOR SYNTHEESIS) Envelope value (between 0~1)
00039  *  @param sineCoef     (FOR SYNTHEESIS) Coefficient for sine wave synthesis
00040  *  @param vSum         (FOR SYNTHEESIS) Divider to prevent clipping
00041  *  @param atkSlope     (FOR SYNTHEESIS) Attack slope for envelope
00042  *  @param relSlope     (FOR SYNTHEESIS) Release slope for envelope
00043  *  @param relOffset    (FOR SYNTHEESIS) Release offset for envelope
00044  *  @param volCoef      (FOR SYNTHEESIS) Volume coefficient to control volume, prevent clipping
00045  *  @param halfPeriod   (FOR SYNTHEESIS) Half period for square, triangle functions
00046  *  @param triSlope     (FOR SYNTHEESIS) Triangle wave slope
00047  *  @param noiseVal     (FOR SYNTHEESIS) Value returned from random noise generation
00048  *  @param triVal       (FOR SYNTHEESIS) Value returned from triangle wave calculation
00049  *  @param counter      Current sample value
00050  *  @param envAtkEnd    (FOR SYNTHEESIS) Counter value at which attack ramp ends
00051  *  @param envRelStart  (FOR SYNTHEESIS) Counter value at which release ramp starts
00052  *  @param val          8-bit sample value
00053  *  @timbre             (FOR SYNTHEESIS) What kind of waveform is playing? 0 - sine, 1 - sq, 2 - tri, 3 - noise
00054  *  @freqIndex          (FOR SYNTHEESIS) What frequency is playing? 0 - rest, 1~freqLength frequencies in ascending order
00055  *  @param bpm          (LOADED FROM MELODY) Tempo, in 1/4th counts per minute
00056  *  @param repeat       (LOADED FROM MELODY) Channel repeat
00057  *  @param endptr       (LOADED FROM MELODY) Points to melody end value
00058  */
00059 struct master{
00060     const uint8_t * notes[CHANNELS];
00061     const uint8_t * durations[CHANNELS]; 
00062     const uint8_t * AR[CHANNELS]; 
00063     const uint8_t * vol[CHANNELS];
00064     uint16_t index[CHANNELS], max[CHANNELS];
00065     float env[CHANNELS], sineCoef[CHANNELS], vSum, atkSlope[CHANNELS], relSlope[CHANNELS], relOffset[CHANNELS], volCoef[CHANNELS], halfPeriod[CHANNELS], triSlope[CHANNELS], noiseVal[CHANNELS], triVal[CHANNELS];
00066     uint32_t counter[CHANNELS], envAtkEnd[CHANNELS], envRelStart[CHANNELS];
00067     uint8_t val, timbre[CHANNELS], freqIndex[CHANNELS], bpm[CHANNELS];
00068     bool repeat[CHANNELS];
00069     bool* endptr[CHANNELS];
00070 };
00071 
00072 /** Basic synthesizer library for STM32F401RE Nucleo or STMstation P.1 development boards - may work with
00073  *  other targets, but not tested yet.
00074  *
00075  *  This is a multi-channel synthesizer, with sine, square, triangle, and noise waveform generation. Music is 
00076  *  stored as arrays in flash, but it is possible to use editable arrays in RAM. Standard number of channels is
00077  *  5, but additional channels can be added by changing the CHANNELS define.
00078  *  
00079  *  Audio signal is output as a PWM signal on PB_0, which MUST be fed into a 1-bit DAC to generate sound!
00080  *
00081  *  Suggested setup:
00082  *  @code
00083  *      (PB_0)-----(R1)-----(C2) 
00084  *                  |        |
00085  *                 (C1)  (SPEAKER)
00086  *                  |        |
00087  *                 (GND)    (GND)
00088  *      
00089  *      R1 = 150 Ohms, C1 = 47nF, C2 = 1uF, Speaker = 0.25W, 8 Ohms
00090  *  @endcode 
00091  */
00092 class STMstation_synth{
00093     public:
00094         /** Create an instance of STMstation_synth 
00095          *  @param audio_pin PWM output
00096          */
00097         STMstation_synth(PinName audio_pin);
00098         /** Create an instance of STMstation_synth
00099          *  Use default output for STMstation P.1, PB_0 
00100          */
00101         STMstation_synth();
00102         /** Play a track
00103          *  @param newMelody    Melody to play
00104          *  @param refChannel   If starting from nonzero index, specify reference channel
00105          *  @param newIndex     Start index
00106          */
00107         void play(melody &newMelody, uint8_t refChannel = 0, uint16_t newIndex = 0);
00108         /** Clear all data from a selected channel
00109          *  @param channel      Channel to clear
00110          */
00111         void clear_channel(uint8_t _channel);
00112         /** Stop playing a track
00113          *  @param newMelody    Melody to stop
00114          */
00115         void stop_track(melody &newMelody);
00116         /** Check if a track is still playing
00117          *  @param newMelody    Melody to check
00118          */
00119         bool check_track(melody &newMelody);
00120                 
00121         struct master Master;
00122     private:
00123         void begin();
00124         void calc_coefs(int i);
00125         void calc_vSum();
00126         void calc_env();
00127         int8_t square(float _halfperiod, uint16_t _counter);
00128         void calc_triangle(uint8_t _channel, float _halfperiod, float _trislope, uint32_t _counter);
00129         void calc_noise(uint8_t _channel, uint8_t _freq, uint32_t _counter);
00130         void calc_val();
00131         void check_end();
00132         void check_start();
00133         void note();
00134         
00135         Ticker sample;
00136         FastPWM tone;
00137 };
00138 
00139 #endif