cmMidi.h/c: Added conversion to/from 14bit values and Pitch Bend.

This commit is contained in:
kevin 2013-04-08 23:05:05 -07:00
parent a39e5f620c
commit 7859bd0a8c
2 changed files with 136 additions and 107 deletions

View File

@ -121,6 +121,31 @@ cmMidiByte_t cmMidiStatusToByteCount( cmMidiByte_t status )
return 0; return 0;
} }
unsigned cmMidiTo14Bits( cmMidiByte_t d0, cmMidiByte_t d1 )
{
unsigned val = d0;
val <<= 7;
val += d1;
return val;
}
void cmMidiSplit14Bits( unsigned v, cmMidiByte_t* d0Ref, cmMidiByte_t* d1Ref )
{
*d0Ref = (v & 0x3f80) >> 7;
*d1Ref = v & 0x7f;
}
int cmMidiToPbend( cmMidiByte_t d0, cmMidiByte_t d1 )
{
int v = cmMidiTo14Bits(d0,d1);
return v - 8192;
}
void cmMidiSplitPbend( int v, cmMidiByte_t* d0Ref, cmMidiByte_t* d1Ref )
{
unsigned uv = v + 8192;
cmMidiSplit14Bits(uv,d0Ref,d1Ref);
}
//==================================================================================================== //====================================================================================================
const char* cmMidiToSciPitch( cmMidiByte_t pitch, char* label, unsigned labelCharCnt ) const char* cmMidiToSciPitch( cmMidiByte_t pitch, char* label, unsigned labelCharCnt )

218
cmMidi.h
View File

@ -5,133 +5,137 @@
extern "C" { extern "C" {
#endif #endif
enum enum
{ {
kMidiChCnt = 16, kMidiChCnt = 16,
kInvalidMidiByte = 128, kInvalidMidiByte = 128,
kMidiNoteCnt = kInvalidMidiByte, kMidiNoteCnt = kInvalidMidiByte,
kMidiCtlCnt = kInvalidMidiByte, kMidiCtlCnt = kInvalidMidiByte,
kMidiPgmCnt = kInvalidMidiByte, kMidiPgmCnt = kInvalidMidiByte,
kInvalidMidiPitch = kInvalidMidiByte, kInvalidMidiPitch = kInvalidMidiByte,
kInvalidMidiVelocity = kInvalidMidiByte, kInvalidMidiVelocity = kInvalidMidiByte,
kInvalidMidiCtl = kInvalidMidiByte, kInvalidMidiCtl = kInvalidMidiByte,
kInvalidMidiPgm = kInvalidMidiByte, kInvalidMidiPgm = kInvalidMidiByte,
kMidiSciPitchCharCnt = 5 // A#-1 kMidiSciPitchCharCnt = 5 // A#-1
}; };
// MIDI status bytes // MIDI status bytes
enum enum
{ {
kInvalidStatusMdId = 0x00, kInvalidStatusMdId = 0x00,
kNoteOffMdId = 0x80, kNoteOffMdId = 0x80,
kNoteOnMdId = 0x90, kNoteOnMdId = 0x90,
kPolyPresMdId = 0xa0, kPolyPresMdId = 0xa0,
kCtlMdId = 0xb0, kCtlMdId = 0xb0,
kPgmMdId = 0xc0, kPgmMdId = 0xc0,
kChPresMdId = 0xd0, kChPresMdId = 0xd0,
kPbendMdId = 0xe0, kPbendMdId = 0xe0,
kSysExMdId = 0xf0, kSysExMdId = 0xf0,
kSysComMtcMdId = 0xf1, kSysComMtcMdId = 0xf1,
kSysComSppMdId = 0xf2, kSysComSppMdId = 0xf2,
kSysComSelMdId = 0xf3, kSysComSelMdId = 0xf3,
kSysComUndef0MdId = 0xf4, kSysComUndef0MdId = 0xf4,
kSysComUndef1MdId = 0xf5, kSysComUndef1MdId = 0xf5,
kSysComTuneMdId = 0xf6, kSysComTuneMdId = 0xf6,
kSysComEoxMdId = 0xf7, kSysComEoxMdId = 0xf7,
kSysRtClockMdId = 0xf8, kSysRtClockMdId = 0xf8,
kSysRtUndef0MdId = 0xf9, kSysRtUndef0MdId = 0xf9,
kSysRtStartMdId = 0xfa, kSysRtStartMdId = 0xfa,
kSysRtContMdId = 0xfb, kSysRtContMdId = 0xfb,
kSysRtStopMdId = 0xfc, kSysRtStopMdId = 0xfc,
kSysRtUndef1MdId = 0xfd, kSysRtUndef1MdId = 0xfd,
kSysRtSenseMdId = 0xfe, kSysRtSenseMdId = 0xfe,
kSysRtResetMdId = 0xff, kSysRtResetMdId = 0xff,
kMetaStId = 0xff, kMetaStId = 0xff,
kSeqNumbMdId = 0x00, kSeqNumbMdId = 0x00,
kTextMdId = 0x01, kTextMdId = 0x01,
kCopyMdId = 0x02, kCopyMdId = 0x02,
kTrkNameMdId = 0x03, kTrkNameMdId = 0x03,
kInstrNameMdId = 0x04, kInstrNameMdId = 0x04,
kLyricsMdId = 0x05, kLyricsMdId = 0x05,
kMarkerMdId = 0x06, kMarkerMdId = 0x06,
kCuePointMdId = 0x07, kCuePointMdId = 0x07,
kMidiChMdId = 0x20, kMidiChMdId = 0x20,
kEndOfTrkMdId = 0x2f, kEndOfTrkMdId = 0x2f,
kTempoMdId = 0x51, kTempoMdId = 0x51,
kSmpteMdId = 0x54, kSmpteMdId = 0x54,
kTimeSigMdId = 0x58, kTimeSigMdId = 0x58,
kKeySigMdId = 0x59, kKeySigMdId = 0x59,
kSeqSpecMdId = 0x7f, kSeqSpecMdId = 0x7f,
kInvalidMetaMdId = 0x80, kInvalidMetaMdId = 0x80,
kSustainCtlMdId = 64 kSustainCtlMdId = 64
}; };
typedef unsigned char cmMidiByte_t; typedef unsigned char cmMidiByte_t;
//=============================================================================================== //===============================================================================================
// Utility Functions // Utility Functions
// //
#define cmMidiIsStatus( s ) (kNoteOffMdId <= (s) /*&& ((unsigned)(s)) <= kSysRtResetMdId*/ ) #define cmMidiIsStatus( s ) (kNoteOffMdId <= (s) /*&& ((unsigned)(s)) <= kSysRtResetMdId*/ )
#define cmMidiIsChStatus( s ) (kNoteOffMdId <= (s) && (s) < kSysExMdId) #define cmMidiIsChStatus( s ) (kNoteOffMdId <= (s) && (s) < kSysExMdId)
const char* cmMidiStatusToLabel( cmMidiByte_t status ); const char* cmMidiStatusToLabel( cmMidiByte_t status );
const char* cmMidiMetaStatusToLabel( cmMidiByte_t metaStatus ); const char* cmMidiMetaStatusToLabel( cmMidiByte_t metaStatus );
// Returns kInvalidMidiByte if status is not a valid status byte // Returns kInvalidMidiByte if status is not a valid status byte
cmMidiByte_t cmMidiStatusToByteCount( cmMidiByte_t status ); cmMidiByte_t cmMidiStatusToByteCount( cmMidiByte_t status );
unsigned cmMidiTo14Bits( cmMidiByte_t d0, cmMidiByte_t d1 );
void cmMidiSplit14Bits( unsigned v, cmMidiByte_t* d0Ref, cmMidiByte_t* d1Ref );
int cmMidiToPbend( cmMidiByte_t d0, cmMidiByte_t d1 );
void cmMidiSplitPbend( int v, cmMidiByte_t* d0Ref, cmMidiByte_t* d1Ref );
//===============================================================================================
// MIDI Communication data types
//
typedef struct
{
unsigned deltaUs; // time since last MIDI msg in microseconds
cmMidiByte_t status; // midi status byte
cmMidiByte_t d0; // midi data byte 0
cmMidiByte_t d1; // midi data byte 1
cmMidiByte_t pad;
} cmMidiMsg;
typedef struct
{
void* cbDataPtr; // application supplied reference value from mdParserCreate()
unsigned devIdx; // the device the msg originated from
unsigned portIdx; // the port index on the source device
cmMidiMsg* msgArray; // pointer to an array of 'msgCnt' mdMsg records or NULL if sysExMsg is non-NULL
cmMidiByte_t* sysExMsg; // pointer to a sys-ex msg or NULL if msgArray is non-NULL (see note below)
unsigned msgCnt; // count of mdMsg records or sys-ex bytes
} cmMidiPacket_t;
// Notes: If the sys-ex message can be contained in a single msg then
// then the first msg byte is kSysExMdId and the last is kSysComEoxMdId.
// If the sys-ex message is broken into multiple pieces then only the
// first will begin with kSysExMdId and the last will end with kSysComEoxMdId.
//=============================================================================================== // If label is NULL or labelCharCnt==0 then a pointer to an internal static
// MIDI Communication data types // buffer is returned. If label[] is given the it
// // should have at least 5 (kMidiPitchCharCnt) char's (including the terminating zero).
// If 'pitch' is outside of the range 0-127 then a blank string is returned.
typedef struct const char* cmMidiToSciPitch( cmMidiByte_t pitch, char* label, unsigned labelCharCnt );
{
unsigned deltaUs; // time since last MIDI msg in microseconds
cmMidiByte_t status; // midi status byte
cmMidiByte_t d0; // midi data byte 0
cmMidiByte_t d1; // midi data byte 1
cmMidiByte_t pad;
} cmMidiMsg;
typedef struct
{
void* cbDataPtr; // application supplied reference value from mdParserCreate()
unsigned devIdx; // the device the msg originated from
unsigned portIdx; // the port index on the source device
cmMidiMsg* msgArray; // pointer to an array of 'msgCnt' mdMsg records or NULL if sysExMsg is non-NULL
cmMidiByte_t* sysExMsg; // pointer to a sys-ex msg or NULL if msgArray is non-NULL (see note below)
unsigned msgCnt; // count of mdMsg records or sys-ex bytes
} cmMidiPacket_t;
// Notes: If the sys-ex message can be contained in a single msg then
// then the first msg byte is kSysExMdId and the last is kSysComEoxMdId.
// If the sys-ex message is broken into multiple pieces then only the
// first will begin with kSysExMdId and the last will end with kSysComEoxMdId.
// If label is NULL or labelCharCnt==0 then a pointer to an internal static // Scientific pitch string: [A-Ga-g][#b][#] where # may be -1 to 9.
// buffer is returned. If label[] is given the it // Return kInvalidMidiPitch if sciPtichStr does not contain a valid
// should have at least 5 (kMidiPitchCharCnt) char's (including the terminating zero). // scientific pitch string. This function will convert C-1 to G9 to
// If 'pitch' is outside of the range 0-127 then a blank string is returned. // valid MIDI pitch values 0 to 127. Scientific pitch strings outside
const char* cmMidiToSciPitch( cmMidiByte_t pitch, char* label, unsigned labelCharCnt ); // of this range will be returned as kInvalidMidiPitch.
cmMidiByte_t cmSciPitchToMidi( const char* sciPitchStr );
// Scientific pitch string: [A-Ga-g][#b][#] where # may be -1 to 9.
// Return kInvalidMidiPitch if sciPtichStr does not contain a valid
// scientific pitch string. This function will convert C-1 to G9 to
// valid MIDI pitch values 0 to 127. Scientific pitch strings outside
// of this range will be returned as kInvalidMidiPitch.
cmMidiByte_t cmSciPitchToMidi( const char* sciPitchStr );
#ifdef __cplusplus #ifdef __cplusplus
} }