summaryrefslogtreecommitdiffstats
path: root/src/synth_engine.c
diff options
context:
space:
mode:
authorgrm <grm@eyesin.space>2025-02-22 03:40:43 +0200
committergrm <grm@eyesin.space>2025-02-22 03:40:43 +0200
commit35208c579c9e7d0078d786e61f4a323919e2dcdf (patch)
tree022f464e6350c18f76443a6e96eccd02698df7d1 /src/synth_engine.c
parent500b9a07b93d6cd3e771edc5698e06d163da60f1 (diff)
downloadsynth-project-35208c579c9e7d0078d786e61f4a323919e2dcdf.tar.gz
synth-project-35208c579c9e7d0078d786e61f4a323919e2dcdf.tar.bz2
synth-project-35208c579c9e7d0078d786e61f4a323919e2dcdf.zip
Small fixesHEADmaster
Diffstat (limited to 'src/synth_engine.c')
-rw-r--r--src/synth_engine.c545
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);
-}