Example #1
0
static bool aucodec_equal(const struct aucodec *a, const struct aucodec *b)
{
	if (!a || !b)
		return false;

	return get_srate(a) == get_srate(b) && a->ch == b->ch;
}
Example #2
0
static int start_player(struct aurx *rx, struct audio *a)
{
	const struct aucodec *ac = rx->ac;
	uint32_t srate_dsp = get_srate(ac);
	int err;

	if (!ac)
		return 0;

	/* Optional resampler, if configured */
	if (a->cfg.srate_play && a->cfg.srate_play != srate_dsp
	    && !rx->resamp) {

		srate_dsp = a->cfg.srate_play;

		(void)re_printf("enable auplay resampler: %u --> %u Hz\n",
				get_srate(ac), srate_dsp);

		rx->sampv_rs = mem_zalloc(AUDIO_SAMPSZ * 2, NULL);
		if (!rx->sampv_rs)
			return ENOMEM;

		err = auresamp_alloc(&rx->resamp, AUDIO_SAMPSZ,
				     get_srate(ac), ac->ch,
				     srate_dsp, ac->ch);
		if (err)
			return err;
	}

	/* Start Audio Player */
	if (!rx->auplay && auplay_find(NULL)) {

		struct auplay_prm prm;

		prm.fmt        = AUFMT_S16LE;
		prm.srate      = srate_dsp;
		prm.ch         = ac->ch;
		prm.frame_size = calc_nsamp(prm.srate, prm.ch, rx->ptime);

		if (!rx->ab) {
			const size_t psize = 2 * prm.frame_size;

			err = aubuf_alloc(&rx->ab, psize * 1, psize * 8);
			if (err)
				return err;
		}

		err = auplay_alloc(&rx->auplay, a->cfg.play_mod,
				   &prm, a->cfg.play_dev,
				   auplay_write_handler, rx);
		if (err) {
			DEBUG_WARNING("start_player failed (%s.%s): %m\n",
				      a->cfg.play_mod,
				      a->cfg.play_dev, err);
			return err;
		}
	}

	return 0;
}
Example #3
0
/*
 * Reference:
 *
 * https://www.avm.de/de/Extern/files/x-rtp/xrtpv32.pdf
 */
int audio_print_rtpstat(struct re_printf *pf, const struct audio *a)
{
	const struct stream *s;
	const struct rtcp_stats *rtcp;
	int srate_tx = 8000;
	int srate_rx = 8000;
	int err;

	if (!a)
		return 1;

	s = a->strm;
	rtcp = &s->rtcp_stats;

	if (!rtcp->tx.sent)
		return 1;

	if (a->tx.ac)
		srate_tx = get_srate(a->tx.ac);
	if (a->rx.ac)
		srate_rx = get_srate(a->rx.ac);

	err = re_hprintf(pf,
			 "EX=BareSip;"   /* Reporter Identifier	             */
			 "CS=%d;"        /* Call Setup in milliseconds       */
			 "CD=%d;"        /* Call Duration in seconds	     */
			 "PR=%u;PS=%u;"  /* Packets RX, TX                   */
			 "PL=%d,%d;"     /* Packets Lost RX, TX              */
			 "PD=%d,%d;"     /* Packets Discarded, RX, TX        */
			 "JI=%.1f,%.1f;" /* Jitter RX, TX in timestamp units */
			 "IP=%J,%J"      /* Local, Remote IPs                */
			 ,
			 call_setup_duration(s->call) * 1000,
			 call_duration(s->call),

			 s->metric_rx.n_packets,
			 s->metric_tx.n_packets,

			 rtcp->rx.lost, rtcp->tx.lost,

			 s->metric_rx.n_err, s->metric_tx.n_err,

			 /* timestamp units (ie: 8 ts units = 1 ms @ 8KHZ) */
			 1.0 * rtcp->rx.jit/1000 * (srate_rx/1000),
			 1.0 * rtcp->tx.jit/1000 * (srate_tx/1000),

			 sdp_media_laddr(s->sdp),
			 sdp_media_raddr(s->sdp)
			 );

	if (a->tx.ac) {
		err |= re_hprintf(pf, ";EN=%s/%d", a->tx.ac->name, srate_tx );
	}
	if (a->rx.ac) {
		err |= re_hprintf(pf, ";DE=%s/%d", a->rx.ac->name, srate_rx );
	}

	return err;
}
Example #4
0
static void aufilt_param_set(struct aufilt_prm *prm, const struct aucodec *ac, uint32_t ptime)
{
	if (!ac) {
		DEBUG_WARNING("aufilt param: NO CODEC!\n");
		memset(prm, 0, sizeof(*prm));
		return;
	}

	prm->srate      = get_srate(ac);
	prm->ch         = ac->ch;
	prm->frame_size = calc_nsamp(get_srate(ac), ac->ch, ptime);
}
Example #5
0
int audio_encoder_set(struct audio *a, const struct aucodec *ac,
		      int pt_tx, const char *params)
{
	struct autx *tx;
	int err = 0;
	bool reset;

	if (!a || !ac)
		return EINVAL;

	tx = &a->tx;

	reset = !aucodec_equal(ac, tx->ac);

	if (ac != tx->ac) {
		(void)re_fprintf(stderr, "Set audio encoder: %s %uHz %dch\n",
				 ac->name, get_srate(ac), ac->ch);

		/* Audio source must be stopped first */
		if (reset) {
			tx->ausrc = mem_deref(tx->ausrc);
		}

		tx->is_g722 = (0 == str_casecmp(ac->name, "G722"));
		tx->enc = mem_deref(tx->enc);
		tx->ac = ac;
	}

	if (ac->encupdh) {
		struct auenc_param prm;

		prm.ptime = tx->ptime;

		err = ac->encupdh(&tx->enc, ac, &prm, params);
		if (err) {
			DEBUG_WARNING("alloc encoder: %m\n", err);
			return err;
		}
	}

	stream_set_srate(a->strm, get_srate(ac), get_srate(ac));
	stream_update_encoder(a->strm, pt_tx);

	if (!tx->ausrc) {
		err |= audio_start(a);
	}

	return err;
}
Example #6
0
int Spectacle::init(int fftlen, int windowlen, int overlap, float srate,
	float maxdeltime)
{
	if (SpectacleBase::init(fftlen, windowlen, overlap, srate) != 0)
		return -1;

	// Compute maximum delay lag and create delay lines for FFT real and
	// imaginary values.  Remember that these delays function at the decimation
	// rate, not at the audio rate, so the memory footprint is not as large
	// as you would expect -- about 44100 samples per second at fftlen=1024,
	// overlap=2 and SR=44100.

	_maxdeltime = maxdeltime;
	_maxdelsamps = long(maxdeltime * get_srate() / float(_decimation) + 0.5);

	for (int i = 0; i < _half_fftlen; i++) {
		Odelay *delay = new Odelay(_maxdelsamps);
		if (delay == NULL)
			goto bad_alloc;
		_real_delay[i] = delay;
		delay = new Odelay(_maxdelsamps);
		if (delay == NULL)
			goto bad_alloc;
		_imag_delay[i] = delay;
	}

	_delay_bin_groups = new int [_half_fftlen];

	set_delay_freqrange(0.0f, 0.0f);

	return 0;
bad_alloc:
	error("%s: Not enough memory for delay lines.", instname());
	return -1;
}
Example #7
0
static int aucodec_print(struct re_printf *pf, const struct aucodec *ac)
{
	if (!ac)
		return 0;

	return re_hprintf(pf, "%s %uHz/%dch", ac->name, get_srate(ac), ac->ch);
}
Example #8
0
int audio_decoder_set(struct audio *a, const struct aucodec *ac,
		      int pt_rx, const char *params)
{
	struct aurx *rx;
	bool reset = false;
	int err = 0;

	if (!a || !ac)
		return EINVAL;

	rx = &a->rx;

	reset = !aucodec_equal(ac, rx->ac);

	if (ac != rx->ac) {

		(void)re_fprintf(stderr, "Set audio decoder: %s %uHz %dch\n",
				 ac->name, get_srate(ac), ac->ch);

		rx->pt = pt_rx;
		rx->ac = ac;
		rx->dec = mem_deref(rx->dec);
	}

	if (ac->decupdh) {
		err = ac->decupdh(&rx->dec, ac, params);
		if (err) {
			DEBUG_WARNING("alloc decoder: %m\n", err);
			return err;
		}
	}

	stream_set_srate(a->strm, get_srate(ac), get_srate(ac));

	if (reset) {

		rx->auplay = mem_deref(rx->auplay);

		/* Reset audio filter chain */
		list_flush(&a->filtl);

		err |= audio_start(a);
	}

	return err;
}
Example #9
0
static inline uint32_t get_framesize(const struct aucodec *ac,
				     uint32_t ptime)
{
	if (!ac)
		return 0;

	return calc_nsamp(get_srate(ac), ac->ch, ptime);
}
Example #10
0
// ----------------------------------------------------------- set_maxdeltime --
// Reset delay lines to accommodate a maximum delay of <time> seconds at the
// current sampling rate.  Assumes that caller constrains all delay times to
// fit this new maximum.
void Spectacle::set_maxdeltime(float time)
{
	_maxdeltime = time;
	_maxdelsamps = long(time * get_srate() / float(_decimation) + 0.5);
	for (int i = 0; i < _half_fftlen; i++) {
		_real_delay[i]->resize(_maxdelsamps);
		_imag_delay[i]->resize(_maxdelsamps);
	}
}
Example #11
0
static int add_audio_codec(struct audio *a, struct sdp_media *m,
			   struct aucodec *ac)
{
	if (!in_range(&a->cfg.srate, get_srate(ac))) {
		debug("audio: skip %uHz codec (audio range %uHz - %uHz)\n",
		      get_srate(ac), a->cfg.srate.min, a->cfg.srate.max);
		return 0;
	}

	if (!in_range(&a->cfg.channels, ac->ch)) {
		debug("audio: skip codec with %uch (audio range %uch-%uch)\n",
		      ac->ch, a->cfg.channels.min, a->cfg.channels.max);
		return 0;
	}

	return sdp_format_add(NULL, m, false, ac->pt, ac->name, ac->srate,
			      ac->ch, ac->fmtp_ench, ac->fmtp_cmph, ac, false,
			      "%s", ac->fmtp);
}
Example #12
0
static void aufilt_param_set(struct aufilt_prm *prm,
			     const struct aucodec *ac, uint32_t ptime)
{
	if (!ac) {
		memset(prm, 0, sizeof(*prm));
		return;
	}

	prm->srate      = get_srate(ac);
	prm->ch         = ac->ch;
	prm->ptime      = ptime;
}
Example #13
0
static int ml26124_hw_params(struct snd_pcm_substream *substream,
			    struct snd_pcm_hw_params *hw_params,
			    struct snd_soc_dai *dai)
{
	struct snd_soc_codec *codec = dai->codec;
	struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
	int i = get_coeff(priv->mclk, params_rate(hw_params));
	int srate;

	if (i < 0)
		return i;
	priv->substream = substream;
	priv->rate = params_rate(hw_params);

	if (priv->clk_in) {
		switch (priv->mclk / params_rate(hw_params)) {
		case 256:
			snd_soc_update_bits(codec, ML26124_CLK_CTL,
					    BIT(0) | BIT(1), 1);
			break;
		case 512:
			snd_soc_update_bits(codec, ML26124_CLK_CTL,
					    BIT(0) | BIT(1), 2);
			break;
		case 1024:
			snd_soc_update_bits(codec, ML26124_CLK_CTL,
					    BIT(0) | BIT(1), 3);
			break;
		default:
			dev_err(codec->dev, "Unsupported MCLKI\n");
			break;
		}
	} else {
		snd_soc_update_bits(codec, ML26124_CLK_CTL,
				    BIT(0) | BIT(1), 0);
	}

	srate = get_srate(params_rate(hw_params));
	if (srate < 0)
		return srate;

	snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf, srate);
	snd_soc_update_bits(codec, ML26124_PLLNL, 0xff, coeff_div[i].pllnl);
	snd_soc_update_bits(codec, ML26124_PLLNH, 0x1, coeff_div[i].pllnh);
	snd_soc_update_bits(codec, ML26124_PLLML, 0xff, coeff_div[i].pllml);
	snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f, coeff_div[i].pllmh);
	snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f, coeff_div[i].plldiv);

	return 0;
}
Example #14
0
// ---------------------------------------------------------- modify_analysis --
void Spectacle::modify_analysis(bool reading_input)
{
	DPRINT("modify_analysis: .....................");

#ifdef PRINT_DELTIMES
	static float *prevdeltimes = NULL;
	if (prevdeltimes == NULL) {
		prevdeltimes = new float [_delay_table_size];
		post("\nmodify_analysis: delay times --------------------------");
		for (int i = 0; i < _delay_table_size; i++) {
			prevdeltimes[i] = _deltimetable[i];
			post("[%d] %f", i, _deltimetable[i]);
		}
 #ifdef PRINT_DELTIME_CHANGES
		post("\nmodify_analysis: delay time changes -------------------");
 #endif
	}
#endif

	const bool posteq = get_posteq();
	float eq;

	// NB: check EQ table size, rather than table pointer, to determine whether
	// we should use an EQ constant. Otherwise, there's a danger we could read
	// a null EQ table pointer, if set_eqtable called by non-perf thread.
	if (_control_table_size == 0)
		eq = _ampdb(_eqconst);

	for (int i = 0; i < _half_fftlen; i++) {
		int index = i << 1;

		if (_control_table_size > 0) {
			// EQ uses base class bin groups array.
			const int bg = _bin_groups[i];
			eq = _ampdb(_eqtable[bg]);
		}

		float real, imag;
		if (reading_input) {
		   if (posteq) {
				real = _fft_buf[index];
				imag = _fft_buf[index + 1];
			}
			else {
				real = _fft_buf[index] * eq;
				imag = _fft_buf[index + 1] * eq;
			}
		}
		else {
			real = 0.0f;
			imag = 0.0f;
		}

		const int bg = _delay_bin_groups[i];

		// NB: caller must assure that deltime is in range
		const float deltime = _deltimetable ? _deltimetable[bg] : _deltimeconst;

#ifdef PRINT_DELTIME_CHANGES
		if (deltime != prevdeltimes[bg]) {
			post("[%d] %f", bg, deltime);
			prevdeltimes[bg] = deltime;
		}
#endif

		if (deltime == 0.0f) {
		   if (posteq) {
				_fft_buf[index] = real * eq;
				_fft_buf[index + 1] = imag * eq;
			}
			else {
				_fft_buf[index] = real;
				_fft_buf[index + 1] = imag;
			}
		}
		else {
			const long delsamps = long((deltime * get_srate()) + 0.5)
			                                                     / _decimation;
			const float newreal = _real_delay[i]->getsamp(delsamps);
			const float newimag = _imag_delay[i]->getsamp(delsamps);
			const float feedback = _feedbacktable ? _feedbacktable[bg]
			                                      : _feedbackconst;
			if (feedback != 0.0) {
#ifdef ANTI_DENORM
				float fbsig = (newreal * feedback) + _antidenorm_offset;
				_real_delay[i]->putsamp(real + fbsig);
				fbsig = (newimag * feedback) + _antidenorm_offset;
				_imag_delay[i]->putsamp(imag + fbsig);
#else
				_real_delay[i]->putsamp(real + (newreal * feedback));
				_imag_delay[i]->putsamp(imag + (newimag * feedback));
#endif
			}
			else {
				_real_delay[i]->putsamp(real);
				_imag_delay[i]->putsamp(imag);
			}
		   if (posteq) {
				_fft_buf[index] = newreal * eq;
				_fft_buf[index + 1] = newimag * eq;
			}
			else {
				_fft_buf[index] = newreal;
				_fft_buf[index + 1] = newimag;
			}
		}
	}

	_fft_buf[1] = 0.0f;	// clear Nyquist real value

#ifdef ANTI_DENORM
	_antidenorm_offset = -_antidenorm_offset;
#endif
}
Example #15
0
static int start_source(struct autx *tx, struct audio *a)
{
	const struct aucodec *ac = tx->ac;
	uint32_t srate_dsp = get_srate(tx->ac);
	int err;

	if (!ac)
		return 0;

	/* Optional resampler, if configured */
	if (a->cfg.srate_src && a->cfg.srate_src != srate_dsp &&
	    !tx->resamp) {

		srate_dsp = a->cfg.srate_src;

		(void)re_printf("enable ausrc resampler: %u --> %u Hz\n",
				get_srate(ac), srate_dsp);

		tx->sampv_rs = mem_zalloc(AUDIO_SAMPSZ * 2, NULL);
		if (!tx->sampv_rs)
			return ENOMEM;

		err = auresamp_alloc(&tx->resamp, AUDIO_SAMPSZ,
				     srate_dsp, ac->ch,
				     get_srate(ac), ac->ch);
		if (err)
			return err;
	}

	/* Start Audio Source */
	if (!tx->ausrc && ausrc_find(NULL)) {

		struct ausrc_prm prm;

		prm.fmt        = AUFMT_S16LE;
		prm.srate      = srate_dsp;
		prm.ch         = ac->ch;
		prm.frame_size = calc_nsamp(prm.srate, prm.ch, tx->ptime);

		tx->psize = 2 * prm.frame_size;

		if (!tx->ab) {
			err = aubuf_alloc(&tx->ab, tx->psize * 2,
					  tx->psize * 30);
			if (err)
				return err;
		}

		err = ausrc_alloc(&tx->ausrc, NULL, a->cfg.src_mod,
				  &prm, a->cfg.src_dev,
				  ausrc_read_handler, ausrc_error_handler, a);
		if (err) {
			DEBUG_WARNING("start_source failed: %m\n", 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;
}
Example #16
0
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;
}
Example #17
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;
}