From 93e305f31149c75cb121b952f63fdee92b9da04e Mon Sep 17 00:00:00 2001 From: coreydunn Date: Thu, 27 Jul 2023 10:04:44 -0500 Subject: [PATCH] Channel state, synth_process stub --- main.c | 6 ++-- synth.c | 89 ++++++++++++++++++++++++++++++++++----------------------- synth.h | 16 +++++++---- ui.c | 29 ++++++++++--------- 4 files changed, 82 insertions(+), 58 deletions(-) diff --git a/main.c b/main.c index 237604e..d2a970b 100644 --- a/main.c +++ b/main.c @@ -158,14 +158,14 @@ int play_stream(const void*input,void*output, { size_t n=MIN(synth->playback_pos+count,SY_BUFFERSIZE); size_t m=n-synth->playback_pos; - /* memcpy(out,&synth->channel[synth->current_channel].buffer[synth->playback_pos],m*sizeof(float)); */ + /* memcpy(out,&synth->channel[synth->current_channel].buffer[0][synth->playback_pos],m*sizeof(float)); */ // Mix all channels for(size_t i=0;ichannel[0].buffer[synth->playback_pos+i]; + out[i]=synth->channel[0].buffer[0][synth->playback_pos+i]; for(size_t j=1;jnchannels;++j) - out[i]+=synth->channel[j].buffer[synth->playback_pos+i]; + out[i]+=synth->channel[j].buffer[0][synth->playback_pos+i]; out[i]/=synth->nchannels; } synth->playback_pos=MIN(synth->playback_pos+count,SY_BUFFERSIZE); diff --git a/synth.c b/synth.c index 742bc88..50c4b91 100644 --- a/synth.c +++ b/synth.c @@ -10,18 +10,39 @@ #define M_PI 3.14159 #endif +// Process channel buffer +void synth_process(Synth*synth) +{ + memset(synth->channel[synth->current_channel].buffer[0],0,SY_BUFFERSIZE*4); +} + +void synth_create_channel(Synth*synth) +{ + memset(synth->channel[0].buffer[0],0,SY_BUFFERSIZE*sizeof(float)); + memset(synth->channel[1].buffer[1],0,SY_BUFFERSIZE*sizeof(float)); + synth->channel[synth->current_channel].freq=synth->knobs[K_FREQ].value; + synth->channel[synth->current_channel].on=true; + synth->channel[synth->current_channel].aenv_time=0; + synth->channel[synth->current_channel].offset=0; + synth->channel[synth->current_channel].playback_buffer=0; +} + +/* void synth_next_buffer(Synth*synth) */ +/* { */ +/* } */ + void synth_recalc(Synth*synth) { - memset(synth->channel[synth->current_channel].buffer,0,SY_BUFFERSIZE*4); - float lp=synth->knobs[K_LP].value; - float hp=synth->knobs[K_HP].value; float lfo1_buffer[SY_BUFFERSIZE]={0}; float lfo2_buffer[SY_BUFFERSIZE]={0}; - uint32_t oscillator_vol[]={K_OSC1_VOL,K_OSC2_VOL,K_OSC3_VOL,K_OSC4_VOL}; - uint32_t oscillator_wavef[]={K_OSC1_WAVEF,K_OSC2_WAVEF,K_OSC3_WAVEF,K_OSC4_WAVEF}; - uint32_t oscillator_duty[]={K_OSC1_PHASE,K_OSC2_PHASE,K_OSC3_PHASE,K_OSC4_PHASE}; - uint32_t oscillator_det[]={K_OSC1_DET,K_OSC2_DET,K_OSC3_DET,K_OSC4_DET}; + const uint32_t oscillator_vol[]={K_OSC1_VOL,K_OSC2_VOL,K_OSC3_VOL,K_OSC4_VOL}; + const uint32_t oscillator_wavef[]={K_OSC1_WAVEF,K_OSC2_WAVEF,K_OSC3_WAVEF,K_OSC4_WAVEF}; + const uint32_t oscillator_duty[]={K_OSC1_PHASE,K_OSC2_PHASE,K_OSC3_PHASE,K_OSC4_PHASE}; + const uint32_t oscillator_det[]={K_OSC1_DET,K_OSC2_DET,K_OSC3_DET,K_OSC4_DET}; + + // Clear buffer + memset(synth->channel[synth->current_channel].buffer[0],0,SY_BUFFERSIZE*4); // Calculate lfo1 (master amp) if(synth->knobs[K_LFO1_VOL].value>0&& @@ -171,7 +192,7 @@ void synth_recalc(Synth*synth) float duty=synth->knobs[oscillator_duty[cur_osc]].value; bool mix=cur_osc>0&&synth->knobs[oscillator_vol[cur_osc-1]].value>0; if(fr==0.0)break; - gen_sin(synth->channel[synth->current_channel].buffer,amp,fr,mix,SY_BUFFERSIZE,synth->samplerate,duty,0); + gen_sin(synth->channel[synth->current_channel].buffer[0],amp,fr,mix,SY_BUFFERSIZE,synth->samplerate,duty,0); } // Triangle @@ -184,7 +205,7 @@ void synth_recalc(Synth*synth) float duty=synth->knobs[oscillator_duty[cur_osc]].value; bool mix=cur_osc>0&&synth->knobs[oscillator_vol[cur_osc-1]].value>0; if(fr==0.0)break; - gen_tri(synth->channel[synth->current_channel].buffer,amp,fr,mix,SY_BUFFERSIZE,synth->samplerate,duty,0); + gen_tri(synth->channel[synth->current_channel].buffer[0],amp,fr,mix,SY_BUFFERSIZE,synth->samplerate,duty,0); } // Sawtooth @@ -197,7 +218,7 @@ void synth_recalc(Synth*synth) float duty=synth->knobs[oscillator_duty[cur_osc]].value; bool mix=cur_osc>0&&synth->knobs[oscillator_vol[cur_osc-1]].value>0; if(fr==0.0)break; - gen_saw(synth->channel[synth->current_channel].buffer,amp,fr,mix,SY_BUFFERSIZE,synth->samplerate,duty,0); + gen_saw(synth->channel[synth->current_channel].buffer[0],amp,fr,mix,SY_BUFFERSIZE,synth->samplerate,duty,0); } // Pulse @@ -214,7 +235,7 @@ void synth_recalc(Synth*synth) synth->knobs[K_LFO2_FREQ].value>0) duty_buf=lfo2_buffer; if(fr==0.0)break; - gen_pul(synth->channel[synth->current_channel].buffer,amp,fr,mix,SY_BUFFERSIZE,synth->samplerate,duty,duty_buf,0); + gen_pul(synth->channel[synth->current_channel].buffer[0],amp,fr,mix,SY_BUFFERSIZE,synth->samplerate,duty,duty_buf,0); } // Noise @@ -225,7 +246,7 @@ void synth_recalc(Synth*synth) float fr=(synth->knobs[K_FREQ].value/synth->knobs[K_FREQ].maxval)*MAXFREQ; fr+=SEMITONE(fr,synth->knobs[K_DET].value); if(fr==0.0)break; - gen_nse(synth->channel[synth->current_channel].buffer,amp,fr,mix,SY_BUFFERSIZE,synth->samplerate,0); + gen_nse(synth->channel[synth->current_channel].buffer[0],amp,fr,mix,SY_BUFFERSIZE,synth->samplerate,0); } } @@ -241,13 +262,13 @@ void synth_recalc(Synth*synth) amp+=lfo1_buffer[i%SY_BUFFERSIZE]; amp/=2.0; } - synth->channel[synth->current_channel].buffer[i]*=amp; + synth->channel[synth->current_channel].buffer[0][i]*=amp; } // Convolution low-pass filter if(synth->knobs[K_AMP].value!=0) { - if((size_t)lp>0) + if((size_t)synth->knobs[K_LP].value>0) { size_t attacklen=synth->knobs[K_FENV_ATK].value*SY_BUFFERSIZE; @@ -256,21 +277,21 @@ void synth_recalc(Synth*synth) float mult=((float)i)/attacklen; float sum=0; - for(int32_t j=MAX(1,i-lp);j<=i;++j) - sum+=synth->channel[synth->current_channel].buffer[j]; + for(int32_t j=MAX(1,i-synth->knobs[K_LP].value);j<=i;++j) + sum+=synth->channel[synth->current_channel].buffer[0][j]; // Weight for filter wet/dry { - float f_val=sum/(lp+1); - float o_val=synth->channel[synth->current_channel].buffer[i]; + float f_val=sum/(synth->knobs[K_LP].value+1); + float o_val=synth->channel[synth->current_channel].buffer[0][i]; float o_mult=MAX(0,1.0-mult); if(mult==0) - synth->channel[synth->current_channel].buffer[i]=o_val; + synth->channel[synth->current_channel].buffer[0][i]=o_val; else if(mult==1||o_mult==0) - synth->channel[synth->current_channel].buffer[i]=f_val; + synth->channel[synth->current_channel].buffer[0][i]=f_val; else - synth->channel[synth->current_channel].buffer[i]=f_val*mult+o_val*MAX(0,1.0-mult); + synth->channel[synth->current_channel].buffer[0][i]=f_val*mult+o_val*MAX(0,1.0-mult); } } @@ -280,15 +301,15 @@ void synth_recalc(Synth*synth) // High-pass filter if(synth->knobs[K_AMP].value!=0) { - if((size_t)hp>0) + if((size_t)synth->knobs[K_HP].value>0) { for(int32_t i=1;ichannel[synth->current_channel].buffer[j]; - synth->channel[synth->current_channel].buffer[i]-=sum/(hp+1); + for(int32_t j=MAX(1,i-synth->knobs[K_HP].value);j<=i;++j) + sum+=synth->channel[synth->current_channel].buffer[0][j]; + synth->channel[synth->current_channel].buffer[0][i]-=sum/(synth->knobs[K_HP].value+1); } } @@ -300,7 +321,7 @@ void synth_recalc(Synth*synth) for(size_t i=0;ichannel[synth->current_channel].buffer[i]*=mult; + synth->channel[synth->current_channel].buffer[0][i]*=mult; } } @@ -310,7 +331,7 @@ void synth_recalc(Synth*synth) for(size_t i=SY_BUFFERSIZE-releaselen;ichannel[synth->current_channel].buffer[i]*=mult; + synth->channel[synth->current_channel].buffer[0][i]*=mult; } } @@ -319,10 +340,10 @@ void synth_recalc(Synth*synth) { for(size_t i=0;ichannel[synth->current_channel].buffer[i]>synth->knobs[K_LIM].value) - synth->channel[synth->current_channel].buffer[i]=synth->knobs[K_LIM].value; - else if(synth->channel[synth->current_channel].buffer[i]<-synth->knobs[K_LIM].value) - synth->channel[synth->current_channel].buffer[i]=-synth->knobs[K_LIM].value; + if(synth->channel[synth->current_channel].buffer[0][i]>synth->knobs[K_LIM].value) + synth->channel[synth->current_channel].buffer[0][i]=synth->knobs[K_LIM].value; + else if(synth->channel[synth->current_channel].buffer[0][i]<-synth->knobs[K_LIM].value) + synth->channel[synth->current_channel].buffer[0][i]=-synth->knobs[K_LIM].value; } } @@ -332,7 +353,7 @@ void synth_recalc(Synth*synth) for(size_t i=SY_BUFFERSIZE+1;ichannel[synth->current_channel].buffer[i]*=mult; + synth->channel[synth->current_channel].buffer[0][i]*=mult; } } @@ -343,10 +364,8 @@ void synth_recalc(Synth*synth) void synth_new(Synth*s) { if(!s)return; - /* memset(s->channel[s->current_channel].buffer,0,SY_BUFFERSIZE*(s->bitrate/8)); */ - /* memset(&s->wave,0,sizeof(WAVE)); */ - /* memset(&s->knobs,0,sizeof(Knob)*SY_NKNOBS); */ + memset(s,0,sizeof(Synth)); s->octave=3; s->play_waveform=false; s->recalculate_waveform=true; diff --git a/synth.h b/synth.h index b8426e4..d854a8a 100644 --- a/synth.h +++ b/synth.h @@ -23,7 +23,13 @@ typedef struct Channel { - float buffer[SY_BUFFERSIZE]; + bool on; // Currently playing? + float aenv_time; // Time in aenv_lvl + float buffer[2][SY_BUFFERSIZE]; // Double-buffers + float freq; // Frequency + size_t aenv_lvl; // 0:A, 1:D, 2:S, 3:R + size_t offset; // Offset for oscillators + size_t playback_buffer; // Rendered buffer } Channel; typedef struct Synth @@ -34,11 +40,7 @@ typedef struct Synth bool cleared; // Buffer was cleared bool play_waveform; // Are we currently rendering? bool recalculate_waveform; // When to regenerate - float amp; // Amplitude - float freq; // Frequency in Hertz float octave; // Octave for keyboard - size_t bitrate; // Bits per sample - size_t bufsize; // Size of buffer size_t current_channel; // Which channel to render to size_t nchannels; size_t playback_pos; // Current position in playback @@ -51,8 +53,10 @@ typedef struct Note float freq; } Note; -void synth_recalc(Synth*synth); +void synth_create_channel(Synth*synth); void synth_new(Synth*s); +void synth_process(Synth*synth); +void synth_recalc(Synth*synth); size_t gen_sin( float*buffer, diff --git a/ui.c b/ui.c index e5dd8d1..f6798a0 100644 --- a/ui.c +++ b/ui.c @@ -92,6 +92,7 @@ void ui_update(Ui*ui) ui->synth->recalculate_waveform=true;\ ui->synth->play_waveform=true;\ ui->synth->playback_pos=0;\ + synth_create_channel(ui->synth);\ }while(0) #define oct(x) ((x)*(float)(pow(2,((int32_t)ui->synth->knobs[K_OCT].value-4)))) @@ -262,9 +263,6 @@ void ui_update(Ui*ui) case SDLK_u:play_note(oct(987.77));break; case SDLK_i:play_note(oct(1046.5));break; -#undef oct -#undef play_note - case SDLK_F1: ui->synth->recalculate_waveform=true; break; @@ -277,7 +275,7 @@ void ui_update(Ui*ui) if(f) { fwrite(&ui->synth->wave,1,sizeof(WAVE),f); - fwrite(ui->synth->channel[ui->synth->current_channel].buffer,1,SY_BUFFERSIZE*sizeof(float),f); + fwrite(ui->synth->channel[ui->synth->current_channel].buffer[0],1,SY_BUFFERSIZE*sizeof(float),f); fclose(f); printf("Wrote file '%s'\n",fname); } @@ -285,10 +283,12 @@ void ui_update(Ui*ui) break; case SDLK_SPACE: - ui->synth->playback_pos=0; - ui->synth->play_waveform=true; + play_note(ui->synth->knobs[K_FREQ].value); break; +#undef oct +#undef play_note + } break; @@ -311,6 +311,7 @@ void ui_update(Ui*ui) // Recalculate waveform if(ui->synth->recalculate_waveform) + /* synth_process(ui->synth); */ synth_recalc(ui->synth); ui->synth->nchannels=ui->synth->knobs[K_NCH].value; @@ -331,7 +332,7 @@ void ui_update(Ui*ui) // Draw realtime oscilloscope for(size_t i=0;isynth->nchannels;++i) - draw_oscilloscope(ui,i,152*(i+1)+17,2,152-16,70); + draw_oscilloscope(ui,i,152*(i+1)+16,2,152-16,70); // Spectrum analyzer? /* { */ @@ -345,10 +346,10 @@ void ui_update(Ui*ui) /* size_t f_lp=f-1; */ /* size_t f_hp=f+1; */ /* for(int32_t j=MAX(1,i-f_lp);j<=i;++j) */ - /* sum_lp+=ui->synth->channel[synth->current_channel].buffer[j]; */ + /* sum_lp+=ui->synth->channel[synth->current_channel].buffer[0][j]; */ /* sum_lp/=f_lp+1; */ /* for(int32_t j=MAX(1,i-f_hp);j<=i;++j) */ - /* sum_hp+=ui->synth->channel[synth->current_channel].buffer[j]; */ + /* sum_hp+=ui->synth->channel[synth->current_channel].buffer[0][j]; */ /* sum_hp/=f_hp+1; */ /* sum_hp=sum_lp-f_hp; */ /* SDL_RenderDrawLine(ui->r,f*10,300,f*10,300+sum_hp); */ @@ -363,7 +364,7 @@ void ui_update(Ui*ui) /* { */ /* float sum=0; */ /* for(int32_t j=f;j>=0;--j) */ - /* sum+=ui->synth->channel[synth->current_channel].buffer[j]; */ + /* sum+=ui->synth->channel[synth->current_channel].buffer[0][j]; */ /* sum/=f+1; */ /* SDL_RenderDrawLine(ui->r,f*10,400,f*10,400-sum*80); */ /* } */ @@ -528,8 +529,8 @@ void draw_waveform(Ui*ui,uint32_t channel,uint32_t wf_x,uint32_t wf_y,uint32_t w { float xratio=(float)wf_w/SY_BUFFERSIZE; float yratio=(float)wf_h/2.0; - float y1=ui->synth->channel[channel].buffer[i-1]; - float y2=ui->synth->channel[channel].buffer[i]; + float y1=ui->synth->channel[channel].buffer[0][i-1]; + float y2=ui->synth->channel[channel].buffer[0][i]; y1=(y1>1?1:(y1<-1?-1:y1)); y2=(y2>1?1:(y2<-1?-1:y2)); SDL_RenderDrawLine(ui->r, @@ -564,8 +565,8 @@ void draw_oscilloscope(Ui*ui,uint32_t channel,uint32_t wf_x,uint32_t wf_y,uint32 ++i ) { - float y1=MIN(ui->synth->channel[channel].buffer[i-1],1.0); - float y2=MIN(ui->synth->channel[channel].buffer[i],1.0); + float y1=MIN(ui->synth->channel[channel].buffer[0][i-1],1.0); + float y2=MIN(ui->synth->channel[channel].buffer[0][i],1.0); SDL_RenderDrawLine(ui->r, wf_x+((float)(i-ui->synth->playback_pos)-1)/SY_BSIZE*wf_w,wf_y+MIN(MAX(wf_h/2-y1*wf_h,wf_y),wf_h), wf_x+((float)(i-ui->synth->playback_pos))/SY_BSIZE*wf_w,wf_y+MIN(MAX(wf_h/2-y2*wf_h,wf_y),wf_h)