Permalink
Cannot retrieve contributors at this time
| /* | |
| delayFadeN.c | |
| aleph - audio | |
| implement delay line using buffer and tap objects | |
| this one uses no interpolation, | |
| and has two taps per read head to enable crossfading | |
| */ | |
| #include "conversion.h" | |
| #include "delayFadeN.h" | |
| #include "pan.h" | |
| // initialize with pointer to audio buffer | |
| extern void delayFadeN_init(delayFadeN* dl, volatile fract16* data, u32 frames) { | |
| buffer16_init(&(dl->buffer), data, frames); | |
| buffer16_tapN_init(&(dl->tapRd[1]), &(dl->buffer)); | |
| buffer16_tapN_init(&(dl->tapWr[1]), &(dl->buffer)); | |
| buffer16_tapN_init(&(dl->tapRd[0]), &(dl->buffer)); | |
| buffer16_tapN_init(&(dl->tapWr[0]), &(dl->buffer)); | |
| dl->tapWr[0].idx = 0; | |
| dl->tapWr[1].idx = 0; | |
| dl->tapRd[0].idx = 0; | |
| dl->tapRd[1].idx = 0; | |
| dl->tapWr[0].loop = frames; | |
| dl->tapWr[1].loop = frames; | |
| dl->tapRd[0].loop = frames; | |
| dl->tapRd[1].loop = frames; | |
| dl->preLevel = 0; | |
| dl->write = 1; | |
| //?? | |
| dl->fadeRd = 0; | |
| dl->fadeWr = 0; | |
| // dl->fadeRd = FR32_MAX; | |
| // dl->fadeWr = FR32_MAX; | |
| } | |
| extern fract16 delayFadeN_next(delayFadeN* dl, fract16 in) { | |
| fract16 readVal; | |
| fract16 pan[2] = { 0, 0 }; | |
| fract16 valWr[2] = { 0, 0 }; | |
| // get read value first. | |
| // so, setting loop == delayFadeNtime gives "sensible" results... | |
| // readVal = buffer_tapN_read( &(dl->tapRd) ); | |
| /// balanced mix given current pan | |
| readVal = pan_lin_mix16( buffer16_tapN_read( &(dl->tapRd[0]) ) , | |
| buffer16_tapN_read( &(dl->tapRd[1]) ) , | |
| dl->fadeRd | |
| ); | |
| // get mix amounts for crossfaded write heads | |
| /// pan_lin_coeff( &(pan[0]), &(pan[1]), dl->fadeWr ); | |
| // valWr[0] = mult_fr1x32x32(in, pan[0]); | |
| // valWr[1] = mult_fr1x32x32(in, pan[1]); | |
| /// FIXME: use single write head for now. | |
| /// need to make them toggle run/stop depending on fade level. | |
| valWr[0] = in; | |
| // figure out how to write/add/mix | |
| if(dl->preLevel == 0) { | |
| if(dl->write) { | |
| // write and replace | |
| buffer16_tapN_write(&(dl->tapWr[0]), valWr[0]); | |
| // FIXME | |
| // buffer_tapN_write(&(dl->tapWr[1]), valWr[1]); | |
| } | |
| } else if(dl->preLevel < 0) { // consider <0 to be == 1 | |
| if(dl->write) { | |
| // overdub | |
| buffer16_tapN_add(&(dl->tapWr[0]), valWr[0]); | |
| // FIXME | |
| // buffer_tapN_add(&(dl->tapWr[1]), valWr[1]); | |
| } | |
| } else { // prelevel is non-zero, non-full | |
| if(dl->write) { | |
| // write mix | |
| buffer16_tapN_mix(&(dl->tapWr[0]), valWr[0], dl->preLevel); | |
| // FIXME | |
| // buffer_tapN_mix(&(dl->tapWr[1]), valWr[1], dl->preLevel); | |
| } | |
| } | |
| // advance the read phasors | |
| if(dl->runRd) { | |
| buffer16_tapN_next( &(dl->tapRd[0]) ); | |
| buffer16_tapN_next( &(dl->tapRd[1]) ); | |
| } | |
| // advance the write phasors | |
| if(dl->runWr) { | |
| buffer16_tapN_next( &(dl->tapWr[0]) ); | |
| /// FIXME | |
| // buffer_tapN_next( &(dl->tapWr[1]) ); | |
| } | |
| return readVal; | |
| } | |
| // set loop endpoint in seconds | |
| extern void delayFadeN_set_loop_sec(delayFadeN* dl, fix16 sec, u8 id) { | |
| u32 samps = sec_to_frames_trunc(sec); | |
| buffer16_tapN_set_loop(&(dl->tapRd[id]), samps - 1); | |
| buffer16_tapN_set_loop(&(dl->tapWr[id]), samps - 1); | |
| } | |
| // set loop endpoint in samples | |
| extern void delayFadeN_set_loop_samp(delayFadeN* dl, u32 samps, u8 id) { | |
| dl->tapRd[id].loop = samps - 1; | |
| dl->tapWr[id].loop = samps - 1; | |
| } | |
| // set delayFadeN in seconds | |
| extern void delayFadeN_set_delay_sec(delayFadeN* dl, fix16 sec, u8 id) { | |
| u32 samp = sec_to_frames_trunc(sec); | |
| // FIXME (why?) | |
| // -- something fucks up with i think delay > looptime... infinite wrap or something | |
| // buffer_tapN_sync(&(dl->tapRd[id]), &(dl->tapWr[id]), samp); | |
| //// FIXME: only one write head for now | |
| buffer16_tapN_sync(&(dl->tapRd[id]), &(dl->tapWr[0]), samp); | |
| } | |
| // set delayFadeN in samples | |
| extern void delayFadeN_set_delay_samp(delayFadeN* dl, u32 samp, u8 id) { | |
| // buffer_tapN_sync(&(dl->tapRd[id]), &(dl->tapWr[id]), samp); | |
| //// FIXME: only one write head for now | |
| buffer16_tapN_sync(&(dl->tapRd[id]), &(dl->tapWr[0]), samp); | |
| } | |
| // set erase level | |
| extern void delayFadeN_set_pre(delayFadeN* dl, fract16 pre) { | |
| dl->preLevel = pre; | |
| } | |
| // set write level | |
| extern void delayFadeN_set_write(delayFadeN* dl, u8 write) { | |
| dl->write = write; | |
| } | |
| // set read head rate | |
| extern void delayFadeN_set_rate(delayFadeN* dl, fix16 rate) { | |
| ///... | |
| } | |
| // set read pos in seconds | |
| extern void delayFadeN_set_pos_read_sec(delayFadeN* dl, fix16 sec, u8 id) { | |
| u32 samp = sec_to_frames_trunc(sec); | |
| buffer16_tapN_set_pos(&(dl->tapRd[id]), samp); | |
| } | |
| extern void delayFadeN_set_pos_read_samp(delayFadeN* dl, u32 samp, u8 id) { | |
| buffer16_tapN_set_pos(&(dl->tapRd[id]), samp); | |
| } | |
| // set write pos in seconds | |
| extern void delayFadeN_set_pos_write_sec(delayFadeN* dl, fix16 sec, u8 id) { | |
| u32 samp = sec_to_frames_trunc(sec); | |
| buffer16_tapN_set_pos(&(dl->tapWr[id]), samp); | |
| } | |
| extern void delayFadeN_set_pos_write_samp(delayFadeN* dl, u32 samp, u8 id) { | |
| buffer16_tapN_set_pos(&(dl->tapWr[id]), samp); | |
| } | |
| // set read run flag | |
| extern void delayFadeN_set_run_read(delayFadeN* dl, u8 val) { | |
| dl->runRd = val; | |
| } | |
| // set write run flag | |
| extern void delayFadeN_set_run_write(delayFadeN* dl, u8 val) { | |
| dl->runWr = val; | |
| } | |
| // set read-head rate multiplier | |
| void delayFadeN_set_mul(delayFadeN* dl, u32 val, u8 id) { | |
| // different terms, dumb... | |
| buffer16_tapN_set_inc( &(dl->tapRd[id]), val ); | |
| } | |
| // set read-head rate divider | |
| void delayFadeN_set_div(delayFadeN* dl, u32 val, u8 id) { | |
| buffer16_tapN_set_div( &(dl->tapRd[id]), val ); | |
| } |