Skip to content

Commit 1ac4db8

Browse files
authored
Merge pull request #696 from anjaldoshi/copy-timestamps-array
Propagate per-sample hardware timestamps through the signal chain
2 parents 73fbe93 + 326892c commit 1ac4db8

20 files changed

Lines changed: 593 additions & 87 deletions

File tree

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
diff --git a/Tests/Processors/CMakeLists.txt b/Tests/Processors/CMakeLists.txt
2-
index a89fa4da4..ab53e8d89 100644
2+
index 5c14d2a0e..7770875b8 100644
33
--- a/Tests/Processors/CMakeLists.txt
44
+++ b/Tests/Processors/CMakeLists.txt
5-
@@ -5,8 +5,8 @@ add_sources(${COMPONENT_NAME}_tests
5+
@@ -5,9 +5,9 @@ add_sources(${COMPONENT_NAME}_tests
66
DataBufferTests.cpp
77
PluginManagerTests.cpp
88
SourceNodeTests.cpp
99
- RecordNodeTests.cpp
10+
+ # RecordNodeTests.cpp
11+
SIMDConverterTests.cpp
1012
- ProcessorGraphTests.cpp
11-
+ #RecordNodeTests.cpp
12-
+ #ProcessorGraphTests.cpp
13+
+ # ProcessorGraphTests.cpp
1314
EventTests.cpp
1415
DataThreadTests.cpp
1516
GenericProcessorTests.cpp

Source/Processors/AudioNode/AudioNode.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,6 @@ class AudioNode : public GenericProcessor
7373
/** Constructor */
7474
AudioNode();
7575

76-
/** Destructor */
77-
~AudioNode() {}
78-
7976
/** Handle incoming data and decide which channels to monitor
8077
*/
8178
void process (AudioBuffer<float>& buffer) override;

Source/Processors/DataThreads/DataBuffer.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ int DataBuffer::getNumSamples() const { return abstractFifo.getNumReady(); }
107107

108108
int DataBuffer::readAllFromBuffer (AudioBuffer<float>& data,
109109
int64* blockSampleNumber,
110-
double* blockTimestamp,
110+
double* blockTimestamps,
111111
uint64* eventCodes,
112112
int maxSize,
113113
int dstStartChannel,
@@ -134,15 +134,15 @@ int DataBuffer::readAllFromBuffer (AudioBuffer<float>& data,
134134
blockSize1); // numSamples
135135
}
136136

137-
memcpy (blockSampleNumber, sampleNumberBuffer + startIndex1, 8);
138-
memcpy (blockTimestamp, timestampBuffer + startIndex1, 8);
139-
memcpy (eventCodes, eventCodeBuffer + startIndex1, blockSize1 * 8);
137+
memcpy (blockSampleNumber, sampleNumberBuffer + startIndex1, sizeof (int64));
138+
memcpy (blockTimestamps, timestampBuffer + startIndex1, (size_t) blockSize1 * sizeof (double));
139+
memcpy (eventCodes, eventCodeBuffer + startIndex1, (size_t) blockSize1 * sizeof (uint64));
140140
}
141141
else
142142
{
143143
// std::cout << "NO SAMPLES" << std::endl;
144-
memcpy (blockSampleNumber, &lastSampleNumber, 8);
145-
memcpy (blockTimestamp, &lastTimestamp, 8);
144+
memcpy (blockSampleNumber, &lastSampleNumber, sizeof (int64));
145+
memcpy (blockTimestamps, &lastTimestamp, sizeof (double));
146146
}
147147

148148
if (blockSize2 > 0)
@@ -156,15 +156,16 @@ int DataBuffer::readAllFromBuffer (AudioBuffer<float>& data,
156156
startIndex2, // sourceStartSample
157157
blockSize2); // numSamples
158158
}
159-
memcpy (eventCodes + blockSize1, eventCodeBuffer + startIndex2, blockSize2 * 8);
159+
memcpy (blockTimestamps + blockSize1, timestampBuffer + startIndex2, (size_t) blockSize2 * sizeof (double));
160+
memcpy (eventCodes + blockSize1, eventCodeBuffer + startIndex2, (size_t) blockSize2 * sizeof (uint64));
160161
}
161162

162163
// std::cout << "START SAMPLE FOR READ: " << *blockSampleNumber << std::endl;
163164

164165
if (numItems > 0)
165166
{
166167
lastSampleNumber = *blockSampleNumber;
167-
lastTimestamp = *blockTimestamp;
168+
lastTimestamp = *blockTimestamps;
168169

169170
// std::cout << "Updating last sample number: " << lastSampleNumber << std::endl;
170171
}

Source/Processors/DataThreads/DataBuffer.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ class PLUGIN_API DataBuffer
6464
/** Returns the number of samples currently available in the buffer.*/
6565
int getNumSamples() const;
6666

67-
/** Copies as many samples as possible from the DataBuffer to an AudioBuffer.*/
67+
/** Copies as many samples as possible from the DataBuffer to an AudioBuffer.
68+
69+
The first sample number is returned in `sampleNumbers[0]`, while `timestamps`
70+
and `eventCodes` receive one value per copied sample.
71+
*/
6872
int readAllFromBuffer (AudioBuffer<float>& data,
6973
int64* sampleNumbers,
7074
double* timestamps,

Source/Processors/Events/Event.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,36 @@ size_t SystemEvent::fillTimestampAndSamplesData (HeapBlock<char>& data,
218218
return eventSize;
219219
}
220220

221+
size_t SystemEvent::fillTimestampArrayData (HeapBlock<char>& data,
222+
const GenericProcessor* proc,
223+
uint16 streamId,
224+
int64 startSampleForBlock,
225+
const double* timestamps,
226+
uint32 nSamplesInBlock,
227+
int64 processStartTime,
228+
uint16 syncStreamId)
229+
{
230+
const size_t timestampDataSize = (size_t) nSamplesInBlock * sizeof (double);
231+
const size_t eventSize = EVENT_BASE_SIZE + 4 + 8 + timestampDataSize;
232+
const double startTimestampForBlock = nSamplesInBlock > 0 && timestamps != nullptr ? timestamps[0] : -1.0;
233+
234+
data.allocate (eventSize, true);
235+
data[0] = SYSTEM_EVENT;
236+
data[1] = TIMESTAMP_ARRAY;
237+
*reinterpret_cast<uint16*> (data.getData() + 2) = proc->getNodeId();
238+
*reinterpret_cast<uint16*> (data.getData() + 4) = streamId;
239+
*reinterpret_cast<uint16*> (data.getData() + 6) = syncStreamId;
240+
*reinterpret_cast<int64*> (data.getData() + 8) = startSampleForBlock;
241+
*reinterpret_cast<double*> (data.getData() + 16) = startTimestampForBlock;
242+
*reinterpret_cast<uint32*> (data.getData() + EVENT_BASE_SIZE) = nSamplesInBlock;
243+
*reinterpret_cast<int64*> (data.getData() + EVENT_BASE_SIZE + 4) = processStartTime;
244+
245+
if (timestampDataSize > 0 && timestamps != nullptr)
246+
memcpy (data.getData() + EVENT_BASE_SIZE + 12, timestamps, timestampDataSize);
247+
248+
return eventSize;
249+
}
250+
221251
size_t SystemEvent::fillTimestampSyncTextData (
222252
HeapBlock<char>& data,
223253
const GenericProcessor* proc,
@@ -277,15 +307,25 @@ size_t SystemEvent::fillReferenceSampleEvent (HeapBlock<char>& data,
277307

278308
uint32 SystemEvent::getNumSamples (const EventPacket& packet)
279309
{
280-
if (getBaseType (packet) != SYSTEM_EVENT && getSystemEventType (packet) != TIMESTAMP_AND_SAMPLES)
310+
if (getBaseType (packet) != SYSTEM_EVENT)
311+
return 0;
312+
313+
Type type = getSystemEventType (packet);
314+
315+
if (type != TIMESTAMP_AND_SAMPLES && type != TIMESTAMP_ARRAY)
281316
return 0;
282317

283318
return *reinterpret_cast<const uint32*> (packet.getRawData() + EVENT_BASE_SIZE);
284319
}
285320

286321
int64 SystemEvent::getHiResTicks (const EventPacket& packet)
287322
{
288-
if (getBaseType (packet) != SYSTEM_EVENT && getSystemEventType (packet) != TIMESTAMP_AND_SAMPLES)
323+
if (getBaseType (packet) != SYSTEM_EVENT)
324+
return 0;
325+
326+
Type type = getSystemEventType (packet);
327+
328+
if (type != TIMESTAMP_AND_SAMPLES && type != TIMESTAMP_ARRAY)
289329
return 0;
290330

291331
return *reinterpret_cast<const int64*> (packet.getRawData() + EVENT_BASE_SIZE + 4);

Source/Processors/Events/Event.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,10 @@ class PLUGIN_API SystemEvent : public EventBase
220220
TIMESTAMP_SYNC_TEXT = 3,
221221

222222
// Indicates reference sample information for each incoming data buffer
223-
REFERENCE_SAMPLE = 4
223+
REFERENCE_SAMPLE = 4,
224+
225+
// Per-sample timestamps for the current buffer
226+
TIMESTAMP_ARRAY = 5
224227
};
225228

226229
/* Create a TIMESTAMP_AND_SAMPLES event (used by processors that update timestamps) */
@@ -233,6 +236,16 @@ class PLUGIN_API SystemEvent : public EventBase
233236
int64 processStartTime,
234237
uint16 syncStreamId = 0);
235238

239+
/* Create a TIMESTAMP_ARRAY event (used by processors that provide per-sample timestamps) */
240+
static size_t fillTimestampArrayData (HeapBlock<char>& data,
241+
const GenericProcessor* proc,
242+
uint16 streamId,
243+
int64 startSampleForBlock,
244+
const double* timestamps,
245+
uint32 nSamplesInBlock,
246+
int64 processStartTime,
247+
uint16 syncStreamId = 0);
248+
236249
/* Create a TIMESTAMP_SYNC_TEXT event (used by Record Node) */
237250
static size_t fillTimestampSyncTextData (HeapBlock<char>& data,
238251
const GenericProcessor* proc,

0 commit comments

Comments
 (0)