├── .gitignore ├── src ├── CMakeLists.txt ├── audio_output.h ├── synth.h ├── synth.c ├── audio_output.c ├── instrument.h ├── main.c └── instrument.c └── CMakeLists.txt /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 2 | 3 | add_executable(jamtoysynth 4 | main.c 5 | synth.c 6 | instrument.c 7 | audio_output.c 8 | ) 9 | -------------------------------------------------------------------------------- /src/audio_output.h: -------------------------------------------------------------------------------- 1 | #ifndef AUDIO_CALLBACK_H 2 | #define AUDIO_CALLBACK_H 3 | 4 | typedef struct audio_callback_userdata_t 5 | { 6 | SDL_AudioSpec audiospec; 7 | synth_t *synth; 8 | } audio_callback_userdata_t; 9 | 10 | void audio_callback(void *userdata, uint8_t *stream, int len); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(jamtoysynth) 3 | 4 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") 5 | 6 | find_package(SDL) 7 | find_package(OpenGL) 8 | 9 | include_directories(${SDL_INCLUDE_DIR}) 10 | include_directories(${OpenGL_INCLUDE_DIR}) 11 | find_library(GLEW_LIBRARY GLEW) 12 | 13 | link_libraries(${OpenGL_gl_LIBRARY}) 14 | link_libraries(${SDL_LIBRARY}) 15 | link_libraries(${GLEW_LIBRARY}) 16 | 17 | add_subdirectory(src) 18 | -------------------------------------------------------------------------------- /src/synth.h: -------------------------------------------------------------------------------- 1 | #ifndef SYNTH_H 2 | #define SYNTH_H 3 | 4 | #include 5 | 6 | #define SYNTH_MAX_INSTRUMENTS 16 7 | 8 | typedef struct synth_t 9 | { 10 | int sample_rate; 11 | instrument_control_t controls[SYNTH_MAX_INSTRUMENTS]; 12 | instrument_t instruments[SYNTH_MAX_INSTRUMENTS]; 13 | } synth_t; 14 | 15 | int synth_init(synth_t *synth, int sample_rate); 16 | void synth_cleanup(synth_t *synth); 17 | 18 | void synth_control(synth_t *synth); 19 | void synth_mix(synth_t *synth, float *left, float *right); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/synth.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | int synth_init(synth_t *synth, int sample_rate) 7 | { 8 | memset(synth, 0, sizeof(synth_t)); 9 | synth->sample_rate = sample_rate; 10 | 11 | for(instrument_control_t *controls = synth->controls; 12 | controls != synth->controls + SYNTH_MAX_INSTRUMENTS; 13 | ++controls) 14 | { 15 | controls->modulation = MODULATION_VIBRATO; 16 | controls->carrier = OSCILLATOR_SINE; 17 | controls->carrier_amplitude = 0.5; 18 | controls->modulator = OSCILLATOR_SQUARE; 19 | controls->modulator_freq = 2.0; 20 | controls->modulator_amplitude = 0.6; 21 | 22 | controls->attack = 0.1; 23 | controls->decay = 1.0; 24 | controls->sustain = 0.7; 25 | controls->release = 1.5; 26 | 27 | controls->filter = FILTER_LOWPASS; 28 | controls->filter_freq = 500.0; 29 | controls->filter_resonance = 0.5; 30 | controls->filter_gain = 0.5; 31 | 32 | controls->echo_delay = 1.0; 33 | controls->echo_feedback = 0.4; 34 | controls->echo_level = 0.3; 35 | } 36 | 37 | return 0; 38 | } 39 | 40 | void synth_cleanup(synth_t *synth) 41 | { 42 | (void)synth; 43 | } 44 | 45 | void synth_control(synth_t *synth) 46 | { 47 | for(int i = 0; i < SYNTH_MAX_INSTRUMENTS; ++i) 48 | instrument_control(synth->instruments + i, synth->controls + i, synth->sample_rate); 49 | } 50 | 51 | void synth_mix(synth_t *synth, float *left, float *right) 52 | { 53 | *left = 0; *right = 0; 54 | 55 | for(instrument_t *instrument = synth->instruments; 56 | instrument != synth->instruments + SYNTH_MAX_INSTRUMENTS; 57 | ++instrument) 58 | { 59 | float l, r; 60 | instrument_play(instrument, synth->sample_rate, &l, &r); 61 | *left += l; *right += r; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/audio_output.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | static int format_bits(uint16_t format) 9 | { 10 | switch(format) 11 | { 12 | case AUDIO_U8: 13 | case AUDIO_S8: 14 | return 8; 15 | case AUDIO_U16LSB: 16 | case AUDIO_S16LSB: 17 | case AUDIO_U16MSB: 18 | case AUDIO_S16MSB: 19 | return 16; 20 | default: 21 | assert(false && "Unknown audio format"); 22 | } 23 | } 24 | 25 | static bool format_signed(uint16_t format) 26 | { 27 | switch(format) 28 | { 29 | case AUDIO_S16LSB: 30 | case AUDIO_S8: 31 | return true; 32 | case AUDIO_U8: 33 | case AUDIO_U16LSB: 34 | return false; 35 | default: 36 | assert(false && "Unknown audio format"); 37 | } 38 | } 39 | 40 | static bool format_swap_endian(uint16_t format) 41 | { 42 | switch(format) 43 | { 44 | case AUDIO_U8: 45 | case AUDIO_S8: 46 | return false; 47 | case AUDIO_U16LSB: 48 | case AUDIO_S16LSB: 49 | return (AUDIO_U16LSB != AUDIO_U16SYS); 50 | case AUDIO_U16MSB: 51 | case AUDIO_S16MSB: 52 | return (AUDIO_U16MSB != AUDIO_U16SYS); 53 | default: 54 | assert(false && "Unknown audio format"); 55 | } 56 | } 57 | 58 | void audio_callback(void *userdata, uint8_t *stream, int len) 59 | { 60 | audio_callback_userdata_t *params = (audio_callback_userdata_t*)userdata; 61 | 62 | int bits = format_bits(params->audiospec.format); 63 | bool sign = format_signed(params->audiospec.format); 64 | bool swap_endian = format_swap_endian(params->audiospec.format); 65 | assert(!swap_endian); 66 | 67 | float factor = ((uint32_t)1 << (sign ? (bits-1) : bits)) - 1; 68 | float bias = sign ? 0.0 : 1.0; 69 | 70 | int num_samples = len / (bits/8) / params->audiospec.channels; 71 | 72 | synth_control(params->synth); 73 | 74 | for(int i = 0; i < num_samples; ++i) 75 | { 76 | float out_samples[2]; 77 | synth_mix(params->synth, out_samples+0, out_samples+1); 78 | 79 | if(params->audiospec.channels == 1) // downmix to mono 80 | out_samples[0] = (out_samples[0] + out_samples[1]) / 2.0; 81 | 82 | for(int j = 0; j < params->audiospec.channels; ++j) 83 | { 84 | float sample = factor * (out_samples[j] + bias); 85 | int32_t isample = sample; 86 | /*printf("%2.3f\t%10d\n", sample, isample);*/ 87 | 88 | for(int byte = 0; byte < (bits/8); ++byte) 89 | *(stream + params->audiospec.channels * (bits/8) * i + j * (bits/8) + byte) = 90 | *((uint8_t*)&isample + byte); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/instrument.h: -------------------------------------------------------------------------------- 1 | #ifndef INSTRUMENT_H 2 | #define INSTRUMENT_H 3 | 4 | #define ECHO_BUFFER_SIZE 96000 // 2 seconds @ 48 kHz 5 | 6 | typedef enum oscillator_waveform_t 7 | { 8 | OSCILLATOR_ZERO = 0, 9 | OSCILLATOR_SINE, 10 | OSCILLATOR_SQUARE, 11 | OSCILLATOR_SAWTOOTH, 12 | OSCILLATOR_TRIANGLE, 13 | OSCILLATOR_NOISE, 14 | } oscillator_waveform_t; 15 | 16 | typedef struct oscillator_t 17 | { 18 | oscillator_waveform_t waveform; 19 | float freq; 20 | float phase; 21 | float amplitude; 22 | } oscillator_t; 23 | 24 | float oscillator(oscillator_t *osc, int sample_rate, float freq_mod); 25 | 26 | typedef enum modulation_t 27 | { 28 | MODULATION_NONE = 0, 29 | MODULATION_AMPLITUDE, 30 | MODULATION_FREQUENCY, 31 | MODULATION_RING, 32 | MODULATION_TREMOLO, 33 | MODULATION_VIBRATO, 34 | } modulation_t; 35 | 36 | float modulate(modulation_t modulation, int sample_rate, oscillator_t *carrier, oscillator_t *modulator); 37 | 38 | typedef struct adsr_t 39 | { 40 | float attackG, releaseG, decayG; 41 | float sustain, decay; 42 | float adsrG, adsrX; 43 | int decay_timer; 44 | float envelope; 45 | } adsr_t; 46 | 47 | void adsr_set(adsr_t *adsr, int sample_rate, float attack, float decay, float sustain, float release); 48 | void adsr_trigger(adsr_t *adsr); 49 | float adsr_envelope(adsr_t *adsr); 50 | 51 | typedef struct filter_state_t 52 | { 53 | float x1, x2, y1, y2; 54 | } filter_state_t; 55 | 56 | typedef struct filter_t 57 | { 58 | float b0, b1, b2, a0, a1, a2; 59 | } filter_t; 60 | 61 | typedef enum filter_type_t 62 | { 63 | FILTER_NONE = 0, 64 | FILTER_LOWPASS, 65 | FILTER_HIGHPASS, 66 | FILTER_BANDPASS, 67 | FILTER_NOTCH, 68 | FILTER_PEAKING_EQ, 69 | FILTER_LOW_SHELF, 70 | FILTER_HIGH_SHELF 71 | } filter_type_t; 72 | 73 | void filter_set(filter_t *filter, int sample_rate, filter_type_t type, float f0, float Q, float dBgain); 74 | float filter(const filter_t *filter, filter_state_t *state, float sample); 75 | 76 | typedef struct echo_t 77 | { 78 | float buffer[ECHO_BUFFER_SIZE]; 79 | int cursor; 80 | int delay_samples; 81 | float feedback, level; 82 | } echo_t; 83 | 84 | float echo(echo_t *echo, float sample); 85 | 86 | typedef struct instrument_control_t 87 | { 88 | modulation_t modulation; 89 | oscillator_waveform_t carrier; 90 | float carrier_amplitude; 91 | oscillator_waveform_t modulator; 92 | float modulator_amplitude, modulator_freq; 93 | 94 | float attack, decay, sustain, release; 95 | 96 | filter_type_t filter; 97 | float filter_freq, filter_resonance, filter_gain; 98 | 99 | float echo_delay, echo_feedback, echo_level; 100 | } instrument_control_t; 101 | 102 | typedef struct instrument_t 103 | { 104 | modulation_t modulation; 105 | oscillator_t carrier, modulator; 106 | adsr_t adsr; 107 | 108 | filter_t filter; 109 | filter_state_t filter0, filter1; 110 | 111 | echo_t echo; 112 | } instrument_t; 113 | 114 | void instrument_control(instrument_t *instrument, const instrument_control_t *control, int sample_rate); 115 | void instrument_play(instrument_t *instrument, int sample_rate, float *left, float *right); 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | static float note_freq(int i) 13 | { 14 | const float A = 440.0; 15 | return (A / 32.0) * pow(2.0, (i - 9) / 12.0); 16 | } 17 | 18 | static int main_loop(synth_t *synth) 19 | { 20 | const SDLKey keyboard[] = { 21 | // c c# d d# e f f# g g# a a# b c d e 22 | SDLK_z, SDLK_s, SDLK_x, SDLK_d, SDLK_c, SDLK_v, SDLK_g, SDLK_b, SDLK_h, SDLK_n, SDLK_j, SDLK_m, SDLK_COMMA, SDLK_l, SDLK_PERIOD, 23 | SDLK_q, SDLK_2, SDLK_w, SDLK_3, SDLK_e, SDLK_r, SDLK_5, SDLK_t, SDLK_6, SDLK_y, SDLK_7, SDLK_u, SDLK_i, SDLK_9, SDLK_o, SDLK_0, SDLK_p 24 | }; 25 | int notes[] = { 26 | // c c# d d# e f f# g g# a a# b c d e 27 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 28 | 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 | }; 30 | 31 | int num_keys = sizeof(keyboard)/sizeof(*keyboard); 32 | int base_octave = 4; 33 | 34 | bool quit = false; 35 | while(!quit) 36 | { 37 | const float background[] = { 0.2, 0.4, 0.7, 1.0 }; 38 | glClearBufferfv(GL_COLOR, 0, background); 39 | 40 | SDL_GL_SwapBuffers(); 41 | 42 | SDL_Event event; 43 | while(SDL_PollEvent(&event)) 44 | { 45 | if(event.type == SDL_KEYDOWN && 46 | event.key.keysym.sym == SDLK_ESCAPE) 47 | quit = true; 48 | else if(event.type == SDL_KEYDOWN && event.key.keysym.sym >= SDLK_F1 && event.key.keysym.sym <= SDLK_F12) 49 | base_octave = event.key.keysym.sym - SDLK_F1; 50 | else if(event.type == SDL_KEYDOWN) 51 | { 52 | for(int i = 0; i < num_keys; ++i) 53 | { 54 | if(keyboard[i] != event.key.keysym.sym) continue; 55 | 56 | SDL_LockAudio(); 57 | synth->instruments->carrier.freq = note_freq(base_octave * 12 + notes[i]); 58 | adsr_trigger(&synth->instruments[0].adsr); 59 | SDL_UnlockAudio(); 60 | } 61 | } 62 | } 63 | } 64 | 65 | return 0; 66 | } 67 | 68 | int main(int argc, char *argv[]) 69 | { 70 | (void)argc; 71 | (void)argv; 72 | 73 | if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) 74 | return -1; 75 | atexit(SDL_Quit); 76 | 77 | SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); 78 | SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); 79 | SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); 80 | SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); 81 | SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); 82 | SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0); 83 | SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); 84 | SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); 85 | SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); 86 | 87 | SDL_Surface *screen = SDL_SetVideoMode(800, 600, 32, SDL_OPENGL); 88 | if(!screen) 89 | return -1; 90 | 91 | if(glewInit() != GLEW_OK) 92 | return -1; 93 | 94 | audio_callback_userdata_t audio_callback_userdata; 95 | 96 | SDL_AudioSpec desired_audio_spec, obtained_audio_spec; 97 | desired_audio_spec.freq = 44100; 98 | desired_audio_spec.format = AUDIO_U16SYS; 99 | desired_audio_spec.channels = 1; 100 | desired_audio_spec.samples = 1024; 101 | desired_audio_spec.callback = audio_callback; 102 | desired_audio_spec.userdata = &audio_callback_userdata; 103 | 104 | if(SDL_OpenAudio(&desired_audio_spec, &obtained_audio_spec) != 0) 105 | return -1; 106 | atexit(SDL_CloseAudio); 107 | 108 | synth_t synth; 109 | synth_init(&synth, obtained_audio_spec.freq); 110 | 111 | audio_callback_userdata.synth = &synth; 112 | audio_callback_userdata.audiospec = obtained_audio_spec; 113 | 114 | SDL_PauseAudio(0); 115 | 116 | int err = main_loop(&synth); 117 | 118 | SDL_PauseAudio(1); 119 | 120 | synth_cleanup(&synth); 121 | 122 | SDL_CloseAudio(); 123 | SDL_Quit(); 124 | 125 | return err; 126 | } 127 | 128 | -------------------------------------------------------------------------------- /src/instrument.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | static float zero(float phase) { (void)phase; return 0; } 7 | static float sine(float phase) { return sinf(phase); } 8 | static float square(float phase) { return phase <= M_PI ? 1.0 : -1.0; } 9 | static float sawtooth(float phase) { return -1.0 + 2.0 * fmod(phase / M_PI, 1.0); } 10 | static float noise(float phase) { (void)phase; return rand() / (float)RAND_MAX; } 11 | static float triangle(float phase) 12 | { 13 | if(phase < M_PI/2.0) return phase / (M_PI/2.0); 14 | if(phase <= 3.0*M_PI/2.0) return 1.0 - 2.0 * (phase-M_PI/2.0)/M_PI; 15 | return -1.0 + (phase - 3.0*M_PI/2.0) / (M_PI/2.0); 16 | } 17 | 18 | float oscillator(oscillator_t *osc, int sample_rate, float freq_mod) 19 | { 20 | typedef float (*wave_fun)(float); 21 | wave_fun waves[] = { zero, sine, square, sawtooth, triangle, noise }; 22 | float sample = osc->amplitude * waves[osc->waveform](osc->phase); 23 | osc->phase = fmod(osc->phase + freq_mod * osc->freq * 2.0 * M_PI / sample_rate, 2.0 * M_PI); 24 | return sample; 25 | } 26 | 27 | float modulate(modulation_t modulation, int sample_rate, oscillator_t *carrier, oscillator_t *modulator) 28 | { 29 | switch(modulation) 30 | { 31 | case MODULATION_NONE: 32 | oscillator(modulator, sample_rate, 1.0); // update phase, ignore result 33 | return oscillator(carrier, sample_rate, 1.0); 34 | case MODULATION_RING: 35 | return oscillator(carrier, sample_rate, 1.0) * oscillator(modulator, sample_rate, 1.0); 36 | case MODULATION_AMPLITUDE: 37 | return oscillator(carrier, sample_rate, 1.0) * (1.0 + oscillator(modulator, sample_rate, carrier->freq)); 38 | case MODULATION_FREQUENCY: 39 | return oscillator(carrier, sample_rate, 1.0 + oscillator(modulator, sample_rate, carrier->freq)); 40 | case MODULATION_TREMOLO: 41 | return oscillator(carrier, sample_rate, 1.0) * (1.0 + oscillator(modulator, sample_rate, 1.0)); 42 | case MODULATION_VIBRATO: 43 | return oscillator(carrier, sample_rate, 1.0 + oscillator(modulator, sample_rate, 1.0)); 44 | default: 45 | break; 46 | } 47 | 48 | return 0; 49 | } 50 | 51 | void adsr_set(adsr_t *adsr, int sample_rate, float attack, float decay, float sustain, float release) 52 | { 53 | adsr->attackG = expf(-1.0 / (attack * sample_rate)); 54 | adsr->decayG = expf(-1.0 / (decay * sample_rate)); 55 | adsr->releaseG = expf(-1.0 / (release * sample_rate)); 56 | adsr->sustain = sustain; 57 | adsr->decay = decay * sample_rate; 58 | } 59 | 60 | void adsr_trigger(adsr_t *adsr) 61 | { 62 | adsr->adsrG = adsr->attackG; 63 | adsr->adsrX = 1.5; // TODO: play with this magic constant (velocity?) 64 | adsr->decay_timer = 0; 65 | } 66 | 67 | float adsr_envelope(adsr_t *adsr) 68 | { 69 | adsr->envelope = adsr->adsrG * (adsr->envelope - adsr->adsrX) + adsr->adsrX; 70 | 71 | if(adsr->envelope >= 1.0) 72 | { 73 | adsr->adsrG = adsr->decayG; 74 | adsr->adsrX = adsr->sustain; 75 | adsr->decay_timer = adsr->decay; 76 | adsr->envelope = 1.0; 77 | } 78 | 79 | adsr->decay_timer -= 1; 80 | 81 | if(adsr->decay_timer == 0) 82 | { 83 | adsr->adsrG = adsr->releaseG; 84 | adsr->adsrX = 0.0; 85 | } 86 | 87 | return adsr->envelope; 88 | } 89 | 90 | void filter_set(filter_t *filter, int sample_rate, filter_type_t type, float f0, float Q, float dBgain) 91 | { 92 | double cosw0 = cos(2*M_PI*f0/sample_rate); 93 | double sinw0 = sqrt(1.0 - cosw0 * cosw0); //sin(2*M_PI*f0/SAMPLE_RATE); 94 | double alpha = sinw0 / (2*Q); 95 | double A = pow(10.0, dBgain/40); 96 | double A2 = 2*sqrt(A); 97 | double a0, a1, a2, b0, b1, b2; 98 | 99 | switch (type) 100 | { 101 | case FILTER_LOWPASS: 102 | b0 = (1 - cosw0)/2; 103 | b1 = 1 - cosw0; 104 | b2 = (1 - cosw0)/2; 105 | a0 = 1 + alpha; 106 | a1 = -2.0 * cosw0; 107 | a2 = 1 - alpha; 108 | break; 109 | case FILTER_HIGHPASS: 110 | b0 = (1 + cosw0)/2; 111 | b1 = -(1 + cosw0); 112 | b2 = (1 + cosw0)/2; 113 | a0 = 1 + alpha; 114 | a1 = -2 * cosw0; 115 | a2 = 1 - alpha; 116 | break; 117 | case FILTER_BANDPASS: 118 | b0 = alpha; 119 | b1 = 0; 120 | b2 = -alpha; 121 | a0 = 1 + alpha; 122 | a1 = -2 * cosw0; 123 | a2 = 1 - alpha; 124 | break; 125 | case FILTER_NOTCH: 126 | b0 = 1; 127 | b1 = -2*cosw0; 128 | b2 = 1; 129 | a0 = 1 + alpha; 130 | a1 = -2*cosw0; 131 | a2 = 1-alpha; 132 | break; 133 | case FILTER_PEAKING_EQ: 134 | b0 = 1 + alpha*A; 135 | b1 = -2*cosw0; 136 | b2 = 1 - alpha*A; 137 | a0 = 1 + alpha/A; 138 | a1 = -2*cosw0; 139 | a2 = 1 - alpha/A; 140 | break; 141 | case FILTER_LOW_SHELF: 142 | b0 = A*((A+1) - (A-1)*cosw0 + A2 * alpha); 143 | b1 = 2*A*((A-1) - (A+1) * cosw0); 144 | b2 = A*((A+1) - (A-1) * cosw0 - A2 * alpha); 145 | a0 = (A+1) + (A-1) * cosw0 + A2 * alpha; 146 | a1 = -2*((A-1) + (A+1) * cosw0); 147 | a2 = (A+1) + (A-1) * cosw0 - A2 * alpha; 148 | break; 149 | case FILTER_HIGH_SHELF: 150 | b0 = A*((A+1) + (A-1) * cosw0 + A2 * alpha); 151 | b1 = -2*A*((A-1) + (A+1) * cosw0); 152 | b2 = A*((A+1) + (A-1) * cosw0 - A2 * alpha); 153 | a0 = (A+1) - (A-1) * cosw0 + A2 * alpha; 154 | a1 = 2*((A-1) - (A+1) * cosw0); 155 | a2 = (A+1) - (A-1) * cosw0 - A2 * alpha; 156 | break; 157 | case FILTER_NONE: 158 | default: 159 | b0 = a0 = 1.0; 160 | b1 = b2 = 0.0; 161 | a1 = a2 = 0.0; 162 | break; 163 | } 164 | 165 | filter->a0 = a0 * 64.0; 166 | filter->a1 = -a1 * 64.0; 167 | filter->a2 = -a2 * 64.0; 168 | filter->b0 = b0 * 64.0; 169 | filter->b1 = b1 * 64.0; 170 | filter->b2 = b2 * 64.0; 171 | } 172 | 173 | float filter(const filter_t *filter, filter_state_t *state, float sample) 174 | { 175 | float out = ( 176 | filter->b0 * sample + 177 | filter->b1 * state->x1 + 178 | filter->b2 * state->x2 + 179 | filter->a1 * state->y1 + 180 | filter->a2 * state->y2) / 181 | filter->a0; 182 | 183 | state->x2 = state->x1; 184 | state->x1 = sample; 185 | state->y2 = state->y1; 186 | state->y1 = out; 187 | 188 | return out; 189 | } 190 | 191 | float echo(echo_t *echo, float sample) 192 | { 193 | int read_cursor = 194 | echo->cursor >= echo->delay_samples ? 195 | echo->cursor - echo->delay_samples : 196 | ECHO_BUFFER_SIZE - (echo->delay_samples - echo->cursor) % ECHO_BUFFER_SIZE; 197 | 198 | float delay_sample = echo->buffer[read_cursor]; 199 | echo->buffer[echo->cursor] = sample + echo->feedback * delay_sample; 200 | echo->cursor = (echo->cursor + 1) % ECHO_BUFFER_SIZE; 201 | 202 | return sample + echo->level * delay_sample; 203 | } 204 | 205 | void instrument_control(instrument_t *instrument, const instrument_control_t *control, int sample_rate) 206 | { 207 | instrument->modulation = control->modulation; 208 | 209 | instrument->carrier.waveform = control->carrier; 210 | instrument->carrier.amplitude = control->carrier_amplitude; 211 | 212 | instrument->modulator.waveform = control->modulator; 213 | instrument->modulator.amplitude = control->modulator_amplitude; 214 | instrument->modulator.freq = control->modulator_freq; 215 | 216 | adsr_set(&instrument->adsr, 217 | sample_rate, 218 | control->attack, 219 | control->decay, 220 | control->sustain, 221 | control->release); 222 | 223 | filter_set(&instrument->filter, 224 | sample_rate, 225 | control->filter, 226 | control->filter_freq, 227 | control->filter_resonance, 228 | control->filter_gain); 229 | 230 | instrument->echo.delay_samples = control->echo_delay * sample_rate; 231 | instrument->echo.feedback = control->echo_feedback; 232 | instrument->echo.level = control->echo_level; 233 | } 234 | 235 | void instrument_play(instrument_t *instrument, int sample_rate, float *left, float *right) 236 | { 237 | float sample = 238 | echo(&instrument->echo, 239 | filter(&instrument->filter, &instrument->filter1, 240 | filter(&instrument->filter, &instrument->filter0, 241 | adsr_envelope(&instrument->adsr) * 242 | modulate(instrument->modulation, sample_rate, &instrument->carrier, &instrument->modulator)))); 243 | 244 | *left = sample; 245 | *right = sample; 246 | } 247 | --------------------------------------------------------------------------------