コード例 #1
0
ファイル: pcm_plug.c プロジェクト: takaswie/alsa-lib
static snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, const snd_pcm_format_mask_t *format_mask)
{
	int w, w1, u, e;
	snd_pcm_format_t f;
	snd_pcm_format_mask_t lin = { SND_PCM_FMTBIT_LINEAR };
	snd_pcm_format_mask_t fl = {
#ifdef BUILD_PCM_PLUGIN_LFLOAT
		SND_PCM_FMTBIT_FLOAT
#else
		{ 0 }
#endif
	};
	if (snd_pcm_format_mask_test(format_mask, format))
		return format;
	if (!snd_pcm_format_mask_test(&lin, format) &&
	    !snd_pcm_format_mask_test(&fl, format)) {
		unsigned int i;
		switch (format) {
#ifdef BUILD_PCM_PLUGIN_MULAW
		case SND_PCM_FORMAT_MU_LAW:
#endif
#ifdef BUILD_PCM_PLUGIN_ALAW
		case SND_PCM_FORMAT_A_LAW:
#endif
#ifdef BUILD_PCM_PLUGIN_ADPCM
		case SND_PCM_FORMAT_IMA_ADPCM:
#endif
			for (i = 0; i < sizeof(linear_preferred_formats) / sizeof(linear_preferred_formats[0]); ++i) {
				snd_pcm_format_t f = linear_preferred_formats[i];
				if (snd_pcm_format_mask_test(format_mask, f))
					return f;
			}
			/* Fall through */
		default:
			return SND_PCM_FORMAT_UNKNOWN;
		}

	}
	snd_mask_intersect(&lin, format_mask);
	snd_mask_intersect(&fl, format_mask);
	if (snd_mask_empty(&lin) && snd_mask_empty(&fl)) {
#ifdef BUILD_PCM_NONLINEAR
		unsigned int i;
		for (i = 0; i < sizeof(nonlinear_preferred_formats) / sizeof(nonlinear_preferred_formats[0]); ++i) {
			snd_pcm_format_t f = nonlinear_preferred_formats[i];
			if (snd_pcm_format_mask_test(format_mask, f))
				return f;
		}
#endif
		return SND_PCM_FORMAT_UNKNOWN;
	}
#ifdef BUILD_PCM_PLUGIN_LFLOAT
	if (snd_pcm_format_float(format)) {
		if (snd_pcm_format_mask_test(&fl, format)) {
			unsigned int i;
			for (i = 0; i < sizeof(float_preferred_formats) / sizeof(float_preferred_formats[0]); ++i) {
				snd_pcm_format_t f = float_preferred_formats[i];
				if (snd_pcm_format_mask_test(format_mask, f))
					return f;
			}
		}
		w = 32;
		u = 0;
		e = snd_pcm_format_big_endian(format);
	} else
#endif
	if (snd_mask_empty(&lin)) {
#ifdef BUILD_PCM_PLUGIN_LFLOAT
		unsigned int i;
		for (i = 0; i < sizeof(float_preferred_formats) / sizeof(float_preferred_formats[0]); ++i) {
			snd_pcm_format_t f = float_preferred_formats[i];
			if (snd_pcm_format_mask_test(format_mask, f))
				return f;
		}
#endif
		return SND_PCM_FORMAT_UNKNOWN;
	} else {
		w = snd_pcm_format_width(format);
		u = snd_pcm_format_unsigned(format);
		e = snd_pcm_format_big_endian(format);
	}
	for (w1 = w; w1 <= 32; w1++) {
		f = check_linear_format(format_mask, w1, u, e);
		if (f != SND_PCM_FORMAT_UNKNOWN)
			return f;
	}
	for (w1 = w - 1; w1 > 0; w1--) {
		f = check_linear_format(format_mask, w1, u, e);
		if (f != SND_PCM_FORMAT_UNKNOWN)
			return f;
	}
	return SND_PCM_FORMAT_UNKNOWN;
}
コード例 #2
0
ファイル: alsa.c プロジェクト: pmyadlowsky/mash
static void *dev_thread(void *arg) {
	int ret, frames, i, j, shift, bits, isfloat;
	int sample_bytes;
	uint32_t (*puller)(unsigned char **, int);
	S32 sample;
	double scale;
	snd_pcm_format_t format;
	int avail;
	//float *fpt, *fbuf;
	float fsample;
	unsigned char *buffer, *pt;
	buffer = (unsigned char *)malloc(blocksize *
			CHANNELS * sizeof(float));
	//fbuf = (float *)malloc(blocksize * CHANNELS);
	snd_pcm_prepare(handle);
	bits = snd_pcm_hw_params_get_sbits(hparams);
	sample_bytes = bits / 8;
	snd_pcm_hw_params_get_format(hparams, &format);
	if ((isfloat = snd_pcm_format_float(format))) scale = 1.0;
	else scale = pow(2.0 , 1 - bits);
	logmsg("1/scale %f [%d]\n", 1.0 / scale, bits);
	running = 1;
	if (snd_pcm_format_big_endian(format) == 1) puller = bepull;
	else puller = lepull;
	shift = 8 * (sizeof(uint32_t) - sample_bytes);
	ret = snd_pcm_readi(handle, buffer, blocksize); // prime pump
	if (scount > 0) sfile = fopen("/tmp/sample.raw", "w");
	while (running) {
		if ((ret = snd_pcm_wait(handle, 1000)) < 0) {
			if (ret == -EPIPE)
				logmsg("wait: xrun\n");
			else if (ret == -ESTRPIPE)
				logmsg("wait: suspend\n");
			else logmsg("poll failed %s\n", strerror(errno));
			continue;
			}
		avail = snd_pcm_avail_update(handle);
		if (avail < 0) {
			if (avail == -EPIPE)
				logmsg("an xrun occurred\n");
			else logmsg("weird avail %d\n", avail);
			break;
			}
		if (avail > blocksize) avail = blocksize;
		frames = snd_pcm_readi(handle, (void *)buffer, avail);
		if (frames < 0) {
			logmsg("read failed %s\n", snd_strerror(frames));
			}
		else if (frames != avail) {
			logmsg("wanted %d got %d\n", avail, frames);
			}
		pt = buffer;
		//fpt = fbuf;
		for (i = 0; i < frames; i++) {
			for (j = 0; j < CHANNELS; j++) {
				sample.u = (*puller)(&pt, sample_bytes);
				if (isfloat) fsample = sample.f;
				else {
					if (shift) sample.s = (sample.s
						<< shift) >> shift;
					fsample = sample.s * scale;
					}
if (scount > 0) {
	scount--;
	fprintf(sfile, "%10d, %1.8f\n", sample.s, fsample);
	if (scount == 0) fclose(sfile);
	}
				push_ringbuf(rbuf, fsample);
				}
			}
		}
	free(buffer);
	//free(fbuf);
	snd_pcm_drain(handle);
	snd_pcm_close(handle);
	handle = NULL;
	return NULL;
	}
コード例 #3
0
ファイル: alsa.c プロジェクト: pmyadlowsky/qmx
static void *dev_thread(void *arg) {
	// capture thread: keep reading and ring-buffering till told to quit
	int ret, frames, i, j, shift, bits, isfloat;
	int sample_bytes;
	uint32_t (*puller)(unsigned char **, int);
	S32 sample;
	double scale;
	snd_pcm_format_t format;
	int avail;
	sample_t fsample;
	unsigned char *buffer, *pt;
	ALSA_CARD *card;
	card = (ALSA_CARD *)arg;
	log_msg("ALSA: recv from %s '%s'\n", card->device, card->name);
	buffer = (unsigned char *)malloc(card->blocksize *
			QMX_CHANNELS * sizeof(float));
	snd_pcm_prepare(card->handle);
	bits = snd_pcm_hw_params_get_sbits(card->hparams);
	sample_bytes = bits / 8;
	snd_pcm_hw_params_get_format(card->hparams, &format);
	if ((isfloat = snd_pcm_format_float(format))) scale = 1.0;
	else scale = pow(2.0 , 1 - bits);
	log_msg("ALSA: 1/scale %f [%d]\n", 1.0 / scale, bits);
	card->running = 1;
	card->ringbuf = jack_ringbuffer_create(sizeof(sample_t) * RB_SECS
				* sampling_rate * QMX_CHANNELS + 0.5);
	if (snd_pcm_format_big_endian(format) == 1) puller = bepull;
	else puller = lepull;
	shift = 8 * (sizeof(uint32_t) - sample_bytes);
	ret = snd_pcm_readi(card->handle, buffer, card->blocksize); // prime pump
	while (card->running) {
		if ((ret = snd_pcm_wait(card->handle, 1000)) < 0) {
			if (ret == -EPIPE) {
				log_msg("ALSA: wait: EPIPE, recover...\n");
				try_recover(card, ret, buffer);
				}
			else if (ret == -ESTRPIPE) {
				log_msg("ALSA: wait: ESTRPIPE, recover...\n");
				try_recover(card, ret, buffer);
				}
			else log_msg("ALSA: poll failed %s\n", strerror(errno));
			continue;
			}
		else if (ret == 0) {
			log_msg("ALSA: card timeout...\n");
			continue;
			}
		avail = snd_pcm_avail_update(card->handle);
		if (avail < 0) {
			if (avail == -EPIPE) {
				log_msg("ALSA: avail_update: EPIPE, recover...\n");
				try_recover(card, avail, buffer);
				continue;
				}
			else {
				log_msg("ALSA: weird avail %d\n", avail);
				break;
				}
			}
		if (avail > card->blocksize) avail = card->blocksize;
		frames = snd_pcm_readi(card->handle, (void *)buffer, avail);
		if (frames < 0) {
			log_msg("ALSA: read failed %s\n", snd_strerror(frames));
			}
		else if (frames != avail) {
			log_msg("ALSA: wanted %d got %d\n", avail, frames);
			}
		pt = buffer;
		for (i = 0; i < frames; i++) {
			for (j = 0; j < QMX_CHANNELS; j++) {
				sample.u = (*puller)(&pt, sample_bytes);
				if (isfloat) fsample = sample.f;
				else {
					if (shift) sample.s = (sample.s
						<< shift) >> shift;
					fsample = sample.s * scale;
					}
				jack_ringbuffer_write(card->ringbuf,
						(const char *)&fsample, sizeof(sample_t));
				}
			}
		}
	free(buffer);
	log_msg("ALSA: stopped %s '%s'\n", card->device, card->name);
	snd_pcm_drain(card->handle);
	return NULL;
	}