4646
4747#define MS_FROM_START Time::highResolutionTicksToSeconds (Time::getHighResolutionTicks() - start) * 1000
4848
49+ namespace
50+ {
51+ using TimestampArrayState = std::unordered_map<const GenericProcessor*, std::map<uint16, std::vector<double >>>;
52+
53+ TimestampArrayState& getTimestampArrayState ()
54+ {
55+ static TimestampArrayState state;
56+ return state;
57+ }
58+
59+ void clearTimestampArrayState (const GenericProcessor* processor)
60+ {
61+ getTimestampArrayState ().erase (processor);
62+ }
63+
64+ void clearTimestampArrayState (const GenericProcessor* processor, uint16 streamId)
65+ {
66+ auto processorIt = getTimestampArrayState ().find (processor);
67+
68+ if (processorIt == getTimestampArrayState ().end ())
69+ return ;
70+
71+ processorIt->second .erase (streamId);
72+
73+ if (processorIt->second .empty ())
74+ getTimestampArrayState ().erase (processorIt);
75+ }
76+
77+ void setTimestampArrayState (const GenericProcessor* processor, uint16 streamId, const double * timestamps, uint32 nSamples)
78+ {
79+ auto & timestampsByStream = getTimestampArrayState ()[processor];
80+ auto & streamTimestamps = timestampsByStream[streamId];
81+ streamTimestamps.assign (timestamps, timestamps + nSamples);
82+ }
83+
84+ const std::vector<double >* findTimestampArrayState (const GenericProcessor* processor, uint16 streamId)
85+ {
86+ auto processorIt = getTimestampArrayState ().find (processor);
87+
88+ if (processorIt == getTimestampArrayState ().end ())
89+ return nullptr ;
90+
91+ auto streamIt = processorIt->second .find (streamId);
92+
93+ if (streamIt == processorIt->second .end () || streamIt->second .empty ())
94+ return nullptr ;
95+
96+ return &streamIt->second ;
97+ }
98+
99+ constexpr int timestampArrayOffset = EVENT_BASE_SIZE + 12 ;
100+ } // namespace
101+
49102LatencyMeter::LatencyMeter (GenericProcessor* processor_)
50103 : processor (processor_),
51104 counter (0 )
@@ -141,6 +194,7 @@ GenericProcessor::GenericProcessor (const String& name, bool headlessMode_)
141194
142195GenericProcessor::~GenericProcessor ()
143196{
197+ clearTimestampArrayState (this );
144198 editor.reset (); // remove parameter editors before parameters
145199
146200 dataStreamParameters.clear (true );
@@ -663,6 +717,7 @@ void GenericProcessor::clearSettings()
663717
664718 ttlEventChannel = nullptr ;
665719
720+ clearTimestampArrayState (this );
666721 startTimestampsForBlock.clear ();
667722 startSamplesForBlock.clear ();
668723 syncStreamIds.clear ();
@@ -1256,12 +1311,46 @@ double GenericProcessor::getFirstTimestampForBlock (uint16 streamId) const
12561311 return startTimestampsForBlock.at (streamId);
12571312}
12581313
1314+ const double * GenericProcessor::getTimestampsForBlock (uint16 streamId) const
1315+ {
1316+ const std::vector<double >* timestamps = findTimestampArrayState (this , streamId);
1317+
1318+ return timestamps != nullptr ? timestamps->data () : nullptr ;
1319+ }
1320+
1321+ bool GenericProcessor::getTimestampForSample (uint16 streamId, int64 sampleNumber, double & timestamp) const
1322+ {
1323+ const std::vector<double >* timestamps = findTimestampArrayState (this , streamId);
1324+
1325+ if (timestamps == nullptr )
1326+ return false ;
1327+
1328+ auto sampleIt = startSamplesForBlock.find (streamId);
1329+ auto countIt = numSamplesInBlock.find (streamId);
1330+
1331+ if (sampleIt == startSamplesForBlock.end () || countIt == numSamplesInBlock.end ())
1332+ return false ;
1333+
1334+ if (sampleNumber < sampleIt->second )
1335+ return false ;
1336+
1337+ const uint32 sampleOffset = static_cast <uint32> (sampleNumber - sampleIt->second );
1338+
1339+ if (sampleOffset >= countIt->second || sampleOffset >= timestamps->size ())
1340+ return false ;
1341+
1342+ timestamp = (*timestamps)[sampleOffset];
1343+ return true ;
1344+ }
1345+
12591346void GenericProcessor::setTimestampAndSamples (int64 sampleNumber,
12601347 double timestamp,
12611348 uint32 nSamples,
12621349 uint16 streamId,
12631350 uint16 syncStreamId)
12641351{
1352+ clearTimestampArrayState (this , streamId);
1353+
12651354 HeapBlock<char > data;
12661355 size_t dataSize = SystemEvent::fillTimestampAndSamplesData (data,
12671356 this ,
@@ -1278,9 +1367,41 @@ void GenericProcessor::setTimestampAndSamples (int64 sampleNumber,
12781367 startTimestampsForBlock[streamId] = timestamp;
12791368 startSamplesForBlock[streamId] = sampleNumber;
12801369 syncStreamIds[streamId] = syncStreamId;
1370+ numSamplesInBlock[streamId] = nSamples;
12811371 processStartTimes[streamId] = m_initialProcessTime;
12821372}
12831373
1374+ void GenericProcessor::setTimestampArrayForBlock (int64 sampleNumber,
1375+ const double * timestamps,
1376+ uint32 nSamples,
1377+ uint16 streamId,
1378+ uint16 syncStreamId)
1379+ {
1380+ clearTimestampArrayState (this , streamId);
1381+
1382+ if (timestamps == nullptr || nSamples == 0 )
1383+ return ;
1384+
1385+ HeapBlock<char > data;
1386+ size_t dataSize = SystemEvent::fillTimestampArrayData (data,
1387+ this ,
1388+ streamId,
1389+ sampleNumber,
1390+ timestamps,
1391+ nSamples,
1392+ m_initialProcessTime,
1393+ syncStreamId);
1394+
1395+ m_currentMidiBuffer->addEvent (data, int (dataSize), 0 );
1396+
1397+ startTimestampsForBlock[streamId] = timestamps[0 ];
1398+ startSamplesForBlock[streamId] = sampleNumber;
1399+ syncStreamIds[streamId] = syncStreamId;
1400+ numSamplesInBlock[streamId] = nSamples;
1401+ processStartTimes[streamId] = m_initialProcessTime;
1402+ setTimestampArrayState (this , streamId, timestamps, nSamples);
1403+ }
1404+
12841405int GenericProcessor::getGlobalChannelIndex (uint16 streamId, int localIndex) const
12851406{
12861407 return getDataStream (streamId)->getContinuousChannels ()[localIndex]->getGlobalIndex ();
@@ -1303,26 +1424,39 @@ int GenericProcessor::processEventBuffer()
13031424 for (const auto meta : *m_currentMidiBuffer)
13041425 {
13051426 const uint8* dataptr = meta.data ;
1427+ const Event::Type baseType = static_cast <Event::Type> (*dataptr);
13061428
1307- if (static_cast <Event::Type> (*dataptr) == Event::Type::SYSTEM_EVENT
1308- && static_cast <SystemEvent::Type> (*(dataptr + 1 ) == SystemEvent::Type::TIMESTAMP_AND_SAMPLES ))
1429+ if (baseType == Event::Type::SYSTEM_EVENT )
13091430 {
1310- uint16 sourceProcessorId = *reinterpret_cast <const uint16*> (dataptr + 2 );
1311- uint16 sourceStreamId = *reinterpret_cast <const uint16*> (dataptr + 4 );
1312- uint16 syncStreamId = *reinterpret_cast <const uint16*> (dataptr + 6 );
1313-
1314- int64 startSample = *reinterpret_cast <const int64*> (dataptr + 8 );
1315- double startTimestamp = *reinterpret_cast <const double *> (dataptr + 16 );
1316- uint32 nSamples = *reinterpret_cast <const uint32*> (dataptr + 24 );
1317- int64 initialTicks = *reinterpret_cast <const int64*> (dataptr + 28 );
1318-
1319- startSamplesForBlock[sourceStreamId] = startSample;
1320- startTimestampsForBlock[sourceStreamId] = startTimestamp;
1321- syncStreamIds[sourceStreamId] = syncStreamId;
1322- numSamplesInBlock[sourceStreamId] = nSamples;
1323- processStartTimes[sourceStreamId] = initialTicks;
1431+ const SystemEvent::Type systemEventType = static_cast <SystemEvent::Type> (*(dataptr + 1 ));
1432+
1433+ if (systemEventType == SystemEvent::Type::TIMESTAMP_AND_SAMPLES
1434+ || systemEventType == SystemEvent::Type::TIMESTAMP_ARRAY )
1435+ {
1436+ uint16 sourceStreamId = *reinterpret_cast <const uint16*> (dataptr + 4 );
1437+ uint16 syncStreamId = *reinterpret_cast <const uint16*> (dataptr + 6 );
1438+
1439+ int64 startSample = *reinterpret_cast <const int64*> (dataptr + 8 );
1440+ double startTimestamp = *reinterpret_cast <const double *> (dataptr + 16 );
1441+ uint32 nSamples = *reinterpret_cast <const uint32*> (dataptr + 24 );
1442+ int64 initialTicks = *reinterpret_cast <const int64*> (dataptr + 28 );
1443+
1444+ clearTimestampArrayState (this , sourceStreamId);
1445+
1446+ startSamplesForBlock[sourceStreamId] = startSample;
1447+ startTimestampsForBlock[sourceStreamId] = startTimestamp;
1448+ syncStreamIds[sourceStreamId] = syncStreamId;
1449+ numSamplesInBlock[sourceStreamId] = nSamples;
1450+ processStartTimes[sourceStreamId] = initialTicks;
1451+
1452+ if (systemEventType == SystemEvent::Type::TIMESTAMP_ARRAY && nSamples > 0 )
1453+ {
1454+ const double * timestamps = reinterpret_cast <const double *> (dataptr + timestampArrayOffset);
1455+ setTimestampArrayState (this , sourceStreamId, timestamps, nSamples);
1456+ }
1457+ }
13241458 }
1325- else if (static_cast <Event::Type> (*dataptr) == Event::Type::PROCESSOR_EVENT
1459+ else if (baseType == Event::Type::PROCESSOR_EVENT
13261460 && static_cast <EventChannel::Type> (*(dataptr + 1 ) == EventChannel::Type::TTL ))
13271461 {
13281462 uint16 sourceStreamId = *reinterpret_cast <const uint16*> (dataptr + 4 );
@@ -1334,7 +1468,7 @@ int GenericProcessor::processEventBuffer()
13341468 getEditor ()->setTTLState (sourceStreamId, eventBit, eventState);
13351469 }
13361470 }
1337- else if (static_cast <Event::Type> (*dataptr) == Event::Type::PROCESSOR_EVENT
1471+ else if (baseType == Event::Type::PROCESSOR_EVENT
13381472 && static_cast <EventChannel::Type> (*(dataptr + 1 ) == EventChannel::Type::TEXT ))
13391473 {
13401474 TextEventPtr textEvent = TextEvent::deserialize (dataptr, getMessageChannel ());
0 commit comments