Skip to content

Commit

Permalink
cleanup sequence player API
Browse files Browse the repository at this point in the history
  • Loading branch information
ddiakopoulos committed Dec 20, 2015
1 parent 00ece8e commit 3bf6e2e
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 57 deletions.
2 changes: 0 additions & 2 deletions ModernMIDI.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
08567C601B6D684A00EB6C0D /* ModernMIDI */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ModernMIDI; sourceTree = BUILT_PRODUCTS_DIR; };
08567C6E1B6D68D700EB6C0D /* RtMidi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RtMidi.cpp; path = third_party/rtmidi/RtMidi.cpp; sourceTree = "<group>"; };
08567C6F1B6D68D700EB6C0D /* RtMidi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RtMidi.h; path = third_party/rtmidi/RtMidi.h; sourceTree = "<group>"; };
08567C711B6D68E200EB6C0D /* circular_buffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = circular_buffer.h; path = src/circular_buffer.h; sourceTree = SOURCE_ROOT; };
08567C721B6D68E200EB6C0D /* concurrent_queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = concurrent_queue.h; path = src/concurrent_queue.h; sourceTree = SOURCE_ROOT; };
08567C741B6D68E200EB6C0D /* midi_input.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = midi_input.cpp; path = src/midi_input.cpp; sourceTree = SOURCE_ROOT; };
08567C751B6D68E200EB6C0D /* midi_input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = midi_input.h; path = src/midi_input.h; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -83,7 +82,6 @@
08264DD01B726E8A004BE7B2 /* util */ = {
isa = PBXGroup;
children = (
08567C711B6D68E200EB6C0D /* circular_buffer.h */,
08567C721B6D68E200EB6C0D /* concurrent_queue.h */,
08567C7F1B6D68E200EB6C0D /* timer.h */,
);
Expand Down
27 changes: 26 additions & 1 deletion sample.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <time.h>
#include <chrono>
#include <functional>
Expand Down Expand Up @@ -79,7 +104,7 @@ int main(int argc, char *argv[], char *envp[])
}
}

std::fstream output("loopback_a.mid", std::ios::out);
std::fstream output("assets/loopback.mid", std::ios::out);
theLetterA.write(output);

output.close();
Expand Down
2 changes: 1 addition & 1 deletion src/midi_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "modernmidi.h"
#include "midi_message.h"
#include "rtmidi/RtMidi.h"
#include <functional>
#include "rtmidi/RtMidi.h"

namespace mm
{
Expand Down
36 changes: 29 additions & 7 deletions src/sequence_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ MidiSequencePlayer::~MidiSequencePlayer()
sequencerThread.join();
}

double MidiSequencePlayer::ticksToSeconds(int ticks)
{
double beats = (double) ticks / ticksPerBeat;
double seconds = beats / (beatsPerMinute / 60.0);
return seconds;
}

int MidiSequencePlayer::secondsToTicks(float seconds)
{
double ticksPerSecond = (beatsPerMinute * ticksPerBeat) / 60.0;
double ticks = ticksPerSecond * seconds;
return (int) ticks;
}

void MidiSequencePlayer::loadSingleTrack(const MidiTrack & track, double ticksPerBeat, double beatsPerMinute)
{
Expand All @@ -62,10 +75,6 @@ void MidiSequencePlayer::loadSingleTrack(const MidiTrack & track, double ticksPe
double deltaTimestampInSeconds = ticksToSeconds(localElapsedTicks);
if (m->m->getMessageType() == (uint8_t) MessageType::NOTE_ON) addTimestampedEvent(0, deltaTimestampInSeconds, m); // already checks if non-meta message
}

//std::cout << "Track Idx: " << trackIdx << std::endl;
//std::cout << "Local Elapsed Ticks " << localElapsedTicks << std::endl;

}

void MidiSequencePlayer::loadMultipleTracks(const std::vector<MidiTrack> & tracks, double ticksPerBeat, double beatsPerMinute)
Expand Down Expand Up @@ -118,7 +127,7 @@ void MidiSequencePlayer::run()

while((timer.running_time_s()) <= (outputMsg.timestamp))
{
continue; // Spinny spin spin.
continue;
}

output.send(*outputMsg.msg);
Expand All @@ -144,15 +153,28 @@ void MidiSequencePlayer::stop()
shouldSequence = false;
}

void MidiSequencePlayer::addTimestampedEvent(int track, double now, std::shared_ptr<TrackEvent> ev)
void MidiSequencePlayer::addTimestampedEvent(int track, double when, std::shared_ptr<TrackEvent> ev)
{
if (ev->m->isMetaEvent() == false)
{
eventList.push_back(MidiPlayerEvent(now, ev->m, track));
eventList.push_back(MidiPlayerEvent(when, ev->m, track));
}
}

float MidiSequencePlayer::length() const
{
return playTimeSeconds;
}

void MidiSequencePlayer::setLooping(bool newState)
{
loop = newState;
}

void MidiSequencePlayer::reset()
{
eventList.clear();
eventCursor = 0;
startTime = 0;
playTimeSeconds = 0;
}
72 changes: 26 additions & 46 deletions src/sequence_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,31 @@ namespace mm

// This class is always a work in progress, and does not currently handle things like
// mid-track tempo changes.

class MidiSequencePlayer
{
MidiOutput & output;

void run();

// Default behavior of this function is to reject playing any metadata events
void addTimestampedEvent(int track, double when, std::shared_ptr<TrackEvent> ev);

double ticksToSeconds(int ticks);

int secondsToTicks(float seconds);

float beatsPerMinute;
double ticksPerBeat;
double msPerTick;

float playTimeSeconds = 0;
float startTime = 0;
int eventCursor = 0;

std::thread sequencerThread;
std::atomic<bool> shouldSequence;
bool loop = false;

public:

MidiSequencePlayer(MidiOutput & output);
Expand All @@ -60,34 +81,11 @@ class MidiSequencePlayer
void start();
void stop();

void setLooping(bool newState)
{
loop = newState;
}
void setLooping(bool newState);

float length() const; // length of the song in seconds

double ticksToSeconds(int ticks)
{
double beats = (double) ticks / ticksPerBeat;
double seconds = beats / (beatsPerMinute / 60.0);
return seconds;
}

int secondsToTicks(float seconds)
{
double ticksPerSecond = (beatsPerMinute * ticksPerBeat) / 60.0;
double ticks = ticksPerSecond * seconds;
return (int) ticks;
}

void reset()
{
eventList.clear();
eventCursor = 0;
startTime = 0;
playTimeSeconds = 0;
}
float length() const;

void reset();

std::function<void ()> startedEvent;
std::function<void ()> stoppedEvent;
Expand All @@ -97,24 +95,6 @@ class MidiSequencePlayer
ConcurrentQueue<MidiPlayerEvent> eventQueue;

std::vector<MidiPlayerEvent> eventList; // indexed by track

private:

void run();

void addTimestampedEvent(int track, double now, std::shared_ptr<TrackEvent> ev);

float beatsPerMinute;
double ticksPerBeat;
double msPerTick;

float playTimeSeconds = 0;
float startTime = 0;
int eventCursor = 0;

std::thread sequencerThread;
std::atomic<bool> shouldSequence;
bool loop = false;
};

} // mm
Expand Down

0 comments on commit 3bf6e2e

Please sign in to comment.