1
Fork 0
jacker/player.hpp

125 lines
2.9 KiB
C++

#pragma once
#include <vector>
#include "midi.hpp"
#include "ring_buffer.hpp"
namespace Jacker {
//=============================================================================
struct Message : MIDI::Message {
enum Type {
// empty, for updating position
TypeEmpty = 0,
// midi package
TypeMIDI = 1,
// command
TypeCommandChannelVolume = 'V',
TypeCommandTempo = 'T',
};
Type type;
long long timestamp;
int frame;
int bus;
int bus_channel;
int port;
Message();
};
class MessageQueue : public RingBuffer<Message> {
public:
MessageQueue();
volatile long long write_samples; // 0-32: subsample, 32-64: sample
volatile int position; // in frames
volatile long long read_samples;
void on_note(int bus, int channel, int value, int velocity);
void on_cc(int bus, int ccindex, int ccvalue);
void on_command(int bus, int channel, Message::Type command, int value, int value2, int value3);
void all_notes_off(int bus);
void status_msg();
void init_message(int bus, Message &msg);
void set_model(class Model &model);
protected:
class Model *model;
};
class Player {
public:
enum {
// how many message queues are used
// for flipping?
QueueCount = 4,
};
struct Channel {
float volume;
int note;
Channel();
};
typedef std::vector<Channel> ChannelArray;
typedef std::vector<char> NoteArray;
struct Bus {
ChannelArray channels;
// stores which key is pressed on
// which channel. (notes[key] = channel)
NoteArray notes;
Bus();
};
Player();
void reset();
void mix();
void process_messages(int size);
virtual void on_message(const Message &msg) {}
void set_model(class Model &model);
void set_sample_rate(int sample_rate);
void stop();
void play();
void seek(int position);
void flush();
int get_position() const;
bool is_playing() const;
void play_event(int track, const class PatternEvent &event);
void stop_events(int track);
protected:
void premix();
void mix_events(MessageQueue &queue, int samples);
void mix_frame(MessageQueue &queue);
void handle_message(Message msg);
long long get_frame_size();
MessageQueue &get_back();
MessageQueue &get_front();
void flip();
int sample_rate;
volatile int front_index; // index of messages front buffer
std::vector<Bus> buses;
MessageQueue messages[QueueCount];
MessageQueue rt_messages;
class Model *model;
volatile int read_position; // last read position, in frames
volatile bool playing;
};
//=============================================================================
} // namespace Jacker