Skip to content

Commit 5618045

Browse files
authored
Merge pull request #177 from lathoub/optimize
Optimize - Performance improvements
2 parents c58f283 + 21e6f64 commit 5618045

3 files changed

Lines changed: 106 additions & 21 deletions

File tree

src/AppleMIDI.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class AppleMIDISession
5252
this->port = port;
5353
#ifdef KEEP_SESSION_NAME
5454
strncpy(this->localName, sessionName, Settings::MaxSessionNameLen);
55+
this->localName[Settings::MaxSessionNameLen] = '\0';
5556
#endif
5657

5758
#ifdef ONE_PARTICIPANT
@@ -117,6 +118,7 @@ class AppleMIDISession
117118
AppleMIDISession &setName(const char *sessionName)
118119
{
119120
strncpy(this->localName, sessionName, Settings::MaxSessionNameLen);
121+
this->localName[Settings::MaxSessionNameLen] = '\0';
120122
return *this;
121123
};
122124
#else
@@ -170,7 +172,7 @@ class AppleMIDISession
170172
// this is our SSRC
171173
//
172174
// NOTE: Arduino random only goes to INT32_MAX (not UINT32_MAX)
173-
this->ssrc = random(1, INT32_MAX) * 2;
175+
this->ssrc = random(1, INT32_MAX / 2) * 2;
174176

175177
controlPort.begin(port);
176178
dataPort.begin(port + 1);

src/AppleMIDI.hpp

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "AppleMIDI_Namespace.h"
4+
#include <string.h>
45

56
BEGIN_APPLEMIDI_NAMESPACE
67

@@ -17,8 +18,7 @@ size_t AppleMIDISession<UdpClass, Settings, Platform>::readControlPackets()
1718
auto bytesRead = controlPort.read(packetBuffer, bytesToRead);
1819
packetSize -= bytesRead;
1920

20-
for (auto i = 0; i < bytesRead; i++)
21-
controlBuffer.push_back(packetBuffer[i]);
21+
controlBuffer.push_back(packetBuffer, bytesRead);
2222
}
2323

2424
return controlBuffer.size();
@@ -65,8 +65,7 @@ size_t AppleMIDISession<UdpClass, Settings, Platform>::readDataPackets()
6565
auto bytesRead = dataPort.read(packetBuffer, bytesToRead);
6666
packetSize -= bytesRead;
6767

68-
for (auto i = 0; i < bytesRead; i++)
69-
dataBuffer.push_back(packetBuffer[i]);
68+
dataBuffer.push_back(packetBuffer, bytesRead);
7069
}
7170

7271
return dataBuffer.size();
@@ -149,6 +148,7 @@ void AppleMIDISession<UdpClass, Settings, Platform>::ReceivedControlInvitation(A
149148
participant.lastSyncExchangeTime = now;
150149
#ifdef KEEP_SESSION_NAME
151150
strncpy(participant.sessionName, invitation.sessionName, Settings::MaxSessionNameLen);
151+
participant.sessionName[Settings::MaxSessionNameLen] = '\0';
152152
#endif
153153

154154
#ifdef KEEP_SESSION_NAME
@@ -692,10 +692,12 @@ void AppleMIDISession<UdpClass, Settings, Platform>::writeRtpMidiBuffer(Particip
692692
return;
693693
}
694694

695-
// write rtp header
696-
dataPort.write((uint8_t *)&rtp, sizeof(rtp));
695+
// Write RTP + rtpMIDI in a single packet to reduce overhead.
696+
uint8_t packet[sizeof(Rtp) + 2 + Settings::MaxBufferSize];
697+
size_t offset = 0;
698+
memcpy(packet + offset, &rtp, sizeof(rtp));
699+
offset += sizeof(rtp);
697700

698-
// Write rtpMIDI section
699701
RtpMIDI_t rtpMidi;
700702

701703
// 0 1 2 3
@@ -713,21 +715,21 @@ void AppleMIDISession<UdpClass, Settings, Platform>::writeRtpMidiBuffer(Particip
713715
{ // Short header
714716
rtpMidi.flags |= (uint8_t)bufferLen;
715717
rtpMidi.flags &= ~RTP_MIDI_CS_FLAG_B; // short header, clear B-FLAG
716-
dataPort.write(rtpMidi.flags);
718+
packet[offset++] = rtpMidi.flags;
717719
}
718720
else
719721
{ // Long header
720722
rtpMidi.flags |= (uint8_t)(bufferLen >> 8);
721723
rtpMidi.flags |= RTP_MIDI_CS_FLAG_B; // set B-FLAG for long header
722-
dataPort.write(rtpMidi.flags);
723-
dataPort.write((uint8_t)(bufferLen));
724+
packet[offset++] = rtpMidi.flags;
725+
packet[offset++] = (uint8_t)(bufferLen);
724726
}
725727

726728
// write out the MIDI Section
727-
for (size_t i = 0; i < bufferLen; i++)
728-
dataPort.write(outMidiBuffer[i]);
729+
offset += outMidiBuffer.copy_out(packet + offset, bufferLen);
729730

730731
// *No* journal section (Not supported)
732+
dataPort.write(packet, offset);
731733

732734
dataPort.endPacket();
733735
dataPort.flush();
@@ -745,19 +747,28 @@ template <class UdpClass, class Settings, class Platform>
745747
void AppleMIDISession<UdpClass, Settings, Platform>::manageSynchronization()
746748
{
747749
#ifndef ONE_PARTICIPANT
748-
for (size_t i = 0; i < participants.size(); i++)
750+
for (size_t i = 0; i < participants.size();)
749751
#endif
750752
{
751753
#ifndef ONE_PARTICIPANT
752754
auto pParticipant = &participants[i];
753-
if (pParticipant->ssrc == 0) continue;
755+
if (pParticipant->ssrc == 0)
756+
{
757+
i++;
758+
continue;
759+
}
754760
#else
755761
auto pParticipant = &participant;
756762
if (pParticipant->ssrc == 0) return;
757763
#endif
758764
#ifdef APPLEMIDI_INITIATOR
759765
if (pParticipant->invitationStatus != Connected)
766+
{
767+
#ifndef ONE_PARTICIPANT
768+
i++;
769+
#endif
760770
continue;
771+
}
761772

762773
// Only for Initiators that are Connected
763774
if (pParticipant->kind == Listener)
@@ -774,6 +785,7 @@ void AppleMIDISession<UdpClass, Settings, Platform>::manageSynchronization()
774785
sendEndSession(pParticipant);
775786
#ifndef ONE_PARTICIPANT
776787
participants.erase(i);
788+
continue;
777789
#else
778790
participant.ssrc = 0;
779791
#endif
@@ -785,6 +797,9 @@ void AppleMIDISession<UdpClass, Settings, Platform>::manageSynchronization()
785797
(pParticipant->synchronizing) ? manageSynchronizationInitiatorInvites(i)
786798
: manageSynchronizationInitiatorHeartBeat(pParticipant);
787799
}
800+
#endif
801+
#ifndef ONE_PARTICIPANT
802+
i++;
788803
#endif
789804
}
790805
}
@@ -884,7 +899,7 @@ template <class UdpClass, class Settings, class Platform>
884899
void AppleMIDISession<UdpClass, Settings, Platform>::manageSessionInvites()
885900
{
886901
#ifndef ONE_PARTICIPANT
887-
for (auto i = 0; i < participants.size(); i++)
902+
for (auto i = 0; i < participants.size();)
888903
#endif
889904
{
890905
#ifndef ONE_PARTICIPANT
@@ -895,7 +910,10 @@ void AppleMIDISession<UdpClass, Settings, Platform>::manageSessionInvites()
895910

896911
if (pParticipant->kind == Listener)
897912
#ifndef ONE_PARTICIPANT
913+
{
914+
i++;
898915
continue;
916+
}
899917
#else
900918
return;
901919
#endif
@@ -913,7 +931,10 @@ void AppleMIDISession<UdpClass, Settings, Platform>::manageSessionInvites()
913931

914932
if (pParticipant->invitationStatus == Connected)
915933
#ifndef ONE_PARTICIPANT
934+
{
935+
i++;
916936
continue;
937+
}
917938
#else
918939
return;
919940
#endif
@@ -932,12 +953,9 @@ void AppleMIDISession<UdpClass, Settings, Platform>::manageSessionInvites()
932953

933954
#ifndef ONE_PARTICIPANT
934955
participants.erase(i);
935-
#else
936-
participant.ssrc = 0;
937-
#endif
938-
#ifndef ONE_PARTICIPANT
939956
continue;
940957
#else
958+
participant.ssrc = 0;
941959
return;
942960
#endif
943961
}
@@ -966,6 +984,9 @@ void AppleMIDISession<UdpClass, Settings, Platform>::manageSessionInvites()
966984
pParticipant->invitationStatus = AwaitingDataInvitationAccepted;
967985
}
968986
}
987+
#ifndef ONE_PARTICIPANT
988+
i++;
989+
#endif
969990
}
970991
}
971992

@@ -1056,7 +1077,7 @@ void AppleMIDISession<UdpClass, Settings, Platform>::sendEndSession()
10561077
participants.pop_front();
10571078
}
10581079
#else
1059-
if (participant.src != 0)
1080+
if (participant.ssrc != 0)
10601081
{
10611082
sendEndSession(&participant);
10621083
participant.ssrc = 0;

src/utility/Deque.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#pragma once
22

3+
#include <string.h>
4+
35
BEGIN_APPLEMIDI_NAMESPACE
46

57
template<typename T, size_t Size>
@@ -25,6 +27,8 @@ class Deque {
2527
const T & back() const;
2628
void push_front(const T &);
2729
void push_back(const T &);
30+
size_t push_back(const T *, size_t);
31+
size_t copy_out(T *, size_t) const;
2832
void pop_front();
2933
void pop_back();
3034

@@ -124,6 +128,64 @@ void Deque<T, Size>::push_back(const T &value)
124128
}
125129
}
126130

131+
template<typename T, size_t Size>
132+
size_t Deque<T, Size>::push_back(const T *values, size_t count)
133+
{
134+
if (values == nullptr || count == 0)
135+
return 0;
136+
137+
const size_t available = free();
138+
if (available == 0)
139+
return 0;
140+
141+
const size_t toWrite = (count < available) ? count : available;
142+
143+
if (empty())
144+
_tail = _head;
145+
146+
size_t first = toWrite;
147+
if (_head + first > Size)
148+
first = Size - _head;
149+
150+
memcpy(&_data[_head], values, first * sizeof(T));
151+
_head = (_head + first) % Size;
152+
153+
const size_t remaining = toWrite - first;
154+
if (remaining > 0)
155+
{
156+
memcpy(&_data[_head], values + first, remaining * sizeof(T));
157+
_head = (_head + remaining) % Size;
158+
}
159+
160+
return toWrite;
161+
}
162+
163+
template<typename T, size_t Size>
164+
size_t Deque<T, Size>::copy_out(T *dest, size_t count) const
165+
{
166+
if (dest == nullptr || count == 0)
167+
return 0;
168+
169+
const size_t available = size();
170+
if (available == 0)
171+
return 0;
172+
173+
const size_t toCopy = (count < available) ? count : available;
174+
const size_t start = (size_t)_tail;
175+
176+
size_t first = toCopy;
177+
if (start + first > Size)
178+
first = Size - start;
179+
180+
memcpy(dest, &_data[start], first * sizeof(T));
181+
182+
const size_t remaining = toCopy - first;
183+
if (remaining > 0)
184+
memcpy(dest + first, &_data[0], remaining * sizeof(T));
185+
186+
return toCopy;
187+
}
188+
127189
template<typename T, size_t Size>
128190
void Deque<T, Size>::pop_front() {
129191
if (empty()) // if empty, do nothing.

0 commit comments

Comments
 (0)