static int vu_decode_update(struct aufilt_dec_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au) { struct vumeter_dec *st; (void)ctx; (void)prm; (void)au; if (!stp || !af) return EINVAL; if (*stp) return 0; if (prm->fmt != AUFMT_S16LE) { warning("vumeter: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } st = mem_zalloc(sizeof(*st), vu_dec_destructor); if (!st) return ENOMEM; gdk_threads_enter(); call_window_got_vu_dec(st); gdk_threads_leave(); *stp = (struct aufilt_dec_st *)st; return 0; }
static int read_stream_open(struct ausrc_st *st, const struct ausrc_prm *prm, unsigned int dev) { WAVEFORMATEX wfmt; MMRESULT res; uint32_t sampc; unsigned format; int i, err = 0; st->sampsz = aufmt_sample_size(prm->fmt); format = winwave_get_format(prm->fmt); if (format == WAVE_FORMAT_UNKNOWN) { warning("winwave: source: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } /* Open an audio INPUT stream. */ st->wavein = NULL; st->pos = 0; st->rdy = false; sampc = prm->srate * prm->ch * prm->ptime / 1000; for (i = 0; i < READ_BUFFERS; i++) { memset(&st->bufs[i].wh, 0, sizeof(WAVEHDR)); st->bufs[i].mb = mbuf_alloc(st->sampsz * sampc); if (!st->bufs[i].mb) return ENOMEM; } wfmt.wFormatTag = format; wfmt.nChannels = prm->ch; wfmt.nSamplesPerSec = prm->srate; wfmt.wBitsPerSample = (WORD)(st->sampsz * 8); wfmt.nBlockAlign = (prm->ch * wfmt.wBitsPerSample) / 8; wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign; wfmt.cbSize = 0; res = waveInOpen(&st->wavein, dev, &wfmt, (DWORD_PTR) waveInCallback, (DWORD_PTR) st, CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT); if (res != MMSYSERR_NOERROR) { warning("winwave: waveInOpen: failed res=%d\n", res); return EINVAL; } /* Prepare enough IN buffers to suite at least 50ms of data */ for (i = 0; i < READ_BUFFERS; i++) err |= add_wave_in(st); waveInStart(st->wavein); return err; }
static int print_summary(struct re_printf *pf, const struct audio_loop *al) { const double scale = al->srate * al->ch; int err; err = re_hprintf(pf, "~~~~~ Audioloop summary: ~~~~~\n"); err |= re_hprintf(pf, "%u Hz %uch %s\n\n", al->srate, al->ch, aufmt_name(al->fmt)); /* Source */ if (al->ausrc) { struct ausrc *as = ausrc_get(al->ausrc); err |= re_hprintf(pf, "* Source\n" " module %s\n" " samples %llu\n" " duration %.3f sec\n" "\n" , as->name, al->n_read, (double)al->n_read / scale); } /* Player */ if (al->auplay) { struct auplay *ap = auplay_get(al->auplay); err |= re_hprintf(pf, "* Player\n" " module %s\n" " samples %llu\n" " duration %.3f sec\n" "\n" , ap->name, al->n_write, (double)al->n_write / scale); } return err; }
static void print_stats(struct audio_loop *al) { double rw_ratio = 0.0; double delay = (double)al->n_read - (double)al->n_write; const double scale = al->srate * al->ch; if (al->n_write) rw_ratio = 1.0 * (double)al->n_read / (double)al->n_write; (void)re_fprintf(stdout, "\r%uHz %dch %s " " n_read=%.3f n_write=%.3f rw_delay=%.3f [sec]" " rw_ratio=%f" , al->srate, al->ch, aufmt_name(al->fmt), (double)al->n_read / scale, (double)al->n_write / scale, delay / scale, rw_ratio); (void)re_fprintf(stdout, " \r"); fflush(stdout); }
static SNDFILE *openfile(const struct aufilt_prm *prm, bool enc) { char filename[128]; SF_INFO sfinfo; time_t tnow = time(0); struct tm *tm = localtime(&tnow); SNDFILE *sf; int format; (void)re_snprintf(filename, sizeof(filename), "%s/dump-%H-%s.wav", file_path, timestamp_print, tm, enc ? "enc" : "dec"); format = get_format(prm->fmt); if (!format) { warning("sndfile: sample format not supported (%s)\n", aufmt_name(prm->fmt)); return NULL; } sfinfo.samplerate = prm->srate; sfinfo.channels = prm->ch; sfinfo.format = SF_FORMAT_WAV | format; sf = sf_open(filename, SFM_WRITE, &sfinfo); if (!sf) { warning("sndfile: could not open: %s\n", filename); puts(sf_strerror(NULL)); return NULL; } info("sndfile: dumping %s audio to %s\n", enc ? "encode" : "decode", filename); return sf; }
int alsa_src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; snd_pcm_format_t pcmfmt; int num_frames; int err; (void)ctx; (void)errh; if (!stp || !as || !prm || !rh) return EINVAL; if (!str_isset(device)) device = alsa_dev; st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; err = str_dup(&st->device, device); if (err) goto out; st->prm = *prm; st->as = as; st->rh = rh; st->arg = arg; st->aufmt = alsa_sample_format; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; num_frames = st->prm.srate * st->prm.ptime / 1000; st->sampv = mem_alloc(2 * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } if (st->aufmt != AUFMT_S16LE) { size_t sz = aufmt_sample_size(st->aufmt) * st->sampc; st->xsampv = mem_alloc(sz, NULL); if (!st->xsampv) { err = ENOMEM; goto out; } } err = snd_pcm_open(&st->read, st->device, SND_PCM_STREAM_CAPTURE, 0); if (err < 0) { warning("alsa: could not open ausrc device '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } pcmfmt = aufmt_to_alsaformat(st->aufmt); if (pcmfmt == SND_PCM_FORMAT_UNKNOWN) { warning("alsa: unknown sample format '%s'\n", aufmt_name(st->aufmt)); err = EINVAL; goto out; } err = alsa_reset(st->read, st->prm.srate, st->prm.ch, num_frames, pcmfmt); if (err) { warning("alsa: could not reset source '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } debug("alsa: recording started (%s)\n", st->device); out: if (err) mem_deref(st); else *stp = st; return err; }
int alsa_play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; snd_pcm_format_t pcmfmt; int num_frames; int err; if (!stp || !ap || !prm || !wh) return EINVAL; if (!str_isset(device)) device = alsa_dev; st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; err = str_dup(&st->device, device); if (err) goto out; st->prm = *prm; st->ap = ap; st->wh = wh; st->arg = arg; st->aufmt = alsa_sample_format; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; num_frames = st->prm.srate * st->prm.ptime / 1000; st->sampv = mem_alloc(2 * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } if (st->aufmt != AUFMT_S16LE) { size_t sz = aufmt_sample_size(st->aufmt) * st->sampc; st->xsampv = mem_alloc(sz, NULL); if (!st->xsampv) { err = ENOMEM; goto out; } } err = snd_pcm_open(&st->write, st->device, SND_PCM_STREAM_PLAYBACK, 0); if (err < 0) { warning("alsa: could not open auplay device '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } pcmfmt = aufmt_to_alsaformat(st->aufmt); if (pcmfmt == SND_PCM_FORMAT_UNKNOWN) { warning("alsa: unknown sample format '%s'\n", aufmt_name(st->aufmt)); err = EINVAL; goto out; } err = alsa_reset(st->write, st->prm.srate, st->prm.ch, num_frames, pcmfmt); if (err) { warning("alsa: could not reset player '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } st->run = true; err = pthread_create(&st->thread, NULL, write_thread, st); if (err) { st->run = false; goto out; } debug("alsa: playback started (%s)\n", st->device); out: if (err) mem_deref(st); else *stp = st; return err; }
static int auloop_reset(struct audio_loop *al, uint32_t srate, uint32_t ch) { struct auplay_prm auplay_prm; struct ausrc_prm ausrc_prm; const struct config *cfg = conf_config(); int err; if (!cfg) return ENOENT; if (cfg->audio.src_fmt != cfg->audio.play_fmt) { warning("auloop: ausrc_format and auplay_format" " must be the same\n"); return EINVAL; } al->fmt = cfg->audio.src_fmt; /* audio player/source must be stopped first */ al->auplay = mem_deref(al->auplay); al->ausrc = mem_deref(al->ausrc); al->aubuf = mem_deref(al->aubuf); al->srate = srate; al->ch = ch; info("Audio-loop: %uHz, %dch, %s\n", al->srate, al->ch, aufmt_name(al->fmt)); err = aubuf_alloc(&al->aubuf, 320, 0); if (err) return err; auplay_prm.srate = al->srate; auplay_prm.ch = al->ch; auplay_prm.ptime = PTIME; auplay_prm.fmt = al->fmt; err = auplay_alloc(&al->auplay, baresip_auplayl(), cfg->audio.play_mod, &auplay_prm, cfg->audio.play_dev, write_handler, al); if (err) { warning("auloop: auplay %s,%s failed: %m\n", cfg->audio.play_mod, cfg->audio.play_dev, err); return err; } ausrc_prm.srate = al->srate; ausrc_prm.ch = al->ch; ausrc_prm.ptime = PTIME; ausrc_prm.fmt = al->fmt; err = ausrc_alloc(&al->ausrc, baresip_ausrcl(), NULL, cfg->audio.src_mod, &ausrc_prm, cfg->audio.src_dev, read_handler, error_handler, al); if (err) { warning("auloop: ausrc %s,%s failed: %m\n", cfg->audio.src_mod, cfg->audio.src_dev, err); return err; } return err; }
static int gst_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; int err; (void)ctx; if (!device) device = gst_uri; if (!prm) return EINVAL; if (prm->fmt != AUFMT_S16LE) { warning("gst: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } st = mem_zalloc(sizeof(*st), gst_destructor); if (!st) return ENOMEM; st->as = as; st->rh = rh; st->errh = errh; st->arg = arg; err = str_dup(&st->uri, device); if (err) goto out; st->prm = *prm; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->psize = 2 * st->sampc; err = aubuf_alloc(&st->aubuf, st->psize, 0); if (err) goto out; err = gst_setup(st); if (err) goto out; st->run = true; err = pthread_create(&st->tid, NULL, thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; }
static int alloc_handler(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *dev, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; struct aufile_prm fprm; int err; (void)ctx; if (!stp || !as || !prm || !rh) return EINVAL; if (prm->fmt != AUFMT_S16LE) { warning("aufile: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } info("aufile: loading input file '%s'\n", dev); st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->as = as; st->rh = rh; st->errh = errh; st->arg = arg; err = aufile_open(&st->aufile, &fprm, dev, AUFILE_READ); if (err) { warning("aufile: failed to open file '%s' (%m)\n", dev, err); goto out; } info("aufile: %s: %u Hz, %d channels\n", dev, fprm.srate, fprm.channels); if (fprm.srate != prm->srate) { warning("aufile: input file (%s) must have sample-rate" " %u Hz\n", dev, prm->srate); err = ENODEV; goto out; } if (fprm.channels != prm->ch) { warning("aufile: input file (%s) must have channels = %d\n", dev, prm->ch); err = ENODEV; goto out; } if (fprm.fmt != AUFMT_S16LE) { warning("aufile: input file must have format S16LE\n"); err = ENODEV; goto out; } st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->ptime = prm->ptime; info("aufile: audio ptime=%u sampc=%zu aubuf=[%u:%u]\n", st->ptime, st->sampc, prm->srate * prm->ch * 2, prm->srate * prm->ch * 40); /* 1 - inf seconds of audio */ err = aubuf_alloc(&st->aubuf, prm->srate * prm->ch * 2, 0); if (err) goto out; err = read_file(st); if (err) goto out; tmr_start(&st->tmr, 1000, timeout, st); st->run = true; err = pthread_create(&st->thread, NULL, play_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; }