static int start_player(struct aurx *rx, struct audio *a) { const struct aucodec *ac = rx->ac; uint32_t srate_dsp = get_srate(ac); uint32_t channels_dsp; bool resamp = false; int err; if (!ac) return 0; channels_dsp = ac->ch; if (a->cfg.srate_play && a->cfg.srate_play != srate_dsp) { resamp = true; srate_dsp = a->cfg.srate_play; } if (a->cfg.channels_play && a->cfg.channels_play != channels_dsp) { resamp = true; channels_dsp = a->cfg.channels_play; } /* Optional resampler, if configured */ if (resamp && !rx->sampv_rs) { info("audio: enable auplay resampler:" " %uHz/%uch --> %uHz/%uch\n", get_srate(ac), ac->ch, srate_dsp, channels_dsp); rx->sampv_rs = mem_zalloc(AUDIO_SAMPSZ * 2, NULL); if (!rx->sampv_rs) return ENOMEM; err = auresamp_setup(&rx->resamp, get_srate(ac), ac->ch, srate_dsp, channels_dsp); if (err) { warning("audio: could not setup auplay resampler" " (%m)\n", err); return err; } } /* Start Audio Player */ if (!rx->auplay && auplay_find(NULL)) { struct auplay_prm prm; prm.srate = srate_dsp; prm.ch = channels_dsp; prm.ptime = rx->ptime; if (!rx->aubuf) { size_t psize; psize = 2 * calc_nsamp(prm.srate, prm.ch, prm.ptime); err = aubuf_alloc(&rx->aubuf, psize * 1, psize * 8); if (err) return err; } err = auplay_alloc(&rx->auplay, a->cfg.play_mod, &prm, rx->device, auplay_write_handler, rx); if (err) { warning("audio: start_player failed (%s.%s): %m\n", a->cfg.play_mod, rx->device, err); return err; } } return 0; }
static int start_source(struct autx *tx, struct audio *a) { const struct aucodec *ac = tx->ac; uint32_t srate_dsp = get_srate(ac); uint32_t channels_dsp; bool resamp = false; int err; if (!ac) return 0; channels_dsp = ac->ch; if (a->cfg.srate_src && a->cfg.srate_src != srate_dsp) { resamp = true; srate_dsp = a->cfg.srate_src; } if (a->cfg.channels_src && a->cfg.channels_src != channels_dsp) { resamp = true; channels_dsp = a->cfg.channels_src; } /* Optional resampler, if configured */ if (resamp && !tx->sampv_rs) { info("audio: enable ausrc resampler:" " %uHz/%uch <-- %uHz/%uch\n", get_srate(ac), ac->ch, srate_dsp, channels_dsp); tx->sampv_rs = mem_zalloc(AUDIO_SAMPSZ * 2, NULL); if (!tx->sampv_rs) return ENOMEM; err = auresamp_setup(&tx->resamp, srate_dsp, channels_dsp, get_srate(ac), ac->ch); if (err) { warning("audio: could not setup ausrc resampler" " (%m)\n", err); return err; } } /* Start Audio Source */ if (!tx->ausrc && ausrc_find(NULL)) { struct ausrc_prm prm; prm.srate = srate_dsp; prm.ch = channels_dsp; prm.ptime = tx->ptime; tx->psize = 2 * calc_nsamp(prm.srate, prm.ch, prm.ptime); if (!tx->aubuf) { err = aubuf_alloc(&tx->aubuf, tx->psize * 2, tx->psize * 30); if (err) return err; } err = ausrc_alloc(&tx->ausrc, NULL, a->cfg.src_mod, &prm, tx->device, ausrc_read_handler, ausrc_error_handler, a); if (err) { warning("audio: start_source failed (%s.%s): %m\n", a->cfg.src_mod, tx->device, err); return err; } switch (a->cfg.txmode) { #ifdef HAVE_PTHREAD case AUDIO_MODE_THREAD: case AUDIO_MODE_THREAD_REALTIME: if (!tx->u.thr.run) { tx->u.thr.run = true; err = pthread_create(&tx->u.thr.tid, NULL, tx_thread, a); if (err) { tx->u.thr.tid = false; return err; } } break; #endif case AUDIO_MODE_TMR: tmr_start(&tx->u.tmr, 1, timeout_tx, a); break; default: break; } } return 0; }
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; }