@@ 841,7 841,7 @@ int lpsampler_write_ringbuffer_block(
/* Aquire a lock on the buffer */
if(lpsampler_aquire(name) < 0) {
- syslog(LOG_ERR, "lpsampler_write_ringbuffer_block: Could not aquire ADC buffer shm for update\n");
+ syslog(LOG_ERR, "lpsampler_write_ringbuffer_block: Could not aquire buffer shm for update\n");
return -1;
}
@@ 874,6 874,54 @@ int lpsampler_write_ringbuffer_block(
return 0;
}
+int lpsampler_overdub_ringbuffer_block(
+ char * name,
+ lpbuffer_t * buf,
+ float ** block,
+ int channels,
+ lpfloat_t volume,
+ lpfloat_t feedback,
+ size_t blocksize_in_frames
+ ) {
+ size_t insert_pos, i, boundry;
+ int c;
+ float * channelp;
+ float sample = 0;
+
+ /* Aquire a lock on the buffer */
+ if(lpsampler_aquire(name) < 0) {
+ syslog(LOG_ERR, "lpsampler_overdub_ringbuffer_block: Could not aquire buffer shm for update\n");
+ return -1;
+ }
+
+ boundry = buf->length * channels;
+
+ /* Copy the block */
+ for(c=0; c < channels; c++) {
+ channelp = block[c];
+ for(i=0; i < blocksize_in_frames; i++) {
+ insert_pos = ((buf->pos+i) * channels + c) % boundry;
+ sample = *channelp++;
+ buf->data[insert_pos] += (lpfilternan(sample) * volume) + (buf->data[insert_pos] * feedback);
+ }
+ }
+
+ /* Increment the write position */
+ buf->pos += blocksize_in_frames;
+ while(buf->pos >= buf->length) {
+ buf->pos -= buf->length;
+ }
+
+ /* Release the lock on the buffer */
+ if(lpsampler_release(name) < 0) {
+ syslog(LOG_ERR, "lpsampler_overdub_ringbuffer_block: Could not release buffer shm after update\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
int lpsampler_read_ringbuffer_block(
char * name,
lpbuffer_t * buf,
@@ 1018,224 1066,6 @@ int lpserial_getctl(int device_id, int ctl, lpfloat_t * value) {
return 0;
}
-
-/* MIDI trigger maps for noteon
- * (and eventually cc triggers)
- * ***************************/
-
-int lpmidi_add_msg_to_notemap(int device_id, int note, lpmsg_t msg) {
- int fd, bytes_written;
- size_t notemap_path_length;
- char * notemap_path;
-
- notemap_path_length = snprintf(NULL, 0, ASTRID_MIDIMAP_NOTEBASE_PATH, device_id, note) + 1;
- notemap_path = (char *)calloc(1, notemap_path_length);
- snprintf(notemap_path, notemap_path_length, ASTRID_MIDIMAP_NOTEBASE_PATH, device_id, note);
-
- if((fd = open(notemap_path, O_RDWR | O_CREAT | O_APPEND, LPIPC_PERMS)) < 0) {
- syslog(LOG_ERR, "Could not open file for appending. Error: %s\n", strerror(errno));
- return -1;
- }
-
- if((bytes_written = write(fd, &msg, sizeof(lpmsg_t))) < 0) {
- syslog(LOG_ERR, "Could not append msg to file. Error: %s\n", strerror(errno));
- return -1;
- }
-
- if(bytes_written != sizeof(lpmsg_t)) {
- syslog(LOG_ERR, "Wrote incorrect number of bytes to notemap. Expected %d, wrote %d\n", (int)sizeof(lpmsg_t), bytes_written);
- return -1;
- }
-
- if(close(fd) < 0) {
- syslog(LOG_ERR, "Could not close notemap file after writing. Error: %s\n", strerror(errno));
- return -1;
- }
-
- free(notemap_path);
-
- return 0;
-}
-
-int lpmidi_remove_msg_from_notemap(int device_id, int note, int index_to_remove) {
- int fd, bytes_read, bytes_written, map_index;
- struct stat statbuf;
- size_t notemap_path_length, notemap_size, read_pos;
- char * notemap_path;
- lpmsg_t msg = {0};
-
- notemap_path_length = snprintf(NULL, 0, ASTRID_MIDIMAP_NOTEBASE_PATH, device_id, note) + 1;
- notemap_path = (char *)calloc(1, notemap_path_length);
- snprintf(notemap_path, notemap_path_length, ASTRID_MIDIMAP_NOTEBASE_PATH, device_id, note);
-
- if((fd = open(notemap_path, O_RDWR)) < 0) {
- syslog(LOG_ERR, "Could not open file for printing. Error: %s\n", strerror(errno));
- return -1;
- }
-
- if(fstat(fd, &statbuf) < 0) {
- syslog(LOG_ERR, "Could not stat notemap file. Error: %s\n", strerror(errno));
- return -1;
- }
-
- notemap_size = statbuf.st_size;
- map_index = 0;
- for(read_pos=0; read_pos < notemap_size; read_pos += sizeof(lpmsg_t)) {
- if((bytes_read = read(fd, &msg, sizeof(lpmsg_t))) < 0) {
- syslog(LOG_ERR, "Could not read msg from file during removal walk. Error: %s\n", strerror(errno));
- return -1;
- }
-
- if(map_index == index_to_remove) {
- msg.type = LPMSG_EMPTY;
-
- if(lseek(fd, read_pos, SEEK_SET) < 0) {
- syslog(LOG_ERR, "Could not rewind midimap to remove msg from file. Error: %s\n", strerror(errno));
- return -1;
- }
-
- if((bytes_written = write(fd, &msg, sizeof(lpmsg_t))) < 0) {
- syslog(LOG_ERR, "Could not remove msg from file. Error: %s\n", strerror(errno));
- return -1;
- }
- }
-
- map_index += 1;
- }
-
- if(close(fd) < 0) {
- syslog(LOG_ERR, "Could not close notemap file after msg removal. Error: %s\n", strerror(errno));
- return -1;
- }
-
- free(notemap_path);
-
- return 0;
-}
-
-int lpmidi_print_notemap(int device_id, int note) {
- int fd, bytes_read, map_index;
- struct stat statbuf;
- size_t notemap_path_length, notemap_size, read_pos;
- char * notemap_path;
- lpmsg_t msg = {0};
-
- notemap_path_length = snprintf(NULL, 0, ASTRID_MIDIMAP_NOTEBASE_PATH, device_id, note) + 1;
- notemap_path = (char *)calloc(1, notemap_path_length);
- snprintf(notemap_path, notemap_path_length, ASTRID_MIDIMAP_NOTEBASE_PATH, device_id, note);
-
- if((fd = open(notemap_path, O_RDONLY)) < 0) {
- syslog(LOG_ERR, "Could not open file for printing. Error: %s\n", strerror(errno));
- return -1;
- }
-
- if(fstat(fd, &statbuf) < 0) {
- syslog(LOG_ERR, "Could not stat notemap file. Error: %s\n", strerror(errno));
- return -1;
- }
-
- notemap_size = statbuf.st_size;
- map_index = 0;
- for(read_pos=0; read_pos < notemap_size; read_pos += sizeof(lpmsg_t)) {
- if((bytes_read = read(fd, &msg, sizeof(lpmsg_t))) < 0) {
- syslog(LOG_ERR, "Could not read msg from file. Error: %s\n", strerror(errno));
- return -1;
- }
-
- printf("\nmap_index: %d\n", map_index);
- printf("bytes_read: %d, read_pos: %ld, notemap_size: %ld\n", bytes_read, read_pos, notemap_size);
- printf("msg.type: %d msg.initiated: %f msg.instrument_name: %s\n", msg.type, msg.initiated, msg.instrument_name);
- if(msg.type == LPMSG_EMPTY) {
- printf("this message is empty!\n");
- }
-
- map_index += 1;
- }
-
- if(close(fd) < 0) {
- syslog(LOG_ERR, "Could not close notemap file after reading. Error: %s\n", strerror(errno));
- return -1;
- }
-
- free(notemap_path);
-
- return 0;
-}
-
-int lpmidi_trigger_notemap(int device_id, int note) {
- int fd, bytes_read;
- struct stat statbuf;
- size_t notemap_path_length, notemap_size, read_pos;
- char * notemap_path;
- double now = 0;
- lpmsg_t msg = {0};
-
- notemap_path_length = snprintf(NULL, 0, ASTRID_MIDIMAP_NOTEBASE_PATH, device_id, note) + 1;
- notemap_path = (char *)calloc(1, notemap_path_length);
- snprintf(notemap_path, notemap_path_length, ASTRID_MIDIMAP_NOTEBASE_PATH, device_id, note);
-
- if(access(notemap_path, F_OK) < 0) {
- syslog(LOG_DEBUG, "No notemap for %s\n", notemap_path);
- return 0;
- }
-
- if((fd = open(notemap_path, O_RDWR)) < 0) {
- syslog(LOG_ERR, "Could not open notemap file for triggering. Error: %s\n", strerror(errno));
- return -1;
- }
-
- if(fstat(fd, &statbuf) < 0) {
- syslog(LOG_ERR, "Could not stat notemap file for triggering. Error: %s\n", strerror(errno));
- return -1;
- }
-
- notemap_size = statbuf.st_size;
- for(read_pos=0; read_pos < notemap_size; read_pos += sizeof(lpmsg_t)) {
- if((bytes_read = read(fd, &msg, sizeof(lpmsg_t))) < 0) {
- syslog(LOG_ERR, "Could not read msg from file during notemap trigger walk. Error: %s\n", strerror(errno));
- return -1;
- }
-
- if(msg.type == LPMSG_EMPTY) continue;
-
- if(lpscheduler_get_now_seconds(&now) < 0) {
- syslog(LOG_ERR, "Could not get now seconds during notemap trigger. Error: %s\n", strerror(errno));
- return -1;
- }
-
- msg.initiated = now;
-
- syslog(LOG_INFO, "Sending message from lpmidi trigger notemap\ninitiated %f\nscheduled %f\ninterval %f\noffset %f\nmax_processing_time %f\nonset_delay %ld\nvoice_id %ld\ncount %ld\ntype %d\nmsg %s\nname %s\n\n",
- msg.initiated,
- msg.scheduled,
- msg.interval,
- msg.offset,
- msg.max_processing_time,
- msg.onset_delay,
- msg.voice_id,
- msg.count,
- msg.type,
- msg.msg,
- msg.instrument_name
- );
-
- if(send_message(msg.instrument_name, msg) < 0) {
- syslog(LOG_ERR, "Could not schedule msg for sending during notemap trigger. Error: %s\n", strerror(errno));
- return -1;
- }
- syslog(LOG_INFO, "Sent! lpmidi trigger notemap message\n");
- }
-
- if(close(fd) < 0) {
- syslog(LOG_ERR, "Could not close notemap file after triggering. Error: %s\n", strerror(errno));
- return -1;
- }
-
- free(notemap_path);
-
- return 0;
-}
-
int lpmidi_relay_to_instrument(char * instrument_name, unsigned char mtype, unsigned char mid, unsigned char mval) {
lpmsg_t msg = {0};
size_t offset = 0;
@@ 2251,6 2081,28 @@ int lpscheduler_get_now_seconds(double * now) {
return 0;
}
+int lpscheduler_get_now_ticks(size_t * now, int samplerate) {
+ // ticks == frames @ given samplerate
+ clockid_t cid;
+ struct timespec ts;
+
+#if defined(__linux__)
+ cid = CLOCK_MONOTONIC_RAW;
+#else
+ cid = CLOCK_MONOTONIC;
+#endif
+
+ if(clock_gettime(cid, &ts) < 0) {
+ syslog(LOG_ERR, "scheduler_get_now_seconds: clock_gettime error: %s\n", strerror(errno));
+ return -1;
+ }
+
+ *now = (size_t)ts.tv_sec * samplerate;
+ *now += (size_t)(((size_t)ts.tv_nsec * samplerate) * 1e-9);
+
+ return 0;
+}
+
void scheduler_get_now(struct timespec * now) {
clock_gettime(CLOCK_MONOTONIC_RAW, now);
}
@@ 2369,7 2221,7 @@ static inline void start_playing(lpscheduler_t * s, lpevent_t * e) {
lpevent_t * current;
lpevent_t * prev;
- syslog(LOG_INFO, "START playing event ID %ld\n", e->id);
+ syslog(LOG_DEBUG, "START playing event ID %ld\n", e->id);
/* Remove from the waiting queue */
if(s->waiting_queue_head == NULL) {
@@ 2406,7 2258,7 @@ static inline void stop_playing(lpscheduler_t * s, lpevent_t * e) {
lpevent_t * current;
lpevent_t * prev;
- syslog(LOG_INFO, "STOP playing event ID %ld\n", e->id);
+ syslog(LOG_DEBUG, "STOP playing event ID %ld\n", e->id);
/* Remove from the playing stack */
if(s->playing_stack_head == NULL) {
@@ 2477,18 2329,21 @@ lpscheduler_t * scheduler_create(int realtime, int channels, lpfloat_t samplerat
/* look for events waiting to be scheduled */
static inline void scheduler_update(lpscheduler_t * s) {
+ size_t now_ticks = 0;
lpevent_t * current;
void * next;
+
+ lpscheduler_get_now_ticks(&now_ticks, s->samplerate);
if(s->waiting_queue_head != NULL) {
current = s->waiting_queue_head;
while(current->next != NULL) {
next = current->next;
- if(s->ticks >= current->onset) {
+ if(now_ticks >= current->onset) {
start_playing(s, current);
}
current = (lpevent_t *)next;
}
- if(s->ticks >= current->onset) {
+ if(now_ticks >= current->onset) {
start_playing(s, current);
}
}
@@ 2592,14 2447,13 @@ void lpscheduler_tick(lpscheduler_t * s) {
/* Increment process ticks and update now timestamp */
s->ticks += 1;
- if(s->realtime == 1) {
- scheduler_get_now(s->now);
- } else {
+ if(s->realtime == 0) {
scheduler_increment_timespec_by_ns(s->now, s->tick_ns);
}
}
void scheduler_schedule_event(lpscheduler_t * s, lpbuffer_t * buf, size_t onset_delay) {
+ size_t now_ticks = 0;
lpevent_t * e;
e = (lpevent_t *)LPMemoryPool.alloc(1, sizeof(lpevent_t));
@@ 2610,10 2464,12 @@ void scheduler_schedule_event(lpscheduler_t * s, lpbuffer_t * buf, size_t onset_
e->buf = buf;
e->pos = 0;
- e->onset = s->ticks + onset_delay;
+ //e->onset = s->ticks + onset_delay;
+ lpscheduler_get_now_ticks(&now_ticks, s->samplerate);
+ e->onset = now_ticks + onset_delay;
- syslog(LOG_INFO, "scheduling event ID %ld\n", e->id);
- syslog(LOG_INFO, " with onset %ld\n", e->onset);
+ syslog(LOG_DEBUG, "scheduling event ID %ld\n", e->id);
+ syslog(LOG_DEBUG, " with onset %ld\n", e->onset);
start_waiting(s, e);
}
@@ 2692,14 2548,12 @@ int scheduler_cleanup_nursery(lpscheduler_t * s) {
current = s->nursery_head;
while(current->next != NULL) {
next = (lpevent_t *)current->next;
- syslog(LOG_INFO, "freeing event ID %ld\n", current->id);
LPBuffer.destroy(current->buf);
free(current);
current = next;
}
if(current != NULL) {
- syslog(LOG_INFO, "freeing event ID %ld\n", current->id);
LPBuffer.destroy(current->buf);
free(current);
}
@@ 2719,13 2573,16 @@ int astrid_instrument_jack_callback(jack_nframes_t nframes, void * arg) {
lpinstrument_t * instrument = (lpinstrument_t *)arg;
float * output_channels[instrument->output_channels];
float * input_channels[instrument->input_channels];
- lpfloat_t volume;
- size_t i;
+ lpfloat_t volume, now=0;
+ size_t i, offset_in_ticks, period_in_ticks, trigger_reset,
+ last_trigger_time, next_trigger_time, delay_from_now_ticks,
+ block_start, block_end, now_ticks=0;
int c;
if(!instrument->is_running) return 0;
- syslog(LOG_DEBUG, "JACK CALLBACK: Begin. input_channels=%d output_channels=%d nframes=%ld %s\n", instrument->input_channels, instrument->output_channels, (size_t)nframes, instrument->name);
+ lpscheduler_get_now_ticks(&now_ticks, instrument->samplerate);
+ lpscheduler_get_now_seconds(&now);
if(!instrument->has_been_initialized) {
syslog(LOG_DEBUG, "Seeding the random number generator from the audio callback. %s\n", instrument->name);
@@ 2735,7 2592,6 @@ int astrid_instrument_jack_callback(jack_nframes_t nframes, void * arg) {
// or is there a reason to have mainthread-before AND audiothread-before?
}
- syslog(LOG_DEBUG, "Zeroing output and getting channel buffers. %s\n", instrument->name);
for(c=0; c < instrument->input_channels; c++) {
input_channels[c] = (float *)jack_port_get_buffer(instrument->inports[c], nframes);
}
@@ 2745,14 2601,12 @@ int astrid_instrument_jack_callback(jack_nframes_t nframes, void * arg) {
}
/* write the block into the adc ringbuffer */
- syslog(LOG_DEBUG, "Writing block to adc ringbuffer. %s\n", instrument->name);
if(lpsampler_write_ringbuffer_block(instrument->adcname, instrument->adcbuf, input_channels, instrument->input_channels, nframes) < 0) {
syslog(LOG_ERR, "Error writing into adc ringbuf\n");
return 0;
}
/* mix in async renders */
- syslog(LOG_DEBUG, "Mixing async renders. %s\n", instrument->name);
for(i=0; i < (size_t)nframes; i++) {
lpscheduler_tick(instrument->async_mixer);
for(c=0; c < instrument->output_channels; c++) {
@@ 2760,11 2614,7 @@ int astrid_instrument_jack_callback(jack_nframes_t nframes, void * arg) {
}
}
- syslog(LOG_DEBUG, "Checking stream callback. %s\n", instrument->name);
if(instrument->stream != NULL) {
- syslog(LOG_DEBUG, "Mixing stream callback. %s\n", instrument->name);
- syslog(LOG_DEBUG, "Mixing stream callback. input=%f\n", input_channels[0][0]);
- syslog(LOG_DEBUG, "Mixing stream callback. output=%f\n", output_channels[0][0]);
if(instrument->stream((size_t)nframes, input_channels, output_channels, (void *)instrument) < 0) {
return -1;
}
@@ 2773,7 2623,6 @@ int astrid_instrument_jack_callback(jack_nframes_t nframes, void * arg) {
/* write the output block into the resampler ringbuffer */
if(astrid_instrument_get_param_int32(instrument, instrument->resampler_param_rec, 1) == 1) {
/* TODO: support overdub with feedback, toggling rec on/off */
- syslog(LOG_DEBUG, "Writing output to resampler ringbuffer. %s\n", instrument->name);
if(lpsampler_write_ringbuffer_block(instrument->resamplername, instrument->resamplerbuf, output_channels, instrument->output_channels, nframes) < 0) {
syslog(LOG_ERR, "Error writing into resampler ringbuf\n");
return 0;
@@ 2782,27 2631,88 @@ int astrid_instrument_jack_callback(jack_nframes_t nframes, void * arg) {
/* clamp output and apply post fader volume */
volume = astrid_instrument_get_param_float(instrument, instrument->param_volume, instrument->initial_volume);
- syslog(LOG_DEBUG, "Clamping output w/volume %f. %s\n", volume, instrument->name);
for(c=0; c < instrument->output_channels; c++) {
for(i=0; i < (size_t)nframes; i++) {
output_channels[c][i] = fmax(-1.f, fmin(output_channels[c][i] * volume, 1.f));
}
}
- syslog(LOG_DEBUG, "JACK CALLBACK: Done. %s\n", instrument->name);
+ /* if autotrigger is engaged, see if we need to send a trigger */
+ if(instrument->autotrigger_is_enabled) {
+ block_start = now_ticks;
+ block_end = block_start + nframes;
+
+ last_trigger_time = astrid_instrument_get_param_int32(instrument, instrument->param_last_trigger_time, now_ticks);
+ period_in_ticks = astrid_instrument_get_param_int32(instrument, instrument->param_period_in_ticks, instrument->samplerate);
+ offset_in_ticks = astrid_instrument_get_param_int32(instrument, instrument->param_offset_in_ticks, 0);
+ trigger_reset = astrid_instrument_get_param_int32(instrument, instrument->param_trigger_reset, 0);
+
+
+ if(trigger_reset != 0) {
+ instrument->autotrigger_msg.count = 0;
+
+ // set the offset to align the phase to 0 at now
+ astrid_instrument_set_param_int32(instrument, instrument->param_offset_in_ticks, 0);
+ offset_in_ticks = 0;
+
+ // update last trigger time, send the trigger and unset the reset flag
+ astrid_instrument_set_param_int32(instrument, instrument->param_last_trigger_time, now_ticks);
+ astrid_instrument_set_param_int32(instrument, instrument->param_trigger_reset, 0);
+ }
+
+ next_trigger_time = last_trigger_time + period_in_ticks + offset_in_ticks;
+ instrument->autotrigger_msg.initiated = now_ticks;
+
+ //if(next_trigger_time < now_ticks) next_trigger_time = now_ticks;
+
+ c = 0;
+ while(next_trigger_time < block_end && c < 10) {
+ c += 1;
+ delay_from_now_ticks = next_trigger_time - now_ticks;
+#if 0
+ syslog(LOG_INFO, "%s block_end=%ld\n", instrument->name, block_end);
+ syslog(LOG_INFO, "%s now_ticks=%ld\n", instrument->name, now_ticks);
+ syslog(LOG_INFO, "%s last_trigger_time=%ld\n", instrument->name, last_trigger_time);
+ syslog(LOG_INFO, "%s next_trigger_time=%ld\n", instrument->name, next_trigger_time);
+ syslog(LOG_INFO, "%s period_in_ticks=%ld\n", instrument->name, period_in_ticks);
+ syslog(LOG_INFO, "%s offset_in_ticks=%ld\n", instrument->name, offset_in_ticks);
+ syslog(LOG_INFO, "%s delay_from_now_ticks=%ld\n", instrument->name, delay_from_now_ticks);
+#endif
+ instrument->autotrigger_msg.scheduled = (lpfloat_t)delay_from_now_ticks / (lpfloat_t)instrument->samplerate;
+ if(relay_message_to_seq(instrument, instrument->autotrigger_msg) < 0) {
+ syslog(LOG_ERR, "%s renderer: Could not read relay message to seq. Error: (%d) %s\n", instrument->name, errno, strerror(errno));
+ }
+
+ last_trigger_time = next_trigger_time;
+ astrid_instrument_set_param_int32(instrument, instrument->param_last_trigger_time, last_trigger_time);
+ next_trigger_time += period_in_ticks;
+ }
+
+ //next_trigger_time = last_trigger_time + period_in_ticks + offset_in_ticks;
+
+ /*
+ if(now_ticks >= next_trigger_time) {
+ instrument->autotrigger_msg.count += 1;
+ send_play_message(instrument->autotrigger_msg);
+ astrid_instrument_set_param_int32(instrument, instrument->param_last_trigger_time, now_ticks);
+ }
+ */
+ }
+
+
return 0;
}
/* instrument seq priority queue callbacks */
-static int msgpq_cmp_pri(double next, double curr) {
+static int msgpq_cmp_pri(size_t next, size_t curr) {
return (next > curr);
}
-static double msgpq_get_pri(void * a) {
+static size_t msgpq_get_pri(void * a) {
return ((lpmsgpq_node_t *)a)->timestamp;
}
-static void msgpq_set_pri(void * a, double timestamp) {
+static void msgpq_set_pri(void * a, size_t timestamp) {
((lpmsgpq_node_t *)a)->timestamp = timestamp;
}
@@ 2843,7 2753,7 @@ void * instrument_seq_pq(void * arg) {
lpmsg_t * msg;
lpmsgpq_node_t * node;
void * d;
- double now;
+ size_t now = 0;
now = 0;
syslog(LOG_DEBUG, ":::: INSTRUMENT SEQ PQ STARTING ::::\n");
@@ 2871,7 2781,7 @@ void * instrument_seq_pq(void * arg) {
}
/* Get now */
- if(lpscheduler_get_now_seconds(&now) < 0) {
+ if(lpscheduler_get_now_ticks(&now, instrument->samplerate) < 0) {
syslog(LOG_CRIT, "Error getting now in message scheduler\n");
exit(1);
}
@@ 2903,7 2813,7 @@ void * instrument_seq_pq(void * arg) {
int relay_message_to_seq(lpinstrument_t * instrument, lpmsg_t msg) {
lpmsgpq_node_t * d;
- double seq_delay, now=0;
+ size_t seq_delay, now=0;
syslog(LOG_DEBUG, "SEQ PQ MSG: got a scheduled message to insert into the sequencer priority queue\n");
syslog(LOG_DEBUG, "SEQ PQ MSG: pqnode_index=%d\n", instrument->pqnode_index);
@@ 2913,17 2823,17 @@ int relay_message_to_seq(lpinstrument_t * instrument, lpmsg_t msg) {
instrument->pqnode_index += 1;
while(instrument->pqnode_index >= NUM_NODES) instrument->pqnode_index -= NUM_NODES;
- if(lpscheduler_get_now_seconds(&now) < 0) {
+ if(lpscheduler_get_now_ticks(&now, instrument->samplerate) < 0) {
syslog(LOG_CRIT, "SEQ PQ MSG: Error getting now in seq relay\n");
return -1;
}
/* Hold on to the message as long as possible while still
* trying to leave some time for processing before the target deadline */
- seq_delay = msg.scheduled - (msg.max_processing_time * 2);
+ seq_delay = (msg.scheduled * instrument->samplerate) - (msg.max_processing_time * 2);
d->timestamp = msg.initiated + seq_delay;
- syslog(LOG_DEBUG, "d->timestamp=%f msg.scheduled=%f msg.initiated=%f\n",
+ syslog(LOG_DEBUG, "d->timestamp=%ld msg.scheduled=%f msg.initiated=%ld\n",
d->timestamp, msg.scheduled, msg.initiated);
// Remove the scheduled flag before relaying the message
@@ 2960,8 2870,6 @@ void * instrument_message_thread(void * arg) {
//double processing_time_so_far, onset_delay_in_seconds, now=0;
lpinstrument_t * instrument = (lpinstrument_t *)arg;
int is_scheduled = 0;
- double now = 0.f;
- size_t onset_delay, ticks, grid_interval=0;
instrument->is_waiting = 1;
while(instrument->is_running) {
@@ 2972,14 2880,12 @@ void * instrument_message_thread(void * arg) {
}
is_scheduled = ((instrument->msg.flags & LPFLAG_IS_SCHEDULED) == LPFLAG_IS_SCHEDULED);
- syslog(LOG_INFO, "C MSG: name=%s\n", instrument->msg.instrument_name);
- syslog(LOG_INFO, "C MSG: scheduled=%f\n", instrument->msg.scheduled);
- syslog(LOG_INFO, "C MSG: interval=%f\n", instrument->msg.interval);
- syslog(LOG_INFO, "C MSG: offset=%f\n", instrument->msg.offset);
- syslog(LOG_INFO, "C MSG: voice_id=%d\n", (int)instrument->msg.voice_id);
- syslog(LOG_INFO, "C MSG: type=%d\n", (int)instrument->msg.type);
- syslog(LOG_INFO, "C MSG: flags=%d\n", (int)instrument->msg.flags);
- syslog(LOG_INFO, "C MSG: is_scheduled=%d\n", is_scheduled);
+ syslog(LOG_DEBUG, "C MSG: name=%s\n", instrument->msg.instrument_name);
+ syslog(LOG_DEBUG, "C MSG: scheduled=%f\n", instrument->msg.scheduled);
+ syslog(LOG_DEBUG, "C MSG: voice_id=%d\n", (int)instrument->msg.voice_id);
+ syslog(LOG_DEBUG, "C MSG: type=%d\n", (int)instrument->msg.type);
+ syslog(LOG_DEBUG, "C MSG: flags=%d\n", (int)instrument->msg.flags);
+ syslog(LOG_DEBUG, "C MSG: is_scheduled=%d\n", is_scheduled);
// Handle shutdown early
if(instrument->msg.type == LPMSG_SHUTDOWN) {
@@ 3030,19 2936,7 @@ void * instrument_message_thread(void * arg) {
}
/* Schedule the buffer for playback */
- lpscheduler_get_now_seconds(&now);
- onset_delay = 0;
- if(bufmsg.interval > 0) {
- ticks = (size_t)(now * instrument->samplerate);
- grid_interval = (size_t)(bufmsg.interval * instrument->samplerate);
- onset_delay = grid_interval - (ticks % grid_interval);
- }
-
- if(bufmsg.offset > 0) {
- onset_delay += (size_t)(bufmsg.offset * instrument->samplerate);
- }
-
- scheduler_schedule_event(instrument->async_mixer, buf, onset_delay);
+ scheduler_schedule_event(instrument->async_mixer, buf, 0);
//scheduler_debug(instrument->async_mixer);
break;
@@ 3413,7 3307,7 @@ handle_serial_message_events:
void * instrument_midi_listener_thread(void * arg) {
snd_seq_t * seq_handle;
- snd_seq_event_t * event;
+ snd_seq_event_t * event = NULL;
int ret, port;
lpinstrument_t * instrument = (lpinstrument_t *)arg;
@@ 3443,6 3337,13 @@ void * instrument_midi_listener_thread(void * arg) {
while(instrument->is_running) {
snd_seq_event_input(seq_handle, &event);
+
+ if(event == NULL) {
+ syslog(LOG_ERR, "%s midi listener: Got NULL event, skipping...\n", instrument->name);
+ usleep((useconds_t)10000);
+ continue;
+ }
+
switch(event->type) {
case SND_SEQ_EVENT_NOTEON:
lpmidi_relay_to_instrument(instrument->name, NOTE_ON, event->data.note.note, event->data.note.velocity);
@@ 3566,12 3467,11 @@ lpinstrument_t * astrid_instrument_start_from_config(lpinstrument_config_t confi
int c=0;
const char ** ports;
int port_count=0;
- char hash_key[PATH_MAX] = {0};
instrument = (lpinstrument_t *)LPMemoryPool.alloc(1, sizeof(lpinstrument_t));
memset(instrument, 0, sizeof(lpinstrument_t));
- setlogmask(LOG_UPTO(LOG_ERR));
+ setlogmask(LOG_UPTO(LOG_INFO));
openlog(config.name, LOG_PID, LOG_USER);
syslog(LOG_DEBUG, "starting %s instrument...\n", config.name);
@@ 3588,6 3488,7 @@ lpinstrument_t * astrid_instrument_start_from_config(lpinstrument_config_t confi
instrument->trigger = config.trigger_callback;
instrument->ext_relay_enabled = config.ext_relay_enabled;
instrument->is_ready = 1;
+ instrument->autotrigger_is_enabled = config.autotrigger_is_enabled;
instrument->midiin_device_id = -1;
if(config.midiin_device_name != NULL) {
@@ 3676,6 3577,12 @@ lpinstrument_t * astrid_instrument_start_from_config(lpinstrument_config_t confi
/* init scheduler */
instrument->async_mixer = scheduler_create(1, instrument->output_channels, instrument->samplerate);
+ /* Prepare the message structs */
+ init_instrument_message(&instrument->msg, instrument->name);
+ init_instrument_message(&instrument->cmd, instrument->name);
+ init_instrument_message(&instrument->autotrigger_msg, instrument->name);
+ instrument->autotrigger_msg.type = LPMSG_TRIGGER;
+
/* Set the main jack callback which always runs: maybe there is an analysis-only use to support too? */
jack_set_process_callback(instrument->jack_client, astrid_instrument_jack_callback, (void *)instrument);
for(c=0; c < instrument->output_channels; c++) {
@@ 3747,34 3654,28 @@ lpinstrument_t * astrid_instrument_start_from_config(lpinstrument_config_t confi
/* Create the internal ringbuffer for sampling from the adc */
snprintf(instrument->adcname, PATH_MAX, "%s-adc", instrument->name);
if((instrument->adcbuf = lpsampler_create(instrument->adcname, config.adc_length, instrument->input_channels, instrument->samplerate)) == NULL) {
- syslog(LOG_INFO, "Could not create instrument ADC buffer\n");
+ syslog(LOG_CRIT, "Could not create instrument ADC buffer\n");
goto astrid_instrument_shutdown_with_error;
}
/* Create the internal ringbuffer for resampling */
snprintf(instrument->resamplername, PATH_MAX, "%s-resampler", instrument->name);
if((instrument->resamplerbuf = lpsampler_create(instrument->resamplername, config.resampler_length, instrument->output_channels, instrument->samplerate)) == NULL) {
- syslog(LOG_INFO, "Could not create instrument resampler buffer\n");
+ syslog(LOG_CRIT, "Could not create instrument resampler buffer\n");
goto astrid_instrument_shutdown_with_error;
}
- /* Create (or open) mix busses if we've selected any */
- // TODO
-
/* Initialize the built-in control param hashes */
- snprintf(hash_key, PATH_MAX, "%s-volume", instrument->name);
- instrument->param_volume = lphashstr(hash_key);
- snprintf(hash_key, PATH_MAX, "%s-resampler-rec", instrument->name);
- instrument->resampler_param_rec = lphashstr(hash_key);
- snprintf(hash_key, PATH_MAX, "%s-resampler-dub", instrument->name);
- instrument->resampler_param_dub = lphashstr(hash_key);
- snprintf(hash_key, PATH_MAX, "%s-resampler-clear", instrument->name);
- instrument->resampler_param_clear = lphashstr(hash_key);
- snprintf(hash_key, PATH_MAX, "%s-resampler-pos", instrument->name);
- instrument->resampler_param_pos = lphashstr(hash_key);
- snprintf(hash_key, PATH_MAX, "%s-resampler-feedback", instrument->name);
- instrument->resampler_param_feedback = lphashstr(hash_key);
-
+ instrument->param_volume = lphashstr("volume");
+ instrument->param_period_in_ticks = lphashstr("at-period"); // autotrigger params
+ instrument->param_offset_in_ticks = lphashstr("at-offset");
+ instrument->param_trigger_reset = lphashstr("at-reset");
+ instrument->param_last_trigger_time = lphashstr("__at-last");
+ instrument->resampler_param_rec = lphashstr("resampler-rec");
+ instrument->resampler_param_dub = lphashstr("resampler-dub");
+ instrument->resampler_param_clear = lphashstr("resampler-clear");
+ instrument->resampler_param_pos = lphashstr("resampler-pos");
+ instrument->resampler_param_feedback = lphashstr("resampler-feedback");
/* Register that everything is running and ready */
instrument->is_running = 1;
@@ 3801,10 3702,6 @@ lpinstrument_t * astrid_instrument_start_from_config(lpinstrument_config_t confi
syslog(LOG_DEBUG, "Opened message relay queue for %s with fd %d\n", instrument->name, instrument->exmsgq);
}
- /* Prepare the message structs */
- init_instrument_message(&instrument->msg, instrument->name);
- init_instrument_message(&instrument->cmd, instrument->name);
-
/* Start the sequencer thread */
if(astrid_instrument_seq_start(instrument) < 0) {
syslog(LOG_CRIT, "Could not start message sequence threads for instrument %s. Error: %s\n", instrument->name, strerror(errno));
@@ 3848,7 3745,16 @@ lpinstrument_t * astrid_instrument_start_from_config(lpinstrument_config_t confi
}
/* setup linenoise repl */
- linenoiseHistoryLoad("history.txt"); // FIXME this goes in the instrument config dir / or share?
+ if(instrument->is_interactive) {
+ linenoiseHistoryLoad("history.txt"); // FIXME this goes in the instrument config dir / or share?
+ }
+
+ /* call the post init callback if there is one */
+ if(config.post_init_callback != NULL) {
+ if(config.post_init_callback((void *)instrument) < 0) {
+ syslog(LOG_ERR, "Post init callback failed. Error: %s\n", strerror(errno));
+ }
+ }
return instrument;
@@ 106,6 106,10 @@ lpfloat_t interpolate_linear_channel(lpbuffer_t* buf, lpfloat_t phase, int chann
lpbuffer_t * param_create_from_float(lpfloat_t value);
lpbuffer_t * param_create_from_int(int value);
+lpsmoother_t param_smoother_create(lpfloat_t samplerate);
+void param_smoother_snap_to_value(lpsmoother_t * smoother, lpfloat_t value);
+void param_smoother_update_samplerate(lpsmoother_t * smoother, lpfloat_t samplerate);
+lpfloat_t param_smooth(lpsmoother_t * s, lpfloat_t value);
lpbuffer_t * create_wavetable(int name, size_t length);
void destroy_wavetable(lpbuffer_t* buf);
@@ 133,7 137,7 @@ lpmemorypool_factory_t LPMemoryPool = { 0, 0, 0, memorypool_init, memorypool_cus
const lparray_factory_t LPArray = { create_array, create_array_from, destroy_array };
const lpbuffer_factory_t LPBuffer = { create_buffer, create_buffer_from_float, create_buffer_from_bytes, copy_buffer, clone_buffer, clear_buffer, split2_buffer, scale_buffer, min_buffer, max_buffer, mag_buffer, play_buffer, pan_stereo_buffer, mix_buffers, remix_buffer, remap_buffer, clip_buffer, cut_buffer, cut_into_buffer, varispeed_buffer, resample_buffer, multiply_buffer, scalar_multiply_buffer, add_buffers, scalar_add_buffer, subtract_buffers, scalar_subtract_buffer, divide_buffers, scalar_divide_buffer, concat_buffers, buffers_are_equal, buffers_are_close, dub_buffer, dub_into_buffer, dub_scalar, env_process, env_buffer, pad_buffer, taper_buffer, trim_buffer, fill_buffer, repeat_buffer, reverse_buffer, resize_buffer, plot_buffer, destroy_buffer };
const lpinterpolation_factory_t LPInterpolation = { interpolate_linear_pos, interpolate_linear_pos2, interpolate_linear, interpolate_linear_channel, interpolate_hermite_pos, interpolate_hermite };
-const lpparam_factory_t LPParam = { param_create_from_float, param_create_from_int };
+const lpparam_factory_t LPParam = { param_create_from_float, param_create_from_int, param_smoother_create, param_smooth, param_smoother_snap_to_value, param_smoother_update_samplerate };
const lpwavetable_factory_t LPWavetable = { create_wavetable, create_wavetable_stack, destroy_wavetable };
const lpwindow_factory_t LPWindow = { create_window, create_window_stack, destroy_window };
const lpringbuffer_factory_t LPRingBuffer = { ringbuffer_create, ringbuffer_fill, ringbuffer_read, ringbuffer_readinto, ringbuffer_writefrom, ringbuffer_write, ringbuffer_readone, ringbuffer_writeone, ringbuffer_dub, ringbuffer_destroy };
@@ 1737,6 1741,43 @@ lpbuffer_t * param_create_from_int(int value) {
return param;
}
+/* This smoother was ported from sndkit with
+ * minimal changes. Thanks, Paul!
+ *
+ * The implementation is explained in detail here:
+ * https://pbat.ch/sndkit/smoother/
+ */
+lpsmoother_t param_smoother_create(lpfloat_t samplerate) {
+ lpsmoother_t smoother = {0};
+ smoother.smooth = 0.012f;
+ smoother.psmooth = -1;
+ smoother.onedsr = 1.f/samplerate;
+ return smoother;
+}
+
+void param_smoother_update_samplerate(lpsmoother_t * smoother, lpfloat_t samplerate) {
+ smoother->onedsr = 1.f/samplerate;
+}
+
+void param_smoother_snap_to_value(lpsmoother_t * smoother, lpfloat_t value) {
+ smoother->y0 = value;
+}
+
+lpfloat_t param_smooth(lpsmoother_t * s, lpfloat_t value) {
+ lpfloat_t out = 0.f;
+
+ if(s->psmooth != s->smooth) {
+ s->a1 = pow(0.5f, s->onedsr/s->smooth);
+ s->b0 = 1.f - s->a1;
+ s->psmooth = s->smooth;
+ }
+
+ s->y0 = s->b0 * value + s->a1 * s->y0;
+ out = s->y0;
+
+ return out;
+}
+
/* Interpolation
* */
lpfloat_t interpolate_hermite(lpbuffer_t* buf, lpfloat_t phase) {
@@ 28,6 28,14 @@ from pippi.soundbuffer cimport SoundBuffer
NUM_COMRADES = 4
+cdef dict DEFAULT_PARAMS = {
+ 'volume': 'float',
+ 'at-period': 'int',
+ 'at-offset': 'int',
+ 'at-reset': 'int',
+ 'last-at': 'int',
+}
+
class InstrumentError(Exception):
pass
@@ 56,12 64,6 @@ cdef bytes serialize_buffer(SoundBuffer buf, int is_looping, int output_channels
samplerate = int(buf.samplerate)
length = <size_t>len(buf)
- if grid_interval > 0:
- msg.interval = grid_interval
-
- if grid_offset > 0:
- msg.offset = grid_offset
-
# size of audio data
audiosize = length * channels * sizeof(lpfloat_t)
headersize = (sizeof(size_t) * 3) + (sizeof(int) * 3) # 3 size_t, 3 int
@@ 139,7 141,7 @@ cdef class MessageEvent:
strcpy(self.msg.msg, byte_params)
strcpy(self.msg.instrument_name, byte_instrument_name)
- cpdef int schedule(MessageEvent self, double now=0):
+ cpdef int schedule(MessageEvent self, size_t now=0):
self.msg.initiated = now
return send_play_message(self.msg[0])
@@ 173,7 175,7 @@ cdef class MidiEvent:
strcpy(self.msg.instrument_name, byte_instrument_name)
lpmidi_encode_msg(self.msg, channel, message_type, note, velocity)
- cpdef int schedule(MidiEvent self, double now):
+ cpdef int schedule(MidiEvent self, size_t now):
self.msg.initiated = now
return send_play_message(self.msg[0])
@@ 374,7 376,7 @@ cdef class EventContext:
size_t count=0,
):
- cdef double now = 0
+ cdef size_t now = 0
self.graph = graph
self.cache = instrument.cache
@@ 385,16 387,23 @@ cdef class EventContext:
self.instrument = instrument
self.vid = voice_id
self.count = count
- if lpscheduler_get_now_seconds(&now) < 0:
- logger.exception('Error getting now seconds during %s event ctx init' % instrument.name)
+ if lpscheduler_get_now_ticks(&now, <int>instrument.samplerate) < 0:
+ logger.exception('Error getting now ticks during %s event ctx init' % instrument.name)
now = 0
self.now = now
+ @property
+ def samplerate(self):
+ return self.instrument.samplerate
+
def adc(self, length=1, offset=0, channels=None):
if channels is None:
channels = self.instrument.input_channels
return self.instrument.read_from_adc(length, offset=offset, channels=channels)
+ def bpm2frames(self, double bpm):
+ return 60./bpm * self.instrument.samplerate
+
def load_sample(self, str name, double length=0, double offset=0, int channels=0):
if length <= 0 and offset == 0:
# just read the entire sample
@@ 452,7 461,8 @@ cdef class Instrument:
double resampler_length,
str midi_input_device_name,
str midi_output_device_name,
- int is_interactive
+ int is_interactive,
+ int autotrigger_is_enabled,
):
cdef char * midi_input_device_cstr
cdef char * midi_output_device_cstr
@@ 496,6 506,7 @@ cdef class Instrument:
config.resampler_length = resampler_length
config.ext_relay_enabled = 1
config.is_interactive = is_interactive
+ config.autotrigger_is_enabled = autotrigger_is_enabled
self.i = astrid_instrument_start_from_config(config)
if self.i == NULL:
@@ 548,17 559,30 @@ cdef class Instrument:
else:
self.default_midi_device = 1
+ self.instrument_param_type_map = {}
+ self.instrument_param_type_map.update(DEFAULT_PARAMS)
if hasattr(self.renderer, 'PARAMS'):
- logger.debug('mapping params...')
- self.instrument_param_type_map = self.renderer.PARAMS
- self.instrument_param_hash_map = dict()
- for k, t in self.instrument_param_type_map.items():
- logger.debug('mapping %s...' % k)
- k_byte_string = k.encode('UTF-8')
- _k = k_byte_string
- logger.debug(' %s...' % _k)
- self.instrument_param_hash_map[k] = lphashstr(_k)
- logger.debug(' %d...' % self.instrument_param_hash_map[k])
+ self.instrument_param_type_map.update(self.renderer.PARAMS)
+
+ self.instrument_param_hash_map = dict()
+ for k, t in self.instrument_param_type_map.items():
+ k_byte_string = k.encode('UTF-8')
+ _k = k_byte_string
+ self.instrument_param_hash_map[k] = lphashstr(_k)
+
+ # Set the autotrigger environment if it's configured
+ if hasattr(self.renderer, 'autotrigger'):
+ at = self.renderer.autotrigger
+ if callable(at):
+ at = at(ctx)
+ if isinstance(at, tuple):
+ if len(at) == 2:
+ grid_interval, grid_offset = at
+ setattr(ctx.s, 'at-period', grid_interval)
+ setattr(ctx.s, 'at-offset', grid_offset)
+ elif isinstance(at, numbers.Real):
+ grid_interval = at
+ setattr(ctx.s, 'at-period', grid_interval)
# finally fill the cache if there is something to fill:
if hasattr(self.renderer, 'cache'):
@@ 792,12 816,6 @@ cdef class Instrument:
cdef EventContext ctx
cdef dict params
cdef str p, k, v
- cdef size_t last_edit
-
- last_edit = os.path.getmtime(self.path)
- if last_edit > self.last_reload:
- self.reload()
- self.last_reload = last_edit
ctx = self.get_event_context()
params = dict()
@@ 892,20 910,10 @@ cdef int render_event(Instrument instrument, str msgstr):
if hasattr(instrument.renderer, 'before'):
instrument.renderer.before(ctx)
- if hasattr(instrument.renderer, 'grid'):
- if isinstance(instrument.renderer.grid, tuple):
- grid_interval, grid_offset = instrument.renderer.grid
- elif isinstance(instrument.renderer.grid, numbers.Real):
- grid_interval = instrument.renderer.GRID
- elif callable(instrument.renderer.grid):
- grid_interval, grid_offset = instrument.renderer.grid(ctx)
-
players, loop = collect_players(instrument)
for player in players:
try:
- ctx.count = 0
- ctx.tick = 0
generator = player(ctx)
try:
@@ 970,7 978,7 @@ cdef int trigger_events(Instrument instrument):
cdef EventContext ctx
cdef list eventlist
cdef int qfd
- cdef double now = 0
+ cdef size_t now = 0
cdef bytes trigger_params = instrument.msg.msg
cdef list trigger_events = []
@@ 985,8 993,6 @@ cdef int trigger_events(Instrument instrument):
planners = collect_trigger_planners(instrument)
for p in planners:
- ctx.count = 0
- ctx.tick = 0
try:
eventlist = p(ctx)
if eventlist is None:
@@ 999,8 1005,8 @@ cdef int trigger_events(Instrument instrument):
# Schedule the trigger events
logger.debug('Scheduling %d trigger events: %s' % (len(trigger_events), trigger_events))
- if lpscheduler_get_now_seconds(&now) < 0:
- logger.exception('Error getting now seconds during %s trigger scheduling' % ctx.instrument_name)
+ if lpscheduler_get_now_ticks(&now, <int>instrument.samplerate) < 0:
+ logger.exception('Error getting now ticks during %s trigger scheduling' % ctx.instrument_name)
now = 0
for t in trigger_events:
@@ 1030,15 1036,15 @@ def render_executor(Instrument instrument, object q, int comrade_id):
logger.debug('Renderer comrade %d shutting down' % comrade_id)
break
+ if lpscheduler_get_now_seconds(&start) < 0:
+ logger.exception('Error getting now seconds')
+ return
+
last_edit = os.path.getmtime(instrument.path)
if last_edit > instrument.last_reload:
instrument.reload()
instrument.last_reload = last_edit
- if lpscheduler_get_now_seconds(&start) < 0:
- logger.exception('Error getting now seconds')
- return
-
if render_event(instrument, msg) < 0:
logger.exception('Error trying to execute python render...')
return
@@ 1051,13 1057,6 @@ def render_executor(Instrument instrument, object q, int comrade_id):
logger.debug('%s render time: %f seconds' % (instrument.name, end - start))
cdef int astrid_schedule_python_triggers(Instrument instrument) except -1:
- cdef size_t last_edit = os.path.getmtime(instrument.path)
-
- # Reload instrument
- if last_edit > instrument.last_reload:
- instrument.reload()
- instrument.last_reload = last_edit
-
try:
return trigger_events(instrument)
except Exception as e:
@@ 1070,11 1069,13 @@ def _run_forever(Instrument instrument,
int input_channels,
int output_channels,
int is_interactive,
+ int autotrigger_is_enabled,
double initial_volume,
double adc_length,
double resampler_length,
object q,
):
+ cdef size_t last_edit
cdef lpmsg_t msg
logger.info(f'PY: running forever... {script_path=} {instrument_name=}')
@@ 1087,6 1088,15 @@ def _run_forever(Instrument instrument,
print('There was a problem reading from the msg q. Maybe try turning it off and on again?')
continue
+ last_edit = os.path.getmtime(instrument.path)
+ if last_edit > instrument.last_reload:
+ try:
+ instrument.reload()
+ instrument.last_reload = last_edit
+ except InstrumentError as e:
+ logger.error('PY: Error trying to reload instrument. Shutting down...')
+ break
+
if msg.type == LPMSG_SHUTDOWN:
logger.debug('PY MSG: shutdown')
for _ in range(NUM_COMRADES):
@@ 1114,26 1124,7 @@ def _run_forever(Instrument instrument,
logger.error('Error trying to schedule python triggers...')
elif msg.type == LPMSG_LOAD:
- # FIXME pass this along to the comrades
- try:
- if instrument is None:
- instrument = Instrument(instrument_name,
- script_path,
- input_channels,
- output_channels,
- initial_volume,
- adc_length,
- resampler_length,
- is_interactive,
- )
- else:
- last_edit = os.path.getmtime(instrument.path)
- if last_edit > instrument.last_reload:
- instrument.reload()
- instrument.last_reload = last_edit
- except InstrumentError as e:
- logger.error('PY: Error trying to reload instrument. Shutting down...')
- break
+ pass
logger.info('PY: python instrument shutting down...')
@@ 1149,6 1140,7 @@ def run_forever(
str midi_input_device_name=None,
str midi_output_device_name=None,
int is_interactive=1,
+ int autotrigger_is_enabled=0,
):
cdef Instrument instrument = None
instrument_name = instrument_name if instrument_name is not None else Path(script_path).stem
@@ 1172,7 1164,8 @@ def run_forever(
resampler_length,
midi_input_device_name,
midi_output_device_name,
- is_interactive
+ is_interactive,
+ autotrigger_is_enabled
)
logger.info(f'PY: started instrument... {script_path=} {instrument_name=}')
except InstrumentError as e:
@@ 1193,6 1186,7 @@ def run_forever(
input_channels,
output_channels,
is_interactive,
+ autotrigger_is_enabled,
initial_volume,
adc_length,
resampler_length,
@@ 1209,7 1203,7 @@ def run_forever(
time.sleep(2)
continue
- for comrade in render_pool:
+ for i, comrade in enumerate(render_pool):
if not comrade.is_alive():
render_pool.remove(comrade)
logger.error('Our comrade has become exhausted, and is being relieved')