Skip to content

Commit

Permalink
Implemented elastic buffering + Output Buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
TheDaChicken committed Jul 20, 2024
1 parent 2a85627 commit 7df2aa8
Show file tree
Hide file tree
Showing 7 changed files with 436 additions and 55 deletions.
41 changes: 35 additions & 6 deletions src/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
#define PCI_AUDIO_FIXED_OPP 0x8D8D33
#define PCI_FIXED 0x3634CE

#define MAX_AUDIO_PACKETS 64

typedef struct
{
unsigned int codec;
Expand Down Expand Up @@ -288,6 +286,32 @@ static unsigned int calc_lc_bits(frame_header_t *hdr)
}
}

static unsigned int calc_avg_packets(frame_header_t *hdr)
{
switch(hdr->codec)
{
case 0:
return 32;
case 1:
case 2:
case 3:
if (hdr->stream_id == 0)
return 4;
else
return 32;
case 10:
if (hdr->stream_id == 0)
return 32;
else
return 4;
case 13:
return 4;
default:
log_warn("unknown codec field (%d)", hdr->codec);
return 32;
}
}

static unsigned int parse_location(uint8_t *buf, unsigned int lc_bits, unsigned int i)
{
if (lc_bits == 16)
Expand Down Expand Up @@ -337,7 +361,7 @@ static void aas_push(frame_t *st, uint8_t* psd, unsigned int length, logical_cha
else
{
// remove protocol and fcs fields
input_aas_push(st->input, psd + 1, length - 3);
output_aas_push(st->input->output, psd + 1, length - 3);
}
}

Expand Down Expand Up @@ -503,7 +527,7 @@ void frame_process(frame_t *st, size_t length, logical_channel_t lc)
while (offset < audio_end - RS_CODEWORD_LEN)
{
unsigned int start = offset;
unsigned int j, lc_bits, loc_bytes, prog;
unsigned int j, lc_bits, loc_bytes, prog, avg, seq;
unsigned short locations[MAX_AUDIO_PACKETS];
frame_header_t hdr = {0};
hef_t hef = {0};
Expand Down Expand Up @@ -535,6 +559,10 @@ void frame_process(frame_t *st, size_t length, logical_channel_t lc)
if (hdr.hef)
offset += parse_hef(st->buffer + offset, audio_end - offset, &hef);
prog = hef.prog_num;
avg = calc_avg_packets(&hdr);
seq = (hdr.seq - hdr.pfirst) % MAX_AUDIO_PACKETS;

output_align(st->input->output, prog, hdr.stream_id, hdr.pdu_seq, hdr.latency, avg, seq, hdr.nop);

parse_hdlc(st, aas_push, st->psd_buf[prog], &st->psd_idx[prog], MAX_AAS_LEN, st->buffer + offset, start + hdr.la_location + 1 - offset, lc);
offset = start + hdr.la_location + 1;
Expand All @@ -555,7 +583,7 @@ void frame_process(frame_t *st, size_t length, logical_channel_t lc)
if (crc == 0)
{
memcpy(&st->pdu[prog][hdr.stream_id][idx], st->buffer + offset, cnt);
input_pdu_push(st->input, st->pdu[prog][hdr.stream_id], cnt + idx, prog, hdr.stream_id);
output_push(st->input->output, st->pdu[prog][hdr.stream_id], cnt + idx, prog, hdr.stream_id, seq);
}
st->pdu_idx[prog][hdr.stream_id] = 0;
}
Expand All @@ -576,11 +604,12 @@ void frame_process(frame_t *st, size_t length, logical_channel_t lc)
{
if (crc == 0)
{
input_pdu_push(st->input, st->buffer + offset, cnt, prog, hdr.stream_id);
output_push(st->input->output, st->buffer + offset, cnt, prog, hdr.stream_id, seq);
}
}

offset += cnt + 1;
seq = (seq + 1) % MAX_AUDIO_PACKETS;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "defines.h"

#define MAX_AUDIO_PACKETS 64
#define MAX_AAS_LEN 8212
#define RS_BLOCK_LEN 255
#define RS_CODEWORD_LEN 96
Expand Down
38 changes: 22 additions & 16 deletions src/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,32 @@ static float decim_taps[] = {
-0.00410953676328063
};

static void input_push_to_acquire(input_t *st)
static unsigned int input_push_to_acquire(input_t *st)
{
unsigned int used = 0;

if (st->skip)
{
if (st->skip > st->avail - st->used)
{
used += st->avail - st->used;
st->skip -= st->avail - st->used;
st->used = st->avail;
}
else
{
used += st->skip;
st->used += st->skip;
st->skip = 0;
}
}

st->used += acquire_push(&st->acq, &st->buffer[st->used], st->avail - st->used);
}
unsigned int needed = acquire_push(&st->acq, &st->buffer[st->used], st->avail - st->used);

void input_pdu_push(input_t *st, uint8_t *pdu, unsigned int len, unsigned int program, unsigned int stream_id)
{
output_push(st->output, pdu, len, program, stream_id);
st->used += needed;
used += needed;

return used;
}

void input_set_skip(input_t *st, unsigned int skip)
Expand Down Expand Up @@ -139,12 +143,13 @@ int input_shift(input_t *st, unsigned int cnt)
return 0;
}

void input_push(input_t *st)
void input_push(input_t *st, unsigned int pos)
{
while (st->avail - st->used >= (st->radio->mode == NRSC5_MODE_FM ? FFTCP_FM : FFTCP_AM))
{
input_push_to_acquire(st);
unsigned int pushed = input_push_to_acquire(st);
acquire_process(&st->acq);
output_advance_elastic(st->output, (int)st->used - (int)pushed - (int)pos, pushed);
}
}

Expand All @@ -164,6 +169,8 @@ void input_push_cu8(input_t *st, const uint8_t *buf, uint32_t len)
if (input_shift(st, len / 4) != 0)
return;

unsigned int pos = st->avail;

for (i = 0; i < len; i += 4)
{
cint16_t x[2];
Expand Down Expand Up @@ -201,7 +208,8 @@ void input_push_cu8(input_t *st, const uint8_t *buf, uint32_t len)
}
}

input_push(st);
input_push(st, pos);
output_advance(st->output, len / 4);
}

void input_push_cs16(input_t *st, const int16_t *buf, uint32_t len)
Expand All @@ -211,10 +219,13 @@ void input_push_cs16(input_t *st, const int16_t *buf, uint32_t len)
if (input_shift(st, len / 2) != 0)
return;

unsigned int pos = st->avail;

memcpy(&st->buffer[st->avail], buf, len * sizeof(int16_t));
st->avail += len / 2;

input_push(st);
input_push(st, pos);
output_advance(st->output, len / 2);
}

void input_set_snr_callback(input_t *st, input_snr_cb_t cb, void *arg)
Expand Down Expand Up @@ -292,9 +303,4 @@ void input_set_sync_state(input_t *st, unsigned int new_state)
}

st->sync_state = new_state;
}

void input_aas_push(input_t *st, uint8_t *psd, unsigned int len)
{
output_aas_push(st->output, psd, len);
}
}
2 changes: 0 additions & 2 deletions src/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,3 @@ void input_push_cu8(input_t *st, const uint8_t *buf, uint32_t len);
void input_push_cs16(input_t *st, const int16_t *buf, uint32_t len);
void input_set_snr_callback(input_t *st, input_snr_cb_t cb, void *);
void input_set_skip(input_t *st, unsigned int skip);
void input_pdu_push(input_t *st, uint8_t *pdu, unsigned int len, unsigned int program, unsigned int stream_id);
void input_aas_push(input_t *st, uint8_t *psd, unsigned int len);
16 changes: 7 additions & 9 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@
#include "log.h"

#define AUDIO_BUFFERS 128
#define AUDIO_THRESHOLD 40
#define AUDIO_DATA_LENGTH 8192
#define MAX_AUDIO_DATA_LENGTH 31072

typedef struct buffer_t {
struct buffer_t *next;
// The samples are signed 16-bit integers, but ao_play requires a char buffer.
char data[AUDIO_DATA_LENGTH];
char data[MAX_AUDIO_DATA_LENGTH];
size_t count;
} audio_buffer_t;

typedef struct {
Expand Down Expand Up @@ -143,8 +143,9 @@ static void push_audio_buffer(state_t *st, unsigned int program, const int16_t *
st->free = b->next;
pthread_mutex_unlock(&st->mutex);

assert(AUDIO_DATA_LENGTH == count * sizeof(data[0]));
assert(MAX_AUDIO_DATA_LENGTH >= count * sizeof(data[0]));
memcpy(b->data, data, count * sizeof(data[0]));
b->count = count;

pthread_mutex_lock(&st->mutex);
if (program != st->program)
Expand All @@ -161,9 +162,6 @@ static void push_audio_buffer(state_t *st, unsigned int program, const int16_t *
st->head = b;
st->tail = b;

if (st->audio_ready < AUDIO_THRESHOLD)
st->audio_ready++;

pthread_cond_signal(&st->cond);

unlock:
Expand Down Expand Up @@ -802,7 +800,7 @@ int main(int argc, char *argv[])
audio_buffer_t *b;

pthread_mutex_lock(&st->mutex);
while (!st->done && (st->head == NULL || st->audio_ready < AUDIO_THRESHOLD))
while (!st->done && (st->head == NULL))
pthread_cond_wait(&st->cond, &st->mutex);

// exit once done and no more audio buffers
Expand All @@ -819,7 +817,7 @@ int main(int argc, char *argv[])
st->tail = NULL;
pthread_mutex_unlock(&st->mutex);

ao_play(st->dev, b->data, sizeof(b->data));
ao_play(st->dev, b->data, b->count * sizeof(int16_t));

pthread_mutex_lock(&st->mutex);
// add to free list
Expand Down
Loading

0 comments on commit 7df2aa8

Please sign in to comment.