Esempio n. 1
0
int snd_pcm_linear_convert_index(snd_pcm_format_t src_format,
				 snd_pcm_format_t dst_format)
{
	int src_endian, dst_endian, sign, src_width, dst_width;

	sign = (snd_pcm_format_signed(src_format) !=
		snd_pcm_format_signed(dst_format));
#ifdef SND_LITTLE_ENDIAN
	src_endian = snd_pcm_format_big_endian(src_format);
	dst_endian = snd_pcm_format_big_endian(dst_format);
#else
	src_endian = snd_pcm_format_little_endian(src_format);
	dst_endian = snd_pcm_format_little_endian(dst_format);
#endif

	if (src_endian < 0)
		src_endian = 0;
	if (dst_endian < 0)
		dst_endian = 0;

	src_width = snd_pcm_format_width(src_format) / 8 - 1;
	dst_width = snd_pcm_format_width(dst_format) / 8 - 1;

	return src_width * 32 + src_endian * 16 + sign * 8 + dst_width * 2 + dst_endian;
}
Esempio n. 2
0
int snd_pcm_linear_get_index(snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
{
	int sign, width, pwidth, endian;
	sign = (snd_pcm_format_signed(src_format) != 
		snd_pcm_format_signed(dst_format));
#ifdef SND_LITTLE_ENDIAN
	endian = snd_pcm_format_big_endian(src_format);
#else
	endian = snd_pcm_format_little_endian(src_format);
#endif
	if (endian < 0)
		endian = 0;
	pwidth = snd_pcm_format_physical_width(src_format);
	width = snd_pcm_format_width(src_format);
	if (pwidth == 24) {
		switch (width) {
		case 24:
			width = 0; break;
		case 20:
			width = 1; break;
		case 18:
		default:
			width = 2; break;
		}
		return width * 4 + endian * 2 + sign + 16;
	} else {
		width = width / 8 - 1;
		return width * 4 + endian * 2 + sign;
	}
}
Esempio n. 3
0
/**
 * \brief Return endian info for a PCM sample format
 * \param format Format
 * \return 0 swapped, 1 CPU endian, a negative error code if endian independent
 */
int snd_pcm_format_cpu_endian(snd_pcm_format_t format)
{
#ifdef SNDRV_LITTLE_ENDIAN
	return snd_pcm_format_little_endian(format);
#else
	return snd_pcm_format_big_endian(format);
#endif
}
Esempio n. 4
0
int snd_pcm_lfloat_get_s32_index(snd_pcm_format_t format)
{
	int width, endian;

	switch (format) {
	case SND_PCM_FORMAT_FLOAT_LE:
	case SND_PCM_FORMAT_FLOAT_BE:
		width = 32;
		break;
	case SND_PCM_FORMAT_FLOAT64_LE:
	case SND_PCM_FORMAT_FLOAT64_BE:
		width = 64;
		break;
	default:
		return -EINVAL;
	}
#ifdef SND_LITTLE_ENDIAN
	endian = snd_pcm_format_big_endian(format);
#else
	endian = snd_pcm_format_little_endian(format);
#endif
	return ((width / 32)-1) * 2 + endian;
}
// returns 1 if successful
// enc: 0 for PCM, 1 for ULAW, 2 for ALAW (see DirectAudio.h)
int getFormatFromAlsaFormat(snd_pcm_format_t alsaFormat,
                            int* sampleSizeInBytes, int* significantBits,
                            int* isSigned, int* isBigEndian, int* enc) {

    *sampleSizeInBytes = (snd_pcm_format_physical_width(alsaFormat) + 7) / 8;
    *significantBits = snd_pcm_format_width(alsaFormat);

    // defaults
    *enc = 0; // PCM
    *isSigned = (snd_pcm_format_signed(alsaFormat) > 0);
    *isBigEndian = (snd_pcm_format_big_endian(alsaFormat) > 0);

    // non-PCM formats
    if (alsaFormat == SND_PCM_FORMAT_MU_LAW) { // Mu-Law
        *sampleSizeInBytes = 8; *enc = 1; *significantBits = *sampleSizeInBytes;
    }
    else if (alsaFormat == SND_PCM_FORMAT_A_LAW) {     // A-Law
        *sampleSizeInBytes = 8; *enc = 2; *significantBits = *sampleSizeInBytes;
    }
    else if (snd_pcm_format_linear(alsaFormat) < 1) {
        return 0;
    }
    return (*sampleSizeInBytes > 0);
}
Esempio n. 6
0
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;
	}
Esempio n. 7
0
/*
 * pdacf_pcm_prepare - prepare callback for playback and capture
 */
static int pdacf_pcm_prepare(struct snd_pcm_substream *subs)
{
    struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
    struct snd_pcm_runtime *runtime = subs->runtime;
    u16 val, nval, aval;

    if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE)
        return -EBUSY;

    chip->pcm_channels = runtime->channels;

    chip->pcm_little = snd_pcm_format_little_endian(runtime->format) > 0;
#ifdef SNDRV_LITTLE_ENDIAN
    chip->pcm_swab = snd_pcm_format_big_endian(runtime->format) > 0;
#else
    chip->pcm_swab = chip->pcm_little;
#endif

    if (snd_pcm_format_unsigned(runtime->format))
        chip->pcm_xor = 0x80008000;

    if (pdacf_pcm_clear_sram(chip) < 0)
        return -EIO;
    
    val = nval = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR);
    nval &= ~(PDAUDIOCF_DATAFMT0|PDAUDIOCF_DATAFMT1);
    switch (runtime->format) {
    case SNDRV_PCM_FORMAT_S16_LE:
    case SNDRV_PCM_FORMAT_S16_BE:
        break;
    default: /* 24-bit */
        nval |= PDAUDIOCF_DATAFMT0 | PDAUDIOCF_DATAFMT1;
        break;
    }
    aval = 0;
    chip->pcm_sample = 4;
    switch (runtime->format) {
    case SNDRV_PCM_FORMAT_S16_LE:
    case SNDRV_PCM_FORMAT_S16_BE:
        aval = AK4117_DIF_16R;
        chip->pcm_frame = 2;
        chip->pcm_sample = 2;
        break;
    case SNDRV_PCM_FORMAT_S24_3LE:
    case SNDRV_PCM_FORMAT_S24_3BE:
        chip->pcm_sample = 3;
        /* fall through */
    default: /* 24-bit */
        aval = AK4117_DIF_24R;
        chip->pcm_frame = 3;
        chip->pcm_xor &= 0xffff0000;
        break;
    }

    if (val != nval) {
        snd_ak4117_reg_write(chip->ak4117, AK4117_REG_IO, AK4117_DIF2|AK4117_DIF1|AK4117_DIF0, aval);
        pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, nval);
    }

    val = pdacf_reg_read(chip,  PDAUDIOCF_REG_IER);
    val &= ~(PDAUDIOCF_IRQLVLEN1);
    val |= PDAUDIOCF_IRQLVLEN0;
    pdacf_reg_write(chip, PDAUDIOCF_REG_IER, val);

    chip->pcm_size = runtime->buffer_size;
    chip->pcm_period = runtime->period_size;
    chip->pcm_area = runtime->dma_area;

    return 0;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
	}