/* * hexter_instantiate * * implements LADSPA (*instantiate)() */ static LADSPA_Handle hexter_instantiate(const LADSPA_Descriptor *descriptor, unsigned long sample_rate) { hexter_instance_t *instance; int i; if (!hexter_synth.initialized) { hexter_synth.instance_count = 0; hexter_synth.instances = NULL; hexter_synth.nugget_remains = 0; hexter_synth.note_id = 0; hexter_synth.global_polyphony = HEXTER_DEFAULT_POLYPHONY; for (i = 0; i < HEXTER_MAX_POLYPHONY; i++) { hexter_synth.voice[i] = dx7_voice_new(); if (!hexter_synth.voice[i]) { DEBUG_MESSAGE(-1, " hexter_instantiate: out of memory!\n"); hexter_cleanup(NULL); return NULL; } } hexter_synth.initialized = 1; } instance = (hexter_instance_t *)calloc(1, sizeof(hexter_instance_t)); if (!instance) { hexter_cleanup(NULL); return NULL; } instance->next = hexter_synth.instances; hexter_synth.instances = instance; hexter_synth.instance_count++; /* do any per-instance one-time initialization here */ pthread_mutex_init(&instance->patches_mutex, NULL); if (!(instance->patches = (dx7_patch_t *)malloc(128 * DX7_VOICE_SIZE_PACKED))) { DEBUG_MESSAGE(-1, " hexter_instantiate: out of memory!\n"); hexter_cleanup(instance); return NULL; } instance->sample_rate = (float)sample_rate; dx7_eg_init_constants(instance); /* depends on sample rate */ instance->polyphony = HEXTER_DEFAULT_POLYPHONY; instance->monophonic = DSSP_MONO_MODE_OFF; instance->max_voices = instance->polyphony; instance->current_voices = 0; instance->last_key = 0; instance->pending_program_change = -1; instance->current_program = 0; instance->overlay_program = -1; hexter_data_performance_init(instance->performance_buffer); hexter_data_patches_init(instance->patches); hexter_instance_select_program(instance, 0, 0); hexter_instance_init_controls(instance); return (LADSPA_Handle)instance; }
/* * hexter_instance_control_change */ void hexter_instance_control_change(hexter_instance_t *instance, unsigned int param, signed int value) { switch (param) { /* these controls we act on always */ case MIDI_CTL_SUSTAIN: DEBUG_MESSAGE(DB_NOTE, " hexter_instance_control_change: got sustain control of %d\n", value); instance->cc[param] = value; if (value < 64) hexter_instance_damp_voices(instance); return; case MIDI_CTL_ALL_SOUNDS_OFF: instance->cc[param] = value; hexter_instance_all_voices_off(instance); return; case MIDI_CTL_RESET_CONTROLLERS: instance->cc[param] = value; hexter_instance_init_controls(instance); return; case MIDI_CTL_ALL_NOTES_OFF: instance->cc[param] = value; hexter_instance_all_notes_off(instance); return; } if (param == MIDI_CTL_REGIST_PARM_NUM_LSB || param == MIDI_CTL_REGIST_PARM_NUM_MSB) { /* reset NRPN numbers on receipt of RPN */ instance->cc[MIDI_CTL_NONREG_PARM_NUM_LSB] = 127; instance->cc[MIDI_CTL_NONREG_PARM_NUM_MSB] = 127; } if (instance->cc[param] == value) /* do nothing if control value has not changed */ return; instance->cc[param] = value; switch (param) { #ifdef HEXTER_DEBUG_CONTROL case MIDI_CTL_MSB_PAN: /* panning */ // hexter_instance_channel_pressure(instance, value); // { float f; // f = 52.75f / (instance->sample_rate * 0.001f * (float)value); // instance->amp_mod_max_slew = FLOAT_TO_FP(f); // printf("new amp_mod_max_slew, %dms => %f = %d\n", value, f, instance->amp_mod_max_slew); // } { if (value == 0) instance->ramp_duration = 1; else instance->ramp_duration = (int)(instance->sample_rate * 0.001f * (float)value); /* value ms ramp */ printf("new ramp_duration, %dms => %d frames\n", value, instance->ramp_duration); dx7_lfo_set_speed_x(instance); } break; case MIDI_CTL_MSB_EXPRESSION: /* 'expression' */ hexter_instance_key_pressure(instance, 60, value); break; #endif /* HEXTER_DEBUG_CONTROL */ case MIDI_CTL_MSB_MODWHEEL: case MIDI_CTL_LSB_MODWHEEL: hexter_instance_update_mod_wheel(instance); break; case MIDI_CTL_MSB_BREATH: case MIDI_CTL_LSB_BREATH: hexter_instance_update_breath(instance); break; case MIDI_CTL_MSB_FOOT: case MIDI_CTL_LSB_FOOT: hexter_instance_update_foot(instance); break; case MIDI_CTL_MSB_MAIN_VOLUME: case MIDI_CTL_LSB_MAIN_VOLUME: hexter_instance_update_volume(instance); break; case MIDI_CTL_MSB_GENERAL_PURPOSE1: case MIDI_CTL_MSB_GENERAL_PURPOSE2: case MIDI_CTL_MSB_GENERAL_PURPOSE3: case MIDI_CTL_MSB_GENERAL_PURPOSE4: hexter_instance_update_fc(instance, param - MIDI_CTL_MSB_GENERAL_PURPOSE1, value); break; case MIDI_CTL_GENERAL_PURPOSE5: case MIDI_CTL_GENERAL_PURPOSE6: hexter_instance_update_fc(instance, param - MIDI_CTL_GENERAL_PURPOSE5 + 4, value); break; /* handle NRPN as real-time parameter change */ case MIDI_CTL_MSB_DATA_ENTRY: case MIDI_CTL_LSB_DATA_ENTRY: if (instance->cc[MIDI_CTL_NONREG_PARM_NUM_MSB] != 127 && instance->cc[MIDI_CTL_NONREG_PARM_NUM_LSB] != 127) { hexter_instance_handle_nrpn(instance); } break; /* what others should we respond to? */ /* these we ignore (let the host handle): * BANK_SELECT_MSB * BANK_SELECT_LSB * RPN_MSB * RPN_LSB * (may want to eventually implement RPN (0, 0) Pitch Bend Sensitivity) */ } }