minor changes
This commit is contained in:
parent
918d31692f
commit
553a02cc25
76
src/main.c
76
src/main.c
|
@ -9,13 +9,11 @@
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
|
|
||||||
#include "midi_interface.h"
|
#include "midi_interface.h"
|
||||||
|
#include "midi_parser.h"
|
||||||
|
|
||||||
typedef struct Note
|
uint32_t time_per_quarter;
|
||||||
{
|
uint32_t ticks_per_quarter;
|
||||||
unsigned char channel;
|
MidiInterface* interface;
|
||||||
unsigned char pitch;
|
|
||||||
unsigned char velocity;
|
|
||||||
} Note;
|
|
||||||
|
|
||||||
typedef struct Offset
|
typedef struct Offset
|
||||||
{
|
{
|
||||||
|
@ -53,16 +51,37 @@ static const Offset pattern[] = {
|
||||||
static int _Atomic stop = ATOMIC_VAR_INIT(0);
|
static int _Atomic stop = ATOMIC_VAR_INIT(0);
|
||||||
static int _Atomic step = ATOMIC_VAR_INIT(0);
|
static int _Atomic step = ATOMIC_VAR_INIT(0);
|
||||||
static Note* _Atomic note = ATOMIC_VAR_INIT(NULL);
|
static Note* _Atomic note = ATOMIC_VAR_INIT(NULL);
|
||||||
|
static int _Atomic playing = ATOMIC_VAR_INIT(0);
|
||||||
|
|
||||||
void *arpeggio_loop(void* data);
|
void* arpeggio_loop(void* data);
|
||||||
|
void* play_track(void* data);
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
MidiInterface* interface;
|
MidiParser* parser;
|
||||||
|
parser = parseMidi("out/pushing_onwards.mid", false, true);
|
||||||
|
if(!parser)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to read MIDI file\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
time_per_quarter = ((uint32_t*)(parser->tracks[0].events[2].infos))[0];
|
||||||
|
ticks_per_quarter = parser->ticks;
|
||||||
|
|
||||||
int result = open_midi_device(&interface, NULL);
|
int result = open_midi_device(&interface, NULL);
|
||||||
if(result < 0)
|
if(result < 0)
|
||||||
exit(result);
|
exit(result);
|
||||||
|
|
||||||
|
pthread_t* threads = (pthread_t*)malloc(parser->nbOfTracks * sizeof(pthread_t));
|
||||||
|
for(int i = 0; i < parser->nbOfTracks; i++)
|
||||||
|
{
|
||||||
|
pthread_create(threads + i, NULL, play_track, parser->tracks + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
playing = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
int key_down = 0;
|
int key_down = 0;
|
||||||
Note current_note;
|
Note current_note;
|
||||||
|
|
||||||
|
@ -107,7 +126,15 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
pthread_join(arpeggio_thread, NULL);
|
pthread_join(arpeggio_thread, NULL);
|
||||||
free_message(message);
|
free_message(message);
|
||||||
|
*/
|
||||||
|
for(int i = 0; i < parser->nbOfTracks; i++)
|
||||||
|
{
|
||||||
|
pthread_join(threads[i], NULL);
|
||||||
|
}
|
||||||
|
free(threads);
|
||||||
close_midi_device(interface);
|
close_midi_device(interface);
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,4 +167,37 @@ void *arpeggio_loop(void* data)
|
||||||
}
|
}
|
||||||
|
|
||||||
free_message(message);
|
free_message(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* play_track(void* data)
|
||||||
|
{
|
||||||
|
Track* track = (Track*)data;
|
||||||
|
Message* message;
|
||||||
|
create_message(&message);
|
||||||
|
message->channel = 0;
|
||||||
|
message->length = 2;
|
||||||
|
|
||||||
|
int current_event = 0;
|
||||||
|
|
||||||
|
while(current_event < track->nbOfEvents)
|
||||||
|
{
|
||||||
|
if(!playing)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Event event = track->events[current_event];
|
||||||
|
usleep(event.timeToAppear * time_per_quarter / ticks_per_quarter);
|
||||||
|
|
||||||
|
if(event.type == MidiNotePressed || event.type == MidiNoteReleased)
|
||||||
|
{
|
||||||
|
message->type = (event.type == MidiNotePressed) ? NOTE_ON : NOTE_OFF;
|
||||||
|
message->data = event.infos + 1;
|
||||||
|
|
||||||
|
// printf("Sending %d %d\n", message->data[0], message->data[1]);
|
||||||
|
int result = write_midi_device(interface, message);
|
||||||
|
if(result < 0)
|
||||||
|
fprintf(stderr, "Write err: %s\n", midi_strerror(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
current_event++;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -94,6 +94,11 @@ int write_midi_device(MidiInterface* interface, const Message* buffer)
|
||||||
return MIDI_WRITE_ERROR;
|
return MIDI_WRITE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int write_midi_device_raw(MidiInterface* interface, const char* buffer)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
int try_open_device(const char* device)
|
int try_open_device(const char* device)
|
||||||
{
|
{
|
||||||
int fd = open(device, O_RDWR, 0);
|
int fd = open(device, O_RDWR, 0);
|
||||||
|
|
|
@ -17,6 +17,7 @@ int close_midi_device(MidiInterface* interface);
|
||||||
|
|
||||||
int read_midi_device(MidiInterface* interface, Message* buffer);
|
int read_midi_device(MidiInterface* interface, Message* buffer);
|
||||||
int write_midi_device(MidiInterface* interface, const Message* buffer);
|
int write_midi_device(MidiInterface* interface, const Message* buffer);
|
||||||
|
int write_midi_device_raw(MidiInterface* interface, const char* buffer);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
1074
src/midi_parser.c
Normal file
1074
src/midi_parser.c
Normal file
File diff suppressed because it is too large
Load diff
91
src/midi_parser.h
Normal file
91
src/midi_parser.h
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/**
|
||||||
|
* https://github.com/Gegel85/midi_parser
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIB_MIDI_PARSER_HEADER_
|
||||||
|
#define __LIB_MIDI_PARSER_HEADER_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MidiSequenceNumber,
|
||||||
|
MidiTextEvent,
|
||||||
|
MidiNewLyric,
|
||||||
|
MidiNewMarker,
|
||||||
|
MidiNewCuePoint,
|
||||||
|
MidiNewChannelPrefix,
|
||||||
|
MidiPortChange,
|
||||||
|
MidiTempoChanged,
|
||||||
|
MidiSMTPEOffset,
|
||||||
|
MidiNewTimeSignature,
|
||||||
|
MidiNewKeySignature,
|
||||||
|
MidiSequencerSpecificEvent,
|
||||||
|
MidiNoteReleased,
|
||||||
|
MidiNotePressed,
|
||||||
|
MidiPolyphonicPressure,
|
||||||
|
MidiControllerValueChanged,
|
||||||
|
MidiProgramChanged,
|
||||||
|
MidiPressureOfChannelChanged,
|
||||||
|
MidiPitchBendChanged,
|
||||||
|
} EventType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EventType type;
|
||||||
|
int timeToAppear;
|
||||||
|
void *infos;
|
||||||
|
} Event;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char numerator;
|
||||||
|
unsigned char denominator;
|
||||||
|
unsigned char clockTicksPerMetTick;
|
||||||
|
unsigned char ticksPerQuarterNote;
|
||||||
|
} MidiTimeSignature;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char channel;
|
||||||
|
unsigned char pitch;
|
||||||
|
unsigned char velocity;
|
||||||
|
} MidiNote;
|
||||||
|
|
||||||
|
typedef struct Note {
|
||||||
|
unsigned char pitch;
|
||||||
|
unsigned char channel;
|
||||||
|
unsigned char velocity;
|
||||||
|
unsigned char fadeOutVelocity;
|
||||||
|
unsigned long int timeBeforeAppear;
|
||||||
|
unsigned long int duration;
|
||||||
|
} Note;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *copyright;
|
||||||
|
char *name;
|
||||||
|
char *instrumentName;
|
||||||
|
int nbOfEvents;
|
||||||
|
int nbOfNotes;
|
||||||
|
Note *notes;
|
||||||
|
Event *events;
|
||||||
|
} Track;
|
||||||
|
|
||||||
|
typedef struct NoteList {
|
||||||
|
Note *note;
|
||||||
|
struct NoteList *next;
|
||||||
|
struct NoteList *prev;
|
||||||
|
} NoteList;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned short format;
|
||||||
|
short nbOfTracks;
|
||||||
|
char fps;
|
||||||
|
short ticks;
|
||||||
|
int nbOfNotes;
|
||||||
|
Track *tracks;
|
||||||
|
} MidiParser;
|
||||||
|
|
||||||
|
bool parseMidiTrack(unsigned char *buffer, int buffLen, Track *track, bool outputDebug, MidiParser *result, int posInFile, bool createNoteArray);
|
||||||
|
MidiParser *parseMidi(char *path, bool outputDebug, bool createNoteArray);
|
||||||
|
char *getNoteString(char note);
|
||||||
|
void deleteTrack(Track *track);
|
||||||
|
void deleteMidiParserStruct(MidiParser *result);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue