-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.c
88 lines (77 loc) · 2.71 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// pim (Playmidi IMproved)
// (c) 2020 Nitin Seshadri.
// Based on initial work (c) 2012 PrZhu.
//
// clang -o playmidi main.c -framework CoreFoundation -framework AudioToolbox -framework CoreMIDI
#include <CoreFoundation/CoreFoundation.h>
#include <AudioToolbox/AudioToolbox.h>
#include <stdlib.h>
#include <stdio.h>
// ____________________________________________________________________________
// Obtain the name of an endpoint without regard for whether it has connections.
// The result should be released by the caller.
// From https://developer.apple.com/library/archive/qa/qa1374/_index.html
static CFStringRef GetEndpointDisplayName(MIDIEndpointRef endpoint) {
CFStringRef result = CFSTR(""); // default
MIDIObjectGetStringProperty(endpoint, kMIDIPropertyDisplayName, &result);
return result;
}
int main(int argc, const char * argv[]) {
CFShow(CFSTR("pim (Playmidi IMproved)\n"));
// Check for input file
if (argc > 1) {
printf("%s\n", argv[1]);
} else {
printf("usage: %s <file> [<device-number>]\n", argv[0]);
return 0;
}
CFStringRef filename = CFStringCreateWithCString(nil, argv[1], kCFStringEncodingUTF8);
CFURLRef url = CFURLCreateWithFileSystemPath(nil, filename, 0, false);
MusicSequence ms;
NewMusicSequence(&ms);
MusicSequenceFileLoad(ms, url, kMusicSequenceFile_MIDIType, kMusicSequenceLoadSMF_ChannelsToTracks);
if (argc > 2) {
int midiDestination = atoi(argv[2]);
CFShow(GetEndpointDisplayName(MIDIGetDestination(midiDestination)));
MusicSequenceSetMIDIEndpoint(ms, MIDIGetDestination(midiDestination));
} else {
CFShow(CFSTR("CoreAudio Software Synthesizer\n"));
}
// Adapted from https://developer.apple.com/library/archive/samplecode/PlaySequence/Listings/main_cpp.html
UInt32 ntracks;
MusicSequenceGetTrackCount(ms, &ntracks);
MusicTimeStamp sequenceLength = 0;
for (UInt32 i = 0; i < ntracks; ++i) {
MusicTrack track;
MusicTimeStamp trackLength;
UInt32 propsize = sizeof(MusicTimeStamp);
MusicSequenceGetIndTrack(ms, i, &track);
MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &trackLength, &propsize);
if (trackLength > sequenceLength) {
sequenceLength = trackLength;
}
}
printf("Length: %lf\n", sequenceLength);
MusicPlayer mp;
NewMusicPlayer(&mp);
MusicPlayerSetSequence(mp, ms);
if (argc > 3) {
float speed = atof(argv[3]);
MusicPlayerSetPlayRateScalar(mp, speed);
printf("Tempo: %lf\n", speed);
} else {
printf("Tempo: 1.0\n");
}
MusicPlayerPreroll(mp);
MusicPlayerStart(mp);
MusicTimeStamp t;
do {
usleep(1000);
MusicPlayerGetTime(mp, &t);
printf("\r%lf", t);
fflush(stdout);
} while (t < sequenceLength);
MusicPlayerStop(mp);
puts("");
return 0;
}