Commit f4b6bacc authored by Sandro Andrade's avatar Sandro Andrade

Use fluidsynth as default soundbackend

Disable drumstick backend building by now
parent 11a6f892
......@@ -109,7 +109,8 @@ Item {
var playMode = core.exerciseController.currentExercise["playMode"]
core.exerciseController.randomlySelectExerciseOptions()
var selectedExerciseOptions = core.exerciseController.selectedExerciseOptions
core.soundBackend.prepareFromExerciseOptions(selectedExerciseOptions, playMode)
core.soundBackend.playMode = playMode
core.soundBackend.prepareFromExerciseOptions(selectedExerciseOptions)
var newChosenExercises = [];
for (var i = 0; i < selectedExerciseOptions.length; ++i)
newChosenExercises.push(selectedExerciseOptions[i].name);
......@@ -120,7 +121,7 @@ Item {
chosenColors[i] = answerGrid.children[j].color
break
}
if (core.exerciseController.currentExercise["playMode"] != "rhythm")
if (playMode != "rhythm")
answerHoverEnter(0, core.exerciseController.chosenRootNote(), 0, "white")
core.soundBackend.play()
}
......
......@@ -10,6 +10,8 @@ set(minuetinterfaces_LIB_SRCS
add_library(minuetinterfaces ${minuetinterfaces_LIB_SRCS})
add_library(Minuet::Interfaces ALIAS minuetinterfaces)
set_target_properties(minuetinterfaces PROPERTIES VERSION 0.0.0 SOVERSION 0)
generate_export_header(minuetinterfaces EXPORT_FILE_NAME minuetinterfacesexport.h)
target_link_libraries(minuetinterfaces
......
......@@ -49,6 +49,19 @@ ISoundBackend::State ISoundBackend::state() const
return m_state;
}
QString ISoundBackend::playMode() const
{
return m_playMode;
}
void ISoundBackend::setPlayMode(QString playMode)
{
if (m_playMode != playMode) {
m_playMode = playMode;
emit playModeChanged(m_playMode);
}
}
void ISoundBackend::setPlaybackLabel(const QString &playbackLabel)
{
if (m_playbackLabel != playbackLabel) {
......
......@@ -42,6 +42,7 @@ class MINUETINTERFACES_EXPORT ISoundBackend : public IPlugin
Q_PROPERTY(QString playbackLabel READ playbackLabel NOTIFY playbackLabelChanged)
Q_ENUMS(State)
Q_PROPERTY(State state READ state NOTIFY stateChanged)
Q_PROPERTY(QString playMode READ playMode WRITE setPlayMode NOTIFY playModeChanged)
public:
~ISoundBackend() override;
......@@ -55,13 +56,15 @@ public:
};
ISoundBackend::State state() const;
QString playMode() const;
public Q_SLOTS:
virtual void setPitch(qint8 pitch) = 0;
virtual void setVolume(quint8 tempo) = 0;
virtual void setVolume(quint8 volume) = 0;
virtual void setTempo(quint8 tempo) = 0;
void setPlayMode(QString playMode);
virtual void prepareFromExerciseOptions(QJsonArray selectedExerciseOptions, const QString &playMode) = 0;
virtual void prepareFromExerciseOptions(QJsonArray selectedExerciseOptions) = 0;
virtual void prepareFromMidiFile(const QString &fileName) = 0;
virtual void play() = 0;
......@@ -74,6 +77,7 @@ Q_SIGNALS:
void tempoChanged(quint8 newTempo);
void playbackLabelChanged(QString newPlaybackLabel);
void stateChanged(State newState);
void playModeChanged(QString newPlayMode);
protected:
explicit ISoundBackend(QObject *parent = 0);
......@@ -85,6 +89,7 @@ protected:
quint8 m_tempo;
QString m_playbackLabel;
State m_state;
QString m_playMode;
};
}
......
......@@ -5,34 +5,34 @@ else()
message(FATAL_ERROR "Program pkg-config not found")
endif()
pkg_check_modules(ALSA REQUIRED alsa>=1.0.0)
if(ALSA_FOUND)
link_directories(${ALSA_LIBDIR})
include_directories(${ALSA_INCLUDEDIR})
else()
message(FATAL_ERROR "Please install ALSA library and headers (libasound2)")
endif()
pkg_check_modules(DRUMSTICK_ALSA REQUIRED drumstick-alsa>=1.0.1)
pkg_check_modules(DRUMSTICK_FILE REQUIRED drumstick-file>=1.0.1)
if(DRUMSTICK_ALSA_FOUND)
link_directories(${DRUMSTICK_ALSA_LIBDIR})
include_directories(${DRUMSTICK_ALSA_INCLUDEDIR})
endif()
if(DRUMSTICK_FILE_FOUND)
link_directories(${DRUMSTICK_FILE_LIBDIR})
include_directories(${DRUMSTICK_FILE_INCLUDEDIR})
endif()
if(NOT DRUMSTICK_ALSA_FOUND OR NOT DRUMSTICK_FILE_FOUND)
message(WARNING "Please install drumstick libraries and headers (package drumstick-devel) if you want to build drumstick soundbackend")
endif()
if(ALSA_FOUND AND DRUMSTICK_ALSA_FOUND AND DRUMSTICK_FILE_FOUND)
add_subdirectory(drumsticksoundbackend)
endif()
#pkg_check_modules(ALSA REQUIRED alsa>=1.0.0)
#if(ALSA_FOUND)
# link_directories(${ALSA_LIBDIR})
# include_directories(${ALSA_INCLUDEDIR})
#else()
# message(FATAL_ERROR "Please install ALSA library and headers (libasound2)")
#endif()
#pkg_check_modules(DRUMSTICK_ALSA REQUIRED drumstick-alsa>=1.0.1)
#pkg_check_modules(DRUMSTICK_FILE REQUIRED drumstick-file>=1.0.1)
#if(DRUMSTICK_ALSA_FOUND)
# link_directories(${DRUMSTICK_ALSA_LIBDIR})
# include_directories(${DRUMSTICK_ALSA_INCLUDEDIR})
#endif()
#if(DRUMSTICK_FILE_FOUND)
# link_directories(${DRUMSTICK_FILE_LIBDIR})
# include_directories(${DRUMSTICK_FILE_INCLUDEDIR})
#endif()
#if(NOT DRUMSTICK_ALSA_FOUND OR NOT DRUMSTICK_FILE_FOUND)
# message(WARNING "Please install drumstick libraries and headers (package drumstick-devel) if you want to build drumstick soundbackend")
#endif()
#if(ALSA_FOUND AND DRUMSTICK_ALSA_FOUND AND DRUMSTICK_FILE_FOUND)
# add_subdirectory(drumsticksoundbackend)
#endif()
pkg_check_modules(FLUIDSYNTH REQUIRED fluidsynth>=1.1.6)
......
......@@ -146,7 +146,7 @@ void DrumstickSoundBackend::setTempo (quint8 tempo)
emit tempoChanged(m_tempo);
}
void DrumstickSoundBackend::prepareFromExerciseOptions(QJsonArray selectedExerciseOptions, const QString &playMode)
void DrumstickSoundBackend::prepareFromExerciseOptions(QJsonArray selectedExerciseOptions)
{
Song *song = new Song;
song->setHeader(0, 1, 60);
......@@ -158,7 +158,7 @@ void DrumstickSoundBackend::prepareFromExerciseOptions(QJsonArray selectedExerci
appendEvent(new drumstick::TempoEvent(m_queueId, 600000), 0);
unsigned int barStart = 0;
if (playMode == "rhythm") {
if (m_playMode == "rhythm") {
appendEvent(new drumstick::NoteOnEvent(9, 80, 120), 0);
appendEvent(new drumstick::NoteOnEvent(9, 80, 120), 60);
appendEvent(new drumstick::NoteOnEvent(9, 80, 120), 120);
......@@ -170,7 +170,7 @@ void DrumstickSoundBackend::prepareFromExerciseOptions(QJsonArray selectedExerci
QString sequence = selectedExerciseOptions[i].toObject()[QStringLiteral("sequence")].toString();
unsigned int chosenRootNote = selectedExerciseOptions[i].toObject()[QStringLiteral("rootNote")].toString().toInt();
if (playMode != "rhythm") {
if (m_playMode != "rhythm") {
appendEvent(new drumstick::NoteOnEvent(1, chosenRootNote, 120), barStart);
appendEvent(new drumstick::NoteOffEvent(1, chosenRootNote, 120), barStart + 60);
......@@ -178,10 +178,10 @@ void DrumstickSoundBackend::prepareFromExerciseOptions(QJsonArray selectedExerci
drumstick::SequencerEvent *ev;
foreach(const QString &additionalNote, sequence.split(' ')) {
appendEvent(ev = new drumstick::NoteOnEvent(1, chosenRootNote + additionalNote.toInt(), 120),
(playMode == "scale") ? barStart+60*j:barStart);
(m_playMode == "scale") ? barStart+60*j:barStart);
ev->setTag(0);
appendEvent(ev = new drumstick::NoteOffEvent(1, chosenRootNote + additionalNote.toInt(), 120),
(playMode == "scale") ? barStart+60*(j+1):barStart+60);
(m_playMode == "scale") ? barStart+60*(j+1):barStart+60);
ev->setTag(0);
++j;
}
......@@ -200,7 +200,7 @@ void DrumstickSoundBackend::prepareFromExerciseOptions(QJsonArray selectedExerci
}
}
}
if (playMode == "rhythm")
if (m_playMode == "rhythm")
appendEvent(new drumstick::NoteOnEvent(9, 80, 120), barStart);
}
......
......@@ -59,7 +59,7 @@ public Q_SLOTS:
virtual void setVolume(quint8 volume);
virtual void setTempo (quint8 tempo);
virtual void prepareFromExerciseOptions(QJsonArray selectedExerciseOptions, const QString &playMode) override;
virtual void prepareFromExerciseOptions(QJsonArray selectedExerciseOptions) override;
virtual void prepareFromMidiFile(const QString &fileName) override;
virtual void play() override;
......
......@@ -11,3 +11,4 @@ target_link_libraries(minuetfluidsynthsoundbackend
)
install(TARGETS minuetfluidsynthsoundbackend DESTINATION ${PLUGIN_INSTALL_DIR}/minuet/)
install(FILES GeneralUser-v1.47.sf2 DESTINATION ${KDE_INSTALL_DATADIR}/minuet/soundfonts)
......@@ -22,17 +22,40 @@
#include "fluidsynthsoundbackend.h"
#include <fluidsynth.h>
#include <QDebug>
#include <QJsonObject>
#include <QStandardPaths>
FluidSynthSoundBackend::FluidSynthSoundBackend(QObject *parent)
: Minuet::ISoundBackend(parent)
: Minuet::ISoundBackend(parent),
m_song(0)
{
fluid_settings_t* settings;
fluid_settings_t *settings;
settings = new_fluid_settings();
fluid_settings_setstr(settings, "synth.reverb.active", "no");
fluid_settings_setstr(settings, "synth.chorus.active", "no");
m_synth = new_fluid_synth(settings);
fluid_settings_setstr(settings, "audio.driver", "alsa");
m_adriver = new_fluid_audio_driver(settings, m_synth);
m_sequencer = new_fluid_sequencer2(0);
// register synth as first destination
m_synthSeqID = fluid_sequencer_register_fluidsynth(m_sequencer, m_synth);
// load soundfont
int fluid_res = fluid_synth_sfload(m_synth, QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("soundfonts/GeneralUser-v1.47.sf2")).toLatin1(), 1);
if (fluid_res == FLUID_FAILED)
qDebug() << "Error when loading soundfont!";
m_tempo = 120;
}
FluidSynthSoundBackend::~FluidSynthSoundBackend()
{
delete_fluid_sequencer(m_sequencer);
delete_fluid_audio_driver(m_adriver);
delete_fluid_synth(m_synth);
}
void FluidSynthSoundBackend::setPitch(qint8 pitch)
......@@ -50,10 +73,39 @@ void FluidSynthSoundBackend::setTempo (quint8 tempo)
Q_UNUSED(tempo);
}
void FluidSynthSoundBackend::prepareFromExerciseOptions(QJsonArray selectedExerciseOptions, const QString &playMode)
void FluidSynthSoundBackend::prepareFromExerciseOptions(QJsonArray selectedExerciseOptions)
{
Q_UNUSED(selectedExerciseOptions)
Q_UNUSED(playMode)
QList<fluid_event_t *> *song = new QList<fluid_event_t *>;
m_song.reset(song);
if (m_playMode == "rhythm")
for (int i = 0; i < 4; ++i)
appendEvent(9, 80, 127, 1000*(60.0/m_tempo));
for (int i = 0; i < selectedExerciseOptions.size(); ++i) {
QString sequence = selectedExerciseOptions[i].toObject()[QStringLiteral("sequence")].toString();
unsigned int chosenRootNote = selectedExerciseOptions[i].toObject()[QStringLiteral("rootNote")].toString().toInt();
if (m_playMode != "rhythm") {
appendEvent(1, chosenRootNote, 127, 1000*(60.0/m_tempo));
foreach(const QString &additionalNote, sequence.split(' '))
appendEvent(1, chosenRootNote + additionalNote.toInt(), 127, 1000*(60.0/m_tempo));
}
else {
appendEvent(9, 80, 127, 1000*(60.0/m_tempo));
foreach(QString additionalNote, sequence.split(' ')) { // krazy:exclude=foreach
float dotted = 1;
if (additionalNote.endsWith('.')) {
dotted = 1.5;
additionalNote.chop(1);
}
unsigned int duration = dotted*1000*(60.0/m_tempo)*(4.0/additionalNote.toInt());
appendEvent(9, 37, 127, duration);
}
}
}
if (m_playMode == "rhythm")
appendEvent(9, 80, 127, 1000*(60.0/m_tempo));
}
void FluidSynthSoundBackend::prepareFromMidiFile(const QString &fileName)
......@@ -63,6 +115,12 @@ void FluidSynthSoundBackend::prepareFromMidiFile(const QString &fileName)
void FluidSynthSoundBackend::play()
{
unsigned int now = fluid_sequencer_get_tick(m_sequencer);
foreach(fluid_event_t *event, *m_song.data()) {
fluid_sequencer_send_at(m_sequencer, event, now, 1);
now += (m_playMode == "rhythm") ? fluid_event_get_duration(event):
(m_playMode == "scale") ? 1000*(60.0/m_tempo):0;
}
}
void FluidSynthSoundBackend::pause()
......@@ -73,5 +131,13 @@ void FluidSynthSoundBackend::stop()
{
}
#include "moc_fluidsynthsoundbackend.cpp"
void FluidSynthSoundBackend::appendEvent(int channel, short key, short velocity, unsigned int duration)
{
fluid_event_t *event = new_fluid_event();
fluid_event_set_source(event, -1);
fluid_event_set_dest(event, m_synthSeqID);
fluid_event_note(event, channel, key, velocity, duration);
m_song->append(event);
}
#include "moc_fluidsynthsoundbackend.cpp"
......@@ -25,6 +25,8 @@
#include <interfaces/isoundbackend.h>
#include <fluidsynth.h>
class FluidSynthSoundBackend : public Minuet::ISoundBackend
{
Q_OBJECT
......@@ -42,12 +44,23 @@ public Q_SLOTS:
virtual void setVolume(quint8 volume);
virtual void setTempo(quint8 tempo);
virtual void prepareFromExerciseOptions(QJsonArray selectedExerciseOptions, const QString &playMode) override;
virtual void prepareFromExerciseOptions(QJsonArray selectedExerciseOptions) override;
virtual void prepareFromMidiFile(const QString &fileName) override;
virtual void play() override;
virtual void pause() override;
virtual void stop() override;
private:
void appendEvent(int channel, short key, short velocity, unsigned int duration);
private:
fluid_synth_t *m_synth;
fluid_audio_driver_t *m_adriver;
fluid_sequencer_t *m_sequencer;
short m_synthSeqID;
QScopedPointer<QList<fluid_event_t *>> m_song;
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment