Channel state, synth_process stub
This commit is contained in:
parent
79efcf3bbe
commit
93e305f311
6
main.c
6
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;i<m;++i)
|
||||
{
|
||||
out[i]=synth->channel[0].buffer[synth->playback_pos+i];
|
||||
out[i]=synth->channel[0].buffer[0][synth->playback_pos+i];
|
||||
for(size_t j=1;j<synth->nchannels;++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);
|
||||
|
89
synth.c
89
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;i<SY_BUFFERSIZE;++i)
|
||||
{
|
||||
float sum=0;
|
||||
for(int32_t j=MAX(1,i-hp);j<=i;++j)
|
||||
sum+=synth->channel[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;i<attacklen;++i)
|
||||
{
|
||||
float mult=((float)i)/attacklen;
|
||||
synth->channel[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;i<SY_BUFFERSIZE;++i)
|
||||
{
|
||||
float mult=((float)SY_BUFFERSIZE-i)/releaselen;
|
||||
synth->channel[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;i<SY_BUFFERSIZE;++i)
|
||||
{
|
||||
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;
|
||||
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;i<SY_BUFFERSIZE;++i)
|
||||
{
|
||||
float mult=((float)SY_BUFFERSIZE-i)/releaselen;
|
||||
synth->channel[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;
|
||||
|
16
synth.h
16
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,
|
||||
|
29
ui.c
29
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;i<ui->synth->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)
|
||||
|
Loading…
Reference in New Issue
Block a user