Teensy Wavetable Synthesis
AudioSynthWavetable.h
1 /* Audio Library for Teensy 3.X
2  * Copyright (c) 2017, TeensyAudio PSU Team
3  *
4  * Development of this audio library was sponsored by PJRC.COM, LLC.
5  * Please support PJRC's efforts to develop open source
6  * software by purchasing Teensy or other PJRC products.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice, development funding notice, and this permission
16  * notice shall be included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26 
27 #pragma once
28 
29 #include "Arduino.h"
30 #include "AudioStream.h"
31 #include <math.h>
32 #include <sample_data.h>
33 #include <stdint.h>
34 
35 #define UNITY_GAIN INT32_MAX // Max amplitude / no attenuation
36 #define DEFAULT_AMPLITUDE 90
37 #define SAMPLES_PER_MSEC (AUDIO_SAMPLE_RATE_EXACT/1000.0)
38 #define TRIANGLE_INITIAL_PHASE (-0x40000000)
39 #define LFO_SMOOTHNESS 3
40 #define LFO_PERIOD (AUDIO_BLOCK_SAMPLES/(1 << (LFO_SMOOTHNESS-1)))
41 
42 #define ENVELOPE_PERIOD 8
43 
44 enum envelopeStateEnum { STATE_IDLE, STATE_DELAY, STATE_ATTACK, STATE_HOLD, STATE_DECAY, STATE_SUSTAIN, STATE_RELEASE };
45 
46 class AudioSynthWavetable : public AudioStream
47 {
48 public:
52  AudioSynthWavetable(void) : AudioStream(0, NULL) {}
53 
62  void setInstrument(const instrument_data& instrument) {
63  cli();
64  this->instrument = &instrument;
65  current_sample = NULL;
66  env_state = STATE_IDLE;
67  state_change = true;
68  sei();
69  }
70 
80  void amplitude(float v) {
81  v = (v < 0.0) ? 0.0 : (v > 1.0) ? 1.0 : v;
82  tone_amp = (uint16_t)(UINT16_MAX*v);
83  }
84 
92  static float midi_volume_transform(int midi_amp) {
93  // scale midi_amp which is 0 t0 127 to be between
94  // 0 and 1 using a logarithmic transformation
95  return powf(midi_amp / 127.0, 4);
96  }
97 
105  static float noteToFreq(int note) {
106  float exp = note * (1.0 / 12.0) + 3.0313597;
107  return powf(2.0, exp);
108  }
109 
117  static int freqToNote(float freq) {
118  return 12*log2f(freq) - 35.8763164;
119  }
120 
121  // Defined in AudioSynthWavetable.cpp
122  void stop(void);
123  void playFrequency(float freq, int amp = DEFAULT_AMPLITUDE);
124  void playNote(int note, int amp = DEFAULT_AMPLITUDE);
125  bool isPlaying(void) { return env_state != STATE_IDLE; }
126  void setFrequency(float freq);
127  virtual void update(void);
128 
129  envelopeStateEnum getEnvState(void) { return env_state; }
130 
131 private:
132  void setState(int note, int amp, float freq);
133  volatile bool state_change = false;
134 
135  volatile const instrument_data* instrument = NULL;
136  volatile const sample_data* current_sample = NULL;
137 
138  //sample output state
139  volatile uint32_t tone_phase = 0;
140  volatile uint32_t tone_incr = 0;
141  volatile uint16_t tone_amp = 0;
142 
143  //volume environment state
144  volatile envelopeStateEnum env_state = STATE_IDLE;
145  volatile int32_t env_count = 0;
146  volatile int32_t env_mult = 0;
147  volatile int32_t env_incr = 0;
148 
149  //vibrato LFO state
150  volatile uint32_t vib_count = 0;
151  volatile uint32_t vib_phase = 0;
152  volatile int32_t vib_pitch_offset_init = 0;
153  volatile int32_t vib_pitch_offset_scnd = 0;
154 
155  //modulation LFO state
156  volatile uint32_t mod_count = 0;
157  volatile uint32_t mod_phase = TRIANGLE_INITIAL_PHASE;
158  volatile int32_t mod_pitch_offset_init = 0;
159  volatile int32_t mod_pitch_offset_scnd = 0;
160 };
161 
Definition: AudioSynthWavetable.h:46
static float midi_volume_transform(int midi_amp)
Scale midi_amp to a value between 0.0 and 1.0 using a logarithmic tranformation.
Definition: AudioSynthWavetable.h:92
virtual void update(void)
Called by the AudioStream library to fill the audio output buffer.
Definition: AudioSynthWavetable.cpp:163
void playNote(int note, int amp=DEFAULT_AMPLITUDE)
Play sample at specified note, amplitude.
Definition: AudioSynthWavetable.cpp:103
AudioSynthWavetable(void)
Class constructor.
Definition: AudioSynthWavetable.h:52
void stop(void)
Stop playing waveform.
Definition: AudioSynthWavetable.cpp:77
void playFrequency(float freq, int amp=DEFAULT_AMPLITUDE)
Play waveform at defined frequency, amplitude.
Definition: AudioSynthWavetable.cpp:93
static float noteToFreq(int note)
Convert a MIDI note value to its corresponding frequency.
Definition: AudioSynthWavetable.h:105
static int freqToNote(float freq)
Convert a frequency to the corressponding MIDI note value.
Definition: AudioSynthWavetable.h:117
void amplitude(float v)
Changes the amplitude to &#39;v&#39;.
Definition: AudioSynthWavetable.h:80
void setInstrument(const instrument_data &instrument)
Set the instrument_data struct to be used as the playback instrument.
Definition: AudioSynthWavetable.h:62
void setFrequency(float freq)
Set various integer offsets to values that will produce intended frequencies.
Definition: AudioSynthWavetable.cpp:148