示例#1
0
static int set_hw_params(snd_pcm_t *pcm,
                         snd_pcm_hw_params_t *hw_params,
                         unsigned int *rate,
                         unsigned int channels,
                         snd_pcm_format_t format,
                         snd_pcm_subformat_t subformat,
                         unsigned int *buffer_time,
                         unsigned int *period_time,
                         snd_pcm_access_t access)
{
    int err;

    /*
     * hardware parameters
     */
    err = snd_pcm_hw_params_any(pcm, hw_params);
    if (err < 0)
        return err;
    err = snd_pcm_hw_params_set_access(pcm, hw_params, access);
    if (err < 0)
        return err;
    err = snd_pcm_hw_params_set_format(pcm, hw_params, format);
    if (err < 0)
        return err;
    if (subformat != SND_PCM_SUBFORMAT_STD) {
        err = snd_pcm_hw_params_set_subformat(pcm, hw_params, subformat);
        if (err < 0)
            return err;
    }
    err = snd_pcm_hw_params_set_channels(pcm, hw_params, channels);
    if (err < 0)
        return err;
    err = INTERNAL(snd_pcm_hw_params_set_rate_near)(pcm, hw_params, rate, 0);
    if (err < 0)
        return err;
    err = INTERNAL(snd_pcm_hw_params_set_buffer_time_near)(pcm, hw_params, buffer_time, NULL);
    if (err < 0)
        return err;
    if (period_time == NULL || *period_time == 0) {
        unsigned int periods = 3;
        err = INTERNAL(snd_pcm_hw_params_set_periods_near)(pcm, hw_params, &periods, NULL);
        if (err < 0)
            return err;
        if (periods == 1)
            return -EINVAL;
        if (*period_time == 0) {
            err = INTERNAL(snd_pcm_hw_params_get_period_time)(hw_params, period_time, NULL);
            if (err < 0)
                return err;
        }
    } else {
        err = snd_pcm_hw_params_set_period_time(pcm, hw_params, *period_time, 0);
        if (err < 0)
            return err;
        if (*buffer_time == *period_time)
            return -EINVAL;
    }
    err = snd_pcm_hw_params(pcm, hw_params);
    if (err < 0)
        return err;
    return 0;
}
示例#2
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);
}