- 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) {
+ /* Look for a suitable packet, dropping any unsuitable ones along the
+ * way. Unsuitable packets are ones that are in the past. */
+ while(pheap_count(&packets)) {
+ p = pheap_first(&packets);
+ if(le(p->timestamp + p->nsamples, next_timestamp))
+ /* This packet is in the past. Drop it and try another one. */
+ drop_first_packet();
+ else
+ /* This packet is NOT in the past. (It might be in the future
+ * however.) */
+ break;
+ }
+ p = pheap_count(&packets) ? pheap_first(&packets) : 0;
+ if(p && contains(p, next_timestamp)) {
+ /* This packet is ready to play */
+ const uint32_t packet_end = p->timestamp + p->nsamples;
+ const uint32_t offset = next_timestamp - p->timestamp;
+ const uint16_t *ptr =
+ (void *)(p->samples_raw + offset * sizeof (uint16_t));
+
+ samples_available = packet_end - next_timestamp;
+ if(samples_available > samplesOutLeft)
+ samples_available = samplesOutLeft;
+ next_timestamp += samples_available;
+ samplesOutLeft -= samples_available;
+ while(samples_available-- > 0)
+ *samplesOut++ = (int16_t)ntohs(*ptr++) * (0.5 / 32767);
+ /* We don't bother junking the packet - that'll be dealt with next time
+ * round */
+ } else {
+ /* No packet is ready to play (and there might be no packet at all) */
+ samples_available = p ? p->timestamp - next_timestamp
+ : samplesOutLeft;
+ if(samples_available > samplesOutLeft)
+ samples_available = samplesOutLeft;
+ info("infill by %"PRIu32, samples_available);
+ /* Conveniently the buffer is 0 to start with */
+ next_timestamp += samples_available;
+ samplesOut += samples_available;
+ samplesOutLeft -= samples_available;
+ }