Skip to content

Commit

Permalink
Support setting the input buffer size and count.
Browse files Browse the repository at this point in the history
  • Loading branch information
radarsat1 committed Sep 19, 2021
1 parent 6e4e763 commit e6ba3e5
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 10 deletions.
23 changes: 14 additions & 9 deletions RtMidi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,12 @@ double MidiInApi :: getMessage( std::vector<unsigned char> *message )
return timeStamp;
}

void MidiInApi :: setBufferSize( unsigned int size, unsigned int count )
{
inputData_.bufferSize = size;
inputData_.bufferCount = count;
}

unsigned int MidiInApi::MidiQueue::size( unsigned int *__back,
unsigned int *__front )
{
Expand Down Expand Up @@ -1560,6 +1566,7 @@ struct AlsaMidiData {
snd_seq_port_subscribe_t *subscription;
snd_midi_event_t *coder;
unsigned int bufferSize;
unsigned int requestedBufferSize;
unsigned char *buffer;
pthread_t thread;
pthread_t dummy_thread_id;
Expand Down Expand Up @@ -1590,7 +1597,6 @@ static void *alsaMidiHandler( void *ptr )

snd_seq_event_t *ev;
int result;
apiData->bufferSize = 32;
result = snd_midi_event_new( 0, &apiData->coder );
if ( result < 0 ) {
data->doInput = false;
Expand Down Expand Up @@ -1842,6 +1848,7 @@ void MidiInAlsa :: initialize( const std::string& clientName )
data->thread = data->dummy_thread_id;
data->trigger_fds[0] = -1;
data->trigger_fds[1] = -1;
data->bufferSize = inputData_.bufferSize;
apiData_ = (void *) data;
inputData_.apiData = (void *) data;

Expand Down Expand Up @@ -2472,17 +2479,14 @@ static std::string ConvertToUTF8(const TCHAR *str)
return u8str;
}

#define RT_SYSEX_BUFFER_SIZE 1024
#define RT_SYSEX_BUFFER_COUNT 4

// A structure to hold variables related to the CoreMIDI API
// implementation.
struct WinMidiData {
HMIDIIN inHandle; // Handle to Midi Input Device
HMIDIOUT outHandle; // Handle to Midi Output Device
DWORD lastTime;
MidiInApi::MidiMessage message;
LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT];
std::vector<LPMIDIHDR> sysexBuffer;
CRITICAL_SECTION _mutex; // [Patrice] see https://groups.google.com/forum/#!topic/mididev/6OUjHutMpEo
};

Expand Down Expand Up @@ -2662,10 +2666,11 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string &/*port
}

// Allocate and init the sysex buffers.
for ( int i=0; i<RT_SYSEX_BUFFER_COUNT; ++i ) {
data->sysexBuffer.resize( inputData_.bufferCount );
for ( int i=0; i < inputData_.bufferCount; ++i ) {
data->sysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ];
data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ];
data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE;
data->sysexBuffer[i]->lpData = new char[ inputData_.bufferSize ];
data->sysexBuffer[i]->dwBufferLength = inputData_.bufferSize;
data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator
data->sysexBuffer[i]->dwFlags = 0;

Expand Down Expand Up @@ -2716,7 +2721,7 @@ void MidiInWinMM :: closePort( void )
midiInReset( data->inHandle );
midiInStop( data->inHandle );

for ( int i=0; i<RT_SYSEX_BUFFER_COUNT; ++i ) {
for ( int i=0; i < data->sysexBuffer.size(); ++i ) {
int result = midiInUnprepareHeader(data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR));
delete [] data->sysexBuffer[i]->lpData;
delete [] data->sysexBuffer[i];
Expand Down
19 changes: 18 additions & 1 deletion RtMidi.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,19 @@ class RTMIDI_DLL_PUBLIC RtMidiIn : public RtMidi
*/
virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 );

//! Set maximum expected incoming message size.
/*!
For APIs that require manual buffer management, it can be useful to set the buffer
size and buffer count when expecting to receive large SysEx messages. Note that
currently this function has no effect when called after openPort(). The default
buffer size is 1024 with a count of 4 buffers, which should be sufficient for most
cases; as mentioned, this does not affect all API backends, since most either support
dynamically scalable buffers or take care of buffer handling themselves. It is
principally intended for users of the Windows MM backend who must support receiving
especially large messages.
*/
virtual void setBufferSize( unsigned int size, unsigned int count );

protected:
void openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit );
};
Expand Down Expand Up @@ -546,6 +559,7 @@ class RTMIDI_DLL_PUBLIC MidiInApi : public MidiApi
void cancelCallback( void );
virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense );
double getMessage( std::vector<unsigned char> *message );
virtual void setBufferSize( unsigned int size, unsigned int count );

// A MIDI structure used internally by the class to store incoming
// messages. Each message represents one and only one MIDI message.
Expand Down Expand Up @@ -587,11 +601,13 @@ class RTMIDI_DLL_PUBLIC MidiInApi : public MidiApi
RtMidiIn::RtMidiCallback userCallback;
void *userData;
bool continueSysex;
unsigned int bufferSize;
unsigned int bufferCount;

// Default constructor.
RtMidiInData()
: ignoreFlags(7), doInput(false), firstMessage(true), apiData(0), usingCallback(false),
userCallback(0), userData(0), continueSysex(false) {}
userCallback(0), userData(0), continueSysex(false), bufferSize(1024), bufferCount(4) {}
};

protected:
Expand Down Expand Up @@ -625,6 +641,7 @@ inline std::string RtMidiIn :: getPortName( unsigned int portNumber ) { return r
inline void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { static_cast<MidiInApi *>(rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); }
inline double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) { return static_cast<MidiInApi *>(rtapi_)->getMessage( message ); }
inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); }
inline void RtMidiIn :: setBufferSize( unsigned int size, unsigned int count ) { static_cast<MidiInApi *>(rtapi_)->setBufferSize(size, count); }

inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }
inline void RtMidiOut :: openPort( unsigned int portNumber, const std::string &portName ) { rtapi_->openPort( portNumber, portName ); }
Expand Down

0 comments on commit e6ba3e5

Please sign in to comment.