summaryrefslogtreecommitdiffstats
path: root/src/synth_engine.c
diff options
context:
space:
mode:
authorgramanas <anastasis.gramm2@gmail.com>2023-06-27 22:37:53 +0300
committergramanas <anastasis.gramm2@gmail.com>2023-06-27 22:37:53 +0300
commit60c82a72fedd719f69c1f1de896aca00784a2881 (patch)
tree3679e0886fc12aa8eeeab60260347ee7a0c5ae0e /src/synth_engine.c
parente77d4d42cacd21bf80e4f47cba2fe85f5a5b0991 (diff)
downloadsynth-project-60c82a72fedd719f69c1f1de896aca00784a2881.tar.gz
synth-project-60c82a72fedd719f69c1f1de896aca00784a2881.tar.bz2
synth-project-60c82a72fedd719f69c1f1de896aca00784a2881.zip
Changes
Diffstat (limited to 'src/synth_engine.c')
-rw-r--r--src/synth_engine.c276
1 files changed, 198 insertions, 78 deletions
diff --git a/src/synth_engine.c b/src/synth_engine.c
index 49c3168..9dc6457 100644
--- a/src/synth_engine.c
+++ b/src/synth_engine.c
@@ -2,6 +2,8 @@
#include "synth_math.h"
#include "lowpass.h"
#include "filter.h"
+#include "control.h"
+#include "sound.h"
#include <string.h>
@@ -37,9 +39,38 @@ sqr_sample(float amp, float freq, float duty_cycle, unsigned long long phase, un
}
float
+gen10(float f, unsigned long long phase, float x, unsigned int sample_rate)
+{
+ return fmodf(phase, sample_rate/f) / (sample_rate/f);
+}
+
+float
+gen1110(float f, unsigned long long phase, float x, unsigned int sample_rate)
+{
+float amplitude = 0.5; // Set the initial amplitude to 0.5
+float period = 1.0 / f; // Calculate the period of the waveform
+float angular_frequency = 2.0 * M_PI * f; // Calculate the angular frequency
+
+// Calculate the phase angle
+float phase_angle = fmodf(angular_frequency * phase / sample_rate, 2.0 * M_PI);
+
+// Generate the sample value using the sine function
+float sample = amplitude * sinf(phase_angle);
+
+return sample;
+}
+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, unsigned long long phase, float x, unsigned int sample_rate)
{
return sin_sample(1, f, phase, sample_rate);
+ //return chirp(phase, f);
/* return sqr_sample(0.1, f, 0.3, phase, sample_rate) */
/* + sqr_sample(0.1, f * 3.0 / 2.0 , 0.5, phase, sample_rate) */
/* + saw_sample(0.3, f, phase, sample_rate) */
@@ -53,10 +84,10 @@ gen0(float f, unsigned long long phase, float x, unsigned int sample_rate)
float
gen1(float f, unsigned long long phase, float x, unsigned int sample_rate)
{
- return saw_sample(1, f, phase, sample_rate);
- /* return sawX_sample(0.5, f, 5, phase, sample_rate) */
- /* + saw_sample(0.3, 2 * f / 5, phase, sample_rate) */
- /* + sin_sample(0.2, f * 5.0 / 7.0 , phase, sample_rate); */
+ //return saw_sample(1, f, phase, sample_rate);
+ return sawX_sample(0.5, f, 5, phase, sample_rate)
+ + saw_sample(0.3, 2 * f / 5, phase, sample_rate)
+ + sin_sample(0.2, f * 5.0 / 7.0 , phase, sample_rate);
}
float
@@ -113,16 +144,17 @@ notes_active(synth_t *synth)
return flag;
}
+float cur_freq, next_freq;
+
float
-make_sample(unsigned long long phase, void *synthData, unsigned int sample_rate, int viz)
+make_sample(void *synthData, unsigned int sample_rate, int frame)
{
synth_t *synth = (synth_t*)synthData;
- float sample = 0;
+ float sample = 0.0f;
- /* should never be 0 if we are here */
-
- /* Notes */
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)
@@ -137,26 +169,49 @@ make_sample(unsigned long long phase, void *synthData, unsigned int sample_rate,
if (!synth->midi_note[i].active)
continue;
- sample += 0.2 * rms
- * adsr_amplitude(&synth->adsr,
- synth->midi_note[i].noteOn,
- synth->midi_note[i].noteOff,
- synth->midi_note[i].elapsed)
- * synth->gen[synth->geni](synth->midi_note[i].freq + synth->freq_offset, synth->midi_note[i].elapsed, synth->x, sample_rate);
+ float adsr = adsr_amplitude(&synth->adsr,
+ synth->midi_note[i].noteOn,
+ synth->midi_note[i].noteOff,
+ synth->midi_note[i].elapsed);
+
+ float targ_freq = synth->midi_note[i].freq * cc_iget(&synth->cc_pitch, frame, FRAMES_PER_BUFFER);
+ float targ_freq_with_repitch = synth->midi_note[i].freq * cc_iget(&synth->cc_pitch, frame, FRAMES_PER_BUFFER);
+
+ float synth_sample = synth->gen[synth->geni](targ_freq,
+ synth->midi_note[i].elapsed,
+ synth->x,
+ sample_rate);
+
+ /* if (targ_freq != targ_freq_with_repitch) { */
+ /* unsigned long long tmp = synth->midi_note[i].elapsed; */
+ /* float next_sample = synth->gen[synth->geni](targ_freq_with_repitch, */
+ /* tmp, */
+ /* synth->x, */
+ /* sample_rate); */
+ /* while (synth_sample - next_sample > 0.001 && next_sample - synth_sample > 0.001) { */
+ /* next_sample = synth->gen[synth->geni](targ_freq_with_repitch, */
+ /* ++tmp, */
+ /* synth->x, */
+ /* sample_rate); */
+ /* } */
+ /* synth_sample = next_sample; */
+ /* } */
+
+ sample += 0.2 * rms * adsr * synth_sample;
}
/* filter */
if (synth->filter) {
// ALLL THE FILTERS
- float cutoff = round(synth->cutoff) + 1;
-
- cutoff = cutoff + cutoff * (synth->lfo.amp) * lfo(synth->lfo.freq, synth->lfo.elapsed, sample_rate);
+ 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;
- LowPass_Update(synth->resonance, cutoff, sample_rate);
+ LowPass_Update(reso, cutoff, sample_rate);
sample = LowPass_Filter(sample);
- update_bw_low_pass_filter(synth->fff, SAMPLE_RATE,cutoff, synth->resonance);
+ update_bw_low_pass_filter(synth->fff, SAMPLE_RATE,cutoff, reso);
sample = bw_low_pass(synth->fff, sample);
}
@@ -165,7 +220,7 @@ make_sample(unsigned long long phase, void *synthData, unsigned int sample_rate,
// band stop for high freqs
sample = bw_band_stop(synth->fff2, sample);
- if (synth->clamp) sample = clamp(sample);
+ if (synth->clamp) sample = clamp(sample, -1, 1);
return sample;
}
@@ -181,6 +236,20 @@ add_to_viz(synth_t *synth, float sample)
}
void
+increment_synth(synth_t *synth)
+{
+ synth->lfo.elapsed++;
+ synth->adsr.elapsed++;
+ synth->n.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;
@@ -205,23 +274,89 @@ get_frame(void *outputBuffer, synth_t *synth, int i)
return;
}
- s = make_sample(synth->n.elapsed, synth, SAMPLE_RATE, 0);
+ s = make_sample(synth, SAMPLE_RATE, i);
*out++ = s;
*out++ = s;
- synth->lfo.elapsed++;
- synth->adsr.elapsed++;
- synth->n.elapsed++;
+ // move time
+ increment_synth(synth);
- for (int i = 0; i < MIDI_NOTES; i++) {
- if (!synth->midi_note[i].active)
- continue;
+ // viz
+ add_to_viz(synth, s);
+}
- synth->midi_note[i].elapsed++;
+#include "fftw3.h"
+
+int
+process(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);
+
+ /* 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 | ", 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; */
+ /* } */
+ /* } */
+
+ 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 ;
}
- // viz
- add_to_viz(synth, s);
+ 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
@@ -233,30 +368,49 @@ sound_gen(const void *inputBuffer, void *outputBuffer,
{
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++ ) {
- //interpolate_changes(i);
- get_frame(outputBuffer, synth, i);
+ // use iget inside
+ get_frame(buffer, synth, i);
+ }
+ // process buffer
+ if (synth->multi) process(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;
}
-
-static void
-StreamFinished( void* synthData )
-{
- synth_t *synth = (synth_t *) synthData;
-}
-
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_pitch, "pitch", -3, 4, 0.01, 1);
+
+ synth->modi = 0;
+
synth->freq_offset = 0;
synth->gain = 1;
synth->x = 1;
@@ -295,14 +449,13 @@ init_synth(synth_t * synth)
synth->multi = 0;
synth->filter = 1;
synth->cutoff = 22000.0f;
- synth->resonance = 1.0f;
synth->clamp = 1;
synth->gen[0] = gen0;
synth->gen[1] = gen1;
synth->gen[2] = gen2;
synth->gen[3] = gen3;
- synth->geni = 0;
+ synth->geni = 2;
synth->active = 0;
@@ -313,46 +466,13 @@ init_synth(synth_t * synth)
synth->fff = create_bw_low_pass_filter(2, SAMPLE_RATE, 400);
synth->fff2 = create_bw_band_stop_filter(8, SAMPLE_RATE, 15000, 22000);
- Pa_Initialize();
-
- int i;
- const PaDeviceInfo *deviceInfo;
- for( i=0; i< Pa_GetDeviceCount(); i++ ) {
- deviceInfo = Pa_GetDeviceInfo( i );
- //if (!strcmp("HyperX Cloud II Wireless: USB Audio (hw:2,0)", deviceInfo->name)) break;
- printf("dev: %s || %f\n", deviceInfo->name, deviceInfo->defaultSampleRate);
- if (!strcmp("HDA Intel PCH: ALC1220 Analog (hw:0,0)", deviceInfo->name)) break;
- }
-
-
- PaStreamParameters outputParameters;
- outputParameters.device = i; Pa_GetDefaultOutputDevice(); /* default output device */
- printf("-------\nSelected device: %s\n-------\n", Pa_GetDeviceInfo(outputParameters.device)->name);
- outputParameters.channelCount = 2; /* stereo output */
- outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
- outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
- outputParameters.hostApiSpecificStreamInfo = NULL;
-
- Pa_OpenStream(&(synth->stream),
- NULL, /* no input */
- &outputParameters,
- SAMPLE_RATE,
- FRAMES_PER_BUFFER,
- paClipOff, /* we won't output out of range samples so don't bother clipping them */
- sound_gen,
- synth );
-
- Pa_SetStreamFinishedCallback(synth->stream, &StreamFinished);
- Pa_StartStream(synth->stream);
+ init_sound(synth, sound_gen);
}
void
free_synth(synth_t * synth)
{
- Pa_StopStream( synth->stream );
- Pa_CloseStream( synth->stream );
- Pa_Terminate();
-
+ destroy_sound(synth);
free_bw_low_pass(synth->fff);
free_bw_band_stop(synth->fff2);