diff --git a/src/plugins/fluidsynthsoundcontroller/fluidsynthsoundcontroller.cpp b/src/plugins/fluidsynthsoundcontroller/fluidsynthsoundcontroller.cpp index cbe6127..f9c5a36 100644 --- a/src/plugins/fluidsynthsoundcontroller/fluidsynthsoundcontroller.cpp +++ b/src/plugins/fluidsynthsoundcontroller/fluidsynthsoundcontroller.cpp @@ -112,6 +112,10 @@ void FluidSynthSoundController::setVolume(quint8 volume) } m_volume = volume; fluid_synth_cc(m_synth, 1, 7, m_volume * 127 / 200); + snd_seq_event_t event; + snd_seq_ev_clear(&event); + snd_seq_ev_set_controller(&event, 1, 7, m_volume * 127 / 200); + snd_seq_event_output_direct(alsa_seq_handle, &event); } void FluidSynthSoundController::setTempo(quint8 tempo) @@ -122,7 +126,9 @@ void FluidSynthSoundController::setTempo(quint8 tempo) void FluidSynthSoundController::prepareFromExerciseOptions(QJsonArray selectedExerciseOptions) { auto *song = new QList; + auto *song_alsa = new QList; m_song.reset(song); + m_song_alsa.reset(song_alsa); if (m_playMode == QLatin1String("rhythm")) { for (int i = 0; i < 4; ++i) { @@ -162,7 +168,16 @@ void FluidSynthSoundController::prepareFromExerciseOptions(QJsonArray selectedEx fluid_event_t *event = new_fluid_event(); fluid_event_set_source(event, -1); fluid_event_all_notes_off(event, 1); + alsaAllNotesOff(); m_song->append(event); + m_song->append(event); +} + +void FluidSynthSoundController::alsaAllNotesOff(){ + snd_seq_event_t event; + snd_seq_ev_clear(&event); + snd_seq_ev_set_controller(&event, 1, 123, 0); + snd_seq_event_output_direct(alsa_seq_handle, &event); } void FluidSynthSoundController::prepareFromMidiFile(const QString &fileName) @@ -190,7 +205,28 @@ void FluidSynthSoundController::play() : (m_playMode == QLatin1String("scale")) ? 1000 * (60.0 / m_tempo) : 0; } + + snd_seq_start_queue(alsa_seq_handle, alsa_seq_queue_id, NULL); + /*snd_seq_queue_status_t *mqueu;*/ + /*snd_seq_queue_status_malloc(&mqueu);*/ + /*snd_seq_get_queue_status(alsa_seq_handle, alsa_seq_queue_id, mqueu);*/ + unsigned int now_alsa = 0; + /*snd_seq_queue_status_free(mqueu);*/ + + foreach (snd_seq_event_t event2, *m_song_alsa.data()) { + snd_seq_ev_schedule_tick(&event2, alsa_seq_queue_id, SND_SEQ_TIME_MODE_REL, now_alsa); + snd_seq_ev_set_source(&event2, alsa_port_out_id); + snd_seq_ev_set_subs(&event2); + snd_seq_event_output(alsa_seq_handle, &event2); + snd_seq_drain_output(alsa_seq_handle); + now_alsa += (m_playMode == QLatin1String("rhythm")) ? event2.data.note.duration + : (m_playMode == QLatin1String("scale")) ? 24 + : 0; + } + + snd_seq_drain_output(alsa_seq_handle); setState(PlayingState); + } } @@ -204,6 +240,9 @@ void FluidSynthSoundController::stop() fluid_event_all_notes_off(event, 1); fluid_event_set_dest(event, m_synthSeqID); fluid_sequencer_send_now(m_sequencer, event); + snd_seq_stop_queue(alsa_seq_handle, alsa_seq_queue_id, NULL); + snd_seq_drain_output(alsa_seq_handle); + alsaAllNotesOff(); resetEngine(); } } @@ -212,6 +251,7 @@ void FluidSynthSoundController::reset() { stop(); m_song.reset(nullptr); + m_song_alsa.reset(nullptr); } void FluidSynthSoundController::appendEvent(int channel, short key, short velocity, @@ -221,6 +261,13 @@ void FluidSynthSoundController::appendEvent(int channel, short key, short veloci fluid_event_set_source(event, -1); fluid_event_note(event, channel, key, velocity, duration); m_song->append(event); + + snd_seq_event_t ev; + unsigned int d2; + snd_seq_ev_clear(&ev); + d2 = duration/(m_tempo); + snd_seq_ev_set_note(&ev, channel, key, velocity, d2); + m_song_alsa->append(ev); } void FluidSynthSoundController::sequencerCallback(unsigned int time, fluid_event_t *event, @@ -282,7 +329,30 @@ void FluidSynthSoundController::resetEngine() = fluid_sequencer_register_client(m_sequencer, "Minuet Fluidsynth Sound Controller", &FluidSynthSoundController::sequencerCallback, this); + if (snd_seq_open(&alsa_seq_handle, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) < 0) { + qCritical() << "Error opening ALSA sequencer\n"; + } + + if ((alsa_port_out_id = snd_seq_create_simple_port(alsa_seq_handle, "output", + SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_APPLICATION | SND_SEQ_PORT_TYPE_MIDI_GENERIC )) < 0) { + qCritical() << "Error creating output port\n"; + snd_seq_close(alsa_seq_handle); + } m_initialTime = 0; + snd_seq_set_client_name(alsa_seq_handle, "Minuet MIDI Port"); + alsa_seq_queue_id = snd_seq_alloc_queue(alsa_seq_handle); + + snd_seq_queue_tempo_t *queue_tempo; + int truetempo = (int) ((6e7 * 4) / (60 * 4)); + + snd_seq_queue_tempo_alloca(&queue_tempo); + snd_seq_queue_tempo_set_tempo(queue_tempo, truetempo); + snd_seq_queue_tempo_set_ppq(queue_tempo, 24); + snd_seq_set_queue_tempo(alsa_seq_handle, alsa_seq_queue_id, queue_tempo); + + + setPlaybackLabel(QStringLiteral("00:00.00")); setState(StoppedState); } @@ -298,6 +368,15 @@ void FluidSynthSoundController::deleteEngine() fluid_sequencer_send_now(m_sequencer, m_unregisteringEvent); #endif delete_fluid_sequencer(m_sequencer); + + snd_seq_remove_events_t *remove_ev; + + snd_seq_remove_events_alloca(&remove_ev); + snd_seq_remove_events_set_queue(remove_ev, alsa_seq_queue_id); + snd_seq_remove_events_set_condition(remove_ev, + SND_SEQ_REMOVE_OUTPUT | + SND_SEQ_REMOVE_IGNORE_OFF); + snd_seq_close(alsa_seq_handle); } if (m_audioDriver) { delete_fluid_audio_driver(m_audioDriver); diff --git a/src/plugins/fluidsynthsoundcontroller/fluidsynthsoundcontroller.h b/src/plugins/fluidsynthsoundcontroller/fluidsynthsoundcontroller.h index 3035786..86547c1 100644 --- a/src/plugins/fluidsynthsoundcontroller/fluidsynthsoundcontroller.h +++ b/src/plugins/fluidsynthsoundcontroller/fluidsynthsoundcontroller.h @@ -26,6 +26,7 @@ #include #include +#include class FluidSynthSoundController : public Minuet::ISoundController { @@ -58,6 +59,7 @@ private: void *data); void resetEngine(); void deleteEngine(); + void alsaAllNotesOff(); private: fluid_settings_t *m_settings; @@ -65,12 +67,16 @@ private: fluid_sequencer_t *m_sequencer; fluid_synth_t *m_synth; fluid_event_t *m_unregisteringEvent; + snd_seq_t *alsa_seq_handle; + int alsa_port_out_id; + int alsa_seq_queue_id; short m_synthSeqID; short m_callbackSeqID; static unsigned int m_initialTime; QScopedPointer> m_song; + QScopedPointer> m_song_alsa; }; #endif -- 2.43.0