diff options
Diffstat (limited to 'src/synth_engine.c')
-rw-r--r-- | src/synth_engine.c | 276 |
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); |