示例#1
0
static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
                        int nfrags, int frag_size)
{
    int bufsizeforthis, err;
    snd_pcm_hw_params_t* hw_params;
    unsigned int tmp_uint;
    snd_pcm_uframes_t tmp_snd_pcm_uframes;

    if (sys_verbose)
    {
        if (out)
            post("configuring sound output...");
        else post("configuring sound input...");
    }

    /* set hardware parameters... */
    snd_pcm_hw_params_alloca(&hw_params);

    /* get the default params */
    err = snd_pcm_hw_params_any(dev->a_handle, hw_params);
    check_error(err, "snd_pcm_hw_params_any");

    /* try to set interleaved access */
    err = snd_pcm_hw_params_set_access(dev->a_handle,
                                       hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err < 0)
        return (-1);
    check_error(err, "snd_pcm_hw_params_set_access");
#if 0       /* enable this to print out which formats are available */
    {
        int i;
        for (i = 0; i <= SND_PCM_FORMAT_LAST; i++)
            fprintf(stderr, "%d -> %d\n",
                    i, snd_pcm_hw_params_test_format(dev->a_handle, hw_params, i));
    }
#endif
    /* Try to set 32 bit format first */
    err = snd_pcm_hw_params_set_format(dev->a_handle,
                                       hw_params, SND_PCM_FORMAT_S32);
    if (err < 0)
    {
        /* fprintf(stderr,
            "PD-ALSA: 32 bit format not available - trying 24\n"); */
        err = snd_pcm_hw_params_set_format(dev->a_handle, hw_params,
                                           SND_PCM_FORMAT_S24_3LE);
        if (err < 0)
        {
            /* fprintf(stderr,
                "PD-ALSA: 32/24 bit format not available - using 16\n"); */
            err = snd_pcm_hw_params_set_format(dev->a_handle, hw_params,
                                               SND_PCM_FORMAT_S16);
            check_error(err, "snd_pcm_hw_params_set_format");
            dev->a_sampwidth = 2;
        }
        else dev->a_sampwidth = 3;
    }
    else dev->a_sampwidth = 4;

    if (sys_verbose)
        post("Sample width set to %d bytes", dev->a_sampwidth);

    /* set the subformat */
    err = snd_pcm_hw_params_set_subformat(dev->a_handle,
                                          hw_params, SND_PCM_SUBFORMAT_STD);
    check_error(err, "snd_pcm_hw_params_set_subformat");

    /* set the number of channels */
    tmp_uint = *channels;
    err = snd_pcm_hw_params_set_channels_min(dev->a_handle,
            hw_params, &tmp_uint);
    check_error(err, "snd_pcm_hw_params_set_channels");
    if (tmp_uint != (unsigned)*channels)
        post("ALSA: set %s channels to %d", (out?"output":"input"), tmp_uint);
    *channels = tmp_uint;
    dev->a_channels = *channels;

    /* set the sampling rate */
    err = snd_pcm_hw_params_set_rate_min(dev->a_handle, hw_params,
                                         (unsigned int *)rate, 0);
    check_error(err, "snd_pcm_hw_params_set_rate_min (input)");
#if 0
    err = snd_pcm_hw_params_get_rate(hw_params, &subunitdir);
    post("input sample rate %d", err);
#endif

    /* post("frag size %d, nfrags %d", frag_size, nfrags); */
    /* set "period size" */
#ifdef ALSAAPI9
    err = snd_pcm_hw_params_set_period_size_near(dev->a_handle,
            hw_params, (snd_pcm_uframes_t)frag_size, 0);
#else
    tmp_snd_pcm_uframes = frag_size;
    err = snd_pcm_hw_params_set_period_size_near(dev->a_handle,
            hw_params, &tmp_snd_pcm_uframes, 0);
#endif
    check_error(err, "snd_pcm_hw_params_set_period_size_near (input)");

    /* set the buffer size */
#ifdef ALSAAPI9
    err = snd_pcm_hw_params_set_buffer_size_near(dev->a_handle,
            hw_params, nfrags * frag_size);
#else
    tmp_snd_pcm_uframes = nfrags * frag_size;
    err = snd_pcm_hw_params_set_buffer_size_near(dev->a_handle,
            hw_params, &tmp_snd_pcm_uframes);
#endif
    check_error(err, "snd_pcm_hw_params_set_buffer_size_near (input)");

    err = snd_pcm_hw_params(dev->a_handle, hw_params);
    check_error(err, "snd_pcm_hw_params (input)");

    /* set up the buffer */
    bufsizeforthis = DEFDACBLKSIZE * dev->a_sampwidth * *channels;
    if (alsa_snd_buf)
    {
        if (alsa_snd_bufsize < bufsizeforthis)
        {
            if (!(alsa_snd_buf = realloc(alsa_snd_buf, bufsizeforthis)))
            {
                post("out of memory");
                return (0);
            }
            memset(alsa_snd_buf, 0, bufsizeforthis);
            alsa_snd_bufsize = bufsizeforthis;
        }
    }
    else
    {
        if (!(alsa_snd_buf = (void *)malloc(bufsizeforthis)))
        {
            post("out of memory");
            return (0);
        }
        memset(alsa_snd_buf, 0, bufsizeforthis);
        alsa_snd_bufsize = bufsizeforthis;
    }
    return (1);
}
示例#2
0
文件: alsa.c 项目: xdsopl/spectrum
int open_alsa_read(struct pcm **p, char *name)
{
	snd_pcm_t *pcm;
	if (snd_pcm_open(&pcm, name, SND_PCM_STREAM_CAPTURE, 0) < 0) {
		fprintf(stderr, "Error opening PCM device %s\n", name);
		return 0;
	}

	snd_pcm_hw_params_t *params;
	snd_pcm_hw_params_alloca(&params);
	if (snd_pcm_hw_params_any(pcm, params) < 0) {
		fprintf(stderr, "Can not configure this PCM device.\n");
		snd_pcm_close(pcm);
		return 0;
	}

	if (snd_pcm_hw_params_set_access(pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
		fprintf(stderr, "Error setting access.\n");
		snd_pcm_close(pcm);
		return 0;
	}

	if (snd_pcm_hw_params_set_format(pcm, params, SND_PCM_FORMAT_S16_LE) < 0) {
		fprintf(stderr, "Error setting S16_LE format.\n");
		snd_pcm_close(pcm);
		return 0;
	}

	if (snd_pcm_hw_params_set_rate_resample(pcm, params, 0) < 0) {
		fprintf(stderr, "Error disabling resampling.\n");
		snd_pcm_close(pcm);
		return 0;
	}

	unsigned rate_min = 8000;
	int dir_min = 0;
	if (snd_pcm_hw_params_set_rate_min(pcm, params, &rate_min, &dir_min) < 0 || rate_min < 8000) {
		fprintf(stderr, "Error setting min rate.\n");
		snd_pcm_close(pcm);
		return 0;
	}

	if (snd_pcm_hw_params(pcm, params) < 0) {
		fprintf(stderr, "Error setting HW params.\n");
		snd_pcm_close(pcm);
		return 0;
	}
	unsigned int rate = 0;
	if (snd_pcm_hw_params_get_rate(params, &rate, 0) < 0) {
		fprintf(stderr, "Error getting rate.\n");
		snd_pcm_close(pcm);
		return 0;
	}
	unsigned int channels = 0;
	if (snd_pcm_hw_params_get_channels(params, &channels) < 0) {
		fprintf(stderr, "Error getting channels.\n");
		snd_pcm_close(pcm);
		return 0;
	}

	struct alsa *alsa = (struct alsa *)malloc(sizeof(struct alsa));
	alsa->base.close = close_alsa;
	alsa->base.info = info_alsa;
	alsa->base.rate = rate_alsa;
	alsa->base.channels = channels_alsa;
	alsa->base.rw = read_alsa;
	alsa->base.data = (void *)alsa;

	alsa->pcm = pcm;
	alsa->r = rate;
	alsa->c = channels;
	alsa->frames = 0;
	*p = &(alsa->base);
	return 1;
}