Version 4.2.0

This commit is contained in:
Gary Scavone
2009-03-24 23:02:14 -04:00
committed by Stephen Sinclair
parent cf06b7598b
commit a6381b9d38
281 changed files with 17152 additions and 12000 deletions

View File

@@ -6,71 +6,171 @@
(via the RtMidi class), parses it, and turns it
into SKINI messages.
by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
by Perry R. Cook and Gary P. Scavone, 1995 - 2004.
*/
/***************************************************/
#include "RtMidi.h"
#include "Thread.h"
#include "Socket.h"
#include "SKINI.msg"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// Exit thread declaration.
extern "C" THREAD_RETURN THREAD_TYPE stdinMonitor(void * ptr);
#include <iostream>
#include <string>
void usage(void) {
printf("\nuseage: Md2Skini <flag(s)>\n\n");
printf(" With no arguments, Md2Skini converts MIDI input to SKINI\n");
printf(" format and sends the output directly to stdout.\n");
printf(" With flag = -s <hostname>, the output is sent over a socket\n");
printf(" connection (port 2001) to the optional hostname (default = localhost).\n");
printf(" With flag = -f <filename>, the output stream is simultaneously\n");
printf(" written to the file specified by the optional <filename>\n");
printf(" (default = test.ski).\n\n");
std::cout << "\nuseage: Md2Skini <flag(s)>\n\n";
std::cout << " With no arguments, Md2Skini converts MIDI input to SKINI\n";
std::cout << " format and sends the output directly to stdout.\n";
std::cout << " With flag = -f <filename>, the output stream is simultaneously\n";
std::cout << " written to the file specified by the optional <filename>\n";
std::cout << " (default = test.ski).\n";
std::cout << " A MIDI input port can be specified with flag = -p portNumber.\n" << std::endl;
exit(0);
}
int main(int argc,char *argv[])
void midiCallback( double deltatime, std::vector< unsigned char > *bytes, void *userData )
{
bool done = false, firstMessage = true, writeFile = false, useSocket = false;
FILE *file = NULL;
char fileName[256];
char hostName[128];
RtMidi *rtmidi = 0;
Socket *soket = 0;
Thread *thread = 0;
if ( bytes->size() < 2 ) return;
if ( argc>5 ) {
usage();
// Parse the MIDI bytes ... only keep MIDI channel messages.
if ( bytes->at(0) > 239 ) return;
register long type = bytes->at(0) & 0xF0;
register long channel = bytes->at(0) & 0x0F;
register long databyte1 = bytes->at(1);
register long databyte2 = 0;
if ( ( type != 0xC0 ) && ( type != 0xD0 ) ) {
if ( bytes->size() < 3 ) return;
databyte2 = bytes->at(2);
}
std::string typeName;
switch( type ) {
case __SK_NoteOn_:
if ( databyte2 == 0 ) {
typeName = "NoteOff\t\t";
databyte2 = 64;
}
else typeName = "NoteOn\t\t";
break;
case __SK_NoteOff_:
typeName = "NoteOff\t\t";
break;
case __SK_PolyPressure_:
typeName = "PolyPressure\t";
break;
case __SK_ProgramChange_:
typeName = "ProgramChange\t";
break;
case __SK_ChannelPressure_:
typeName = "ChannelPressure\t";
break;
case __SK_PitchBend_:
typeName = "PitchBend\t";
break;
case __SK_ControlChange_:
switch( databyte1 ) {
case __SK_PitchChange_:
typeName = "PitchChange\t";
break;
case __SK_Volume_:
typeName = "Volume\t";
break;
case __SK_ModWheel_:
typeName = "ModWheel\t";
break;
case __SK_Breath_:
typeName = "Breath\t\t";
break;
case __SK_FootControl_:
typeName = "FootControl\t";
break;
case __SK_Portamento_:
typeName = "Portamento\t";
break;
case __SK_Balance_:
typeName = "Balance\t";
break;
case __SK_Pan_:
typeName = "Pan\t\t";
break;
case __SK_Sustain_:
typeName = "Sustain\t";
break;
case __SK_Expression_:
typeName = "Expression\t";
break;
default:
typeName = "ControlChange\t";
break;
}
default:
typeName = "Unknown\t";
}
FILE *file = (FILE *) userData;
if ( type == 0xC0 || type == 0xD0 || type == 0xE0 ) { // program change, channel pressure, or pitchbend
fprintf( stdout, "%s %.3f %d %.1f\n", typeName.c_str(), 0.0, channel, (float)databyte1 );
if ( file != NULL )
fprintf( file, "%s %.3f %d %.1f\n", typeName.c_str(), deltatime, channel, (float)databyte1 );
}
else if ( type == 0xB0 ) { // control change
fprintf( stdout, "%s %.3f %d %.1f\n", typeName.c_str(), 0.0, channel, (float)databyte2 );
if ( file != NULL )
fprintf( file, "%s %.3f %d %.1f\n", typeName.c_str(), deltatime, channel, (float)databyte2 );
}
else { // noteon, noteoff, aftertouch, and unknown
fprintf( stdout, "%s %.3f %d %.1f %.1f\n", typeName.c_str(), 0.0, channel, (float)databyte1, (float)databyte2 );
if ( file != NULL )
fprintf( file, "%s %.3f %d %.1f %.1f\n", typeName.c_str(), deltatime, channel, (float)databyte1, (float)databyte2 );
}
}
int main( int argc,char *argv[] )
{
FILE *file = NULL;
std::string fileName;
RtMidiIn *midiin = 0;
unsigned int port = 0;
if ( argc > 5 ) usage();
// Parse the command-line arguments.
int i = 1;
while (i < argc) {
while ( i < argc ) {
if (argv[i][0] == '-') {
switch(argv[i][1]) {
case 's':
if ((i+1 < argc) && argv[i+1][0] != '-') {
i++;
strncpy(hostName, argv[i], 128);
}
else strcpy(hostName, "localhost");
useSocket = true;
break;
case 'f':
if ((i+1 < argc) && argv[i+1][0] != '-') {
if ( (i+1 < argc) && argv[i+1][0] != '-' ) {
i++;
strncpy(fileName, argv[i], 252);
if ( strstr(fileName,".ski") == NULL ) strcat(fileName, ".ski");
fileName = argv[i];
if ( fileName.find( ".ski" ) == std::string::npos ) fileName.append( ".ski" );
}
else strcpy(fileName, "test.ski");
file = fopen(fileName,"wb");
writeFile = true;
else fileName = "test.ski";
file = fopen( fileName.c_str(), "wb" );
break;
case 'p':
if ( i++ >= argc) usage();
port = (unsigned int) atoi( argv[i] );
break;
default:
@@ -82,234 +182,51 @@ int main(int argc,char *argv[])
i++;
}
MY_FLOAT dt=0.0;
try {
rtmidi = new RtMidi();
midiin = new RtMidiIn();
}
catch (StkError &) {
exit(0);
catch (RtError &error) {
error.printMessage();
if ( file != NULL ) fclose( file );
exit(EXIT_FAILURE);
}
// If using sockets, setup the client socket
if (useSocket) {
try {
soket = new Socket( 2001, hostName );
}
catch (StkError &) {
exit(0);
}
// Check available ports vs. specified.
unsigned int nPorts = midiin->getPortCount();
if ( nPorts == 0 ) {
std::cout << "No MIDI ports available!\n";
goto cleanup;
}
// Start the "exit" thread.
thread = new Thread();
if ( !thread->start( (THREAD_FUNCTION)&stdinMonitor, (void *) &done ) ) {
fprintf(stderr, "Unable to create exit thread ... aborting.\n");
else if ( port >= nPorts ) {
std::cout << "Invalid port specifier!\n";
goto cleanup;
}
// Write SKINI messages to buffer 's'. This is the easiest way to
// allow this single executable to work for both socketing and
// printf's to stdout.
char s[128];
int channel, j;
MY_FLOAT byte2, byte3;
while ( !done ) {
if (rtmidi->nextMessage() > 0) {
byte3 = rtmidi->getByteThree();
byte2 = rtmidi->getByteTwo();
channel = rtmidi->getChannel();
if (writeFile) dt = rtmidi->getDeltaTime();
if (firstMessage) { // first MIDI message time stamp is meaningless
dt = 0.0;
firstMessage = false;
}
switch(rtmidi->getType()) {
case __SK_NoteOn_:
if (byte3 < 1.0) {
sprintf(s,"NoteOff\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,64.0);
if (writeFile) {
fprintf(file,"NoteOff\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,64.0);
}
} else {
sprintf(s,"NoteOn\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
if (writeFile) {
fprintf(file,"NoteOn\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
}
}
break;
case __SK_NoteOff_:
if (byte3 < 2.0) byte3 = 64.0;
sprintf(s,"NoteOff\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
if (writeFile) {
fprintf(file,"NoteOff\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
}
break;
case __SK_PolyPressure_:
sprintf(s,"PolyPressure\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
if (writeFile) {
fprintf(file,"PolyPressure\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
}
break;
case __SK_ControlChange_:
j = (int) byte2;
switch(j) {
case __SK_PitchChange_:
sprintf(s,"PitchChange\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"PitchChange\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Volume_:
sprintf(s,"Volume\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Volume\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_ModWheel_:
sprintf(s,"ModWheel\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"ModWheel\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Breath_:
sprintf(s,"Breath\t\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Breath\t\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_FootControl_:
sprintf(s,"FootControl\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"FootControl\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Portamento_:
sprintf(s,"Portamento\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Portamento\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Balance_:
sprintf(s,"Balance\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Balance\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Pan_:
sprintf(s,"Pan\t\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Pan\t\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Sustain_:
sprintf(s,"Sustain\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Sustain\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Expression_:
sprintf(s,"Expression\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFile) {
fprintf(file,"Expression\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
default:
sprintf(s,"ControlChange\t%.3f %d %d %.1f\n",0.0,channel,j,byte3);
if (writeFile) {
fprintf(file,"ControlChange\t%.3f %d %d %.1f\n",dt,channel,j,byte3);
}
break;
}
break;
case __SK_ProgramChange_:
j = (int) byte2;
sprintf(s,"ProgramChange\t%.3f %d %d\n",0.0,channel,j);
if (writeFile) {
fprintf(file,"ProgramChange\t%.3f %d %d\n",dt,channel,j);
}
break;
case __SK_ChannelPressure_:
sprintf(s,"ChannelPressure\t%.3f %d %.1f\n",0.0,channel,byte2);
if (writeFile) {
fprintf(file,"ChannelPressure\t%.3f %d %.1f\n",dt,channel,byte2);
}
break;
case __SK_PitchBend_:
sprintf(s,"PitchBend\t%.3f %d %f\n",0.0,channel,byte2);
if (writeFile) {
fprintf(file,"PitchBend\t%.3f %d %f\n",dt,channel,byte2);
}
break;
default:
sprintf(s,"// Unknown\t%.3f %d %f %f\n",0.0,channel,byte2,byte3);
if (writeFile) {
fprintf(file,"// Unknown\t\t%.3f %d %f %f\n",dt,channel,byte2,byte3);
}
break;
}
if (useSocket) {
if ( soket->writeBuffer( s, strlen(s), 0 ) < 0 ) {
fprintf(stderr,"Socket connection failed ... aborting.\n");
goto cleanup;
}
}
else {
printf("%s", s);
fflush(stdout);
}
memset(s, 0, sizeof(s));
} else {
// Sleep for 10 milliseconds
Stk::sleep( 10 );
}
// Open the port.
try {
midiin->openPort( port );
}
catch (RtError &error) {
error.printMessage();
goto cleanup;
}
sprintf(s, "Exiting Md2Skini process ... bye!\n");
if (useSocket)
soket->writeBuffer( s, strlen(s), 0 );
else {
printf("%s", s);
fflush(stdout);
}
// Set our callback function. This should be done immediately after
// opening the port to avoid having incoming messages written to the
// queue instead of sent to the callback function.
midiin->setCallback( &midiCallback, file );
if (writeFile) {
printf("Wrote SKINI output to file %s.\n", fileName);
fclose(file);
}
// We'll ignore sysex, timing, and active sensing messages.
midiin->ignoreTypes( true, true, true );
std::cout << "\nReading MIDI input ... press <enter> to quit.\n";
char input;
std::cin.get(input);
cleanup:
done = true;
delete rtmidi;
delete soket;
delete thread;
delete midiin;
if ( file != NULL ) fclose( file );
return 0;
}
THREAD_RETURN THREAD_TYPE stdinMonitor(void * ptr)
{
bool *done = (bool *) ptr;
char inputString[128];
printf("Type 'Exit<cr>' to quit.\n");
while ( !*done ) {
fgets(inputString, 128, stdin);
if (inputString[3] == 't' && inputString[1] == 'x'
&& inputString[2] == 'i' && inputString[0] == 'E') {
*done = true;
}
else {
printf(inputString);
fflush(stdout);
}
}
std::cout << "Md2Skini finished ... bye!" << std::endl;
return 0;
}