Skip to content

Commit 748cee7

Browse files
committed
Add support for writing explicit per-sample timestamps in Record Node
1 parent 5f30733 commit 748cee7

4 files changed

Lines changed: 73 additions & 27 deletions

File tree

Source/Processors/RecordNode/DataQueue.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,30 @@ float DataQueue::writeSynchronizedTimestamps (double start, double step, int des
185185
return 1.0f - (float) m_FTSFifos[destChannel]->getFreeSpace() / (float) m_FTSFifos[destChannel]->getTotalSize();
186186
}
187187

188+
float DataQueue::writeSynchronizedTimestamps (const double* timestamps, int destChannel, int nSamples)
189+
{
190+
int index1, size1, index2, size2;
191+
192+
m_FTSFifos[destChannel]->prepareToWrite (nSamples, index1, size1, index2, size2);
193+
194+
if ((size1 + size2) < nSamples)
195+
{
196+
LOGE (__FUNCTION__, " Recording Data Queue Overflow: sz1: ", size1, " sz2: ", size2, " nSamples: ", nSamples);
197+
}
198+
199+
double* writePtr = m_FTSBuffer.getWritePointer (destChannel);
200+
201+
if (size1 > 0)
202+
memcpy (writePtr + index1, timestamps, (size_t) size1 * sizeof (double));
203+
204+
if (size2 > 0)
205+
memcpy (writePtr + index2, timestamps + size1, (size_t) size2 * sizeof (double));
206+
207+
m_FTSFifos[destChannel]->finishedWrite (size1 + size2);
208+
209+
return 1.0f - (float) m_FTSFifos[destChannel]->getFreeSpace() / (float) m_FTSFifos[destChannel]->getTotalSize();
210+
}
211+
188212
float DataQueue::writeChannel (const AudioBuffer<float>& buffer,
189213
int srcChannel,
190214
int destChannel,

Source/Processors/RecordNode/DataQueue.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ class DataQueue
8888
/** Writes an array of timestamps for one stream */
8989
float writeSynchronizedTimestamps (double start, double step, int destChannel, int nSamples);
9090

91+
/** Writes explicit per-sample timestamps for one stream */
92+
float writeSynchronizedTimestamps (const double* timestamps, int destChannel, int nSamples);
93+
9194
/** Returns the number of samples available to read (minimum across all channels) */
9295
int getNumSamplesReady() const;
9396

Source/Processors/RecordNode/RecordNode.cpp

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -990,15 +990,7 @@ void RecordNode::handleTTLEvent (TTLEventPtr event)
990990
size_t size = event->getChannelInfo()->getDataSize() + event->getChannelInfo()->getTotalEventMetadataSize() + EVENT_BASE_SIZE;
991991
uint16 streamId = event->getStreamId();
992992

993-
double ts = -1.0;
994-
if (synchronizer.streamGeneratesTimestamps (streamKey))
995-
{
996-
ts = getFirstTimestampForBlock (streamId) + (sampleNumber - getFirstSampleNumberForBlock (streamId)) / getDataStream (streamId)->getSampleRate();
997-
}
998-
else
999-
{
1000-
ts = synchronizer.convertSampleNumberToTimestamp (streamKey, sampleNumber);
1001-
}
993+
double ts = resolveRecordedTimestamp (streamKey, streamId, sampleNumber);
1002994

1003995
HeapBlock<char> buffer (size);
1004996
event->setTimestampInSeconds (ts);
@@ -1020,7 +1012,7 @@ void RecordNode::handleEvent (const EventChannel* eventInfo, const EventPacket&
10201012

10211013
String streamKey = getDataStream (eventInfo->getStreamId())->getKey();
10221014

1023-
Event::setTimestampInSeconds (packet, synchronizer.convertSampleNumberToTimestamp (streamKey, sampleNumber));
1015+
Event::setTimestampInSeconds (packet, resolveRecordedTimestamp (streamKey, eventInfo->getStreamId(), sampleNumber));
10241016

10251017
eventQueue->addEvent (packet, sampleNumber, eventIndex);
10261018
}
@@ -1037,15 +1029,7 @@ void RecordNode::handleSpike (SpikePtr spike)
10371029
uint16 streamId = spike->getStreamId();
10381030
int64 sampleNumber = spike->getSampleNumber();
10391031

1040-
double ts = -1.0;
1041-
if (synchronizer.streamGeneratesTimestamps (streamKey))
1042-
{
1043-
ts = getFirstTimestampForBlock (streamId) + (sampleNumber - getFirstSampleNumberForBlock (streamId)) / getDataStream (streamId)->getSampleRate();
1044-
}
1045-
else
1046-
{
1047-
ts = synchronizer.convertSampleNumberToTimestamp (streamKey, sampleNumber);
1048-
}
1032+
double ts = resolveRecordedTimestamp (streamKey, streamId, sampleNumber);
10491033

10501034
spike->setTimestampInSeconds (ts);
10511035
writeSpike (spike, spike->getChannelInfo());
@@ -1143,19 +1127,36 @@ void RecordNode::process (AudioBuffer<float>& buffer)
11431127
{
11441128
first = synchronizer.convertSampleNumberToTimestamp (streamKey, sampleNumber);
11451129
second = synchronizer.convertSampleNumberToTimestamp (streamKey, sampleNumber + 1);
1130+
1131+
dataQueues[streamIndex]->writeSynchronizedTimestamps (
1132+
first,
1133+
second - first,
1134+
0,
1135+
numSamples);
11461136
}
11471137
else
11481138
{
1149-
first = getFirstTimestampForBlock (streamId);
1150-
second = first + 1 / stream->getSampleRate();
1139+
const double* blockTimestamps = getTimestampsForBlock (streamId);
1140+
1141+
if (blockTimestamps != nullptr)
1142+
{
1143+
first = blockTimestamps[0];
1144+
dataQueues[streamIndex]->writeSynchronizedTimestamps (blockTimestamps, 0, (int) numSamples);
1145+
}
1146+
else
1147+
{
1148+
first = getFirstTimestampForBlock (streamId);
1149+
second = first + 1 / stream->getSampleRate();
1150+
1151+
dataQueues[streamIndex]->writeSynchronizedTimestamps (
1152+
first,
1153+
second - first,
1154+
0,
1155+
numSamples);
1156+
}
1157+
11511158
synchronizer.setHardwareTimestamp (sampleNumber, first, streamKey);
11521159
}
1153-
// Each per-stream queue has only 1 timestamp stream (index 0)
1154-
dataQueues[streamIndex]->writeSynchronizedTimestamps (
1155-
first,
1156-
second - first,
1157-
0, // timestamp stream index within this queue
1158-
numSamples);
11591160
}
11601161

11611162
if (numSamples > 0 && recordChanCount > 0 && streamSourceChannels[streamIndex] != nullptr)
@@ -1210,6 +1211,22 @@ void RecordNode::process (AudioBuffer<float>& buffer)
12101211
}
12111212
}
12121213

1214+
double RecordNode::resolveRecordedTimestamp (const String& streamKey, uint16 streamId, int64 sampleNumber)
1215+
{
1216+
if (synchronizer.streamGeneratesTimestamps (streamKey))
1217+
{
1218+
double timestamp = -1.0;
1219+
1220+
if (getTimestampForSample (streamId, sampleNumber, timestamp))
1221+
return timestamp;
1222+
1223+
return getFirstTimestampForBlock (streamId)
1224+
+ (sampleNumber - getFirstSampleNumberForBlock (streamId)) / getDataStream (streamId)->getSampleRate();
1225+
}
1226+
1227+
return synchronizer.convertSampleNumberToTimestamp (streamKey, sampleNumber);
1228+
}
1229+
12131230
// called in RecordNode::handleSpike
12141231
void RecordNode::writeSpike (const Spike* spike, const SpikeChannel* spikeElectrode)
12151232
{

Source/Processors/RecordNode/RecordNode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ class TESTABLE RecordNode : public GenericProcessor,
256256
static bool overrideTimestampWarningShown;
257257

258258
private:
259+
double resolveRecordedTimestamp (const String& streamKey, uint16 streamId, int64 sampleNumber);
260+
259261
/** Handles other types of events (text, sync texts, etc.) */
260262
void handleEvent (const EventChannel* channel, const EventPacket& eventPacket);
261263

0 commit comments

Comments
 (0)