// Syntax: C++
// $Smake: cc -g -c %b.cc && rm -f %b.o
//
#ifndef _SIGTIMER_H_INCLUDED
#define _SIGTIMER_H_INCLUDED
#ifdef VISUAL
#include
typedef LONGLONG int64bits;
#else
typedef long long int int64bits;
#endif
class SigTimer {
public:
SigTimer (void);
SigTimer (int aSpeed);
SigTimer (SigTimer& aTimer);
~SigTimer ();
static int64bits clockCycles (void);
int expired (void) const;
static int getCpuSpeed (void);
double getPeriod (void) const;
double getPeriodCount (void) const;
int getTicksPerSecond (void) const;
int getTime (void) const;
double getTimeInSeconds (void) const;
int getTimeInTicks (void) const;
int measureCpuSpeed (int quantize = 0) const;
void reset (void);
static void setCpuSpeed (int aSpeed);
void setPeriod (double aPeriod);
void setTempo (double beatsPerMinute);
void setTicksPerSecond (int aTickRate);
void start (void);
void sync (SigTimer& aTimer);
void update (void);
void update (int periodCount);
protected:
static int64bits globalOffset;
static int cpuSpeed;
int64bits offset;
int ticksPerSecond;
double period;
// protected functions
double getFactor (void) const;
};
#endif _SIGTIMER_H_INCLUDED
##################################
// Syntax: C++
// $Smake: g++ -O3 -Wall -o %b %f && strip %b
//
#include
#include
#include
#include
#include
#include "SigTimer.cpp"
// global variables:
const char* dev = "/dev/sequencer"; // name of sequencer file
int status; // for error checking
// function declarations:
void randomwalk(int seqfd, int device);
int main(int argc, char** argv) {
int seqfd = open(dev, O_WRONLY, 0);
if (seqfd < 0) {
cout << "Error: cannot open " << dev << endl;
exit(1);
}
int numMidi; // number of midi outputs
status = ioctl(seqfd, SNDCTL_SEQ_NRMIDIS, &numMidi);
if (status != 0) {
cout << "Error: cannot access MIDI devices on soundcard" << endl;
exit(1);
}
cout << "\nThere are: " << numMidi << " Midi output devices" << endl;
int device = 0; // MIDI output device to use
if (argc >= 2) {
device = argv[1][0] - '0';
}
if (device >= numMidi) {
cout << "Error: specified device is not valid: " << device << endl;
exit(1);
} else {
cout << "Device set to: " << device << endl;
}
randomwalk(seqfd, device);
close(seqfd);
return 0;
}
void randomwalk(int seqfd, int device) {
unsigned char outpacket[4];
outpacket[0] = SEQ_MIDIPUTC;
outpacket[2] = device;
outpacket[3] = 0;
cout << "What timbre do you want: ";
int userinput;
cin >> userinput;
outpacket[1] = 0xc0;
write(seqfd, outpacket, 4);
outpacket[1] = userinput & 0xff;
write(seqfd, outpacket, 4);
SigTimer timer;
cout << "Enter a tempo for quarter notes per minute: ";
double tempo = 120.0;
cin >> tempo;
timer.setTempo(tempo);
timer.reset();
timer.update(-1);
int key = 60;
while (1) {
if (timer.expired()) {
timer.update();
switch (rand() % 2) {
case 0: key--; if (key < 0) key = 0; break;
case 1: key++; if (key > 127) key = 127; break;
}
outpacket[1] = 0x90; // note-on MIDI command
write(seqfd, outpacket, 4);
outpacket[1] = key; // note-on key MIDI data
write(seqfd, outpacket, 4);
outpacket[1] = 127; // note-on velocity MIDI data
write(seqfd, outpacket, 4);
}
}
close(seqfd);
}
###################################
for MIDI Input:
// Syntax: C; pthread
// $Smake: gcc -O3 -Wall -o %b %f -static -lpthread && strip %b
//
#include
#include
#include
#include
#define MIDI_DEVICE "/dev/sequencer"
int main(void) {
unsigned char inpacket[4];
// first open the sequencer device for reading.
int seqfd = open(MIDI_DEVICE, O_RDONLY);
if (seqfd == -1) {
printf("Error: cannot open %s\n", MIDI_DEVICE);
exit(1);
}
// now just wait around for MIDI bytes to arrive and print them to screen.
while (1) {
read(seqfd, &inpacket, sizeof(inpacket));
// print the MIDI byte if this input packet contains one
if (inpacket[0] == SEQ_MIDIPUTC) {
printf("received MIDI byte: %d\n", inpacket[1]);
}
}
return 0;
}
##########################################
// Filename: insimple.c
// Syntax: C; pthread
// $Smake: gcc -O3 -Wall -o %b %f -lpthread && strip %b
//
#include
#include
#include
#include
#include
#define MIDI_DEVICE "/dev/sequencer"
// global variables:
int seqfd; // sequencer file descriptor
pthread_t midiInThread; // thread blocker for midi input
// function declarations
void* threadFunction(void*); // thread function for MIDI input interpreter
///////////////////////////////////////////////////////////////////////////
int main(void) {
int status; // for error checking
// (1) first open the sequencer device for reading.
// some examples also have a nonblocking options in 2nd param
seqfd = open(MIDI_DEVICE, O_RDONLY);
if (seqfd == -1) {
printf("Error: cannot open %s\n", MIDI_DEVICE);
exit(1);
}
// (2) now start the thread that interpreting incoming MIDI bytes:
status = pthread_create(&midiInThread, NULL, threadFunction, NULL);
if (status == -1) {
printf("Error: unable to create MIDI input thread.\n");
exit(1);
}
// (3) finally, just wait around for MIDI messages to appear in the
// input buffer and print them to the screen.
while (1) {
// do nothing, just wait around for thread function.
}
return 0;
}
///////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// threadFunction -- this function is sent to the pthread library
// functions for running as a separate thread.
//
void* threadFunction(void* x) {
unsigned char inbytes[4]; // bytes from sequencer driver
int status; // for error checking
while (1) {
status = read(seqfd, &inbytes, sizeof(inbytes));
if (status < 0) {
printf("Error reading %s\n", MIDI_DEVICE);
exit(1);
}
if (inbytes[0] == SEQ_MIDIPUTC) {
printf("received MIDI byte: %d\n", inbytes[1]);
}
}
}
#####################################
for MIDI I/O Interface
// Syntax: C++
//
#ifndef _SEQUENCER_H_INCLUDED
#define _SEQUENCER_H_INCLUDED
#include
#define MIDI_EXTERNAL (1)
#define MIDI_INTERNAL (2)
typedef unsigned char uchar;
class Sequencer {
public:
Sequencer (int autoOpen = 1);
~Sequencer ();
void close (void);
void displayInputs (ostream& out = cout,
char* initial = "\t") const;
void displayOutputs (ostream& out = cout,
char* initial = "\t") const;
int getNumInputs (void) const;
int getNumOutputs (void) const;
const char* getInputName (int aDevice) const;
const char* getOutputName (int aDevice) const;
int is_open (void) const;
int open (void);
void read (uchar* buf, uchar* dev, int count);
void rawread (uchar* buf, int packetCount);
void rebuildInfoDatabase (void);
void write (int aDevice, int aByte);
void write (int aDevice, uchar* bytes, int count);
void write (int aDevice, int* bytes, int count);
protected:
static const char* sequencer; // name of sequencer device
static int sequencer_fd; // sequencer file descriptor
static int class_count; // number of existing classes using
static uchar midi_write_packet[4]; // for writing MIDI bytes out
static uchar midi_read_packet[4]; // for reading MIDI bytes out
static uchar synth_write_message[8]; // for writing to internal seq
static int indevcount; // number of MIDI input devices
static int outdevcount; // number of MIDI output devices
static char** indevnames; // MIDI input device names
static char** outdevnames; // MIDI output device names
static int* indevnum; // total number of MIDI inputs
static int* outdevnum; // total number of MIDI outputs
static int* indevtype; // 1 = External, 2 = Internal
static int* outdevtype; // 1 = External, 2 = Internal
static uchar synth_message_buffer[1024]; // hold bytes for synth dev
static int synth_message_buffer_count; // count of synth buffer
static int synth_message_bytes_expected; // expected count of synth
static int synth_message_curr_device; // for keeping track of dev
private:
void buildInfoDatabase (void);
int getFd (void) const;
int getInDeviceValue (int aDevice) const;
int getInputType (int aDevice) const;
int getOutDeviceValue (int aDevice) const;
int getOutputType (int aDevice) const;
void removeInfoDatabase (void);
void setFd (int anFd);
void writeInternal(int aDevice, int aByte);
void transmitMessageToInternalSynth(void);
void transmitVoiceMessage(void);
void transmitCommonMessage(void);
};
#endif // _SEQUENCER_H_INCLUDED
####################################################
// Syntax: C++
// $Smake: g++ -Wall -g -c %f && rm -f %b.o
//
#include
#include
#include
#include
#include
#include
#include "Sequencer.h"
// define static variables:
const char* Sequencer::sequencer = "/dev/sequencer";
int Sequencer::sequencer_fd = -1;
int Sequencer::class_count = 0;
uchar Sequencer::midi_write_packet[4] = {SEQ_MIDIPUTC, 0, 0, 0};
uchar Sequencer::midi_read_packet[4];
// static variables for MIDI I/O information database
int Sequencer::indevcount = 0;
int Sequencer::outdevcount = 0;
int* Sequencer::indevnum = NULL;
int* Sequencer::outdevnum = NULL;
int* Sequencer::indevtype = NULL;
int* Sequencer::outdevtype = NULL;
char** Sequencer::indevnames = NULL;
char** Sequencer::outdevnames = NULL;
///////////////////////////////
//
// Sequencer::Sequencer --
// default value: autoOpen = 1;
//
Sequencer::Sequencer(int autoOpen) {
if (autoOpen) {
open();
}
if (class_count < 0) {
cerr << "Unusual class instatiation count: " << class_count << endl;
exit(1);
} else if (class_count == 0) {
buildInfoDatabase();
}
class_count++;
}
//////////////////////////////
//
// Sequencer::~Sequencer --
//
Sequencer::~Sequencer() {
class_count--;
if (class_count == 0) {
close();
removeInfoDatabase();
} else if (class_count < 0) {
cerr << "Unusual class instatiation count: " << class_count << endl;
exit(1);
}
}
//////////////////////////////
//
// Sequencer::close -- close the sequencer device. The device
// automatically closes once the program ends, but you can close it
// so that other programs can use it.
//
void Sequencer::close(void) {
::close(getFd());
}
//////////////////////////////
//
// Sequencer::displayInputs -- display a list of the
// available MIDI input devices.
// default values: out = cout, initial = "\t"
//
void Sequencer::displayInputs(ostream& out, char* initial) const {
for (int i=0; i
}
}
//////////////////////////////
//
// Sequencer::displayOutputs -- display a list of the
// available MIDI output devices.
// default values: out = cout, initial = "\t"
//
void Sequencer::displayOutputs(ostream& out, char* initial) const {
for (int i=0; i
}
}
//////////////////////////////
//
// Sequencer::getInputName -- returns a string to the name of
// the specified input device. The string will remain valid as
// long as there are any sequencer devices in existence.
//
const char* Sequencer::getInputName(int aDevice) const {
if (aDevice >= getNumInputs()) {
cerr << "Error: " << aDevice << " is greater than max in ("
<< getNumInputs() << ")" << endl;
exit(1);
}
return indevnames[aDevice];
}
//////////////////////////////
//
// Sequencer::getNumInputs -- returns the total number of
// MIDI inputs that can be used.
//
int Sequencer::getNumInputs(void) const {
return indevcount;
}
//////////////////////////////
//
// Sequencer::getNumOutputs -- returns the total number of
// MIDI inputs that can be used.
//
int Sequencer::getNumOutputs(void) const {
return outdevcount;
}
//////////////////////////////
//
// Sequencer::getOutputName -- returns a string to the name of
// the specified output device. The string will remain valid as
// long as there are any sequencer devices in existence.
//
const char* Sequencer::getOutputName(int aDevice) const {
if (aDevice >= getNumOutputs()) {
cerr << "Error: " << aDevice << " is greater than max out ("
<< getNumOutputs() << ")" << endl;
exit(1);
}
return outdevnames[aDevice];
}
//////////////////////////////
//
// Sequencer::is_open -- returns true if the
// sequencer device is open, false otherwise.
//
int Sequencer::is_open(void) const {
if (getFd() > 0) {
return 1;
} else {
return 0;
}
}
/////////////////////////////
//
// Sequencer::open -- returns true if the device
// was successfully opended (or already opened)
//
int Sequencer::open(void) {
if (getFd() <= 0) {
setFd(::open(sequencer, O_RDWR, 0));
}
return is_open();
}
//////////////////////////////
//
// Sequencer::read -- reads MIDI bytes and also stores the
// device from which the byte was read from. Timing is not
// saved from the device. If needed, then it would have to
// be saved in this function, or just return the raw packet
// data (use rawread function).
//
void Sequencer::read(uchar* buf, uchar* dev, int count) {
int i = 0;
while (i < count) {
::read(getFd(), midi_read_packet, sizeof(midi_read_packet));
if (midi_read_packet[1] == SEQ_MIDIPUTC) {
buf[i] = midi_read_packet[1];
dev[i] = midi_read_packet[2];
i++;
}
}
}
//////////////////////////////
//
// Sequencer::rawread -- read Input MIDI packets.
// each packet contains 4 bytes.
//
void Sequencer::rawread(uchar* buf, int packetCount) {
::read(getFd(), buf, packetCount * 4);
}
//////////////////////////////
//
// Sequencer::rebuildInfoDatabase -- rebuild the internal
// database that keeps track of the MIDI input and output devices.
//
void Sequencer::rebuildInfoDatabase(void) {
removeInfoDatabase();
buildInfoDatabase();
}
///////////////////////////////
//
// Sequencer::write -- Send a byte out the specified MIDI
// port which can be either an internal or an external synthesizer.
//
void Sequencer::write(int device, int aByte) {
switch (getOutputType(device)) {
case MIDI_EXTERNAL:
midi_write_packet[1] = (uchar) (0xff & aByte);
midi_write_packet[2] = getOutDeviceValue(device);
::write(getFd(), midi_write_packet, sizeof(midi_write_packet));
break;
case MIDI_INTERNAL:
writeInternal(getOutDeviceValue(device), aByte);
break;
}
}
void Sequencer::write(int device, uchar* bytes, int count) {
for (int i=0; i
}
}
void Sequencer::write(int device, int* bytes, int count) {
for (int i=0; i
}
}
///////////////////////////////////////////////////////////////////////////
//
// private functions
//
//////////////////////////////
//
// Sequencer::buildInfoDatabase -- determines the number
// of MIDI input and output devices available from
// /dev/sequencer, and determines their names.
//
void Sequencer::buildInfoDatabase(void) {
int status;
// read number of inputs available (external MIDI devices only)
status = ioctl(getFd(), SNDCTL_SEQ_NRMIDIS, &indevcount);
if (status!= 0) {
cerr << "Error determining the number of MIDI inputs" << endl;
exit(1);
}
// read number of output available
int extmidi = indevcount;
int intmidi;
status = ioctl(getFd(), SNDCTL_SEQ_NRSYNTHS, &intmidi);
if (status!= 0) {
cerr << "Error determining the number of MIDI inputs" << endl;
exit(1);
}
outdevcount = extmidi + intmidi;
// allocate space for names and device number arrays
if (indevnum != NULL || outdevnum != NULL || indevnames != NULL ||
outdevnames != NULL || indevtype != NULL || outdevtype != NULL) {
cerr << "Error: buildInfoDatabase called twice." << endl;
exit(1);
}
indevnum = new int[indevcount];
outdevnum = new int[outdevcount];
indevtype = new int[indevcount];
outdevtype = new int[outdevcount];
indevnames = new char*[indevcount];
outdevnames = new char*[outdevcount];
// fill in the device translation table and fill in the device names
int i;
struct midi_info midiinfo;
for (i=0; i
status = ioctl(getFd(), SNDCTL_MIDI_INFO, &midiinfo);
if (status != 0) {
cerr << "Error while reading MIDI device " << i << endl;
exit(1);
}
indevnum[i] = midiinfo.device;
outdevnum[i] = midiinfo.device;
indevtype[i] = MIDI_EXTERNAL;
outdevtype[i] = MIDI_EXTERNAL;
indevnames[i] = new char[strlen(midiinfo.name) + 1 + 10];
outdevnames[i] = new char[strlen(midiinfo.name) + 1 + 11];
strcpy(indevnames[i], midiinfo.name);
strcpy(outdevnames[i], midiinfo.name);
strcat(indevnames[i], " (MIDI In)");
strcat(outdevnames[i], " (MIDI Out)");
}
char tempstring[1024] = {0};
struct synth_info synthinfo;
for (i=0; i
status = ioctl(getFd(), SNDCTL_SYNTH_INFO, &synthinfo);
if (status != 0) {
cerr << "Error while reading MIDI device " << i << endl;
exit(1);
}
outdevnum[extmidi+i] = i;
outdevtype[extmidi + i] = MIDI_INTERNAL;
strcpy(tempstring, synthinfo.name);
switch (synthinfo.synth_type) {
case SYNTH_TYPE_FM: // 0
strcat(tempstring, " (FM");
switch (synthinfo.synth_subtype) {
case FM_TYPE_ADLIB: // 0
strcat(tempstring, " Adlib");
break;
case FM_TYPE_OPL3: // 1
strcat(tempstring, " OPL3");
break;
}
strcat(tempstring, ")");
break;
case SYNTH_TYPE_SAMPLE: // 1
strcat(tempstring, " (Wavetable)");
break;
case SYNTH_TYPE_MIDI: // 2
strcat(tempstring, " (MIDI Interface");
switch (synthinfo.synth_subtype) {
case SYNTH_TYPE_MIDI: // 0x401
strcat(tempstring, " MPU401");
break;
}
strcat(tempstring, ")");
break;
}
outdevnames[i+extmidi] = new char[strlen(tempstring) + 1];
strcpy(outdevnames[i+extmidi], tempstring);
}
}
//////////////////////////////
//
// Sequencer::getFd -- returns the file descriptor of the
// sequencer device.
//
int Sequencer::getFd(void) const {
return sequencer_fd;
}
//////////////////////////////
//
// Sequencer::getInDeviceValue --
//
int Sequencer::getInDeviceValue(int aDevice) const {
if (aDevice >= getNumInputs()) {
cerr << "Error: " << aDevice << " is greater than max in ("
<< getNumInputs() << ")" << endl;
exit(1);
}
return indevnum[aDevice];
}
//////////////////////////////
//
// Sequencer::getInputType -- returns 1 = external MIDI,
// 2 = internal MIDI
//
int Sequencer::getInputType(int aDevice) const {
if (aDevice >= getNumInputs()) {
cerr << "Error: " << aDevice << " is greater than max in ("
<< getNumInputs() << ")" << endl;
exit(1);
}
return indevtype[aDevice];
}
//////////////////////////////
//
// Sequencer::getOutDeviceValue --
//
int Sequencer::getOutDeviceValue(int aDevice) const {
if (aDevice >= getNumOutputs()) {
cerr << "Error: " << aDevice << " is greater than max out ("
<< getNumOutputs() << ")" << endl;
exit(1);
}
return outdevnum[aDevice];
}
//////////////////////////////
//
// Sequencer::getOutputType -- returns 1 = external MIDI,
// 2 = internal MIDI
//
int Sequencer::getOutputType(int aDevice) const {
if (aDevice >= getNumOutputs()) {
cerr << "Error: " << aDevice << " is greater than max out ("
<< getNumOutputs() << ")" << endl;
exit(1);
}
return outdevtype[aDevice];
}
//////////////////////////////
//
// Sequencer::removeInfoDatabase --
//
void Sequencer::removeInfoDatabase(void) {
if (indevnum != NULL) delete [] indevnum;
if (outdevnum != NULL) delete [] outdevnum;
if (indevtype != NULL) delete [] indevtype;
if (outdevtype != NULL) delete [] outdevtype;
int i;
if (indevnames != NULL) {
for (i=0; i
}
delete [] indevnames;
}
if (outdevnames != NULL) {
for (i=0; i
}
delete [] outdevnames;
}
indevnum = NULL;
outdevnum = NULL;
indevtype = NULL;
outdevtype = NULL;
indevnames = NULL;
outdevnames = NULL;
indevcount = 0;
outdevcount = 0;
}
//////////////////////////////
//
// Sequencer::setFd --
//
void Sequencer::setFd(int anFd) {
sequencer_fd = anFd;
}
///////////////////////////////////////////////////////////////////////////
//
// private functions dealing with the stupid internal sythesizer messages
// which have to be processed as complete messages as opposed to
// external MIDI devices which are processed on the driver level as
// discrete bytes.
//
// static variables related to the processing of message for internal MIDI:
uchar Sequencer::synth_write_message[8];
uchar Sequencer::synth_message_buffer[1024] = {0};
int Sequencer::synth_message_buffer_count = 0;
int Sequencer::synth_message_bytes_expected = 0;
int Sequencer::synth_message_curr_device = -1;
//////////////////////////////
//
// Sequencer::writeInternal -- the device number is the
// driver's device number *NOT* this class's device numbering
// system. MIDI bytes are stored in a buffer until a complete
// message is received, then a synth message is generated.
// While a complete message is being received, the device number
// cannot change. The first byte of a message must be a MIDI
// command (i.e., no running status).
//
void Sequencer::writeInternal(int aDevice, int aByte) {
if (synth_message_bytes_expected == 0) {
// a new message is coming in.
synth_message_curr_device = aDevice;
if (aByte < 128) {
cerr << "Error: MIDI output byte: " << aByte
<< " is not a command byte." << endl;
exit(1);
} else {
synth_message_buffer[0] = aByte;
synth_message_buffer_count = 1;
}
switch (aByte & 0xf0) {
case 0x80: synth_message_bytes_expected = 3; break;
case 0x90: synth_message_bytes_expected = 3; break;
case 0xA0: synth_message_bytes_expected = 3; break;
case 0xB0: synth_message_bytes_expected = 3; break;
case 0xC0: synth_message_bytes_expected = 2; break;
case 0xD0: synth_message_bytes_expected = 2; break;
case 0xE0: synth_message_bytes_expected = 3; break;
case 0xF0: cerr << "Can't handle 0xE0 yet" << endl; exit(1);
default: cerr << "Unknown error" << endl; exit(1);
}
}
// otherwise expecting at least one more byte for the MIDI message
else {
if (synth_message_curr_device != aDevice) {
cerr << "Error: device number changed during message" << endl;
exit(1);
}
if (aByte > 127) {
cerr << "Error: expecting MIDI data but got MIDI command: "
<< aByte << endl;
exit(1);
}
synth_message_buffer[synth_message_buffer_count++] = aByte;
}
// check to see if the message is complete:
if (synth_message_bytes_expected == synth_message_buffer_count) {
transmitMessageToInternalSynth();
synth_message_bytes_expected = 0;
synth_message_buffer_count = 0;
}
}
//////////////////////////////
//
// Sequencer::transmitMessageToInternalSynth -- send the stored
// MIDI message to the internal synthesizer.
//
void Sequencer::transmitMessageToInternalSynth(void) {
switch (synth_message_buffer[0] & 0xf0) {
case 0x80: // Note-off
case 0x90: // Note-on
case 0xA0: // Aftertouch
transmitVoiceMessage();
break;
case 0xB0: // Control change
case 0xC0: // Patch change
case 0xD0: // Channel pressure
case 0xE0: // Pitch wheel
transmitCommonMessage();
break;
case 0xF0:
cerr << "Cannot handle 0xf0 commands yet" << endl;
exit(1);
break;
default:
cerr << "Error: unknown MIDI command" << endl;
exit(1);
}
}
//////////////////////////////
//
// Sequencer::transmitVoiceMessage -- send a voice-type MIDI
// message to an internal synthesizer.
//
void Sequencer::transmitVoiceMessage(void) {
synth_write_message[0] = EV_CHN_VOICE;
synth_write_message[1] = synth_message_curr_device;
synth_write_message[2] = synth_message_buffer[0] & 0xf0;
synth_write_message[3] = synth_message_buffer[0] & 0x0f;
synth_write_message[4] = synth_message_buffer[1];
synth_write_message[5] = synth_message_buffer[2];
synth_write_message[6] = 0;
synth_write_message[7] = 0;
::write(getFd(), synth_write_message, sizeof(synth_write_message));
}
//////////////////////////////
//
// Sequencer::transmitCommonMessage -- send a common-type MIDI
// message to an internal synthesizer.
//
void Sequencer::transmitCommonMessage(void) {
synth_write_message[0] = EV_CHN_COMMON;
synth_write_message[1] = synth_message_curr_device;
synth_write_message[2] = synth_message_buffer[0] & 0xf0;
synth_write_message[3] = synth_message_buffer[0] & 0x0f;
switch (synth_write_message[2]) {
case 0xB0: // Control change
synth_write_message[4] = synth_message_buffer[1];
synth_write_message[5] = 0;
synth_write_message[6] = synth_message_buffer[2];
synth_write_message[7] = 0;
break;
case 0xC0: // Patch change
case 0xD0: // Channel pressure
synth_write_message[4] = synth_message_buffer[1];
synth_write_message[5] = 0;
synth_write_message[6] = 0;
synth_write_message[7] = 0;
break;
case 0xE0: // Pitch wheel
synth_write_message[4] = 0;
synth_write_message[5] = 0;
synth_write_message[6] = synth_message_buffer[1];
synth_write_message[7] = synth_message_buffer[2];
break;
default:
cerr << "Unknown Common MIDI message" << endl;
exit(1);
}
::write(getFd(), synth_write_message, sizeof(synth_write_message));
}
##################################
// Filename: ...linuxmidi/cpp/midiinfo.cpp
// Syntax: C++
// $Smake: g++ -DLINUX -O3 -Wall -o %b %f Sequencer.cpp && strip %b
//
// Description: displays the MIDI input/output devices which can be
// accessed through /dev/sequencer.
//
#include
#include "Sequencer.h"
int main(void) {
Sequencer sequencer;
cout << "\nNumber of MIDI outputs: " << sequencer.getNumOutputs() << '\n';
sequencer.displayOutputs();
cout << "\nNumber of MIDI inputs: " << sequencer.getNumInputs() << '\n';
sequencer.displayInputs();
cout << endl;
return 0;
}
##########################################
// Syntax: C++
// $Smake: g++ -DLINUX -O3 -Wall -o %b %f Sequencer.cpp && strip %b
//
#include
#include "Sequencer.h"
int main(void) {
Sequencer sequencer; // MIDI I/O interface
int outputDevice = 0; // MIDI output device number to send to
int keynumber = 60; // MIDI keynumber to play
int velocity; // MIDI attack velocity
int userInput; // computer keyboard input number
cout << "There are " << sequencer.getNumOutputs() << " MIDI outputs:.\n";
sequencer.displayOutputs();
cout << "\nEnter a device number to send out on (offset zero): ";
cin >> outputDevice;
while (1) {
cout << "Enter a key number to play (negative=off, >127=quit): ";
cin >> userInput;
if (userInput > 127) {
exit(0);
} else if (userInput >= 0 && userInput < sequencer.getNumOutputs()) {
outputDevice = userInput;
cout << "Changing to device " << outputDevice << ": "
<< sequencer.getOutputName(outputDevice) << endl;
continue;
} else {
keynumber = userInput;
}
if (keynumber < 0) {
keynumber = -keynumber;
velocity = 0;
} else {
velocity = 127;
}
// send a MIDI note-on message on MIDI channel 1:
sequencer.write(outputDevice, 0x90); // MIDI chan 1 note-on command
sequencer.write(outputDevice, keynumber); // MIDI key number
sequencer.write(outputDevice, velocity); // MIDI attack velocity
}
return 0;
}
#####################################
Keine Kommentare:
Kommentar veröffentlichen
Hinweis: Nur ein Mitglied dieses Blogs kann Kommentare posten.