/* * hexter_instance_handle_polyphony */ char * hexter_instance_handle_polyphony(hexter_instance_t *instance, const char *value) { int polyphony = atoi(value); int i; dx7_voice_t *voice; if (polyphony < 1 || polyphony > HEXTER_MAX_POLYPHONY) { return dssp_error_message("error: polyphony value out of range"); } /* set the new limit */ instance->polyphony = polyphony; if (!instance->monophonic) { dssp_voicelist_mutex_lock(instance); instance->max_voices = polyphony; /* turn off any voices above the new limit */ for (i = polyphony; i < HEXTER_MAX_POLYPHONY; i++) { voice = instance->voice[i]; if (_PLAYING(voice)) { if (instance->held_keys[0] != -1) hexter_instance_clear_held_keys(instance); dx7_voice_off(voice); } } dssp_voicelist_mutex_unlock(instance); } return NULL; /* success */ }
/* * hexter_instance_handle_monophonic */ char * hexter_instance_handle_monophonic(hexter_instance_t *instance, const char *value) { int mode = -1; if (!strcmp(value, "on")) mode = DSSP_MONO_MODE_ON; else if (!strcmp(value, "once")) mode = DSSP_MONO_MODE_ONCE; else if (!strcmp(value, "both")) mode = DSSP_MONO_MODE_BOTH; else if (!strcmp(value, "off")) mode = DSSP_MONO_MODE_OFF; if (mode == -1) { return dssp_error_message("error: monophonic value not recognized"); } if (mode == DSSP_MONO_MODE_OFF) { /* polyphonic mode */ instance->monophonic = 0; instance->max_voices = instance->polyphony; } else { /* one of the monophonic modes */ if (!instance->monophonic) { dssp_voicelist_mutex_lock(instance); hexter_instance_all_voices_off(instance); instance->max_voices = 1; instance->mono_voice = NULL; hexter_instance_clear_held_keys(instance); dssp_voicelist_mutex_unlock(instance); } instance->monophonic = mode; } return NULL; /* success */ }
/* * hexter_run_multiple_synths * * implements DSSI (*run_multiple_synths)() */ static void hexter_run_multiple_synths(unsigned long instance_count, LADSPA_Handle *handles, unsigned long sample_count, snd_seq_event_t **events, unsigned long *event_count) { hexter_instance_t **instances = (hexter_instance_t **)handles; unsigned long samples_done = 0; unsigned long event_index[instance_count]; unsigned long this_pending_event_tick; unsigned long next_pending_event_tick; unsigned long burst_size; int i; /* attempt the mutex, return only silence if lock fails. */ if (dssp_voicelist_mutex_trylock()) { for (i = 0; i < instance_count; i++) { memset(instances[i]->output, 0, sizeof(LADSPA_Data) * sample_count); } return; } for (i = 0; i < instance_count; i++) { event_index[i] = 0; /* silence the buffer */ memset(instances[i]->output, 0, sizeof(LADSPA_Data) * sample_count); #if defined(DSSP_DEBUG) && (DSSP_DEBUG & DB_AUDIO) *instances[i]->output += 0.10f; /* add a 'buzz' to output so there's something audible even when quiescent */ #endif /* defined(DSSP_DEBUG) && (DSSP_DEBUG & DB_AUDIO) */ if (instances[i]->pending_program_change > -1) hexter_handle_pending_program_change(instances[i]); } next_pending_event_tick = 0; while (samples_done < sample_count) { if (!hexter_synth.nugget_remains) hexter_synth.nugget_remains = HEXTER_NUGGET_SIZE; /* process any ready events */ while (next_pending_event_tick <= samples_done) { this_pending_event_tick = next_pending_event_tick; next_pending_event_tick = sample_count; for (i = 0; i < instance_count; i++) { while (event_index[i] < event_count[i] && events[i][event_index[i]].time.tick == this_pending_event_tick) { hexter_handle_event(instances[i], &events[i][event_index[i]]); event_index[i]++; } if (event_index[i] < event_count[i] && events[i][event_index[i]].time.tick < next_pending_event_tick) { next_pending_event_tick = events[i][event_index[i]].time.tick; } } } /* calculate the sample count (burst_size) for the next * hexter_synth_render_voices() call to be the smallest of: * - control calculation quantization size (HEXTER_NUGGET_SIZE, * in samples) * - the number of samples remaining in an already-begun nugget * (hexter_synth.nugget_remains) * - the number of samples left in this run * - the number of samples until the next event is ready */ burst_size = HEXTER_NUGGET_SIZE; if (hexter_synth.nugget_remains < burst_size) { /* we're still in the middle of a nugget, so reduce the burst size * to end when the nugget ends */ burst_size = hexter_synth.nugget_remains; } if (sample_count - samples_done < burst_size) { /* reduce burst size to end at end of this run */ burst_size = sample_count - samples_done; } else if (next_pending_event_tick - samples_done < burst_size) { /* reduce burst size to end when next event is ready */ burst_size = next_pending_event_tick - samples_done; } /* render the burst */ hexter_synth_render_voices(samples_done, burst_size, (burst_size == hexter_synth.nugget_remains)); samples_done += burst_size; hexter_synth.nugget_remains -= burst_size; } dssp_voicelist_mutex_unlock(); }