@@ 0,0 1,228 @@
+#include "astrid.h"
+
+#define NAME "longtone"
+
+#define NUMFREQS 8
+#define VOICES 8
+#define WTSIZE 4096
+#define SR 48000
+#define INPUT_CHANNELS 2
+#define OUTPUT_CHANNELS 2
+
+lpfloat_t FREQS_A[NUMFREQS] = {55.f, 110.f, 220.f, 330.f, 440.f, 550.f, 660.f, 770.f};
+lpfloat_t FREQS_B[NUMFREQS] = {61.735f, 123.471f, 246.942f, 370.413f, 493.883f, 617.355f, 740.826, 987.767f};
+
+enum InstrumentParams {
+ PARAM_NOOP,
+ PARAM_PULSEWIDTH,
+ PARAM_FREQS_A,
+ PARAM_FREQS_B,
+ PARAM_OSCA_VOLUME,
+ PARAM_OSCB_VOLUME,
+ NUMPARAMS
+};
+
+typedef struct localctx_t {
+ lpfloat_t limitprev;
+ lpbuffer_t * limitbuf;
+ lpbuffer_t * sinewt;
+ lpbuffer_t * hannwin;
+ lpbuffer_t * hanninwin;
+ lpbuffer_t * hannoutwin;
+ lppulsarosc_t * voicesA[VOICES];
+ lppulsarosc_t * voicesB[VOICES];
+ lpbuffer_t * voice_amp[VOICES];
+ lpfloat_t param_phase;
+ lpfloat_t voice_amp_phase[VOICES];
+ lpfloat_t voice_amp_phaseinc[VOICES];
+ lpfloat_t voice_foldback_prev[VOICES];
+ lpsmoother_t pw_smooth;
+ int numfreqs_a;
+ int numfreqs_b;
+} localctx_t;
+
+lpfloat_t interp(lpfloat_t * buf, size_t size, lpfloat_t phase) {
+ lpfloat_t frac, a, b;
+ size_t i;
+
+ phase *= size;
+ frac = phase - (int)phase;
+ i = (int)phase;
+
+ if (i >= size-1) return 0;
+
+ a = buf[i];
+ b = buf[i+1];
+
+ return (1.0f - frac) * a + (frac * b);
+}
+
+int param_map_callback(void * arg, char * keystr, char * valstr) {
+ lpinstrument_t * instrument = (lpinstrument_t *)arg;
+ localctx_t * ctx = (localctx_t *)instrument->context;
+ float val_f = 0;
+ int32_t val_i32 = 0;
+ lpfloat_t val_floatlist[NUMFREQS] = {220.};
+
+ syslog(LOG_ERR, "Got param %s=%s\n", keystr, valstr);
+
+ if(strcmp(keystr, "pw") == 0) {
+ extract_float_from_token(valstr, &val_f);
+ astrid_instrument_set_param_float(instrument, PARAM_PULSEWIDTH, val_f);
+ } else if(strcmp(keystr, "afreqs") == 0) {
+ ctx->numfreqs_a = extract_floatlist_from_token(valstr, val_floatlist, NUMFREQS);
+ astrid_instrument_set_param_float_list(instrument, PARAM_FREQS_A, val_floatlist, ctx->numfreqs_a);
+ } else if(strcmp(keystr, "bfreqs") == 0) {
+ ctx->numfreqs_b = extract_floatlist_from_token(valstr, val_floatlist, NUMFREQS);
+ astrid_instrument_set_param_float_list(instrument, PARAM_FREQS_B, val_floatlist, ctx->numfreqs_b);
+
+ } else if(strcmp(keystr, "av") == 0) {
+ extract_float_from_token(valstr, &val_f);
+ astrid_instrument_set_param_float(instrument, PARAM_OSCA_VOLUME, val_f);
+ } else if(strcmp(keystr, "bv") == 0) {
+ extract_float_from_token(valstr, &val_f);
+ astrid_instrument_set_param_float(instrument, PARAM_OSCB_VOLUME, val_f);
+
+ } else if(strcmp(keystr, "save") == 0) {
+ extract_int32_from_token(valstr, &val_i32);
+ astrid_instrument_save_param_session_snapshot(instrument, NUMPARAMS, val_i32);
+ } else if(strcmp(keystr, "restore") == 0) {
+ extract_int32_from_token(valstr, &val_i32);
+ astrid_instrument_restore_param_session_snapshot(instrument, val_i32);
+ }
+
+ return 0;
+}
+
+
+int audio_callback(size_t blocksize, __attribute__((unused)) float ** input, float ** output, void * arg) {
+ size_t i;
+ int v;
+ lpfloat_t out, osc_sample, voice, av, bv, amp, ab, pw;
+ lpinstrument_t * instrument = (lpinstrument_t *)arg;
+ localctx_t * ctx = (localctx_t *)instrument->context;
+
+ lpfloat_t freqs_a[NUMFREQS];
+ lpfloat_t freqs_b[NUMFREQS];
+
+ amp = interp(ctx->hanninwin->data, WTSIZE, ctx->param_phase) * 2.f;
+ ab = interp(ctx->hannoutwin->data, WTSIZE, ctx->param_phase);
+ pw = interp(ctx->hannoutwin->data, WTSIZE, ctx->param_phase);
+
+ syslog(LOG_ERR, "amp: %f\nphase:%f\n\n", amp, ctx->param_phase);
+
+ av = astrid_instrument_get_param_float(instrument, PARAM_OSCA_VOLUME, 1.f);
+ bv = astrid_instrument_get_param_float(instrument, PARAM_OSCB_VOLUME, 0.f);
+
+ av = 1.f-ab;
+ bv = ab;
+
+ astrid_instrument_get_param_float_list(instrument, PARAM_FREQS_A, ctx->numfreqs_a, freqs_a);
+ astrid_instrument_get_param_float_list(instrument, PARAM_FREQS_B, ctx->numfreqs_b, freqs_b);
+
+ if(!instrument->is_running) return 1;
+
+ for(i=0; i < blocksize; i++) {
+ osc_sample = out = 0.f;
+
+ for(v=0; v < VOICES; v++) {
+ voice = LPPulsarOsc.process(ctx->voicesA[v]) * av;
+ voice += LPPulsarOsc.process(ctx->voicesB[v]) * bv;
+ voice *= LPInterpolation.linear_pos(ctx->voice_amp[v], ctx->voice_amp_phase[v]);
+ ctx->voice_amp_phase[v] += ctx->voice_amp_phaseinc[v];
+ if(ctx->voice_amp_phase[v] >= 1.f) {
+ ctx->voicesA[v]->freq = (freqs_a[v % ctx->numfreqs_a]*1) + LPRand.rand(-1.f, 1.f);
+ ctx->voicesB[v]->freq = (freqs_b[v % ctx->numfreqs_b]*1) + LPRand.rand(-1.f, 1.f);
+ ctx->voicesA[v]->pulsewidth = pw;
+ ctx->voicesB[v]->pulsewidth = pw;
+ }
+ while(ctx->voice_amp_phase[v] >= 1.f) ctx->voice_amp_phase[v] -= 1.f;
+
+ voice = LPFX.fold(voice, &ctx->voice_foldback_prev[v], instrument->samplerate);
+ osc_sample += voice * 0.5f;
+ }
+
+ out += osc_sample;
+ out = LPFX.limit(out*1.f, &ctx->limitprev, 0.8f, 0.2f, ctx->limitbuf);
+ //out *= amp;
+
+ output[0][i] = out;
+ output[1][i] = out;
+
+ ctx->param_phase += (1.f / instrument->samplerate) * 0.000833f;
+ while(ctx->param_phase >= 1.f) ctx->param_phase -= 1.f;
+ }
+
+ return 0;
+}
+
+
+int main() {
+ int i;
+ lpinstrument_t * instrument;
+ lpinstrument_config_t config = astrid_instrument_init_config(NAME);
+ localctx_t * ctx;
+
+ ctx = (localctx_t *)calloc(1, sizeof(localctx_t));
+ if(ctx == NULL) {
+ printf("Could not alloc ctx: (%d) %s\n", errno, strerror(errno));
+ exit(1);
+ }
+
+ ctx->limitprev = 1.f;
+ ctx->limitbuf = LPBuffer.create(1024, 1, (lpfloat_t)SR);
+
+ ctx->sinewt = LPWavetable.create(WT_SINE, WTSIZE);
+ ctx->hannwin = LPWindow.create(WIN_HANN, WTSIZE);
+ ctx->hannoutwin = LPWindow.create(WIN_HANNOUT, WTSIZE);
+ ctx->hanninwin = LPWindow.create(WIN_SINEIN, WTSIZE);
+ ctx->numfreqs_a = NUMFREQS;
+ ctx->numfreqs_b = NUMFREQS;
+
+ for(i=0; i < VOICES; i++) {
+ ctx->voicesA[i] = LPPulsarOsc.create(2, 2, // number of wavetables, windows
+ WT_SINE, WTSIZE, WT_TRI2, WTSIZE, // wavetables and sizes
+ WIN_SINE, WTSIZE, WIN_HANN, WTSIZE // windows and sizes
+ );
+ ctx->voicesA[i]->freq = FREQS_A[i % NUMFREQS] + LPRand.rand(-1.f, 1.f);
+
+ ctx->voicesB[i] = LPPulsarOsc.create(2, 2, // number of wavetables, windows
+ WT_SINE, WTSIZE, WT_TRI2, WTSIZE, // wavetables and sizes
+ WIN_SINE, WTSIZE, WIN_HANN, WTSIZE // windows and sizes
+ );
+ ctx->voicesB[i]->freq = FREQS_B[i % NUMFREQS] + LPRand.rand(-1.f, 1.f);
+
+ ctx->voice_amp[i] = LPWindow.create(WIN_HANN, WTSIZE);
+ ctx->voice_amp_phase[i] = LPRand.rand(0.f, 1.f);
+ ctx->voice_amp_phaseinc[i] = (1.f/SR) * LPRand.rand(0.08f, 0.15f);
+ }
+
+ config.input_channels = INPUT_CHANNELS;
+ config.output_channels = OUTPUT_CHANNELS;
+ config.ctx = (void*)ctx;
+ config.stream_callback = audio_callback;
+ config.update_callback = param_map_callback;
+ config.initial_volume = 0.2f;
+
+ if((instrument = astrid_instrument_start_from_config(config)) == NULL) {
+ fprintf(stderr, "Could not start instrument: (%d) %s\n", errno, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ astrid_instrument_set_param_float_list(instrument, PARAM_FREQS_A, FREQS_A, NUMFREQS);
+ astrid_instrument_set_param_float_list(instrument, PARAM_FREQS_B, FREQS_B, NUMFREQS);
+
+ /* twiddle thumbs until shutdown */
+ while(instrument->is_running) {
+ astrid_instrument_tick(instrument);
+ }
+
+ /* stop jack and cleanup threads */
+ if(astrid_instrument_stop(instrument) < 0) {
+ fprintf(stderr, "There was a problem stopping the instrument. (%d) %s\n", errno, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Done!\n");
+ return 0;
+}
@@ 0,0 1,126 @@
+#include "astrid.h"
+
+#define NAME "rec"
+
+#define WTSIZE 4096
+#define SR 48000
+#define INPUT_CHANNELS 2
+#define OUTPUT_CHANNELS 2
+
+enum InstrumentParams {
+ PARAM_NOOP,
+ PARAM_REC_ENABLED,
+ NUMPARAMS
+};
+
+typedef struct localctx_t {
+ lpbuffer_t * recbuf;
+} localctx_t;
+
+void ringbuffer_write_channel(lpbuffer_t * ringbuf, lpfloat_t sample, int channel, size_t offset) {
+ size_t index = 0;
+ if (channel >= ringbuf->channels) return;
+ index = ((ringbuf->pos+offset) * ringbuf->channels + channel) % (ringbuf->length * ringbuf->channels);
+ ringbuf->data[index] = sample;
+}
+
+lpfloat_t ringbuffer_read_channel(lpbuffer_t * ringbuf, int channel, size_t offset) {
+ size_t index = 0;
+ if (channel >= ringbuf->channels) return 0.0f;
+ index = ((ringbuf->pos+offset) * ringbuf->channels + channel) % (ringbuf->length * ringbuf->channels);
+ return ringbuf->data[index];
+}
+
+/*
+int param_map_callback(void * arg, char * keystr, char * valstr) {
+ lpinstrument_t * instrument = (lpinstrument_t *)arg;
+ int32_t val_i32 = 0;
+ syslog(LOG_ERR, "Got param %s=%s\n", keystr, valstr);
+
+ if(strcmp(keystr, "rec") == 0) {
+ extract_int32_from_token(valstr, &val_i32);
+ astrid_instrument_set_param_int32(instrument, PARAM_REC_ENABLED, val_i32);
+ } else if(strcmp(keystr, "save") == 0) {
+ extract_int32_from_token(valstr, &val_i32);
+ astrid_instrument_save_param_session_snapshot(instrument, NUMPARAMS, val_i32);
+ } else if(strcmp(keystr, "restore") == 0) {
+ extract_int32_from_token(valstr, &val_i32);
+ astrid_instrument_restore_param_session_snapshot(instrument, val_i32);
+ }
+
+ return 0;
+}
+*/
+
+
+int audio_callback(size_t blocksize, float ** input, float ** output, void * arg) {
+ size_t i, c, offset;
+ int32_t rec_enabled;
+ lpinstrument_t * instrument = (lpinstrument_t *)arg;
+ localctx_t * ctx = (localctx_t *)instrument->context;
+
+ rec_enabled = astrid_instrument_get_param_int32(instrument, PARAM_REC_ENABLED, 1);
+ rec_enabled = 1;
+ offset = SR*7;
+
+ if(!instrument->is_running) return 1;
+
+ for(i=0; i < blocksize; i++) {
+ if(rec_enabled) {
+ for(c=0; c < INPUT_CHANNELS; c++) {
+ ringbuffer_write_channel(ctx->recbuf, input[c][i], c, i);
+ }
+ }
+
+ for(c=0; c < OUTPUT_CHANNELS; c++) {
+ output[c][i] = ringbuffer_read_channel(ctx->recbuf, c, i-offset);
+ }
+ }
+
+ ctx->recbuf->pos += blocksize;
+ ctx->recbuf->pos = ctx->recbuf->pos % ctx->recbuf->length;
+
+ return 0;
+}
+
+int main() {
+ lpinstrument_t * instrument;
+ lpinstrument_config_t config = astrid_instrument_init_config(NAME);
+ localctx_t * ctx;
+
+ ctx = (localctx_t *)calloc(1, sizeof(localctx_t));
+ if(ctx == NULL) {
+ printf("Could not alloc ctx: (%d) %s\n", errno, strerror(errno));
+ exit(1);
+ }
+
+ ctx->recbuf = LPBuffer.create(SR * 10, INPUT_CHANNELS, SR);
+
+ config.input_channels = INPUT_CHANNELS;
+ config.output_channels = OUTPUT_CHANNELS;
+ config.ctx = (void*)ctx;
+ config.stream_callback = audio_callback;
+ //config.update_callback = param_map_callback;
+ config.initial_volume = 0.2f;
+
+ //astrid_config_register_param_int32(&config, PARAM_REC_ENABLED, "rec");
+
+ if((instrument = astrid_instrument_start_from_config(config)) == NULL) {
+ fprintf(stderr, "Could not start instrument: (%d) %s\n", errno, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ /* twiddle thumbs until shutdown */
+ while(instrument->is_running) {
+ astrid_instrument_tick(instrument);
+ }
+
+ /* stop jack and cleanup threads */
+ if(astrid_instrument_stop(instrument) < 0) {
+ fprintf(stderr, "There was a problem stopping the instrument. (%d) %s\n", errno, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Done!\n");
+ return 0;
+}