diff options
Diffstat (limited to 'src/synth_engine.c')
-rw-r--r-- | src/synth_engine.c | 545 |
1 files changed, 0 insertions, 545 deletions
diff --git a/src/synth_engine.c b/src/synth_engine.c deleted file mode 100644 index 34f876a..0000000 --- a/src/synth_engine.c +++ /dev/null @@ -1,545 +0,0 @@ -#include "synth_engine.h" -#include "synth_math.h" -#include "lowpass.h" -#include "filter.h" -#include "control.h" -#include "sound.h" -#include "osc.h" - -#include <string.h> - -float -sin_sample(float amp, float freq, unsigned long long phase, unsigned int sample_rate) -{ - return amp * sinf(2.0 * M_PI * freq * ((float)phase / (float)sample_rate)); -} - -float -saw_sample(float amp, float freq, unsigned long long phase, unsigned int sample_rate) -{ - return amp * (0.17 * (1.0 - (2.0 * M_PI * freq * fmod((float)phase, (float)(sample_rate / (freq)))) / (float)sample_rate)); -} - -float -sawX_sample(float amp, float freq, float sm, unsigned long long phase, unsigned int sample_rate) -{ - float dOutput = 0.0; - for (float n = 1.0; n < sm; n++) - dOutput += (sinf(n * 2.0 * M_PI * freq * ((float)phase / (float)sample_rate))) / n; - return 0.5 * amp * dOutput; -} - -float -sqr_sample(float amp, float freq, float duty_cycle, unsigned long long phase, unsigned int sample_rate) -{ - if (duty_cycle < 0.0001 || duty_cycle > 0.9999) { - duty_cycle = 0.5; - } - - return (fmod((float)phase / (float)sample_rate, 1.0 / freq) < duty_cycle * (1.0 / freq)) ? amp : -amp; -} - -float -gen10(float f, unsigned long long phase, float x, unsigned int sample_rate) -{ - return fmodf(phase, sample_rate/f) / (sample_rate/f); -} - -float -gen110(float f, unsigned long long phase, float x, unsigned int sample_rate) -{ - float a = fmodf(phase, sample_rate/f); - return a > (sample_rate/f) / 2.0f ? 0.9999f : -0.9999f; -} - -float -gen0(float f, midi_note_t * midi_note, float x, unsigned int sample_rate) -{ - float sample = osc_sin(midi_note->wvt_index); - midi_note->wvt_index = osc_sin_next(f, midi_note->wvt_index); - return sample; -} - -float -gen1(float f, midi_note_t * midi_note, float x, unsigned int sample_rate) -{ - float sample = osc_saw(midi_note->wvt_index); - midi_note->wvt_index = osc_saw_next(f, midi_note->wvt_index); - return sample; -} - -float -gen2(float f, midi_note_t * midi_note, float x, unsigned int sample_rate) -{ - float sample = osc_weird(midi_note->wvt_index); - midi_note->wvt_index = osc_weird_next(f, midi_note->wvt_index); - return sample; -} - -float -gen3(float f, midi_note_t * midi_note, float x, unsigned int sample_rate) -{ - float sample = osc_tri(midi_note->wvt_index); - midi_note->wvt_index = osc_tri_next(f, midi_note->wvt_index); - return sample; -} - -float -gen4(float f, midi_note_t * midi_note, float x, unsigned int sample_rate) -{ - float sample = osc_sound(midi_note->wvt_index); - midi_note->wvt_index = osc_sound_next(f, midi_note->wvt_index); - return sample; -} - -float -gen5(float f, midi_note_t * midi_note, float x, unsigned int sample_rate) -{ - float sample = osc_digisaw(midi_note->wvt_index); - midi_note->wvt_index = osc_digisaw_next(f, midi_note->wvt_index); - return sample; -} - -float -gen6(float f, midi_note_t * midi_note, float x, unsigned int sample_rate) -{ - float sample = osc_sqr(midi_note->wvt_index); - midi_note->wvt_index = osc_sqr_next(f, midi_note->wvt_index); - return sample; -} - -float -lfo(float f, unsigned long long phase, unsigned int sample_rate) { - return sin_sample(1, f, phase, sample_rate); -} - -int -notes_active(synth_t *synth) -{ - int flag = 0; - - for (int i = 0; i < MIDI_NOTES; i++) { - if (!synth->midi_note[i].active) - continue; - - if (!fix_adsr(&synth->adsr, - (float)synth->midi_note[i].noteOn, - (float)synth->midi_note[i].noteOff, - synth->midi_note[i].elapsed, - synth->midi_note[i].noteOffSample) - && synth->midi_note[i].noteOff != 0) { - synth->midi_note[i].freq = 0; - synth->midi_note[i].channel = -1; - synth->midi_note[i].noteOn = -1; - synth->midi_note[i].noteOff = -1; - synth->midi_note[i].wvt_index = 0; - synth->midi_note[i].lfo_index = 0; - synth->midi_note[i].velocity = -1; - synth->midi_note[i].elapsed = -1; - synth->midi_note[i].noteOffSample = 0; - synth->midi_note[i].active = 0; - } else { - flag++; - } - } - - return flag; -} - -float lfo_index; - -float -make_sample(void *synthData, unsigned int sample_rate, int frame) -{ - synth_t *synth = (synth_t*)synthData; - float sample = 0.0f; - - float n = notes_active(synth); - if (n == 0) return sample; - - float rms = 0; - for (int i = 0; i < MIDI_NOTES; i++) { - if (!synth->midi_note[i].active) - continue; - - rms += synth->midi_note[i].velocity * synth->midi_note[i].velocity; - } - - // if rms == 0 we can deduce there are no notes however notes_active handles - // stopping any already playing notes and if we remove it we need to make - // sure that notes stop some other way (it also happens every frame) - rms = sqrt(rms / (float)n); - // printf("rms %f\n", rms); - - for (int i = 0; i < MIDI_NOTES; i++) { - if (!synth->midi_note[i].active) - continue; - - float adsr = fix_adsr(&synth->adsr, - synth->midi_note[i].noteOn, - synth->midi_note[i].noteOff, - synth->midi_note[i].elapsed, - synth->midi_note[i].noteOffSample); - - float targ_freq = synth->midi_note[i].freq * cc_iget(&synth->cc_pitch, frame, FRAMES_PER_BUFFER); - targ_freq = targ_freq + targ_freq * - cc_iget(&synth->cc_lfo_amp, frame, FRAMES_PER_BUFFER) * - // (1.05946309436/24.0) * - osc_sin(synth->midi_note[i].lfo_index); - //(wvt_next(wvt_tri, (wvt_next(wvt_sound, 2 * cc_iget(&synth->cc_lfo_freq, frame, FRAMES_PER_BUFFER), SAMPLE_RATE, &lfo_index) / 2.0 + 0.5) * cc_iget(&synth->cc_lfo_freq, frame, FRAMES_PER_BUFFER), SAMPLE_RATE, &synth->midi_note[i].lfo_index) / 2.0 + 0.5); - - synth->midi_note[i].lfo_index = osc_sin_next(cc_iget(&synth->cc_lfo_freq, frame, FRAMES_PER_BUFFER), synth->midi_note[i].lfo_index); - /* float synth_sample = synth->osctri->ops->sample(synth->osctri, synth->midi_note[i].wvt_index); */ - /* synth->midi_note[i].wvt_index = synth->osctri->ops->next(synth->osctri, targ_freq, synth->midi_note[i].wvt_index); */ - float synth_sample = synth->gen[synth->geni](targ_freq, - &synth->midi_note[i], - synth->x, - sample_rate); - - sample += synth->midi_note[i].velocity * adsr * synth_sample; - } - - /* filter */ - if (synth->filter) { - // ALLL THE FILTERS - float cutoff = cc_iget(&synth->cc_cutoff, frame, FRAMES_PER_BUFFER); - float reso = round(cc_iget(&synth->cc_resonance, frame, FRAMES_PER_BUFFER)); - - //cutoff = cutoff + cutoff * (synth->lfo.amp) * lfo(cc_iget(&synth->cc_lfo_freq, frame, FRAMES_PER_BUFFER), synth->lfo.elapsed, sample_rate); - if (cutoff == 0) cutoff = 0.001; - lpf_update(reso, cutoff, sample_rate); - sample = lpf_filter(sample); - - update_bw_low_pass_filter(synth->fff, SAMPLE_RATE,cutoff, reso); - sample = bw_low_pass(synth->fff, sample); - } - - sample = synth->gain * sample; - - // band stop for high freqs - sample = bw_band_stop(synth->fff2, sample); - - if (synth->clamp) sample = clamp(sample, -1, 1); - - return sample; -} - -void -add_to_viz(synth_t *synth, float sample) -{ - synth->viz.wave[synth->viz.wi++] = sample; - - if (synth->viz.wi >= VIZ_BUF) { - synth->viz.wi = 0; - } -} - -void -add_to_fftviz(synth_t *synth, float sample) -{ - synth->fftviz.wave[synth->fftviz.wi++] = sample; - - if (synth->fftviz.wi >= VIZ_BUF) { - synth->fftviz.wi = 0; - } -} - -void -add_to_delay(synth_t *synth, float sample) -{ - synth->del[synth->deli++] = sample; - - if (synth->deli >= SAMPLE_RATE * 10) { - synth->deli = 0; - } -} - -void -increment_synth(synth_t *synth) -{ - synth->lfo.elapsed++; - synth->adsr.elapsed++; - for (int i = 0; i < MIDI_NOTES; i++) { - if (!synth->midi_note[i].active) - continue; - - synth->midi_note[i].elapsed++; - } -} - -void -get_frame(void *outputBuffer, synth_t *synth, int i) -{ - float *out = (float*)outputBuffer + 2 * i; - float s = 0.0f; - - - if (!synth->active) { - lfo_index = 0; - } - - if (!notes_active(synth)) { - synth->active = 0; - lfo_index = 0; - } - - if (!synth->delay) { - synth->counter = 0; - } - - s = make_sample(synth, SAMPLE_RATE, i); - synth->counter++; - if (synth->counter >= (int)(synth->del_time * SAMPLE_RATE * 10)) { - int idx = (synth->deli - (int)(synth->del_time * SAMPLE_RATE * 10)) % (SAMPLE_RATE * 10); - float tmp; - if (idx >= 0) { - tmp = synth->del[idx]; - } else { - tmp = synth->del[SAMPLE_RATE * 10 + idx]; - } - - s = clamp(s + synth->del_feedback * tmp, -1, 1); - } - - add_to_delay(synth, s); - *out++ = s; - *out++ = s; - - // move time - increment_synth(synth); - - // viz - add_to_viz(synth, s); -} - -#include "fftw3.h" - -int -get_spectrum(synth_t * synth, float * buffer) -{ - int fft_output_len = FRAMES_PER_BUFFER / 2 + 1; - float input[FRAMES_PER_BUFFER]; - - for( unsigned long i=0; i < FRAMES_PER_BUFFER * 2; i += 2 ) { - input[i / 2] = buffer[i]; - } - fftwf_complex* output = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fft_output_len); - - fftwf_plan forward_plan = fftwf_plan_dft_r2c_1d(fft_output_len, input, output, FFTW_ESTIMATE); - - fftwf_execute(forward_plan); - - for (int i=0; i < fft_output_len - 2*fft_output_len/3; i++ ) { - add_to_fftviz(synth, sqrt(output[i][0] * output[i][0] + output[i][1] * output[i][1])); - } - - fftwf_destroy_plan(forward_plan); - fftwf_free(output); -} - -int -process(synth_t * synth, float * buffer) -{ - int len = FRAMES_PER_BUFFER; - - float buf[FRAMES_PER_BUFFER]; - - for( unsigned long i=0; i < len * 2; i += 2 ) { - buf[i / 2] = buffer[i]; - } - - fftwf_complex* frequency_signal = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * (len / 2 + 1)); - //double* time_signal = (double*)fftwf_malloc(sizeof(double) * len); - - fftwf_plan forward_plan = fftwf_plan_dft_r2c_1d(len, buf, frequency_signal, FFTW_ESTIMATE); - fftwf_plan backward_plan = fftwf_plan_dft_c2r_1d(len, frequency_signal, buf, FFTW_ESTIMATE); - - fftwf_execute(forward_plan); - - // cont: - /* printf("ASDASD!!!\n"); */ - /* for (int i=0; i < (len / 2 + 1); i++ ) { */ - /* if (frequency_signal[i][0] > 1) { */ - /* frequency_signal[i][0] = 0; */ - /* } */ - /* if (frequency_signal[i][1] > 1) { */ - /* frequency_signal[i][1] = 0; */ - /* } */ - /* printf("%f %f | \n", sqrt(frequency_signal[i][0] * frequency_signal[i][0] + frequency_signal[i][1] * frequency_signal[i][1]), atan2(frequency_signal[i][1], frequency_signal[i][0])); */ - - /* /\* float f = atan2(frequency_signal[i][1], frequency_signal[i][0]); *\/ */ - /* /\* if (f > M_PI / 2 && f < 2 * M_PI / 3) { *\/ */ - /* /\* frequency_signal[i][0] = 0.0; *\/ */ - /* /\* frequency_signal[i][1] = 0.0; *\/ */ - /* /\* } *\/ */ - /* } */ - - /* printf("ASDASD!!!\n"); */ - fftwf_execute(backward_plan); - - for (unsigned long i=0; i < len * 2; i += 2) { - buffer[i] = buf[i / 2] / len ; - buffer[i + 1] = buf[i / 2] / len ; - } - - fftwf_destroy_plan(forward_plan); - fftwf_destroy_plan(backward_plan); - fftwf_free(frequency_signal); - //fftwf_free(time_signal); - - /* for( unsigned long i=0; i < len * 2; i += 2 ) { */ - /* buf[i / 2] = buffer[i]; */ - /* } */ - /* float kernel[7] = {.01, .88, .21, .36, .21, .13, .01}; */ - /* float res[len + 7 - 1]; */ - /* convole(buf, kernel, len, 7, res); */ - - /* int N = (len + 7 - 1); */ - /* int M = len; */ - - /* float ratio = (float) N / M; */ - - /* for (int i = 0; i < M; i++) { */ - /* int index = (int)(i * ratio); */ - /* buf[i] = res[index]; */ - /* } */ - - /* for (unsigned long i=0; i < len * 2; i += 2) { */ - /* buffer[i] = buf[i / 2] ; */ - /* buffer[i + 1] = buf[i / 2] ; */ - /* } */ - - return 0; -} - -int -sound_gen(const void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, - void *synthData) -{ - synth_t *synth = (synth_t*)synthData; - float *out = (float*)outputBuffer; - - float buffer[2 * FRAMES_PER_BUFFER]; - - (void) timeInfo; - (void) statusFlags; - (void) inputBuffer; - - // get_changes(); - for (int i = 0; i < synth->cci; i++) { - cc_prep(synth->ccs[i]); - } - // fill buffer - for( unsigned long i=0; i<framesPerBuffer; i++ ) { - // use iget inside - get_frame(buffer, synth, i); - } - // process buffer - // process(synth, buffer); - get_spectrum(synth, buffer); - - // output buffer - for( unsigned long i=0; i<framesPerBuffer * 2; i += 2 ) { - // use iget inside - *out++ = buffer[i]; - *out++ = buffer[i+1]; - } - // finalize_changes(); - for (int i = 0; i < synth->cci; i++) { - cc_fix(synth->ccs[i]); - } - return paContinue; -} - -void -init_synth(synth_t * synth) -{ - synth->cci = 0; - CC(synth->cc_cutoff, "cutoff", 10, 5000, 30, 5000); - CC(synth->cc_resonance, "resonance", 1, 10, .02, 1); - //CC(synth->cc_lfo_freq, "lfo_freq", .01, 10, .02, 1); - CC(synth->cc_lfo_freq, "lfo_freq", 1, 1000, 2, 1); - CC(synth->cc_lfo_amp, "lfo_amp", 0, 1, .01, 0); - CC(synth->cc_pitch, "pitch", -3, 4, 0.01, 1); - CC(synth->cc_adsr_a, "attack", 0, 3, 0.05, 0.00); - CC(synth->cc_adsr_d, "decay", 0, 2, 0.05, 0.3); - CC(synth->cc_adsr_s, "sustain", 0, 1.0f, 0.05f, 0.7f); - CC(synth->cc_adsr_r, "release", 0, 5, 0.05f, 0.2f); - - synth->modi = 0; - - synth->gain = 0.5; - synth->x = 1; - - synth->adsr.a = 0.00001f; - synth->adsr.peak = 1.0f; - synth->adsr.d = 0.3; - synth->adsr.s = 0.7; - synth->adsr.r = 0.4; - synth->adsr.elapsed = 0; - - synth->lfo.freq = 1.0f; - synth->lfo.amp = 0.0f; - synth->lfo.elapsed = 0; - - for (int i =0; i<MIDI_NOTES; i++) { - synth->midi_note[i].freq = 0; - synth->midi_note[i].channel = -1; - synth->midi_note[i].noteOn = -1; - synth->midi_note[i].noteOff = -1; - synth->midi_note[i].velocity = -1; - synth->midi_note[i].elapsed = -1; - synth->midi_note[i].active = 0; - synth->midi_note[i].wvt_index = 0; - synth->midi_note[i].lfo_index = 0; - synth->midi_note[i].adsr = &(synth->adsr); - } - - synth->octave = 3; - - synth->delay = 0; - synth->del[SAMPLE_RATE * 10]; - synth->deli = 0; - synth->del_time = .1; - synth->del_feedback = 0.5f; - synth->counter; - - synth->filter = 1; - synth->clamp = 1; - - synth->gen[0] = gen0; - synth->gen[1] = gen1; - synth->gen[2] = gen2; - synth->gen[3] = gen3; - synth->gen[4] = gen4; - synth->gen[5] = gen5; - synth->gen[6] = gen6; - synth->geni = 3; - - synth->active = 0; - - synth->viz.sample_rate_divider = 1; - synth->viz.wi = 0; - synth->fftviz.sample_rate_divider = 1; - synth->fftviz.wi = 0; - - lpf_init(); - synth->fff = create_bw_low_pass_filter(2, SAMPLE_RATE, 400); - synth->fff2 = create_bw_band_stop_filter(8, SAMPLE_RATE, 15000, 22000); - - init_sound(synth, sound_gen); - - synth->osctri = make_tri("triangle"); -} - -void -free_synth(synth_t * synth) -{ - destroy_sound(synth); - - free_bw_low_pass(synth->fff); - free_bw_band_stop(synth->fff2); -} |