Commit 205b7387 authored by Sandro Andrade's avatar Sandro Andrade

Move song generation to midisequencer

parent 57c2f6f2
......@@ -111,6 +111,7 @@ Item {
exerciseView.state = "waitingForAnswer"
exerciseController.randomlySelectOptions()
var selectedOptions = exerciseController.selectedOptions
sequencer.generateSong(selectedOptions)
var newChosenExercises = [];
for (var i = 0; i < selectedOptions.length; ++i)
newChosenExercises.push(selectedOptions[i].name);
......
......@@ -97,8 +97,8 @@ Item {
}
var playMode = delegateRect.ListView.view.model[index].playMode
if (playMode != undefined) {
if (playMode == "scale") exerciseController.setPlayMode(0) // ScalePlayMode
if (playMode == "chord") exerciseController.setPlayMode(1) // ChordPlayMode
if (playMode == "scale") sequencer.setPlayMode(0) // ScalePlayMode
if (playMode == "chord") sequencer.setPlayMode(1) // ChordPlayMode
exerciseController.answerLength = 1
if (playMode == "rhythm") {
exerciseController.setPlayMode(2) // RhythmPlayMode
......
......@@ -40,7 +40,6 @@ namespace Minuet
ExerciseController::ExerciseController(MidiSequencer *midiSequencer) :
m_midiSequencer(midiSequencer),
m_playMode(ScalePlayMode),
m_chosenRootNote(0)
{
m_exercises["exercises"] = QJsonArray();
......@@ -65,11 +64,6 @@ bool ExerciseController::initialize()
return definitionsMerge & exercisesMerge;
}
void ExerciseController::setPlayMode(PlayMode playMode)
{
m_playMode = playMode;
}
void ExerciseController::randomlySelectOptions()
{
while (!m_selectedOptions.isEmpty())
......@@ -77,75 +71,26 @@ void ExerciseController::randomlySelectOptions()
qsrand(QDateTime::currentDateTimeUtc().toTime_t());
Song *song = new Song;
song->setHeader(0, 1, 60);
song->setInitialTempo(600000);
m_midiSequencer->setSong(song);
m_midiSequencer->appendEvent(m_midiSequencer->SMFTempo(600000), 0);
int minNote = INT_MAX;
int maxNote = INT_MIN;
for (quint8 i = 0; i < m_answerLength; ++i) {
quint8 chosenExercise = qrand() % m_currentExercise.size();
unsigned int barStart = 0;
if (m_playMode == RhythmPlayMode) {
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 80, 120), 0);
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 80, 120), 60);
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 80, 120), 120);
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 80, 120), 180);
barStart = 240;
}
for (unsigned int i = 0; i < m_answerLength; ++i) {
unsigned int chosenExercise = qrand() % m_currentExercise.size();
QString sequence = m_currentExercise[chosenExercise].toObject()[QStringLiteral("sequence")].toString();
if (m_playMode != RhythmPlayMode) {
int minNote = INT_MAX;
int maxNote = INT_MIN;
foreach(const QString &additionalNote, sequence.split(' ')) {
int note = additionalNote.toInt();
if (note > maxNote) maxNote = note;
if (note < minNote) minNote = note;
}
do
m_chosenRootNote = m_minRootNote + qrand() % (m_maxRootNote - m_minRootNote);
while (m_chosenRootNote + maxNote > 108 || m_chosenRootNote + minNote < 21);
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(1, m_chosenRootNote, 120), barStart);
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOff(1, m_chosenRootNote, 120), barStart + 60);
unsigned int j = 1;
drumstick::SequencerEvent *ev;
foreach(const QString &additionalNote, sequence.split(' ')) {
m_midiSequencer->appendEvent(ev = m_midiSequencer->SMFNoteOn(1,
m_chosenRootNote + additionalNote.toInt(),
120),
(m_playMode == ScalePlayMode) ? barStart+60*j:barStart);
ev->setTag(0);
m_midiSequencer->appendEvent(ev = m_midiSequencer->SMFNoteOff(1,
m_chosenRootNote + additionalNote.toInt(),
120),
(m_playMode == ScalePlayMode) ? barStart+60*(j+1):barStart+60);
ev->setTag(0);
++j;
}
barStart += 60;
}
else {
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 80, 120), barStart);
foreach(QString additionalNote, sequence.split(' ')) { // krazy:exclude=foreach
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 37, 120), barStart);
float dotted = 1;
if (additionalNote.endsWith('.')) {
dotted = 1.5;
additionalNote.chop(1);
}
barStart += dotted*60*(4.0/additionalNote.toInt());
}
foreach(const QString &additionalNote, sequence.split(' ')) {
int note = additionalNote.toInt();
if (note > maxNote) maxNote = note;
if (note < minNote) minNote = note;
}
do
m_chosenRootNote = m_minRootNote + qrand() % (m_maxRootNote - m_minRootNote);
while (m_chosenRootNote + maxNote > 108 || m_chosenRootNote + minNote < 21);
QJsonObject jsonObject = m_currentExercise[chosenExercise].toObject();
jsonObject["rootNote"] = QString::number(m_chosenRootNote);
m_currentExercise[chosenExercise] = jsonObject;
m_selectedOptions.append(m_currentExercise[chosenExercise]);
}
if (m_playMode == RhythmPlayMode) {
m_midiSequencer->appendEvent(m_midiSequencer->SMFNoteOn(9, 80, 120), barStart);
}
}
unsigned int ExerciseController::chosenRootNote()
......
......@@ -38,7 +38,6 @@ namespace Minuet
class MINUETSHELL_EXPORT ExerciseController : public IExerciseController
{
Q_OBJECT
Q_ENUMS(PlayMode)
public:
explicit ExerciseController(MidiSequencer *midiSequencer = 0);
......@@ -46,13 +45,6 @@ public:
bool initialize();
enum PlayMode {
ScalePlayMode = 0,
ChordPlayMode,
RhythmPlayMode
};
Q_INVOKABLE void setPlayMode(PlayMode playMode);
Q_INVOKABLE unsigned int chosenRootNote();
Q_INVOKABLE void playChoosenExercise();
......@@ -75,7 +67,6 @@ private:
MidiSequencer *m_midiSequencer;
QJsonObject m_exercises;
QJsonObject m_definitions;
PlayMode m_playMode;
unsigned int m_chosenRootNote;
QString m_errorString;
};
......
......@@ -44,7 +44,8 @@ MidiSequencer::MidiSequencer(QObject *parent) :
m_tick(0),
m_song(0),
m_eventSchedulingMode(FROM_ENGINE),
m_state(StoppedState)
m_state(StoppedState),
m_playMode(ScalePlayMode)
{
qmlRegisterType<MidiSequencer>("org.kde.minuet", 1, 0, "MidiSequencer");
// MidiClient configuration
......@@ -170,6 +171,71 @@ void MidiSequencer::clearSong()
}
}
void MidiSequencer::generateSong(QJsonArray selectedOptions)
{
Song *song = new Song;
song->setHeader(0, 1, 60);
song->setInitialTempo(600000);
setSong(song);
appendEvent(SMFTempo(600000), 0);
unsigned int barStart = 0;
if (m_playMode == RhythmPlayMode) {
appendEvent(SMFNoteOn(9, 80, 120), 0);
appendEvent(SMFNoteOn(9, 80, 120), 60);
appendEvent(SMFNoteOn(9, 80, 120), 120);
appendEvent(SMFNoteOn(9, 80, 120), 180);
barStart = 240;
}
for (int i = 0; i < selectedOptions.size(); ++i) {
QString sequence = selectedOptions[i].toObject()[QStringLiteral("sequence")].toString();
unsigned int m_chosenRootNote = selectedOptions[i].toObject()[QStringLiteral("rootNote")].toString().toInt();
if (m_playMode != RhythmPlayMode) {
appendEvent(SMFNoteOn(1, m_chosenRootNote, 120), barStart);
appendEvent(SMFNoteOff(1, m_chosenRootNote, 120), barStart + 60);
unsigned int j = 1;
drumstick::SequencerEvent *ev;
foreach(const QString &additionalNote, sequence.split(' ')) {
appendEvent(ev = SMFNoteOn(1,
m_chosenRootNote + additionalNote.toInt(),
120),
(m_playMode == ScalePlayMode) ? barStart+60*j:barStart);
ev->setTag(0);
appendEvent(ev = SMFNoteOff(1,
m_chosenRootNote + additionalNote.toInt(),
120),
(m_playMode == ScalePlayMode) ? barStart+60*(j+1):barStart+60);
ev->setTag(0);
++j;
}
barStart += 60;
}
else {
appendEvent(SMFNoteOn(9, 80, 120), barStart);
foreach(QString additionalNote, sequence.split(' ')) { // krazy:exclude=foreach
appendEvent(SMFNoteOn(9, 37, 120), barStart);
float dotted = 1;
if (additionalNote.endsWith('.')) {
dotted = 1.5;
additionalNote.chop(1);
}
barStart += dotted*60*(4.0/additionalNote.toInt());
}
}
}
if (m_playMode == RhythmPlayMode) {
appendEvent(SMFNoteOn(9, 80, 120), barStart);
}
}
void MidiSequencer::setPlayMode(PlayMode playMode)
{
m_playMode = playMode;
}
void MidiSequencer::appendEvent(drumstick::SequencerEvent *ev, unsigned long tick)
{
ev->setSource(m_outputPortId);
......
......@@ -48,6 +48,7 @@ class MidiSequencer : public QObject
Q_PROPERTY(QString playbackLabel READ playbackLabel WRITE setPlaybackLabel NOTIFY playbackLabelChanged)
Q_ENUMS(State)
Q_PROPERTY(State state READ state NOTIFY stateChanged)
Q_ENUMS(PlayMode)
public:
explicit MidiSequencer(QObject *parent = 0);
......@@ -63,6 +64,11 @@ public:
PlayingState,
PausedState
};
enum PlayMode {
ScalePlayMode = 0,
ChordPlayMode,
RhythmPlayMode
};
void subscribeTo(const QString &portName);
void openFile(const QString &fileName);
......@@ -97,6 +103,8 @@ public Q_SLOTS:
void setState(State state);
void setSong(Song *song);
void clearSong();
void generateSong(QJsonArray selectedOptions);
void setPlayMode(PlayMode playMode);
// Slots for events generated when reading a MIDI file
void SMFHeader(int format, int ntrks, int division);
......@@ -142,6 +150,7 @@ private:
QString m_currentSubscribedPort;
QString m_playbackLabel;
State m_state;
PlayMode m_playMode;
};
#endif // MIDISEQUENCER_H
......
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