static void set_effect_value(struct SoundPlugin *plugin, int64_t time, int effect_num, float value, enum ValueFormat value_format, FX_when when){ Data *data = (Data*)plugin->data; if(value_format==PLUGIN_FORMAT_SCALED){ switch(effect_num){ case EFF_PITCH: data->pitch = scale(value,0.0f,1.0f,0,16383); //printf("Setting Pitch to %d\n",(int)data->pitch); sendpitchbend(data,0,data->pitch,time); break; case EFF_PITCH_RANGE: data->pitch_range = scale(value,0.0f,1.0f,1,48); fluid_synth_pitch_wheel_sens(data->synth,0,data->pitch_range); break; case EFF_MODULATION: data->modulation = value * 127; sendcontrolchange(data,0,1,data->modulation,time); break; case EFF_SUSTAIN_PEDAL: data->sustain_on = value*127; sendcontrolchange(data,0,64,data->sustain_on,time); break; default: RError("Unknown effect number %d\n",effect_num); } }else{ switch(effect_num){ case EFF_PITCH: data->pitch = value; sendpitchbend(data,0,value,time); break; case EFF_PITCH_RANGE: data->pitch_range = value; fluid_synth_pitch_wheel_sens(data->synth,0,value); break; case EFF_MODULATION: data->modulation = value; sendcontrolchange(data,0,1,value,time); break; case EFF_SUSTAIN_PEDAL: data->sustain_on = value; sendcontrolchange(data,0,64,value,time); break; default: RError("Unknown effect number %d\n",effect_num); } } }
// Could we get iph-based instruments support sample-exact models by using a // frame-length of 1 while rendering? void sf2Instrument::play( sampleFrame * _working_buffer ) { const fpp_t frames = engine::mixer()->framesPerPeriod(); m_synthMutex.lock(); const int currentMidiPitch = instrumentTrack()->midiPitch(); if( m_lastMidiPitch != currentMidiPitch ) { m_lastMidiPitch = currentMidiPitch; fluid_synth_pitch_bend( m_synth, m_channel, m_lastMidiPitch ); } const int currentMidiPitchRange = instrumentTrack()->midiPitchRange(); if( m_lastMidiPitchRange != currentMidiPitchRange ) { m_lastMidiPitchRange = currentMidiPitchRange; fluid_synth_pitch_wheel_sens( m_synth, m_channel, m_lastMidiPitchRange ); } if( m_internalSampleRate < engine::mixer()->processingSampleRate() && m_srcState != NULL ) { const fpp_t f = frames * m_internalSampleRate / engine::mixer()->processingSampleRate(); #ifdef __GNUC__ sampleFrame tmp[f]; #else sampleFrame * tmp = new sampleFrame[f]; #endif fluid_synth_write_float( m_synth, f, tmp, 0, 2, tmp, 1, 2 ); SRC_DATA src_data; src_data.data_in = tmp[0]; src_data.data_out = _working_buffer[0]; src_data.input_frames = f; src_data.output_frames = frames; src_data.src_ratio = (double) frames / f; src_data.end_of_input = 0; int error = src_process( m_srcState, &src_data ); #ifndef __GNUC__ delete[] tmp; #endif if( error ) { qCritical( "sf2Instrument: error while resampling: %s", src_strerror( error ) ); } if( src_data.output_frames_gen > frames ) { qCritical( "sf2Instrument: not enough frames: %ld / %d", src_data.output_frames_gen, frames ); } } else { fluid_synth_write_float( m_synth, frames, _working_buffer, 0, 2, _working_buffer, 1, 2 ); } m_synthMutex.unlock(); instrumentTrack()->processAudioBuffer( _working_buffer, frames, NULL ); }
JNIEXPORT void JNICALL Java_org_herac_tuxguitar_player_impl_midiport_fluidsynth_MidiSynth_controlChange(JNIEnv* env, jobject ojb, jlong ptr, jint channel, jint control, jint value) { fluid_handle_t *handle = NULL; memcpy(&handle, &ptr, sizeof(handle)); if(handle != NULL && handle->synth != NULL){ fluid_synth_cc(handle->synth, channel, control, value); if( control == 0x06 ){ fluid_synth_pitch_wheel_sens(handle->synth, channel, value); } } }
void soundfonts_pitchbend_range(t_soundfonts *instance, t_floatarg range) { if ((range <= 72) && (range >= 0)) { fluid_synth_pitch_wheel_sens(instance->synth, 0, range); } }
void sf2Instrument::play( sampleFrame * _working_buffer ) { const fpp_t frames = Engine::mixer()->framesPerPeriod(); // set midi pitch for this period const int currentMidiPitch = instrumentTrack()->midiPitch(); if( m_lastMidiPitch != currentMidiPitch ) { m_lastMidiPitch = currentMidiPitch; m_synthMutex.lock(); fluid_synth_pitch_bend( m_synth, m_channel, m_lastMidiPitch ); m_synthMutex.unlock(); } const int currentMidiPitchRange = instrumentTrack()->midiPitchRange(); if( m_lastMidiPitchRange != currentMidiPitchRange ) { m_lastMidiPitchRange = currentMidiPitchRange; m_synthMutex.lock(); fluid_synth_pitch_wheel_sens( m_synth, m_channel, m_lastMidiPitchRange ); m_synthMutex.unlock(); } // if we have no new noteons/noteoffs, just render a period and call it a day if( m_playingNotes.isEmpty() ) { renderFrames( frames, _working_buffer ); instrumentTrack()->processAudioBuffer( _working_buffer, frames, NULL ); return; } // processing loop // go through noteplayhandles in processing order f_cnt_t currentFrame = 0; while( ! m_playingNotes.isEmpty() ) { // find the note with lowest offset NotePlayHandle * currentNote = m_playingNotes[0]; for( int i = 1; i < m_playingNotes.size(); ++i ) { SF2PluginData * currentData = static_cast<SF2PluginData *>( currentNote->m_pluginData ); SF2PluginData * iData = static_cast<SF2PluginData *>( m_playingNotes[i]->m_pluginData ); if( currentData->offset > iData->offset ) { currentNote = m_playingNotes[i]; } } // process the current note: // first see if we're synced in frame count SF2PluginData * currentData = static_cast<SF2PluginData *>( currentNote->m_pluginData ); if( currentData->offset > currentFrame ) { renderFrames( currentData->offset - currentFrame, _working_buffer + currentFrame ); currentFrame = currentData->offset; } if( currentData->isNew ) { noteOn( currentData ); if( currentNote->isReleased() ) // if the note is released during the same period, we have to process it again for noteoff { currentData->isNew = false; currentData->offset = currentNote->framesBeforeRelease(); } else // otherwise remove the handle { m_playingNotesMutex.lock(); m_playingNotes.remove( m_playingNotes.indexOf( currentNote ) ); m_playingNotesMutex.unlock(); } } else { noteOff( currentData ); m_playingNotesMutex.lock(); m_playingNotes.remove( m_playingNotes.indexOf( currentNote ) ); m_playingNotesMutex.unlock(); } } if( currentFrame < frames ) { renderFrames( frames - currentFrame, _working_buffer + currentFrame ); } instrumentTrack()->processAudioBuffer( _working_buffer, frames, NULL ); }
static int fluidsynth_midi_write(struct _midi_writer *self, unsigned char *buf, int len) { if (buf[0] == 0xf0) sciprintf("FluidSynth: Skipping sysex message.\n"); else if (len == 2) { guint8 command, channel; command = buf[0] & 0xf0; channel = buf[0] & 0x0f; switch(command) { case 0xc0: fluid_synth_program_change(synth, channel, buf[1]); break; default: printf("FluidSynth: MIDI command [%02x %02x] not supported\n", buf[0], buf[1]); } } else if (len == 3) { guint8 command, channel; command = buf[0] & 0xf0; channel = buf[0] & 0x0f; switch(command) { case 0x80: fluid_synth_noteoff(synth, channel, buf[1]); break; case 0x90: fluid_synth_noteon(synth, channel, buf[1], buf[2]); break; case 0xb0: switch (buf[1]) { case 0x06: /* Data Entry Slider - course */ if (rpn[channel] == 0) fluid_synth_pitch_wheel_sens(synth, channel, buf[2]); else sciprintf("FluidSynth: RPN %i not supported\n", rpn[channel]); case 0x64: /* Registered Parameter Number (RPN) - fine */ rpn[channel] &= ~0x7f; rpn[channel] |= buf[2] & 0x7f; break; case 0x65: /* Registered Parameter Number (RPN) - course */ rpn[channel] &= ~0x3f80; rpn[channel] |= (buf[2] & 0x7f) << 7; break; default: fluid_synth_cc(synth, channel, buf[1], buf[2]); } break; case 0xe0: fluid_synth_pitch_bend(synth, channel, (buf[2] << 7) | buf[1]); break; default: sciprintf("FluidSynth: MIDI command [%02x %02x %02x] not supported\n", buf[0], buf[1], buf[2]); } } else sciprintf("FluidSynth: Skipping invalid message of %i bytes.\n", len); return SFX_OK; }
/* Callback for midi events */ void fluid_seq_fluidsynth_callback(unsigned int time, fluid_event_t* evt, fluid_sequencer_t* seq, void* data) { fluid_synth_t* synth; fluid_seqbind_t* seqbind = (fluid_seqbind_t *) data; synth = seqbind->synth; switch (fluid_event_get_type(evt)) { case FLUID_SEQ_NOTEON: fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt)); break; case FLUID_SEQ_NOTEOFF: fluid_synth_noteoff(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt)); break; case FLUID_SEQ_NOTE: { unsigned int dur; fluid_synth_noteon(synth, fluid_event_get_channel(evt), fluid_event_get_key(evt), fluid_event_get_velocity(evt)); dur = fluid_event_get_duration(evt); fluid_event_noteoff(evt, fluid_event_get_channel(evt), fluid_event_get_key(evt)); fluid_sequencer_send_at(seq, evt, dur, 0); } break; case FLUID_SEQ_ALLSOUNDSOFF: /* NYI */ break; case FLUID_SEQ_ALLNOTESOFF: fluid_synth_cc(synth, fluid_event_get_channel(evt), 0x7B, 0); break; case FLUID_SEQ_BANKSELECT: fluid_synth_bank_select(synth, fluid_event_get_channel(evt), fluid_event_get_bank(evt)); break; case FLUID_SEQ_PROGRAMCHANGE: fluid_synth_program_change(synth, fluid_event_get_channel(evt), fluid_event_get_program(evt)); break; case FLUID_SEQ_PROGRAMSELECT: fluid_synth_program_select(synth, fluid_event_get_channel(evt), fluid_event_get_sfont_id(evt), fluid_event_get_bank(evt), fluid_event_get_program(evt)); break; case FLUID_SEQ_ANYCONTROLCHANGE: /* nothing = only used by remove_events */ break; case FLUID_SEQ_PITCHBEND: fluid_synth_pitch_bend(synth, fluid_event_get_channel(evt), fluid_event_get_pitch(evt)); break; case FLUID_SEQ_PITCHWHHELSENS: fluid_synth_pitch_wheel_sens(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt)); break; case FLUID_SEQ_CONTROLCHANGE: fluid_synth_cc(synth, fluid_event_get_channel(evt), fluid_event_get_control(evt), fluid_event_get_value(evt)); break; case FLUID_SEQ_MODULATION: { short ctrl = 0x01; // MODULATION_MSB fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); } break; case FLUID_SEQ_SUSTAIN: { short ctrl = 0x40; // SUSTAIN_SWITCH fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); } break; case FLUID_SEQ_PAN: { short ctrl = 0x0A; // PAN_MSB fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); } break; case FLUID_SEQ_VOLUME: { short ctrl = 0x07; // VOLUME_MSB fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); } break; case FLUID_SEQ_REVERBSEND: { short ctrl = 0x5B; // EFFECTS_DEPTH1 fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); } break; case FLUID_SEQ_CHORUSSEND: { short ctrl = 0x5D; // EFFECTS_DEPTH3 fluid_synth_cc(synth, fluid_event_get_channel(evt), ctrl, fluid_event_get_value(evt)); } break; case FLUID_SEQ_CHANNELPRESSURE: { fluid_synth_channel_pressure(synth, fluid_event_get_channel(evt), fluid_event_get_value(evt)); } break; case FLUID_SEQ_SYSTEMRESET: { fluid_synth_system_reset(synth); } break; case FLUID_SEQ_UNREGISTERING: /* free ourselves */ { seqbind->client_id = -1; /* avoid recursive call to fluid_sequencer_unregister_client */ delete_fluid_seqbind(seqbind); } break; case FLUID_SEQ_TIMER: /* nothing in fluidsynth */ break; default: break; } }