/* * @note This function has REAL-TIME properties */ static void poll_aubuf_tx(struct audio *a) { struct autx *tx = &a->tx; int16_t *sampv = tx->sampv; size_t sampc; struct le *le; int err = 0; sampc = tx->psize / 2; /* timed read from audio-buffer */ aubuf_read_samp(tx->aubuf, tx->sampv, sampc); /* optional resampler */ if (tx->resamp.resample) { size_t sampc_rs = AUDIO_SAMPSZ; err = auresamp(&tx->resamp, tx->sampv_rs, &sampc_rs, tx->sampv, sampc); if (err) return; sampv = tx->sampv_rs; sampc = sampc_rs; } /* Process exactly one audio-frame in list order */ for (le = tx->filtl.head; le; le = le->next) { struct aufilt_enc_st *st = le->data; if (st->af && st->af->ench) err |= st->af->ench(st, sampv, &sampc); } if (err) { warning("audio: aufilter encode: %m\n", err); } /* Encode and send */ encode_rtp_send(a, tx, sampv, sampc); }
static int aurx_stream_decode(struct aurx *rx, struct mbuf *mb) { size_t sampc = AUDIO_SAMPSZ; int16_t *sampv; struct le *le; int err = 0; /* No decoder set */ if (!rx->ac) return 0; if (mbuf_get_left(mb)) { err = rx->ac->dech(rx->dec, rx->sampv, &sampc, mbuf_buf(mb), mbuf_get_left(mb)); } else if (rx->ac->plch) { err = rx->ac->plch(rx->dec, rx->sampv, &sampc); } else { /* no PLC in the codec, might be done in filters below */ sampc = 0; } if (err) { warning("audio: %s codec decode %u bytes: %m\n", rx->ac->name, mbuf_get_left(mb), err); goto out; } /* Process exactly one audio-frame in reverse list order */ for (le = rx->filtl.tail; le; le = le->prev) { struct aufilt_dec_st *st = le->data; if (st->af && st->af->dech) err |= st->af->dech(st, rx->sampv, &sampc); } if (!rx->aubuf) goto out; sampv = rx->sampv; /* optional resampler */ if (rx->resamp.resample) { size_t sampc_rs = AUDIO_SAMPSZ; err = auresamp(&rx->resamp, rx->sampv_rs, &sampc_rs, rx->sampv, sampc); if (err) return err; sampv = rx->sampv_rs; sampc = sampc_rs; } err = aubuf_write_samp(rx->aubuf, sampv, sampc); if (err) goto out; out: return err; }
static void *device_thread(void *arg) { uint64_t now, ts = tmr_jiffies(); struct device *dev = arg; struct auresamp rs; int16_t *sampv_in, *sampv_out; size_t sampc_in; size_t sampc_out; int err; sampc_in = dev->auplay->prm.srate * dev->auplay->prm.ch * PTIME/1000; sampc_out = dev->ausrc->prm.srate * dev->ausrc->prm.ch * PTIME/1000; auresamp_init(&rs); sampv_in = mem_alloc(2 * sampc_in, NULL); sampv_out = mem_alloc(2 * sampc_out, NULL); if (!sampv_in || !sampv_out) goto out; err = auresamp_setup(&rs, dev->auplay->prm.srate, dev->auplay->prm.ch, dev->ausrc->prm.srate, dev->ausrc->prm.ch); if (err) goto out; while (dev->run) { (void)sys_msleep(4); if (!dev->run) break; now = tmr_jiffies(); if (ts > now) continue; if (dev->auplay && dev->auplay->wh) { dev->auplay->wh(sampv_in, sampc_in, dev->auplay->arg); } err = auresamp(&rs, sampv_out, &sampc_out, sampv_in, sampc_in); if (err) { warning("aubridge: auresamp error: %m\n", err); } if (dev->ausrc && dev->ausrc->rh) { dev->ausrc->rh(sampv_out, sampc_out, dev->ausrc->arg); } ts += PTIME; } out: mem_deref(sampv_in); mem_deref(sampv_out); return NULL; }