diff --git a/src/MidiAnalyzer.cpp b/src/MidiAnalyzer.cpp index 01758a7..0088d18 100644 --- a/src/MidiAnalyzer.cpp +++ b/src/MidiAnalyzer.cpp @@ -3,269 +3,291 @@ #include #include /* union stash { - U64 mData2; - S8 channel; - } stash1; + U64 mData2; + S8 channel; + } stash1; */ -MidiAnalyzer::MidiAnalyzer() : Analyzer2(), mSettings( new MidiAnalyzerSettings() ), mSimulationInitilized( false ) { - SetAnalyzerSettings( mSettings.get() ); - distanceFromLastCommandPacket = -1; +MidiAnalyzer::MidiAnalyzer() : Analyzer2(), mSettings( new MidiAnalyzerSettings() ), mSimulationInitilized( false ) +{ + SetAnalyzerSettings( mSettings.get() ); + distanceFromLastCommandPacket = -1; } -MidiAnalyzer::~MidiAnalyzer() { - KillThread(); +MidiAnalyzer::~MidiAnalyzer() +{ + KillThread(); } -void MidiAnalyzer::WorkerThread() { +void MidiAnalyzer::WorkerThread() +{ + mSampleRateHz = GetSampleRate(); + + mSerial = GetAnalyzerChannelData( mSettings->mInputChannel ); + + if( mSerial->GetBitState() == BIT_LOW ) + mSerial->AdvanceToNextEdge(); + + // double Stop_Bits = mSettings->mStopBits; + unsigned short DataBits = 8; // FIXME + bool BigEndian = false; // FIXME + /* + * Big endian / Little endian. + * 31.25 kBaud, 1 start, 8 data, 1 stop bit. + * Asynchronous + */ + + U32 samples_per_bit = mSampleRateHz / mSettings->mBitRate; + U32 samples_to_first_center_of_first_data_bit = U32( 1.5 * double( mSampleRateHz ) / double( mSettings->mBitRate ) ); + // U8 dataQueue[5]; // Storage for previous frames, arranged in a FIFO. + // memset( &dataQueue, 0, sizeof(dataQueue) ); // clear it. + + for( ;; ) + { + U8 data = 0; + U8 mask = 0; + + if( BigEndian ) + mask = 1 << 7; + else + mask = 1; + + enum MidiFrameType FrameType; + union stash stash1; + + mSerial->AdvanceToNextEdge(); // falling edge -- beginning of the start bit + U64 starting_sample = mSerial->GetSampleNumber(); + mSerial->Advance( samples_to_first_center_of_first_data_bit ); - mSampleRateHz = GetSampleRate(); - - mSerial = GetAnalyzerChannelData( mSettings->mInputChannel ); - - if( mSerial->GetBitState() == BIT_LOW ) - mSerial->AdvanceToNextEdge(); - - //double Stop_Bits = mSettings->mStopBits; - unsigned short DataBits = 8; // FIXME - bool BigEndian = false; // FIXME - /* - * Big endian / Little endian. - * 31.25 kBaud, 1 start, 8 data, 1 stop bit. - * Asynchronous - */ - - U32 samples_per_bit = mSampleRateHz / mSettings->mBitRate; - U32 samples_to_first_center_of_first_data_bit = U32( 1.5 * double( mSampleRateHz ) / double( mSettings->mBitRate ) ); - //U8 dataQueue[5]; // Storage for previous frames, arranged in a FIFO. - //memset( &dataQueue, 0, sizeof(dataQueue) ); // clear it. - - for( ; ; ) { - U8 data = 0; - U8 mask = 0; + for( U32 i = 0; i < DataBits; i++ ) + { // Read in data. + // let's put a dot exactly where we sample this bit: + mResults->AddMarker( mSerial->GetSampleNumber(), AnalyzerResults::Dot, mSettings->mInputChannel ); + if( mSerial->GetBitState() == BIT_HIGH ) + { + data |= mask; + } + mSerial->Advance( samples_per_bit ); - if( BigEndian ) - mask = 1 << 7; - else - mask = 1; + if( BigEndian ) + mask = mask >> 1; + else + mask = mask << 1; + } - enum MidiFrameType FrameType; - union stash stash1; - - mSerial->AdvanceToNextEdge(); //falling edge -- beginning of the start bit - U64 starting_sample = mSerial->GetSampleNumber(); - mSerial->Advance( samples_to_first_center_of_first_data_bit ); - - for( U32 i=0; i < DataBits; i++ ) { // Read in data. - //let's put a dot exactly where we sample this bit: - mResults->AddMarker( mSerial->GetSampleNumber(), AnalyzerResults::Dot, mSettings->mInputChannel ); - if( mSerial->GetBitState() == BIT_HIGH ) { - data |= mask; - } - mSerial->Advance( samples_per_bit ); + // Set defaults, debugging aid. + FrameType = error; + stash1.channel = -8; - if( BigEndian ) - mask = mask >> 1; - else - mask = mask << 1; - } - - // Set defaults, debugging aid. - FrameType = error; - stash1.channel = -8; - - // Determine if data is a DATA byte or a COMMAND byte. - if ( data >= 0x80 ) { // COMMAND byte. Data has the MSB clear, Command bytes have it set. - if ( (data & 0xF0) == 0xF0 ) { // All system messages have 0xF in the high nibble. - systemMessage( data, &FrameType, &stash1 ); - } else { - channelMessage( data, &FrameType, &stash1 ); - distanceFromLastCommandPacket = 0; - } - } else { // DATA byte - dataParameter( data, &FrameType, &stash1 ); - } - - //we have a byte to save. - Frame frame; - frame.mData1 = data; - frame.mData2 = stash1.mData2; - frame.mType = FrameType; - frame.mFlags = 0; - frame.mStartingSampleInclusive = starting_sample; - frame.mEndingSampleInclusive = mSerial->GetSampleNumber(); - - mResults->AddFrame( frame ); - mResults->CommitResults(); - ReportProgress( frame.mEndingSampleInclusive ); - - if( distanceFromLastCommandPacket != -1 ) { - distanceFromLastCommandPacket++; - } - } + // Determine if data is a DATA byte or a COMMAND byte. + if( data >= 0x80 ) + { // COMMAND byte. Data has the MSB clear, Command bytes have it set. + if( ( data & 0xF0 ) == 0xF0 ) + { // All system messages have 0xF in the high nibble. + systemMessage( data, &FrameType, &stash1 ); + } + else + { + channelMessage( data, &FrameType, &stash1 ); + distanceFromLastCommandPacket = 0; + } + } + else + { // DATA byte + dataParameter( data, &FrameType, &stash1 ); + } + + // we have a byte to save. + Frame frame; + frame.mData1 = data; + frame.mData2 = stash1.mData2; + frame.mType = FrameType; + frame.mFlags = 0; + frame.mStartingSampleInclusive = starting_sample; + frame.mEndingSampleInclusive = mSerial->GetSampleNumber(); + + mResults->AddFrame( frame ); + mResults->CommitResults(); + ReportProgress( frame.mEndingSampleInclusive ); + + if( distanceFromLastCommandPacket != -1 ) + { + distanceFromLastCommandPacket++; + } + } } -void MidiAnalyzer::dataParameter( U8 mData, enum MidiFrameType *mFrameType, union stash *mStash1) +void MidiAnalyzer::dataParameter( U8 mData, enum MidiFrameType* mFrameType, union stash* mStash1 ) { - (*mStash1).channel = -2; // Channel is not stored in a data byte. - *mFrameType = Data; - if( distanceFromLastCommandPacket == 1 ) { // First parameter - (*mStash1).channel = dataFrameCorrespondingChannel; - switch (lastCommandPacketType) { - case NoteOff: - *mFrameType = Key; - break; - case NoteOn: - *mFrameType = Key; - break; - case Aftertouch: - *mFrameType = Key; - break; - case ContinuousController: - *mFrameType = ControllerNum; - break; - case PatchChange: - *mFrameType = InstrumentNum; - break; - case ChannelPressure: - *mFrameType = Pressure; - break; - case PitchBend: - *mFrameType = LSB; - break; - default: - *mFrameType = error; - break; - } - } else if( distanceFromLastCommandPacket == 2 ) { // Second parameter - (*mStash1).channel = dataFrameCorrespondingChannel; - switch (lastCommandPacketType) { - case NoteOff: - *mFrameType = Velocity; - break; - case NoteOn: - *mFrameType = Velocity; - break; - case Aftertouch: - *mFrameType = Touch; - break; - case ContinuousController: - *mFrameType = ControllerValue; - break; - case PatchChange: - *mFrameType = error; - break; - case ChannelPressure: - *mFrameType = error; - break; - case PitchBend: - *mFrameType = MSB; - break; - default: - *mFrameType = error; - break; - } - } else { - *mFrameType = orphanedData; - } + ( *mStash1 ).channel = -2; // Channel is not stored in a data byte. + *mFrameType = Data; + if( distanceFromLastCommandPacket == 1 ) + { // First parameter + ( *mStash1 ).channel = dataFrameCorrespondingChannel; + switch( lastCommandPacketType ) + { + case NoteOff: + *mFrameType = Key; + break; + case NoteOn: + *mFrameType = Key; + break; + case Aftertouch: + *mFrameType = Key; + break; + case ContinuousController: + *mFrameType = ControllerNum; + break; + case PatchChange: + *mFrameType = InstrumentNum; + break; + case ChannelPressure: + *mFrameType = Pressure; + break; + case PitchBend: + *mFrameType = LSB; + break; + default: + *mFrameType = error; + break; + } + } + else if( distanceFromLastCommandPacket == 2 ) + { // Second parameter + ( *mStash1 ).channel = dataFrameCorrespondingChannel; + switch( lastCommandPacketType ) + { + case NoteOff: + *mFrameType = Velocity; + break; + case NoteOn: + *mFrameType = Velocity; + break; + case Aftertouch: + *mFrameType = Touch; + break; + case ContinuousController: + *mFrameType = ControllerValue; + break; + case PatchChange: + *mFrameType = error; + break; + case ChannelPressure: + *mFrameType = error; + break; + case PitchBend: + *mFrameType = MSB; + break; + default: + *mFrameType = error; + break; + } + } + else + { + *mFrameType = orphanedData; + } } -void MidiAnalyzer::systemMessage( U8 mData, enum MidiFrameType *mFrameType, union stash *mStash1) +void MidiAnalyzer::systemMessage( U8 mData, enum MidiFrameType* mFrameType, union stash* mStash1 ) { - (*mStash1).channel = -1; // Channel is not stored in a System Message byte. - switch (mData) { - case 0xF0: - *mFrameType = BeginSystemExclusiveMessage; - break; - case 0xF1: - *mFrameType = MIDITimeCodeQuarterFrame; - break; - case 0xF2: - *mFrameType = SongPositionPointer; - break; - case 0xF3: - *mFrameType = SongSelect; - break; - case 0xF4: - *mFrameType = F4; - break; - case 0xF5: - *mFrameType = F5; - break; - case 0xF6: - *mFrameType = TuneRequest; - break; - case 0xF7: - *mFrameType = EndSystemExclusiveMessage; - break; - case 0xF8: - *mFrameType = TimingClock; - break; - case 0xF9: - *mFrameType = F9; - break; - case 0xFA: - *mFrameType = Start_; - break; - case 0xFB: - *mFrameType = Continue; - break; - case 0xFC: - *mFrameType = Stop_; - break; - case 0xFD: - *mFrameType = FD; - break; - case 0xFE: - *mFrameType = ActiveSensing; - break; - case 0xFF: - *mFrameType = SystemReset; - break; - default: - *mFrameType = error; - break; - } + ( *mStash1 ).channel = -1; // Channel is not stored in a System Message byte. + switch( mData ) + { + case 0xF0: + *mFrameType = BeginSystemExclusiveMessage; + break; + case 0xF1: + *mFrameType = MIDITimeCodeQuarterFrame; + break; + case 0xF2: + *mFrameType = SongPositionPointer; + break; + case 0xF3: + *mFrameType = SongSelect; + break; + case 0xF4: + *mFrameType = F4; + break; + case 0xF5: + *mFrameType = F5; + break; + case 0xF6: + *mFrameType = TuneRequest; + break; + case 0xF7: + *mFrameType = EndSystemExclusiveMessage; + break; + case 0xF8: + *mFrameType = TimingClock; + break; + case 0xF9: + *mFrameType = F9; + break; + case 0xFA: + *mFrameType = Start_; + break; + case 0xFB: + *mFrameType = Continue; + break; + case 0xFC: + *mFrameType = Stop_; + break; + case 0xFD: + *mFrameType = FD; + break; + case 0xFE: + *mFrameType = ActiveSensing; + break; + case 0xFF: + *mFrameType = SystemReset; + break; + default: + *mFrameType = error; + break; + } } -void MidiAnalyzer::channelMessage( U8 mData, enum MidiFrameType *mFrameType, union stash *mStash1) +void MidiAnalyzer::channelMessage( U8 mData, enum MidiFrameType* mFrameType, union stash* mStash1 ) { - U8 lowerNibble = mData & 0x0F; // Channel is stored in the lower nibble. - (*mStash1).channel = lowerNibble; - dataFrameCorrespondingChannel = lowerNibble; - - U8 mDataLowerNibbleCleared = mData & 0xF0; - //upperNibble = upperNibble >> 4; // Shift to lower nibble - switch (mDataLowerNibbleCleared) { - case 0x80: - *mFrameType = NoteOff; - break; - case 0x90: - *mFrameType = NoteOn; - break; - case 0xA0: - *mFrameType = Aftertouch; - break; - case 0xB0: - *mFrameType = ContinuousController; - break; - case 0xC0: - *mFrameType = PatchChange; - break; - case 0xD0: - *mFrameType = ChannelPressure; - break; - case 0xE0: - *mFrameType = PitchBend; - break; - default: - *mFrameType = error; - (*mStash1).channel = -4; - break; - } - lastCommandPacketType = *mFrameType; + U8 lowerNibble = mData & 0x0F; // Channel is stored in the lower nibble. + ( *mStash1 ).channel = lowerNibble; + dataFrameCorrespondingChannel = lowerNibble; + + U8 mDataLowerNibbleCleared = mData & 0xF0; + // upperNibble = upperNibble >> 4; // Shift to lower nibble + switch( mDataLowerNibbleCleared ) + { + case 0x80: + *mFrameType = NoteOff; + break; + case 0x90: + *mFrameType = NoteOn; + break; + case 0xA0: + *mFrameType = Aftertouch; + break; + case 0xB0: + *mFrameType = ContinuousController; + break; + case 0xC0: + *mFrameType = PatchChange; + break; + case 0xD0: + *mFrameType = ChannelPressure; + break; + case 0xE0: + *mFrameType = PitchBend; + break; + default: + *mFrameType = error; + ( *mStash1 ).channel = -4; + break; + } + lastCommandPacketType = *mFrameType; } -bool MidiAnalyzer::NeedsRerun() { +bool MidiAnalyzer::NeedsRerun() +{ return false; } @@ -276,31 +298,39 @@ void MidiAnalyzer::SetupResults() mResults->AddChannelBubblesWillAppearOn( mSettings->mInputChannel ); } -U32 MidiAnalyzer::GenerateSimulationData( U64 minimum_sample_index, U32 device_sample_rate, SimulationChannelDescriptor** simulation_channels ) { - if( mSimulationInitilized == false ) { - mSimulationDataGenerator.Initialize( GetSimulationSampleRate(), mSettings.get() ); - mSimulationInitilized = true; - } +U32 MidiAnalyzer::GenerateSimulationData( U64 minimum_sample_index, U32 device_sample_rate, + SimulationChannelDescriptor** simulation_channels ) +{ + if( mSimulationInitilized == false ) + { + mSimulationDataGenerator.Initialize( GetSimulationSampleRate(), mSettings.get() ); + mSimulationInitilized = true; + } - return mSimulationDataGenerator.GenerateSimulationData( minimum_sample_index, device_sample_rate, simulation_channels ); + return mSimulationDataGenerator.GenerateSimulationData( minimum_sample_index, device_sample_rate, simulation_channels ); } -U32 MidiAnalyzer::GetMinimumSampleRateHz() { - return mSettings->mBitRate * 4; +U32 MidiAnalyzer::GetMinimumSampleRateHz() +{ + return mSettings->mBitRate * 4; } -const char* MidiAnalyzer::GetAnalyzerName() const { - return "Midi"; +const char* MidiAnalyzer::GetAnalyzerName() const +{ + return "Midi"; } -const char* GetAnalyzerName() { - return "Midi"; +const char* GetAnalyzerName() +{ + return "Midi"; } -Analyzer* CreateAnalyzer() { - return new MidiAnalyzer(); +Analyzer* CreateAnalyzer() +{ + return new MidiAnalyzer(); } -void DestroyAnalyzer( Analyzer* analyzer ) { - delete analyzer; +void DestroyAnalyzer( Analyzer* analyzer ) +{ + delete analyzer; } diff --git a/src/MidiAnalyzer.h b/src/MidiAnalyzer.h index f720343..a82716e 100644 --- a/src/MidiAnalyzer.h +++ b/src/MidiAnalyzer.h @@ -8,51 +8,52 @@ class MidiAnalyzerSettings; class MidiAnalyzer : public Analyzer2 { -public: - MidiAnalyzer(); - virtual ~MidiAnalyzer(); - virtual void WorkerThread(); - - virtual U32 GenerateSimulationData( U64 newest_sample_requested, U32 sample_rate, SimulationChannelDescriptor** simulation_channels ); - virtual U32 GetMinimumSampleRateHz(); - - virtual const char* GetAnalyzerName() const; - virtual bool NeedsRerun(); - + public: + MidiAnalyzer(); + virtual ~MidiAnalyzer(); + virtual void WorkerThread(); + + virtual U32 GenerateSimulationData( U64 newest_sample_requested, U32 sample_rate, SimulationChannelDescriptor** simulation_channels ); + virtual U32 GetMinimumSampleRateHz(); + + virtual const char* GetAnalyzerName() const; + virtual bool NeedsRerun(); + virtual void SetupResults(); -protected: //vars - union stash { - U64 mData2; - S8 channel; - } stash1; - bool inCommandPacket; - S64 distanceFromLastCommandPacket; - S32 dataFrameCorrespondingChannel; - enum MidiFrameType lastCommandPacketType; - -protected: //functions - void dataParameter( U8 mData, enum MidiFrameType *mFrameType, union stash *mStash1); - void systemMessage( U8 mData, enum MidiFrameType *mFrameType, union stash *mStash1); - void channelMessage( U8 mData, enum MidiFrameType *mFrameType, union stash *mStash1); - -protected: //vars - std::auto_ptr< MidiAnalyzerSettings > mSettings; - std::auto_ptr< MidiAnalyzerResults > mResults; - AnalyzerChannelData* mSerial; - - MidiSimulationDataGenerator mSimulationDataGenerator; - bool mSimulationInitilized; - double Stop_Bits; - double Parity_Bit; - - //Serial analysis vars: - U32 mSampleRateHz; - U32 mStartOfStopBitOffset; - U32 mEndOfStopBitOffset; + + protected: // vars + union stash { + U64 mData2; + S8 channel; + } stash1; + bool inCommandPacket; + S64 distanceFromLastCommandPacket; + S32 dataFrameCorrespondingChannel; + enum MidiFrameType lastCommandPacketType; + + protected: // functions + void dataParameter( U8 mData, enum MidiFrameType* mFrameType, union stash* mStash1 ); + void systemMessage( U8 mData, enum MidiFrameType* mFrameType, union stash* mStash1 ); + void channelMessage( U8 mData, enum MidiFrameType* mFrameType, union stash* mStash1 ); + + protected: // vars + std::auto_ptr mSettings; + std::auto_ptr mResults; + AnalyzerChannelData* mSerial; + + MidiSimulationDataGenerator mSimulationDataGenerator; + bool mSimulationInitilized; + double Stop_Bits; + double Parity_Bit; + + // Serial analysis vars: + U32 mSampleRateHz; + U32 mStartOfStopBitOffset; + U32 mEndOfStopBitOffset; }; extern "C" ANALYZER_EXPORT const char* __cdecl GetAnalyzerName(); -extern "C" ANALYZER_EXPORT Analyzer* __cdecl CreateAnalyzer( ); +extern "C" ANALYZER_EXPORT Analyzer* __cdecl CreateAnalyzer(); extern "C" ANALYZER_EXPORT void __cdecl DestroyAnalyzer( Analyzer* analyzer ); -#endif //MIDI_ANALYZER_H +#endif // MIDI_ANALYZER_H diff --git a/src/MidiAnalyzerResults.cpp b/src/MidiAnalyzerResults.cpp index e703eb3..917cccd 100644 --- a/src/MidiAnalyzerResults.cpp +++ b/src/MidiAnalyzerResults.cpp @@ -11,9 +11,7 @@ #include MidiAnalyzerResults::MidiAnalyzerResults( MidiAnalyzer* analyzer, MidiAnalyzerSettings* settings ) -: AnalyzerResults(), - mSettings( settings ), - mAnalyzer( analyzer ) + : AnalyzerResults(), mSettings( settings ), mAnalyzer( analyzer ) { } @@ -23,762 +21,944 @@ MidiAnalyzerResults::~MidiAnalyzerResults() void MidiAnalyzerResults::GenerateBubbleText( U64 frame_index, Channel& channel, DisplayBase display_base ) { - ClearResultStrings(); - Frame frame = GetFrame( frame_index ); - - enum MidiFrameType FrameType; - union stash stash1; - FrameType = (enum MidiFrameType) frame.mType; - stash1.mData2 = frame.mData2; - - localDisplay_base = display_base; - localFrame = frame; - localFrame_index = frame_index; - - - results( FrameType, stash1 ); + ClearResultStrings(); + Frame frame = GetFrame( frame_index ); + + enum MidiFrameType FrameType; + union stash stash1; + FrameType = ( enum MidiFrameType )frame.mType; + stash1.mData2 = frame.mData2; + + localDisplay_base = display_base; + localFrame = frame; + localFrame_index = frame_index; + + + results( FrameType, stash1 ); } void MidiAnalyzerResults::results( enum MidiFrameType mFrameType, union stash mStash1 ) -{ - char * result = NULL; - char * frameType = NULL; - //char * channelNum = NULL; - char channelNum[1024]; - char buffer[1024]; - const int size = 1024; - int charsPrinted; - int nchars; - S8 channel = mStash1.channel; - - char number_str[128]; - AnalyzerHelpers::GetNumberString( localFrame.mData1, localDisplay_base, 8, number_str, 128 ); - - // Makes a string describing the message type (data, command, what command). - switch (mFrameType) { - case Command: - nchars = snprintf(buffer, size, "Command Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - nchars = snprintf(buffer, size, "Com Ch %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "C" ); - break; - case Data: - nchars = snprintf(buffer, size, "Data Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - nchars = snprintf(buffer, size, "Data Ch %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "D" ); - break; - // End misc - // Start data - case Key: - nchars = snprintf(buffer, size, "Key Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "Key" ); - AddResultString( "K" ); - break; - case Velocity: - nchars = snprintf(buffer, size, "Velocity Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "Velocity" ); - AddResultString( "V" ); - break; - case Touch: - nchars = snprintf(buffer, size, "Touch Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "Touch" ); - AddResultString( "T" ); - break; - case ControllerNum: - nchars = snprintf(buffer, size, "ControllerNum Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "ControllerNum" ); - AddResultString( "CN" ); - break; - case ControllerValue: - nchars = snprintf(buffer, size, "ControllerValue Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "ControllerValue" ); - AddResultString( "CV" ); - break; - case InstrumentNum: - nchars = snprintf(buffer, size, "InstrumentNum Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "InstrumentNum" ); - AddResultString( "IN" ); - break; - case Pressure: - nchars = snprintf(buffer, size, "Pressure Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "Pressure" ); - AddResultString( "P" ); - break; - case LSB: - nchars = snprintf(buffer, size, "LSB Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "LSB" ); - AddResultString( "L" ); - break; - case MSB: - nchars = snprintf(buffer, size, "MSB Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "MSB" ); - AddResultString( "M" ); - break; - case orphanedData: - nchars = snprintf(buffer, size, "orphanedData Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "orphanedData" ); - AddResultString( "o" ); - break; - // End data - // Start commands - case NoteOff: - nchars = snprintf(buffer, size, "NoteOff Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - nchars = snprintf(buffer, size, "NOff Chan %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "NOff" ); - AddResultString( "N" ); - break; - case NoteOn: - nchars = snprintf(buffer, size, "NoteOn Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - nchars = snprintf(buffer, size, "NOn Chan %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "NOn" ); - AddResultString( "N" ); - break; - case Aftertouch: - nchars = snprintf(buffer, size, "Aftertouch Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - nchars = snprintf(buffer, size, "Aft Chan %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "Aft" ); - AddResultString( "A" ); - break; - case ContinuousController: - nchars = snprintf(buffer, size, "ContinuousController Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - nchars = snprintf(buffer, size, "ContinuControl Chan %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "ContinuControl" ); - AddResultString( "CC" ); - AddResultString( "C" ); - break; - case PatchChange: - nchars = snprintf(buffer, size, "PatchChange Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - nchars = snprintf(buffer, size, "P_Ch Chan %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "PCh" ); - AddResultString( "P" ); - break; - case ChannelPressure: - nchars = snprintf(buffer, size, "ChannelPressure Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - nchars = snprintf(buffer, size, "ChanPres Chan %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "ChanPres" ); - AddResultString( "C" ); - break; - case PitchBend: - nchars = snprintf(buffer, size, "PitchBend Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - nchars = snprintf(buffer, size, "PitchB Chan %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "PitchB" ); - AddResultString( "P" ); - break; - // End commands - // Start non-musical commands. They do not have channels. - case BeginSystemExclusiveMessage: - nchars = snprintf(buffer, size, "BeginSystemExclusiveMessage [%s]", number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - nchars = snprintf(buffer, size, "BegSystemExclMessage [%s]", number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "BegSystemExclMessage" ); - AddResultString( "SysExclMes" ); - AddResultString( "SysEx" ); - AddResultString( "SE" ); - break; - case MIDITimeCodeQuarterFrame: - nchars = snprintf(buffer, size, "MIDITimeCodeQuarterFrame [%s]", number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - nchars = snprintf(buffer, size, "TimeCodeQuarFr [%s]", number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "TimeCodeQuarFr" ); - AddResultString( "QuarFr" ); - AddResultString( "QF" ); - break; - case SongPositionPointer: - nchars = snprintf(buffer, size, "SongPositionPointer [%s]", number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - nchars = snprintf(buffer, size, "SongPosPoint [%s]", number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "SongPosPoint" ); - AddResultString( "SongPos" ); - AddResultString( "SPP" ); - AddResultString( "SP" ); - break; - case SongSelect: - nchars = snprintf(buffer, size, "SongSelect [%s]", number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - nchars = snprintf(buffer, size, "SongSel [%s]", number_str); - if (nchars >= 0 && nchars < size) { - AddResultString( buffer ); - } else AddResultString( "IE" ); - - AddResultString( "SongSel" ); - AddResultString( "SoSel" ); - AddResultString( "SS" ); - break; - case F4: - nchars = sprintf(channelNum, "F4 [%s]", number_str); - if (nchars >= 0) { - AddResultString( channelNum ); - } else AddResultString( "IE" ); - AddResultString( "4" ); - break; - case F5: - nchars = sprintf(channelNum, "F5 [%s]", number_str); - if (nchars >= 0) { - AddResultString( channelNum ); - } else AddResultString( "IE" ); - AddResultString( "5" ); - break; - case TuneRequest: - nchars = sprintf(channelNum, "TuneRequest [%s]", number_str); - if (nchars >= 0) { - AddResultString( channelNum ); - } else AddResultString( "IE" ); - AddResultString( "TuneReq" ); - AddResultString( "Tune" ); - AddResultString( "T" ); - break; - case EndSystemExclusiveMessage: - nchars = sprintf(channelNum, "EndSystemExclusiveMessage [%s]", number_str); - if (nchars >= 0) { - AddResultString( channelNum ); - } else AddResultString( "IE" ); - AddResultString( "EndSystemExcMess" ); - AddResultString( "EndSysExc" ); - AddResultString( "ESEM" ); - AddResultString( "ES" ); - break; - case TimingClock: - nchars = sprintf(channelNum, "TimingClock [%s]", number_str); - if (nchars >= 0) { - AddResultString( channelNum ); - } else AddResultString( "IE" ); - AddResultString( "TimClk" ); - AddResultString( "TiCl" ); - AddResultString( "TC" ); - break; - case F9: - nchars = sprintf(channelNum, "F9 [%s]", number_str); - if (nchars >= 0) { - AddResultString( channelNum ); - } else AddResultString( "IE" ); - AddResultString( "9" ); - break; - case Start_: - nchars = sprintf(channelNum, "Start [%s]", number_str); - if (nchars >= 0) { - AddResultString( channelNum ); - } else AddResultString( "IE" ); - AddResultString( "Sta" ); - AddResultString( "S" ); - break; - case Continue: - nchars = sprintf(channelNum, "Continue [%s]", number_str); - if (nchars >= 0) { - AddResultString( channelNum ); - } else AddResultString( "IE" ); - AddResultString( "Cont" ); - AddResultString( "C" ); - break; - case Stop_: - nchars = sprintf(channelNum, "Stop [%s]", number_str); - if (nchars >= 0) { - AddResultString( channelNum ); - } else AddResultString( "IE" ); - AddResultString( "St" ); - AddResultString( "S" ); - break; - case FD: - nchars = sprintf(channelNum, "FD [%s]", number_str); - if (nchars >= 0) { - AddResultString( channelNum ); - } else AddResultString( "IE" ); - AddResultString( "D" ); - break; - case ActiveSensing: - nchars = sprintf(channelNum, "ActiveSensing [%s]", number_str); - if (nchars >= 0) { - AddResultString( channelNum ); - } else AddResultString( "IE" ); - AddResultString( "ActSens" ); - AddResultString( "AS" ); - break; - case SystemReset: - nchars = sprintf(channelNum, "SystemReset [%s]", number_str); - if (nchars >= 0) { - AddResultString( channelNum ); - } else AddResultString( "IE" ); - AddResultString( "SysRes" ); - AddResultString( "SR" ); - break; - // non-musical commands - // Start errors - case error: - AddResultString( "Error" ); - AddResultString( "Err" ); - AddResultString( "E" ); - break; - default: - AddResultString( "Internal Error, no match" ); - AddResultString( "Internal Error" ); - AddResultString( "IntErr" ); - AddResultString( "IE" ); - break; - } - // Command, Data, - // NoteOff, NoteOn, Aftertouch, ContinuousController, PatchChange, ChannelPressure, PitchBend, - // BeginSystemExclusiveMessage, MIDITimeCodeQuarterFrame, SongPositionPointer, SongSelect, F4, F5, TuneRequest, EndSystemExclusiveMessage, - // TimingClock, Start, Continue, Stop, FD, ActiveSensing, SystemReset +{ + char* result = NULL; + char* frameType = NULL; + // char * channelNum = NULL; + char channelNum[ 1024 ]; + char buffer[ 1024 ]; + const int size = 1024; + int charsPrinted; + int nchars; + S8 channel = mStash1.channel; + + char number_str[ 128 ]; + AnalyzerHelpers::GetNumberString( localFrame.mData1, localDisplay_base, 8, number_str, 128 ); + + // Makes a string describing the message type (data, command, what command). + switch( mFrameType ) + { + case Command: + nchars = snprintf( buffer, size, "Command Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + nchars = snprintf( buffer, size, "Com Ch %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "C" ); + break; + case Data: + nchars = snprintf( buffer, size, "Data Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + nchars = snprintf( buffer, size, "Data Ch %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "D" ); + break; + // End misc + // Start data + case Key: + nchars = snprintf( buffer, size, "Key Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "Key" ); + AddResultString( "K" ); + break; + case Velocity: + nchars = snprintf( buffer, size, "Velocity Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "Velocity" ); + AddResultString( "V" ); + break; + case Touch: + nchars = snprintf( buffer, size, "Touch Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "Touch" ); + AddResultString( "T" ); + break; + case ControllerNum: + nchars = snprintf( buffer, size, "ControllerNum Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "ControllerNum" ); + AddResultString( "CN" ); + break; + case ControllerValue: + nchars = snprintf( buffer, size, "ControllerValue Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "ControllerValue" ); + AddResultString( "CV" ); + break; + case InstrumentNum: + nchars = snprintf( buffer, size, "InstrumentNum Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "InstrumentNum" ); + AddResultString( "IN" ); + break; + case Pressure: + nchars = snprintf( buffer, size, "Pressure Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "Pressure" ); + AddResultString( "P" ); + break; + case LSB: + nchars = snprintf( buffer, size, "LSB Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "LSB" ); + AddResultString( "L" ); + break; + case MSB: + nchars = snprintf( buffer, size, "MSB Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "MSB" ); + AddResultString( "M" ); + break; + case orphanedData: + nchars = snprintf( buffer, size, "orphanedData Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "orphanedData" ); + AddResultString( "o" ); + break; + // End data + // Start commands + case NoteOff: + nchars = snprintf( buffer, size, "NoteOff Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + nchars = snprintf( buffer, size, "NOff Chan %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "NOff" ); + AddResultString( "N" ); + break; + case NoteOn: + nchars = snprintf( buffer, size, "NoteOn Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + nchars = snprintf( buffer, size, "NOn Chan %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "NOn" ); + AddResultString( "N" ); + break; + case Aftertouch: + nchars = snprintf( buffer, size, "Aftertouch Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + nchars = snprintf( buffer, size, "Aft Chan %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "Aft" ); + AddResultString( "A" ); + break; + case ContinuousController: + nchars = snprintf( buffer, size, "ContinuousController Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + nchars = snprintf( buffer, size, "ContinuControl Chan %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "ContinuControl" ); + AddResultString( "CC" ); + AddResultString( "C" ); + break; + case PatchChange: + nchars = snprintf( buffer, size, "PatchChange Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + nchars = snprintf( buffer, size, "P_Ch Chan %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "PCh" ); + AddResultString( "P" ); + break; + case ChannelPressure: + nchars = snprintf( buffer, size, "ChannelPressure Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + nchars = snprintf( buffer, size, "ChanPres Chan %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "ChanPres" ); + AddResultString( "C" ); + break; + case PitchBend: + nchars = snprintf( buffer, size, "PitchBend Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + nchars = snprintf( buffer, size, "PitchB Chan %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "PitchB" ); + AddResultString( "P" ); + break; + // End commands + // Start non-musical commands. They do not have channels. + case BeginSystemExclusiveMessage: + nchars = snprintf( buffer, size, "BeginSystemExclusiveMessage [%s]", number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + nchars = snprintf( buffer, size, "BegSystemExclMessage [%s]", number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "BegSystemExclMessage" ); + AddResultString( "SysExclMes" ); + AddResultString( "SysEx" ); + AddResultString( "SE" ); + break; + case MIDITimeCodeQuarterFrame: + nchars = snprintf( buffer, size, "MIDITimeCodeQuarterFrame [%s]", number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + nchars = snprintf( buffer, size, "TimeCodeQuarFr [%s]", number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "TimeCodeQuarFr" ); + AddResultString( "QuarFr" ); + AddResultString( "QF" ); + break; + case SongPositionPointer: + nchars = snprintf( buffer, size, "SongPositionPointer [%s]", number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + nchars = snprintf( buffer, size, "SongPosPoint [%s]", number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "SongPosPoint" ); + AddResultString( "SongPos" ); + AddResultString( "SPP" ); + AddResultString( "SP" ); + break; + case SongSelect: + nchars = snprintf( buffer, size, "SongSelect [%s]", number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + nchars = snprintf( buffer, size, "SongSel [%s]", number_str ); + if( nchars >= 0 && nchars < size ) + { + AddResultString( buffer ); + } + else + AddResultString( "IE" ); + + AddResultString( "SongSel" ); + AddResultString( "SoSel" ); + AddResultString( "SS" ); + break; + case F4: + nchars = sprintf( channelNum, "F4 [%s]", number_str ); + if( nchars >= 0 ) + { + AddResultString( channelNum ); + } + else + AddResultString( "IE" ); + AddResultString( "4" ); + break; + case F5: + nchars = sprintf( channelNum, "F5 [%s]", number_str ); + if( nchars >= 0 ) + { + AddResultString( channelNum ); + } + else + AddResultString( "IE" ); + AddResultString( "5" ); + break; + case TuneRequest: + nchars = sprintf( channelNum, "TuneRequest [%s]", number_str ); + if( nchars >= 0 ) + { + AddResultString( channelNum ); + } + else + AddResultString( "IE" ); + AddResultString( "TuneReq" ); + AddResultString( "Tune" ); + AddResultString( "T" ); + break; + case EndSystemExclusiveMessage: + nchars = sprintf( channelNum, "EndSystemExclusiveMessage [%s]", number_str ); + if( nchars >= 0 ) + { + AddResultString( channelNum ); + } + else + AddResultString( "IE" ); + AddResultString( "EndSystemExcMess" ); + AddResultString( "EndSysExc" ); + AddResultString( "ESEM" ); + AddResultString( "ES" ); + break; + case TimingClock: + nchars = sprintf( channelNum, "TimingClock [%s]", number_str ); + if( nchars >= 0 ) + { + AddResultString( channelNum ); + } + else + AddResultString( "IE" ); + AddResultString( "TimClk" ); + AddResultString( "TiCl" ); + AddResultString( "TC" ); + break; + case F9: + nchars = sprintf( channelNum, "F9 [%s]", number_str ); + if( nchars >= 0 ) + { + AddResultString( channelNum ); + } + else + AddResultString( "IE" ); + AddResultString( "9" ); + break; + case Start_: + nchars = sprintf( channelNum, "Start [%s]", number_str ); + if( nchars >= 0 ) + { + AddResultString( channelNum ); + } + else + AddResultString( "IE" ); + AddResultString( "Sta" ); + AddResultString( "S" ); + break; + case Continue: + nchars = sprintf( channelNum, "Continue [%s]", number_str ); + if( nchars >= 0 ) + { + AddResultString( channelNum ); + } + else + AddResultString( "IE" ); + AddResultString( "Cont" ); + AddResultString( "C" ); + break; + case Stop_: + nchars = sprintf( channelNum, "Stop [%s]", number_str ); + if( nchars >= 0 ) + { + AddResultString( channelNum ); + } + else + AddResultString( "IE" ); + AddResultString( "St" ); + AddResultString( "S" ); + break; + case FD: + nchars = sprintf( channelNum, "FD [%s]", number_str ); + if( nchars >= 0 ) + { + AddResultString( channelNum ); + } + else + AddResultString( "IE" ); + AddResultString( "D" ); + break; + case ActiveSensing: + nchars = sprintf( channelNum, "ActiveSensing [%s]", number_str ); + if( nchars >= 0 ) + { + AddResultString( channelNum ); + } + else + AddResultString( "IE" ); + AddResultString( "ActSens" ); + AddResultString( "AS" ); + break; + case SystemReset: + nchars = sprintf( channelNum, "SystemReset [%s]", number_str ); + if( nchars >= 0 ) + { + AddResultString( channelNum ); + } + else + AddResultString( "IE" ); + AddResultString( "SysRes" ); + AddResultString( "SR" ); + break; + // non-musical commands + // Start errors + case error: + AddResultString( "Error" ); + AddResultString( "Err" ); + AddResultString( "E" ); + break; + default: + AddResultString( "Internal Error, no match" ); + AddResultString( "Internal Error" ); + AddResultString( "IntErr" ); + AddResultString( "IE" ); + break; + } + // Command, Data, + // NoteOff, NoteOn, Aftertouch, ContinuousController, PatchChange, ChannelPressure, PitchBend, + // BeginSystemExclusiveMessage, MIDITimeCodeQuarterFrame, SongPositionPointer, SongSelect, F4, F5, TuneRequest, + //EndSystemExclusiveMessage, TimingClock, Start, Continue, Stop, FD, ActiveSensing, SystemReset } -char * MidiAnalyzerResults::stringResults( enum MidiFrameType mFrameType, union stash mStash1 ) -{ - char * result = NULL; - char * frameType = NULL; - char channelNum[1024]; - int charsPrinted; - S8 channel = mStash1.channel; - - const int size = 1024; - char buffer[size]; - int nchars; - - char number_str[128]; - AnalyzerHelpers::GetNumberString( localFrame.mData1, localDisplay_base, 8, number_str, 128 ); - - // Makes a string describing the message type (data, command, what command). - switch (mFrameType) { - case Command: - frameType = strdup( "Command" ); - charsPrinted = sprintf(channelNum, " Channel: %i", channel); - result = concatenateStrings( frameType, channelNum, charsPrinted ); - return result; - break; - case Data: - result = strdup( "Data" ); - return result; - break; - // End misc - // Start data - case Key: - nchars = snprintf(buffer, size, "Key Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - result = (char *) malloc ( nchars + 1 ); - strcpy (result, buffer); - } else result = strdup( "Internal Error" ); - return result; - break; - case Velocity: - nchars = snprintf(buffer, size, "Velocity Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - result = (char *) malloc ( nchars + 1 ); - strcpy (result, buffer); - } else result = strdup( "Internal Error" ); - return result; - break; - case Touch: - nchars = snprintf(buffer, size, "Touch Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - result = (char *) malloc ( nchars + 1 ); - strcpy (result, buffer); - } else result = strdup( "Internal Error" ); - return result; - break; - case ControllerNum: - nchars = snprintf(buffer, size, "ControllerNum Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - result = (char *) malloc ( nchars + 1 ); - strcpy (result, buffer); - } else result = strdup( "Internal Error" ); - return result; - break; - case ControllerValue: - nchars = snprintf(buffer, size, "ControllerValue Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - result = (char *) malloc ( nchars + 1 ); - strcpy (result, buffer); - } else result = strdup( "Internal Error" ); - return result; - break; - case InstrumentNum: - nchars = snprintf(buffer, size, "InstrumentNum Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - result = (char *) malloc ( nchars + 1 ); - strcpy (result, buffer); - } else result = strdup( "Internal Error" ); - return result; - break; - case Pressure: - nchars = snprintf(buffer, size, "Pressure Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - result = (char *) malloc ( nchars + 1 ); - strcpy (result, buffer); - } else result = strdup( "Internal Error" ); - return result; - break; - case LSB: - nchars = snprintf(buffer, size, "LSB Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - result = (char *) malloc ( nchars + 1 ); - strcpy (result, buffer); - } else result = strdup( "Internal Error" ); - return result; - break; - case MSB: - nchars = snprintf(buffer, size, "MSB Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - result = (char *) malloc ( nchars + 1 ); - strcpy (result, buffer); - } else result = strdup( "Internal Error" ); - return result; - break; - case orphanedData: - nchars = snprintf(buffer, size, "orphanedData Channel: %i [%s]", channel, number_str); - if (nchars >= 0 && nchars < size) { - result = (char *) malloc ( nchars + 1 ); - strcpy (result, buffer); - } else result = strdup( "Internal Error" ); - return result; - break; - - - // End data - // Start commands - case NoteOff: - frameType = strdup( "NoteOff" ); - charsPrinted = sprintf(channelNum, " Channel: %i", channel); - result = concatenateStrings( frameType, channelNum, charsPrinted ); - return result; - break; - case NoteOn: - frameType = strdup( "NoteOn" ); - charsPrinted = sprintf(channelNum, " Channel: %i", channel); - result = concatenateStrings( frameType, channelNum, charsPrinted ); - return result; - break; - case Aftertouch: - frameType = strdup( "Aftertouch" ); - charsPrinted = sprintf(channelNum, " Channel: %i", channel); - result = concatenateStrings( frameType, channelNum, charsPrinted ); - return result; - break; - case ContinuousController: - frameType = strdup( "ContinuousController" ); - charsPrinted = sprintf(channelNum, " Channel: %i", channel); - result = concatenateStrings( frameType, channelNum, charsPrinted ); - return result; - break; - case PatchChange: - frameType = strdup( "PatchChange" ); - charsPrinted = sprintf(channelNum, " Channel: %i", channel); - result = concatenateStrings( frameType, channelNum, charsPrinted ); - return result; - break; - case ChannelPressure: - frameType = strdup( "ChannelPressure" ); - charsPrinted = sprintf(channelNum, " Channel: %i", channel); - result = concatenateStrings( frameType, channelNum, charsPrinted ); - return result; - break; - case PitchBend: - frameType = strdup( "PitchBend" ); - charsPrinted = sprintf(channelNum, " Channel: %i", channel); - result = concatenateStrings( frameType, channelNum, charsPrinted ); - return result; - break; - // End commands - // Start non-musical commands. They do not have channels. - case BeginSystemExclusiveMessage: - result = strdup( "BeginSystemExclusiveMessage" ); - return result; - break; - case MIDITimeCodeQuarterFrame: - result = strdup( "MIDITimeCodeQuarterFrame" ); - return result; - break; - case SongPositionPointer: - result = strdup( "SongPositionPointer" ); - return result; - break; - case SongSelect: - result = strdup( "SongSelect" ); - return result; - break; - case F4: - result = strdup( "F4" ); - return result; - break; - case F5: - result = strdup( "F5" ); - return result; - break; - case TuneRequest: - result = strdup( "TuneRequest" ); - return result; - break; - case EndSystemExclusiveMessage: - result = strdup( "EndSystemExclusiveMessage" ); - return result; - break; - case TimingClock: - result = strdup( "TimingClock" ); - return result; - break; - case F9: - result = strdup( "F9" ); - return result; - break; - case Start_: - result = strdup( "Start" ); - return result; - break; - case Continue: - result = strdup( "Continue" ); - return result; - break; - case Stop_: - result = strdup( "Stop" ); - return result; - break; - case FD: - result = strdup( "FD" ); - return result; - break; - case ActiveSensing: - result = strdup( "ActiveSensing" ); - return result; - break; - case SystemReset: - result = strdup( "SystemReset" ); - return result; - break; - // non-musical commands - // Start errors - case error: - result = strdup( "Error" ); - return result; - break; - default: - result = strdup( "Internal Error, no match" ); - return result; - break; - } +char* MidiAnalyzerResults::stringResults( enum MidiFrameType mFrameType, union stash mStash1 ) +{ + char* result = NULL; + char* frameType = NULL; + char channelNum[ 1024 ]; + int charsPrinted; + S8 channel = mStash1.channel; + + const int size = 1024; + char buffer[ size ]; + int nchars; + + char number_str[ 128 ]; + AnalyzerHelpers::GetNumberString( localFrame.mData1, localDisplay_base, 8, number_str, 128 ); + + // Makes a string describing the message type (data, command, what command). + switch( mFrameType ) + { + case Command: + frameType = strdup( "Command" ); + charsPrinted = sprintf( channelNum, " Channel: %i", channel ); + result = concatenateStrings( frameType, channelNum, charsPrinted ); + return result; + break; + case Data: + result = strdup( "Data" ); + return result; + break; + // End misc + // Start data + case Key: + nchars = snprintf( buffer, size, "Key Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + result = ( char* )malloc( nchars + 1 ); + strcpy( result, buffer ); + } + else + result = strdup( "Internal Error" ); + return result; + break; + case Velocity: + nchars = snprintf( buffer, size, "Velocity Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + result = ( char* )malloc( nchars + 1 ); + strcpy( result, buffer ); + } + else + result = strdup( "Internal Error" ); + return result; + break; + case Touch: + nchars = snprintf( buffer, size, "Touch Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + result = ( char* )malloc( nchars + 1 ); + strcpy( result, buffer ); + } + else + result = strdup( "Internal Error" ); + return result; + break; + case ControllerNum: + nchars = snprintf( buffer, size, "ControllerNum Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + result = ( char* )malloc( nchars + 1 ); + strcpy( result, buffer ); + } + else + result = strdup( "Internal Error" ); + return result; + break; + case ControllerValue: + nchars = snprintf( buffer, size, "ControllerValue Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + result = ( char* )malloc( nchars + 1 ); + strcpy( result, buffer ); + } + else + result = strdup( "Internal Error" ); + return result; + break; + case InstrumentNum: + nchars = snprintf( buffer, size, "InstrumentNum Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + result = ( char* )malloc( nchars + 1 ); + strcpy( result, buffer ); + } + else + result = strdup( "Internal Error" ); + return result; + break; + case Pressure: + nchars = snprintf( buffer, size, "Pressure Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + result = ( char* )malloc( nchars + 1 ); + strcpy( result, buffer ); + } + else + result = strdup( "Internal Error" ); + return result; + break; + case LSB: + nchars = snprintf( buffer, size, "LSB Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + result = ( char* )malloc( nchars + 1 ); + strcpy( result, buffer ); + } + else + result = strdup( "Internal Error" ); + return result; + break; + case MSB: + nchars = snprintf( buffer, size, "MSB Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + result = ( char* )malloc( nchars + 1 ); + strcpy( result, buffer ); + } + else + result = strdup( "Internal Error" ); + return result; + break; + case orphanedData: + nchars = snprintf( buffer, size, "orphanedData Channel: %i [%s]", channel, number_str ); + if( nchars >= 0 && nchars < size ) + { + result = ( char* )malloc( nchars + 1 ); + strcpy( result, buffer ); + } + else + result = strdup( "Internal Error" ); + return result; + break; + + + // End data + // Start commands + case NoteOff: + frameType = strdup( "NoteOff" ); + charsPrinted = sprintf( channelNum, " Channel: %i", channel ); + result = concatenateStrings( frameType, channelNum, charsPrinted ); + return result; + break; + case NoteOn: + frameType = strdup( "NoteOn" ); + charsPrinted = sprintf( channelNum, " Channel: %i", channel ); + result = concatenateStrings( frameType, channelNum, charsPrinted ); + return result; + break; + case Aftertouch: + frameType = strdup( "Aftertouch" ); + charsPrinted = sprintf( channelNum, " Channel: %i", channel ); + result = concatenateStrings( frameType, channelNum, charsPrinted ); + return result; + break; + case ContinuousController: + frameType = strdup( "ContinuousController" ); + charsPrinted = sprintf( channelNum, " Channel: %i", channel ); + result = concatenateStrings( frameType, channelNum, charsPrinted ); + return result; + break; + case PatchChange: + frameType = strdup( "PatchChange" ); + charsPrinted = sprintf( channelNum, " Channel: %i", channel ); + result = concatenateStrings( frameType, channelNum, charsPrinted ); + return result; + break; + case ChannelPressure: + frameType = strdup( "ChannelPressure" ); + charsPrinted = sprintf( channelNum, " Channel: %i", channel ); + result = concatenateStrings( frameType, channelNum, charsPrinted ); + return result; + break; + case PitchBend: + frameType = strdup( "PitchBend" ); + charsPrinted = sprintf( channelNum, " Channel: %i", channel ); + result = concatenateStrings( frameType, channelNum, charsPrinted ); + return result; + break; + // End commands + // Start non-musical commands. They do not have channels. + case BeginSystemExclusiveMessage: + result = strdup( "BeginSystemExclusiveMessage" ); + return result; + break; + case MIDITimeCodeQuarterFrame: + result = strdup( "MIDITimeCodeQuarterFrame" ); + return result; + break; + case SongPositionPointer: + result = strdup( "SongPositionPointer" ); + return result; + break; + case SongSelect: + result = strdup( "SongSelect" ); + return result; + break; + case F4: + result = strdup( "F4" ); + return result; + break; + case F5: + result = strdup( "F5" ); + return result; + break; + case TuneRequest: + result = strdup( "TuneRequest" ); + return result; + break; + case EndSystemExclusiveMessage: + result = strdup( "EndSystemExclusiveMessage" ); + return result; + break; + case TimingClock: + result = strdup( "TimingClock" ); + return result; + break; + case F9: + result = strdup( "F9" ); + return result; + break; + case Start_: + result = strdup( "Start" ); + return result; + break; + case Continue: + result = strdup( "Continue" ); + return result; + break; + case Stop_: + result = strdup( "Stop" ); + return result; + break; + case FD: + result = strdup( "FD" ); + return result; + break; + case ActiveSensing: + result = strdup( "ActiveSensing" ); + return result; + break; + case SystemReset: + result = strdup( "SystemReset" ); + return result; + break; + // non-musical commands + // Start errors + case error: + result = strdup( "Error" ); + return result; + break; + default: + result = strdup( "Internal Error, no match" ); + return result; + break; + } } -void MidiAnalyzerResults::concatenateAndAddResultString( char * frameType, char * channelNum, int channelNumCharsPrinted ) -{ - if (channelNumCharsPrinted >= 0 && frameType != NULL) { - int lengthOfFrameType = strlen(frameType); - char * ready = (char *) alloca (lengthOfFrameType + channelNumCharsPrinted + 1 ); - strcpy (ready, frameType); - strcat (ready, channelNum); // Last half of result string. - AddResultString( ready ); - } else AddResultString( "IE" ); - free( frameType ); //free( channelNum ); +void MidiAnalyzerResults::concatenateAndAddResultString( char* frameType, char* channelNum, int channelNumCharsPrinted ) +{ + if( channelNumCharsPrinted >= 0 && frameType != NULL ) + { + int lengthOfFrameType = strlen( frameType ); + char* ready = ( char* )alloca( lengthOfFrameType + channelNumCharsPrinted + 1 ); + strcpy( ready, frameType ); + strcat( ready, channelNum ); // Last half of result string. + AddResultString( ready ); + } + else + AddResultString( "IE" ); + free( frameType ); // free( channelNum ); } -char * MidiAnalyzerResults::concatenateStrings( char * frameType, char * channelNum, int channelNumCharsPrinted ) -{ - char * result = NULL; - if (channelNumCharsPrinted >= 0 && frameType != NULL) { - int lengthOfFrameType = strlen(frameType); - result = (char *) malloc (lengthOfFrameType + channelNumCharsPrinted + 1 ); - strcpy (result, frameType); - strcat (result, channelNum); // Last half of result string. - } else result = strdup( "Internal Error" ); - free( frameType ); //free( channelNum ); - return result; +char* MidiAnalyzerResults::concatenateStrings( char* frameType, char* channelNum, int channelNumCharsPrinted ) +{ + char* result = NULL; + if( channelNumCharsPrinted >= 0 && frameType != NULL ) + { + int lengthOfFrameType = strlen( frameType ); + result = ( char* )malloc( lengthOfFrameType + channelNumCharsPrinted + 1 ); + strcpy( result, frameType ); + strcat( result, channelNum ); // Last half of result string. + } + else + result = strdup( "Internal Error" ); + free( frameType ); // free( channelNum ); + return result; } void MidiAnalyzerResults::GenerateExportFile( const char* file, DisplayBase display_base, U32 export_type_user_id ) { - std::ofstream file_stream( file, std::ios::out ); - - U64 trigger_sample = mAnalyzer->GetTriggerSample(); - U32 sample_rate = mAnalyzer->GetSampleRate(); - - file_stream << "Time [s],Value" << std::endl; - - U64 num_frames = GetNumFrames(); - for( U32 i=0; i < num_frames; i++ ) - { - Frame frame = GetFrame( i ); - - char time_str[128]; - AnalyzerHelpers::GetTimeString( frame.mStartingSampleInclusive, trigger_sample, sample_rate, time_str, 128 ); - - enum MidiFrameType FrameType; - union stash stash1; - FrameType = (enum MidiFrameType) frame.mType; - stash1.mData2 = frame.mData2; - - char * result = NULL; - result = stringResults( FrameType, stash1 ); - - - char number_str[128]; - AnalyzerHelpers::GetNumberString( frame.mData1, display_base, 8, number_str, 128 ); - - //file_stream << time_str << "," << number_str << std::endl; - file_stream << time_str << "," << result << "," << number_str << std::endl; - - free ( result ); - - - if( UpdateExportProgressAndCheckForCancel( i, num_frames ) == true ) - { - file_stream.close(); - return; - } - } - - UpdateExportProgressAndCheckForCancel( 0, 0 ); - - file_stream.close(); + std::ofstream file_stream( file, std::ios::out ); + + U64 trigger_sample = mAnalyzer->GetTriggerSample(); + U32 sample_rate = mAnalyzer->GetSampleRate(); + + file_stream << "Time [s],Value" << std::endl; + + U64 num_frames = GetNumFrames(); + for( U32 i = 0; i < num_frames; i++ ) + { + Frame frame = GetFrame( i ); + + char time_str[ 128 ]; + AnalyzerHelpers::GetTimeString( frame.mStartingSampleInclusive, trigger_sample, sample_rate, time_str, 128 ); + + enum MidiFrameType FrameType; + union stash stash1; + FrameType = ( enum MidiFrameType )frame.mType; + stash1.mData2 = frame.mData2; + + char* result = NULL; + result = stringResults( FrameType, stash1 ); + + + char number_str[ 128 ]; + AnalyzerHelpers::GetNumberString( frame.mData1, display_base, 8, number_str, 128 ); + + // file_stream << time_str << "," << number_str << std::endl; + file_stream << time_str << "," << result << "," << number_str << std::endl; + + free( result ); + + + if( UpdateExportProgressAndCheckForCancel( i, num_frames ) == true ) + { + file_stream.close(); + return; + } + } + + UpdateExportProgressAndCheckForCancel( 0, 0 ); + + file_stream.close(); } void MidiAnalyzerResults::GenerateFrameTabularText( U64 frame_index, DisplayBase display_base ) { - Frame frame = GetFrame( frame_index ); + Frame frame = GetFrame( frame_index ); ClearTabularText(); - char number_str[128]; - AnalyzerHelpers::GetNumberString( frame.mData1, display_base, 8, number_str, 128 ); + char number_str[ 128 ]; + AnalyzerHelpers::GetNumberString( frame.mData1, display_base, 8, number_str, 128 ); AddTabularText( number_str ); } void MidiAnalyzerResults::GeneratePacketTabularText( U64 packet_id, DisplayBase display_base ) { - ClearResultStrings(); - AddResultString( "not supported" ); + ClearResultStrings(); + AddResultString( "not supported" ); } void MidiAnalyzerResults::GenerateTransactionTabularText( U64 transaction_id, DisplayBase display_base ) { - ClearResultStrings(); - AddResultString( "not supported" ); + ClearResultStrings(); + AddResultString( "not supported" ); } diff --git a/src/MidiAnalyzerResults.h b/src/MidiAnalyzerResults.h index 52d9dbf..f575089 100644 --- a/src/MidiAnalyzerResults.h +++ b/src/MidiAnalyzerResults.h @@ -6,60 +6,91 @@ class MidiAnalyzer; class MidiAnalyzerSettings; -//enum CanFrameType { IdentifierField, IdentifierFieldEx, ControlField, DataField, CrcField, AckField, CanError }; -enum MidiFrameType { // Note: something else had the keywords Start and Stop; appended '_' to these. - Command, Data, // Meta, probably not used. - NoteOff, NoteOn, Aftertouch, ContinuousController, PatchChange, ChannelPressure, PitchBend, // Commands - Key, Velocity, Touch, ControllerNum, ControllerValue, InstrumentNum, Pressure, LSB, MSB, orphanedData, // Data - BeginSystemExclusiveMessage, MIDITimeCodeQuarterFrame, SongPositionPointer, SongSelect, // non-musical commands - F4, F5, TuneRequest, EndSystemExclusiveMessage, // Ditto - TimingClock, F9, Start_, Continue, Stop_, FD, ActiveSensing, SystemReset, // Ditto - error +// enum CanFrameType { IdentifierField, IdentifierFieldEx, ControlField, DataField, CrcField, AckField, CanError }; +enum MidiFrameType +{ // Note: something else had the keywords Start and Stop; appended '_' to these. + Command, + Data, // Meta, probably not used. + NoteOff, + NoteOn, + Aftertouch, + ContinuousController, + PatchChange, + ChannelPressure, + PitchBend, // Commands + Key, + Velocity, + Touch, + ControllerNum, + ControllerValue, + InstrumentNum, + Pressure, + LSB, + MSB, + orphanedData, // Data + BeginSystemExclusiveMessage, + MIDITimeCodeQuarterFrame, + SongPositionPointer, + SongSelect, // non-musical commands + F4, + F5, + TuneRequest, + EndSystemExclusiveMessage, // Ditto + TimingClock, + F9, + Start_, + Continue, + Stop_, + FD, + ActiveSensing, + SystemReset, // Ditto + error }; class MidiAnalyzerResults : public AnalyzerResults { -public: - MidiAnalyzerResults( MidiAnalyzer* analyzer, MidiAnalyzerSettings* settings ); - virtual ~MidiAnalyzerResults(); - - virtual void GenerateBubbleText( U64 frame_index, Channel& channel, DisplayBase display_base ); - virtual void GenerateExportFile( const char* file, DisplayBase display_base, U32 export_type_user_id ); - - virtual void GenerateFrameTabularText(U64 frame_index, DisplayBase display_base ); - virtual void GeneratePacketTabularText( U64 packet_id, DisplayBase display_base ); - virtual void GenerateTransactionTabularText( U64 transaction_id, DisplayBase display_base ); + public: + MidiAnalyzerResults( MidiAnalyzer* analyzer, MidiAnalyzerSettings* settings ); + virtual ~MidiAnalyzerResults(); -protected: //vars - struct node { - char * data; - struct node * next; - }; - union stash { - U64 mData2; - S8 channel; - S8 commandOffset; - } stash1; - DisplayBase localDisplay_base; // Set by GenerateBubbleText. Made local variable to avoid shipping. - Frame localFrame; // Same. - U64 localFrame_index; // Same. - -protected: //functions - //struct node * frameType( enum MidiFrameType mFrameType ); - void results( enum MidiFrameType mFrameType, union stash mStash1 ); - void concatenateAndAddResultString( char * frameType, char * channelNum, int channelNumCharsPrinted ); - char * stringResults( enum MidiFrameType mFrameType, union stash mStash1 ); - char * concatenateStrings( char * frameType, char * channelNum, int channelNumCharsPrinted ); - /* - #ifndef __USE_GNU - int asprintf (char **__restrict __ptr, __const char *__restrict __fmt, ...); - #endif - */ + virtual void GenerateBubbleText( U64 frame_index, Channel& channel, DisplayBase display_base ); + virtual void GenerateExportFile( const char* file, DisplayBase display_base, U32 export_type_user_id ); -protected: //vars - MidiAnalyzerSettings* mSettings; - MidiAnalyzer* mAnalyzer; + virtual void GenerateFrameTabularText( U64 frame_index, DisplayBase display_base ); + virtual void GeneratePacketTabularText( U64 packet_id, DisplayBase display_base ); + virtual void GenerateTransactionTabularText( U64 transaction_id, DisplayBase display_base ); + + protected: // vars + struct node + { + char* data; + struct node* next; + }; + union stash { + U64 mData2; + S8 channel; + S8 commandOffset; + } stash1; + DisplayBase localDisplay_base; // Set by GenerateBubbleText. Made local variable to avoid shipping. + Frame localFrame; // Same. + U64 localFrame_index; // Same. + + protected: // functions + // struct node * frameType( enum MidiFrameType mFrameType ); + void results( enum MidiFrameType mFrameType, union stash mStash1 ); + void concatenateAndAddResultString( char* frameType, char* channelNum, int channelNumCharsPrinted ); + char* stringResults( enum MidiFrameType mFrameType, union stash mStash1 ); + char* concatenateStrings( char* frameType, char* channelNum, int channelNumCharsPrinted ); + /* + #ifndef __USE_GNU + int asprintf (char **__restrict __ptr, __const char *__restrict __fmt, ...); + #endif + */ + + protected: // vars + MidiAnalyzerSettings* mSettings; + MidiAnalyzer* mAnalyzer; }; -#endif //MIDI_ANALYZER_RESULTS +#endif // MIDI_ANALYZER_RESULTS diff --git a/src/MidiAnalyzerSettings.cpp b/src/MidiAnalyzerSettings.cpp index 46603cf..6c821e2 100644 --- a/src/MidiAnalyzerSettings.cpp +++ b/src/MidiAnalyzerSettings.cpp @@ -2,61 +2,62 @@ #include -MidiAnalyzerSettings::MidiAnalyzerSettings() : mInputChannel( UNDEFINED_CHANNEL ), mBitRate( 31250 ) { - mParity = 3; // default is No parity. - mStopBits = 1; // default is 1 stop bit. 1=1, 2=1.5, 3=2. - mDataBits = 8; // default - mEndianness = 1; // TRUE, Big Endian is default. 0=FALSE=LE, 1=TRUE=BE. - mInputChannelInterface.reset( new AnalyzerSettingInterfaceChannel() ); - mInputChannelInterface->SetTitleAndTooltip( "MIDI", "General MIDI" ); - mInputChannelInterface->SetChannel( mInputChannel ); -/* - mBitRateInterface.reset( new AnalyzerSettingInterfaceInteger() ); - mBitRateInterface->SetTitleAndTooltip( "Bit Rate (Bits/S)", "Specify the bit rate in bits per second." ); - mBitRateInterface->SetMax( 31250 ); - mBitRateInterface->SetMin( 31250 ); // Midi only has one speed. Tolerance is +/- 1%. - mBitRateInterface->SetInteger( mBitRate ); - - mStopBitsInterface.reset( new AnalyzerSettingInterfaceNumberList() ); - mStopBitsInterface->SetTitleAndTooltip( "Stop Bits", "Specify number of stop bits, 1, 1.5, or 2." ); - mStopBitsInterface->AddNumber( 1, "1", "1 stop bit (common)"); - mStopBitsInterface->AddNumber( 1.5, "1.5", "1.5 stop bits (rare)"); - mStopBitsInterface->AddNumber( 2, "2", "2 stop bits (less common, better for noisy lines)"); - mStopBitsInterface->SetNumber( mStopBits ); - - mParityInterface.reset( new AnalyzerSettingInterfaceNumberList() ); - mParityInterface->SetTitleAndTooltip( "Parity", "Parity: Even, Odd, or None." ); - mParityInterface->AddNumber( 1, "Even", "Even Parity"); - mParityInterface->AddNumber( 2, "Odd", "Odd Parity"); - mParityInterface->AddNumber( 3, "None", "No Parity"); - mParityInterface->SetNumber( mParity ); - - // FIXME: the below is unfinished! - mDataBitsInterface.reset( new AnalyzerSettingInterfaceNumberList() ); - mDataBitsInterface->SetTitleAndTooltip( "Data Bits", "" ); - mDataBitsInterface->AddNumber( 1, "Even", "Even Parity"); - mDataBitsInterface->AddNumber( 2, "Odd", "Odd Parity"); - mDataBitsInterface->AddNumber( 3, "None", "No Parity"); - mDataBitsInterface->SetNumber( mParity ); - - mEndiannessInterface.reset( new AnalyzerSettingInterfaceNumberList() ); - mEndiannessInterface->SetTitleAndTooltip( "Endianness", "Little or Big Endian" ); - mEndiannessInterface->AddNumber( 0, "Little", "Odd Parity"); - mEndiannessInterface->AddNumber( 1, "Big", "Even Parity"); - mEndiannessInterface->SetNumber( mParity ); -*/ - - AddInterface( mInputChannelInterface.get() ); - //AddInterface( mBitRateInterface.get() ); - //AddInterface( mStopBitsInterface.get() ); - //AddInterface( mParityInterface.get() ); - - AddExportOption( 0, "Export as text/csv file" ); - AddExportExtension( 0, "text", "txt" ); - AddExportExtension( 0, "csv", "csv" ); - - ClearChannels(); - AddChannel( mInputChannel, "MIDI", false ); +MidiAnalyzerSettings::MidiAnalyzerSettings() : mInputChannel( UNDEFINED_CHANNEL ), mBitRate( 31250 ) +{ + mParity = 3; // default is No parity. + mStopBits = 1; // default is 1 stop bit. 1=1, 2=1.5, 3=2. + mDataBits = 8; // default + mEndianness = 1; // TRUE, Big Endian is default. 0=FALSE=LE, 1=TRUE=BE. + mInputChannelInterface.reset( new AnalyzerSettingInterfaceChannel() ); + mInputChannelInterface->SetTitleAndTooltip( "MIDI", "General MIDI" ); + mInputChannelInterface->SetChannel( mInputChannel ); + /* + mBitRateInterface.reset( new AnalyzerSettingInterfaceInteger() ); + mBitRateInterface->SetTitleAndTooltip( "Bit Rate (Bits/S)", "Specify the bit rate in bits per second." ); + mBitRateInterface->SetMax( 31250 ); + mBitRateInterface->SetMin( 31250 ); // Midi only has one speed. Tolerance is +/- 1%. + mBitRateInterface->SetInteger( mBitRate ); + + mStopBitsInterface.reset( new AnalyzerSettingInterfaceNumberList() ); + mStopBitsInterface->SetTitleAndTooltip( "Stop Bits", "Specify number of stop bits, 1, 1.5, or 2." ); + mStopBitsInterface->AddNumber( 1, "1", "1 stop bit (common)"); + mStopBitsInterface->AddNumber( 1.5, "1.5", "1.5 stop bits (rare)"); + mStopBitsInterface->AddNumber( 2, "2", "2 stop bits (less common, better for noisy lines)"); + mStopBitsInterface->SetNumber( mStopBits ); + + mParityInterface.reset( new AnalyzerSettingInterfaceNumberList() ); + mParityInterface->SetTitleAndTooltip( "Parity", "Parity: Even, Odd, or None." ); + mParityInterface->AddNumber( 1, "Even", "Even Parity"); + mParityInterface->AddNumber( 2, "Odd", "Odd Parity"); + mParityInterface->AddNumber( 3, "None", "No Parity"); + mParityInterface->SetNumber( mParity ); + + // FIXME: the below is unfinished! + mDataBitsInterface.reset( new AnalyzerSettingInterfaceNumberList() ); + mDataBitsInterface->SetTitleAndTooltip( "Data Bits", "" ); + mDataBitsInterface->AddNumber( 1, "Even", "Even Parity"); + mDataBitsInterface->AddNumber( 2, "Odd", "Odd Parity"); + mDataBitsInterface->AddNumber( 3, "None", "No Parity"); + mDataBitsInterface->SetNumber( mParity ); + + mEndiannessInterface.reset( new AnalyzerSettingInterfaceNumberList() ); + mEndiannessInterface->SetTitleAndTooltip( "Endianness", "Little or Big Endian" ); + mEndiannessInterface->AddNumber( 0, "Little", "Odd Parity"); + mEndiannessInterface->AddNumber( 1, "Big", "Even Parity"); + mEndiannessInterface->SetNumber( mParity ); + */ + + AddInterface( mInputChannelInterface.get() ); + // AddInterface( mBitRateInterface.get() ); + // AddInterface( mStopBitsInterface.get() ); + // AddInterface( mParityInterface.get() ); + + AddExportOption( 0, "Export as text/csv file" ); + AddExportExtension( 0, "text", "txt" ); + AddExportExtension( 0, "csv", "csv" ); + + ClearChannels(); + AddChannel( mInputChannel, "MIDI", false ); } MidiAnalyzerSettings::~MidiAnalyzerSettings() @@ -65,49 +66,49 @@ MidiAnalyzerSettings::~MidiAnalyzerSettings() bool MidiAnalyzerSettings::SetSettingsFromInterfaces() { - mInputChannel = mInputChannelInterface->GetChannel(); - //mBitRate = mBitRateInterface->GetInteger(); - //mStopBits = mStopBitsInterface->GetNumber(); - //mParity = mParityInterface->GetNumber(); + mInputChannel = mInputChannelInterface->GetChannel(); + // mBitRate = mBitRateInterface->GetInteger(); + // mStopBits = mStopBitsInterface->GetNumber(); + // mParity = mParityInterface->GetNumber(); - ClearChannels(); - AddChannel( mInputChannel, "MIDI", true ); + ClearChannels(); + AddChannel( mInputChannel, "MIDI", true ); - return true; + return true; } void MidiAnalyzerSettings::UpdateInterfacesFromSettings() { - mInputChannelInterface->SetChannel( mInputChannel ); - //mBitRateInterface->SetInteger( mBitRate ); - //mStopBitsInterface->SetNumber( mStopBits ); - //mParityInterface->SetNumber( mParity ); + mInputChannelInterface->SetChannel( mInputChannel ); + // mBitRateInterface->SetInteger( mBitRate ); + // mStopBitsInterface->SetNumber( mStopBits ); + // mParityInterface->SetNumber( mParity ); } void MidiAnalyzerSettings::LoadSettings( const char* settings ) { - SimpleArchive text_archive; - text_archive.SetString( settings ); + SimpleArchive text_archive; + text_archive.SetString( settings ); - text_archive >> mInputChannel; - text_archive >> mBitRate; - text_archive >> mStopBits; - text_archive >> mParity; + text_archive >> mInputChannel; + text_archive >> mBitRate; + text_archive >> mStopBits; + text_archive >> mParity; - ClearChannels(); - AddChannel( mInputChannel, "MIDI", true ); + ClearChannels(); + AddChannel( mInputChannel, "MIDI", true ); - UpdateInterfacesFromSettings(); + UpdateInterfacesFromSettings(); } const char* MidiAnalyzerSettings::SaveSettings() { - SimpleArchive text_archive; + SimpleArchive text_archive; - text_archive << mInputChannel; - text_archive << mBitRate; - text_archive << mStopBits; - text_archive << mParity; + text_archive << mInputChannel; + text_archive << mBitRate; + text_archive << mStopBits; + text_archive << mParity; - return SetReturnString( text_archive.GetString() ); + return SetReturnString( text_archive.GetString() ); } diff --git a/src/MidiAnalyzerSettings.h b/src/MidiAnalyzerSettings.h index 90e1c2b..baa7e2e 100644 --- a/src/MidiAnalyzerSettings.h +++ b/src/MidiAnalyzerSettings.h @@ -6,30 +6,30 @@ class MidiAnalyzerSettings : public AnalyzerSettings { -public: - MidiAnalyzerSettings(); - virtual ~MidiAnalyzerSettings(); + public: + MidiAnalyzerSettings(); + virtual ~MidiAnalyzerSettings(); - virtual bool SetSettingsFromInterfaces(); - void UpdateInterfacesFromSettings(); - virtual void LoadSettings( const char* settings ); - virtual const char* SaveSettings(); + virtual bool SetSettingsFromInterfaces(); + void UpdateInterfacesFromSettings(); + virtual void LoadSettings( const char* settings ); + virtual const char* SaveSettings(); - Channel mInputChannel; - U32 mBitRate; - double mStopBits; - double mParity; - char mDataBits; - bool mEndianness; + Channel mInputChannel; + U32 mBitRate; + double mStopBits; + double mParity; + char mDataBits; + bool mEndianness; -protected: - std::auto_ptr< AnalyzerSettingInterfaceChannel > mInputChannelInterface; - std::auto_ptr< AnalyzerSettingInterfaceInteger > mBitRateInterface; - std::auto_ptr< AnalyzerSettingInterfaceNumberList > mStopBitsInterface; - std::auto_ptr< AnalyzerSettingInterfaceNumberList > mParityInterface; - std::auto_ptr< AnalyzerSettingInterfaceNumberList > mDataBitsInterface; - std::auto_ptr< AnalyzerSettingInterfaceNumberList > mEndiannessInterface; + protected: + std::auto_ptr mInputChannelInterface; + std::auto_ptr mBitRateInterface; + std::auto_ptr mStopBitsInterface; + std::auto_ptr mParityInterface; + std::auto_ptr mDataBitsInterface; + std::auto_ptr mEndiannessInterface; }; -#endif //MIDI_ANALYZER_SETTINGS +#endif // MIDI_ANALYZER_SETTINGS diff --git a/src/MidiSimulationDataGenerator.cpp b/src/MidiSimulationDataGenerator.cpp index b38e546..96d9199 100644 --- a/src/MidiSimulationDataGenerator.cpp +++ b/src/MidiSimulationDataGenerator.cpp @@ -7,170 +7,175 @@ MidiSimulationDataGenerator::MidiSimulationDataGenerator() { - //loadTestData(); - loadSampleData(); + // loadTestData(); + loadSampleData(); } void MidiSimulationDataGenerator::loadTestData() -{ // Only for testing - mMidiBuf[0] = 0x81; - mMidiBuf[1] = 0x92; - mMidiBuf[2] = 0xa0; - mMidiBuf[3] = 0xb1; - mMidiBuf[4] = 0xc2; - mMidiBuf[5] = 0xd4; - mMidiBuf[6] = 0xe5; - - mMidiBuf[7] = 0xf0; - mMidiBuf[8] = 0xf1; - mMidiBuf[9] = 0xf2; - mMidiBuf[10] = 0xf3; - mMidiBuf[11] = 0xf4; - mMidiBuf[12] = 0xf5; - mMidiBuf[13] = 0xf6; - mMidiBuf[14] = 0xff; - mMidiBuf[15] = 0xf8; - mMidiBuf[16] = 0xf9; - mMidiBuf[17] = 0xfa; - mMidiBuf[18] = 0xfb; - mMidiBuf[19] = 0xfc; - mMidiBuf[20] = 0xfd; - mMidiBuf[21] = 0xfe; - mMidiBuf[22] = 0xf7; - - mMidiBuf[23] = 0xb1; - mMidiBuf[24] = 0xc2; - - mMidiBufIndex = 0; - mMidiBufShortEnd = 25; // Not relevant here, but needs to be initialized to a - // value >= the size of the storage array. +{ // Only for testing + mMidiBuf[ 0 ] = 0x81; + mMidiBuf[ 1 ] = 0x92; + mMidiBuf[ 2 ] = 0xa0; + mMidiBuf[ 3 ] = 0xb1; + mMidiBuf[ 4 ] = 0xc2; + mMidiBuf[ 5 ] = 0xd4; + mMidiBuf[ 6 ] = 0xe5; + + mMidiBuf[ 7 ] = 0xf0; + mMidiBuf[ 8 ] = 0xf1; + mMidiBuf[ 9 ] = 0xf2; + mMidiBuf[ 10 ] = 0xf3; + mMidiBuf[ 11 ] = 0xf4; + mMidiBuf[ 12 ] = 0xf5; + mMidiBuf[ 13 ] = 0xf6; + mMidiBuf[ 14 ] = 0xff; + mMidiBuf[ 15 ] = 0xf8; + mMidiBuf[ 16 ] = 0xf9; + mMidiBuf[ 17 ] = 0xfa; + mMidiBuf[ 18 ] = 0xfb; + mMidiBuf[ 19 ] = 0xfc; + mMidiBuf[ 20 ] = 0xfd; + mMidiBuf[ 21 ] = 0xfe; + mMidiBuf[ 22 ] = 0xf7; + + mMidiBuf[ 23 ] = 0xb1; + mMidiBuf[ 24 ] = 0xc2; + + mMidiBufIndex = 0; + mMidiBufShortEnd = 25; // Not relevant here, but needs to be initialized to a + // value >= the size of the storage array. } void MidiSimulationDataGenerator::loadSampleData() -{ // Plausible MIDI for end-user - mMidiBuf[0] = 0x90; - mMidiBuf[1] = 0x3f; - mMidiBuf[2] = 0x40; - mMidiBuf[3] = 0x81; - mMidiBuf[4] = 0x3f; - mMidiBuf[5] = 0x40; - mMidiBuf[6] = 0x92; - mMidiBuf[7] = 0x3c; - mMidiBuf[8] = 0x40; - mMidiBuf[9] = 0x83; - mMidiBuf[10] = 0x3c; - mMidiBuf[11] = 0x40; - - mMidiBufIndex = 0; - mMidiBufShortEnd = 12; // Needed to prevent reading past the initialized part of the array. - /* - * 672: 90 3f 40 note on (channel 0): pitch 63, velocity 64 - 480: 80 3f 40 note off (channel 0): pitch 63, velocity 64 - 384: 90 3c 40 note on (channel 0): pitch 60, velocity 64 - 192: 80 3c 40 note off (channel 0): pitch 60, velocity 64 - */ +{ // Plausible MIDI for end-user + mMidiBuf[ 0 ] = 0x90; + mMidiBuf[ 1 ] = 0x3f; + mMidiBuf[ 2 ] = 0x40; + mMidiBuf[ 3 ] = 0x81; + mMidiBuf[ 4 ] = 0x3f; + mMidiBuf[ 5 ] = 0x40; + mMidiBuf[ 6 ] = 0x92; + mMidiBuf[ 7 ] = 0x3c; + mMidiBuf[ 8 ] = 0x40; + mMidiBuf[ 9 ] = 0x83; + mMidiBuf[ 10 ] = 0x3c; + mMidiBuf[ 11 ] = 0x40; + + mMidiBufIndex = 0; + mMidiBufShortEnd = 12; // Needed to prevent reading past the initialized part of the array. + /* + * 672: 90 3f 40 note on (channel 0): pitch 63, velocity 64 + 480: 80 3f 40 note off (channel 0): pitch 63, velocity 64 + 384: 90 3c 40 note on (channel 0): pitch 60, velocity 64 + 192: 80 3c 40 note off (channel 0): pitch 60, velocity 64 + */ } void MidiSimulationDataGenerator::injectBurstErrors() { - // This function adds random transitions while advancing the stream. - // Pseudocode Example: - // write numSamplesToOverwrite samples of garbage. - // done. - - const int startingSample = mMidiSimulationData.GetCurrentSampleNumber(); - U32 samples_per_bit = mSimulationSampleRateHz / mSettings->mBitRate; - const int numSamplesToOverwrite = 13 * samples_per_bit; - U64 currentSample = startingSample; - int r; - float probability = 0.2f; - srand( 1 ); // Default seed, will produce repeatable sequences. - while ( currentSample < ( startingSample + numSamplesToOverwrite ) ) { - mMidiSimulationData.Advance( 1 ); - r = rand(); - if ( (float) r < ( (float)RAND_MAX * probability ) ) { - mMidiSimulationData.Transition(); // - } - currentSample++; - } + // This function adds random transitions while advancing the stream. + // Pseudocode Example: + // write numSamplesToOverwrite samples of garbage. + // done. + + const int startingSample = mMidiSimulationData.GetCurrentSampleNumber(); + U32 samples_per_bit = mSimulationSampleRateHz / mSettings->mBitRate; + const int numSamplesToOverwrite = 13 * samples_per_bit; + U64 currentSample = startingSample; + int r; + float probability = 0.2f; + srand( 1 ); // Default seed, will produce repeatable sequences. + while( currentSample < ( startingSample + numSamplesToOverwrite ) ) + { + mMidiSimulationData.Advance( 1 ); + r = rand(); + if( ( float )r < ( ( float )RAND_MAX * probability ) ) + { + mMidiSimulationData.Transition(); // + } + currentSample++; + } } void MidiSimulationDataGenerator::CreateMidiMessage() { - U32 samples_per_bit = mSimulationSampleRateHz / mSettings->mBitRate; - - U8 byte = mMidiBuf[ mMidiBufIndex ]; - - //we're currenty high - //let's move forward a little - mMidiSimulationData.Advance( samples_per_bit * 3 ); - - mMidiSimulationData.Transition(); //low-going edge for start bit - mMidiSimulationData.Advance( samples_per_bit ); //add start bit time - - U8 mask = 1 << 7; - U32 dataBitsCounter = 0; - for( dataBitsCounter = 0; dataBitsCounter < 8; dataBitsCounter++ ) - { - if( ( byte & mask ) != 0 ) - mMidiSimulationData.TransitionIfNeeded( BIT_HIGH ); - else - mMidiSimulationData.TransitionIfNeeded( BIT_LOW ); - - mMidiSimulationData.Advance( samples_per_bit ); - - mask = mask >> 1; - } - - mMidiSimulationData.TransitionIfNeeded( BIT_HIGH ); //we need to end high - - //lets pad the end a bit for the stop bit: - mMidiSimulationData.Advance( samples_per_bit ); - if( mMidiBufIndex == 15 && mMidiBufShortEnd == 25 && false ) { - injectBurstErrors(); - mMidiBufIndex++; - } - - mMidiBufIndex++; - if( mMidiBufIndex >= (sizeof(mMidiBuf) / sizeof(U32)) || mMidiBufIndex >= mMidiBufShortEnd ) { - mMidiBufIndex = 0; - mMidiSimulationData.Advance( samples_per_bit * 30 ); - } + U32 samples_per_bit = mSimulationSampleRateHz / mSettings->mBitRate; + + U8 byte = mMidiBuf[ mMidiBufIndex ]; + + // we're currenty high + // let's move forward a little + mMidiSimulationData.Advance( samples_per_bit * 3 ); + + mMidiSimulationData.Transition(); // low-going edge for start bit + mMidiSimulationData.Advance( samples_per_bit ); // add start bit time + + U8 mask = 1 << 7; + U32 dataBitsCounter = 0; + for( dataBitsCounter = 0; dataBitsCounter < 8; dataBitsCounter++ ) + { + if( ( byte & mask ) != 0 ) + mMidiSimulationData.TransitionIfNeeded( BIT_HIGH ); + else + mMidiSimulationData.TransitionIfNeeded( BIT_LOW ); + + mMidiSimulationData.Advance( samples_per_bit ); + + mask = mask >> 1; + } + + mMidiSimulationData.TransitionIfNeeded( BIT_HIGH ); // we need to end high + + // lets pad the end a bit for the stop bit: + mMidiSimulationData.Advance( samples_per_bit ); + if( mMidiBufIndex == 15 && mMidiBufShortEnd == 25 && false ) + { + injectBurstErrors(); + mMidiBufIndex++; + } + + mMidiBufIndex++; + if( mMidiBufIndex >= ( sizeof( mMidiBuf ) / sizeof( U32 ) ) || mMidiBufIndex >= mMidiBufShortEnd ) + { + mMidiBufIndex = 0; + mMidiSimulationData.Advance( samples_per_bit * 30 ); + } } MidiSimulationDataGenerator::~MidiSimulationDataGenerator() { - } void MidiSimulationDataGenerator::Initialize( U32 simulation_sample_rate, MidiAnalyzerSettings* settings ) { - mSimulationSampleRateHz = simulation_sample_rate; - mSettings = settings; - - mMidiSimulationData.SetChannel( mSettings->mInputChannel ); - mMidiSimulationData.SetSampleRate( simulation_sample_rate ); - mMidiSimulationData.SetInitialBitState( BIT_HIGH ); + mSimulationSampleRateHz = simulation_sample_rate; + mSettings = settings; + + mMidiSimulationData.SetChannel( mSettings->mInputChannel ); + mMidiSimulationData.SetSampleRate( simulation_sample_rate ); + mMidiSimulationData.SetInitialBitState( BIT_HIGH ); } -U32 MidiSimulationDataGenerator::GenerateSimulationData( U64 largest_sample_requested, U32 sample_rate, SimulationChannelDescriptor** simulation_channel ) +U32 MidiSimulationDataGenerator::GenerateSimulationData( U64 largest_sample_requested, U32 sample_rate, + SimulationChannelDescriptor** simulation_channel ) { - U64 adjusted_largest_sample_requested = AnalyzerHelpers::AdjustSimulationTargetSample( largest_sample_requested, sample_rate, mSimulationSampleRateHz ); - - while( mMidiSimulationData.GetCurrentSampleNumber() < adjusted_largest_sample_requested ) - { - CreateMidiMessage(); - } - - *simulation_channel = &mMidiSimulationData; - return 1; + U64 adjusted_largest_sample_requested = + AnalyzerHelpers::AdjustSimulationTargetSample( largest_sample_requested, sample_rate, mSimulationSampleRateHz ); + + while( mMidiSimulationData.GetCurrentSampleNumber() < adjusted_largest_sample_requested ) + { + CreateMidiMessage(); + } + + *simulation_channel = &mMidiSimulationData; + return 1; } /* * Big endian. * 31.25 kBaud, 1 start, 8 data, 1 stop bit. * Asynchronous - * + * * Midi is transmitted as asynchronous bytes at 31250 bits per second. One start bit, eight data bits, @@ -184,8 +189,8 @@ usually one, two, or three bytes in length. System Exclusive messages are variable length, and have a beginning and ending status byte. - * - * + * + * * Source: http://soundlab.cs.princeton.edu/learning/tutorials/InputMidi/midisoft.html */ @@ -216,8 +221,9 @@ beginning and ending status byte. 0 0 0 255 FF 11111111 - Midi commands and data are distinguished according to the most significant bit of the byte. - * If there is a zero in the top bit, then the byte is a data byte, and if there is a one in the top bit, then the byte is a command byte. + Midi commands and data are distinguished according to the most significant bit of the byte. + * If there is a zero in the top bit, then the byte is a data byte, and if there is a one in the top bit, then the byte is a command +byte. * Here is how they are separated: Division of data and commands by values @@ -234,10 +240,10 @@ beginning and ending status byte. ... ... ... 255 FF 11111111 - Furthermore, command bytes are split into half. - * The most significant half contains the actual Midi command, and the second half contains the Midi channel - * for which the command is for. For example, 0x91 is the note-on command for the second Midi channel. - * The 9 digit is the actual command for note-on and the digit 1 specifies the second channel (the first channel being 0). + Furthermore, command bytes are split into half. + * The most significant half contains the actual Midi command, and the second half contains the Midi channel + * for which the command is for. For example, 0x91 is the note-on command for the second Midi channel. + * The 9 digit is the actual command for note-on and the digit 1 specifies the second channel (the first channel being 0). * The 0xF0 set of commands do not follow this convention. Here is a table of the Midi commands: @@ -253,16 +259,16 @@ beginning and ending status byte. 0xE0 Pitch bend 0xF0 (non-musical commands) - The messages from 0x80 to 0xEF are called Channel Messages because the second four bits - * of the command specify which channel the message affects. - * The messages from 0xF0 to 0xFF are called System Messages; they do not affect any particular channel. + The messages from 0x80 to 0xEF are called Channel Messages because the second four bits + * of the command specify which channel the message affects. + * The messages from 0xF0 to 0xFF are called System Messages; they do not affect any particular channel. Midi messages - A Midi command plus its Midi data parameters to be called a Midi message. - * The minimum size of a Midi message is 1 byte (one command byte and no parameter bytes). - * The maximum size of a Midi message (note considering 0xF0 commands) is three bytes. - * A Midi message always starts with a command byte. + A Midi command plus its Midi data parameters to be called a Midi message. + * The minimum size of a Midi message is 1 byte (one command byte and no parameter bytes). + * The maximum size of a Midi message (note considering 0xF0 commands) is three bytes. + * A Midi message always starts with a command byte. * Here is a table of the Midi messages that are possible in the Midi protocol: Command Meaning # parameters param 1 param 2 @@ -270,31 +276,31 @@ Midi messages 0x90 Note-on 2 key velocity 0xA0 Aftertouch 2 key touch 0xB0 Continuous controller 2 controller # controller value - 0xC0 Patch change 2 instrument # + 0xC0 Patch change 2 instrument # 0xD0 Channel Pressure 1 pressure 0xE0 Pitch bend 2 lsb (7 bits) msb (7 bits) - 0xF0 (non-musical commands) + 0xF0 (non-musical commands) I won't discuss the 0xF0 set of commands (System messages) here very much, but here is a basic table of them: command meaning # param 0xF0 start of system exclusive message variable - 0xF1 Midi Time Code Quarter Frame (Sys Common) - 0xF2 Song Position Pointer (Sys Common) - 0xF3 Song Select (Sys Common) - 0xF4 ??? - 0xF5 ??? - 0xF6 Tune Request (Sys Common) + 0xF1 Midi Time Code Quarter Frame (Sys Common) + 0xF2 Song Position Pointer (Sys Common) + 0xF3 Song Select (Sys Common) + 0xF4 ??? + 0xF5 ??? + 0xF6 Tune Request (Sys Common) 0xF7 end of system exclusive message 0 - 0xF8 Timing Clock (Sys Realtime) - 0xFA Start (Sys Realtime) - 0xFB Continue (Sys Realtime) - 0xFC Stop (Sys Realtime) - 0xFD ??? - 0xFE Active Sensing (Sys Realtime) - 0xFF System Reset (Sys Realtime) - - Running status should be mentioned around here... - * + 0xF8 Timing Clock (Sys Realtime) + 0xFA Start (Sys Realtime) + 0xFB Continue (Sys Realtime) + 0xFC Stop (Sys Realtime) + 0xFD ??? + 0xFE Active Sensing (Sys Realtime) + 0xFF System Reset (Sys Realtime) + + Running status should be mentioned around here... + * * Source: https://ccrma.stanford.edu/~craig/articles/linuxmidi/misc/essenmidi.html */ diff --git a/src/MidiSimulationDataGenerator.h b/src/MidiSimulationDataGenerator.h index b80c23a..881a75d 100644 --- a/src/MidiSimulationDataGenerator.h +++ b/src/MidiSimulationDataGenerator.h @@ -7,29 +7,29 @@ class MidiAnalyzerSettings; class MidiSimulationDataGenerator { -public: - MidiSimulationDataGenerator(); - ~MidiSimulationDataGenerator(); - - void Initialize( U32 simulation_sample_rate, MidiAnalyzerSettings* settings ); - U32 GenerateSimulationData( U64 newest_sample_requested, U32 sample_rate, SimulationChannelDescriptor** simulation_channel ); - -protected: - MidiAnalyzerSettings* mSettings; - U32 mSimulationSampleRateHz; - SimulationChannelDescriptor mMidiSimulationData; - // Make functions to add bad data to simulation. - void injectBurstErrors(); - - void CreateMidiMessage(); - void loadTestData(); // Only for testing - void loadSampleData(); // Plausible MIDI for end-user - //std::string mSerialText; - //const char *mSerialTextBuf; - U32 mMidiBuf[31]; - //U32 mStringIndex; - U32 mMidiBufIndex; - U32 mMidiBufShortEnd; + public: + MidiSimulationDataGenerator(); + ~MidiSimulationDataGenerator(); + + void Initialize( U32 simulation_sample_rate, MidiAnalyzerSettings* settings ); + U32 GenerateSimulationData( U64 newest_sample_requested, U32 sample_rate, SimulationChannelDescriptor** simulation_channel ); + + protected: + MidiAnalyzerSettings* mSettings; + U32 mSimulationSampleRateHz; + SimulationChannelDescriptor mMidiSimulationData; + // Make functions to add bad data to simulation. + void injectBurstErrors(); + + void CreateMidiMessage(); + void loadTestData(); // Only for testing + void loadSampleData(); // Plausible MIDI for end-user + // std::string mSerialText; + // const char *mSerialTextBuf; + U32 mMidiBuf[ 31 ]; + // U32 mStringIndex; + U32 mMidiBufIndex; + U32 mMidiBufShortEnd; }; -#endif //MIDI_SIMULATION_DATA_GENERATOR +#endif // MIDI_SIMULATION_DATA_GENERATOR