Example #1
0
static HRESULT SetFormat(IDsDriverBufferImpl *This, LPWAVEFORMATEX pwfx)
{
    snd_pcm_t *pcm = NULL;
    snd_pcm_hw_params_t *hw_params = This->hw_params;
    unsigned int buffer_time = 500000;
    snd_pcm_format_t format = -1;
    snd_pcm_uframes_t psize;
    DWORD rate = pwfx->nSamplesPerSec;
    int err=0;

    switch (pwfx->wBitsPerSample)
    {
    case  8:
        format = SND_PCM_FORMAT_U8;
        break;
    case 16:
        format = SND_PCM_FORMAT_S16_LE;
        break;
    case 24:
        format = SND_PCM_FORMAT_S24_3LE;
        break;
    case 32:
        format = SND_PCM_FORMAT_S32_LE;
        break;
    default:
        FIXME("Unsupported bpp: %d\n", pwfx->wBitsPerSample);
        return DSERR_GENERIC;
    }

    err = snd_pcm_open(&pcm, WOutDev[This->drv->wDevID].pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
    if (err < 0)
    {
        if (errno != EBUSY || !This->pcm)
        {
            WARN("Cannot open sound device: %s\n", snd_strerror(err));
            return DSERR_GENERIC;
        }
        snd_pcm_drop(This->pcm);
        snd_pcm_close(This->pcm);
        This->pcm = NULL;
        err = snd_pcm_open(&pcm, WOutDev[This->drv->wDevID].pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
        if (err < 0)
        {
            WARN("Cannot open sound device: %s\n", snd_strerror(err));
            return DSERR_BUFFERLOST;
        }
    }

    /* Set some defaults */
    snd_pcm_hw_params_any(pcm, hw_params);
    err = snd_pcm_hw_params_set_channels(pcm, hw_params, pwfx->nChannels);
    if (err < 0) {
        WARN("Could not set channels to %d\n", pwfx->nChannels);
        goto err;
    }

    err = snd_pcm_hw_params_set_format(pcm, hw_params, format);
    if (err < 0) {
        WARN("Could not set format to %d bpp\n", pwfx->wBitsPerSample);
        goto err;
    }

    /* Alsa's rate resampling is only used if the application specifically requests
     * a buffer at a certain frequency, else it is better to disable it due to unwanted
     * side effects, which may include: Less granular pointer, changing buffer sizes, etc
     */
#if SND_LIB_VERSION >= 0x010009
    snd_pcm_hw_params_set_rate_resample(pcm, hw_params, 0);
#endif

    err = snd_pcm_hw_params_set_rate_near(pcm, hw_params, &rate, NULL);
    if (err < 0) {
        rate = pwfx->nSamplesPerSec;
        WARN("Could not set rate\n");
        goto err;
    }

    if (!ALSA_NearMatch(rate, pwfx->nSamplesPerSec))
    {
        WARN("Could not set sound rate to %d, but instead to %d\n", pwfx->nSamplesPerSec, rate);
        pwfx->nSamplesPerSec = rate;
        pwfx->nAvgBytesPerSec = rate * pwfx->nBlockAlign;
        /* Let DirectSound detect this */
    }

    snd_pcm_hw_params_set_periods_integer(pcm, hw_params);
    snd_pcm_hw_params_set_buffer_time_near(pcm, hw_params, &buffer_time, NULL);
    buffer_time = 10000;
    snd_pcm_hw_params_set_period_time_near(pcm, hw_params, &buffer_time, NULL);
    err = snd_pcm_hw_params(pcm, hw_params);
    err = snd_pcm_sw_params(pcm, This->sw_params);
    snd_pcm_prepare(pcm);

    err = snd_pcm_hw_params_get_period_size(hw_params, &psize, NULL);
    TRACE("Period size is: %lu\n", psize);

    /* ALSA needs at least 3 buffers to work successfully */
    This->mmap_commitahead = 3 * psize;
    while (This->mmap_commitahead <= 512)
        This->mmap_commitahead += psize;

    if (This->pcm)
    {
        snd_pcm_drop(This->pcm);
        snd_pcm_close(This->pcm);
    }
    This->pcm = pcm;
    snd_pcm_prepare(This->pcm);
    DSDB_CreateMMAP(This);
    return S_OK;

err:
    if (err < 0)
        WARN("Failed to apply changes: %s\n", snd_strerror(err));

    if (!This->pcm)
        This->pcm = pcm;
    else
        snd_pcm_close(pcm);

    if (This->pcm)
        snd_pcm_hw_params_current(This->pcm, This->hw_params);

    return DSERR_BADFORMAT;
}
Example #2
0
void stop_audio(void)
{
	snd_pcm_drop(playback_handle);
}