- samplesOut = ab->data;
- samplesOutLeft = ab->mDataByteSize / sizeof (float);
- while(packets && nbuffers > 0) {
- if(packets->used == packets->nsamples) {
- /* TODO if we dropped a packet then we should introduce a gap here */
- struct packet *const p = packets;
- packets = p->next;
- free(p);
- pthread_cond_broadcast(&cond);
- continue;
- }
- if(samplesOutLeft == 0) {
- --nbuffers;
- ++ab;
- samplesOut = ab->data;
- samplesOutLeft = ab->mDataByteSize / sizeof (float);
- continue;
+ while(nbuffers > 0) {
+ float *samplesOut = ab->mData;
+ size_t samplesOutLeft = ab->mDataByteSize / sizeof (float);
+
+ while(samplesOutLeft > 0) {
+ if(packets) {
+ /* There's a packet */
+ const uint32_t packet_start = packets->timestamp;
+ const uint32_t packet_end = packets->timestamp + packets->nsamples;
+
+ if(le(packet_end, next_timestamp)) {
+ /* This packet is in the past */
+ info("dropping buffered past packet %"PRIx32" < %"PRIx32,
+ packet_start, next_timestamp);
+ drop_first_packet();
+ continue;
+ }
+ if(ge(next_timestamp, packet_start)
+ && lt(next_timestamp, packet_end)) {
+ /* This packet is suitable */
+ const uint32_t offset = next_timestamp - packet_start;
+ uint32_t samples_available = packet_end - next_timestamp;
+ if(samples_available > samplesOutLeft)
+ samples_available = samplesOutLeft;
+ memcpy(samplesOut,
+ packets->samples_float + offset,
+ samples_available * sizeof(float));
+ samplesOut += samples_available;
+ next_timestamp += samples_available;
+ samplesOutLeft -= samples_available;
+ if(ge(next_timestamp, packet_end))
+ drop_first_packet();
+ continue;
+ }
+ }
+ /* We didn't find a suitable packet (though there might still be
+ * unsuitable ones). We infill with 0s. */
+ if(packets) {
+ /* There is a next packet, only infill up to that point */
+ uint32_t samples_available = packets->timestamp - next_timestamp;
+
+ if(samples_available > samplesOutLeft)
+ samples_available = samplesOutLeft;
+ info("infill by %"PRIu32, samples_available);
+ /* Convniently the buffer is 0 to start with */
+ next_timestamp += samples_available;
+ samplesOut += samples_available;
+ samplesOutLeft -= samples_available;
+ } else {
+ /* There's no next packet at all */
+ info("infilled by %zu", samplesOutLeft);
+ next_timestamp += samplesOutLeft;
+ samplesOut += samplesOutLeft;
+ samplesOutLeft = 0;
+ }