snd_pcm_hw_params_set_buffer_size_near иногда дает сбой - PullRequest
0 голосов
/ 28 февраля 2020

Я обычно не имею дело с аудио драйверами, поэтому, пожалуйста, прости меня за любое невежество. У меня есть программа C ++, работающая на Raspberry Pi 3 с Ubuntu 18.04 Server LTS для ОС. ALSA работает с aplay и arecord без проблем.

В моем приложении я настроил ALSA со следующим кодом

int LinuxAudioPlayer::Open(const std::string& device, AudioPlayerFormat format){
    //PCM variables
    int rc;
    int err;
    unsigned int val;
    int dir;

    m_device = device;

    //begin PCM setup

    /* Open PCM device for playback. */
    if ((err = snd_pcm_open(&m_playback_handle, device.c_str(), SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
    fprintf(stderr, "cannot open output audio device %s: %s\n", device.c_str(), snd_strerror(err));
    exit(1);
    }

    /* Allocate a hardware parameters object. */
    snd_pcm_hw_params_alloca(&m_params);

    /* Fill it in with default values. */
    snd_pcm_hw_params_any(m_playback_handle, m_params);

    /* Set the desired hardware parameters. */

    /* Interleaved mode */
    snd_pcm_hw_params_set_access(m_playback_handle, m_params,
                        SND_PCM_ACCESS_RW_INTERLEAVED);

    switch(format){
        case AudioPlayerFormat::Mono16khz16bit:
        default:
            /* Signed 16-bit little-endian format */
            fprintf(stdout, "Format = Mono16khz16bit\n");
            m_numChannels = 1;
            m_bytesPerSample = 2;
            m_bitsPerSecond = 16000;
            snd_pcm_hw_params_set_format(m_playback_handle, m_params,
                                SND_PCM_FORMAT_S16_LE);
    }

    /* set number of Channels */
    snd_pcm_hw_params_set_channels(m_playback_handle, m_params, m_numChannels);

    /* set bits/second sampling rate */
    snd_pcm_hw_params_set_rate_near(m_playback_handle, m_params,
                                    &m_bitsPerSecond, &dir);

    /* Set buffer size */
    unsigned int bufferSize = 8192;
    rc = snd_pcm_hw_params_set_buffer_size_near(m_playback_handle, m_params, (snd_pcm_uframes_t *)&bufferSize);

    if(rc < 0){
        fprintf(stdout, "snd_pcm_hw_params_set_buffer_size_near failed: %s\n", snd_strerror(rc) );
    }

    /* Set period size to 32 frames. */
    m_frames = 32;
    rc = snd_pcm_hw_params_set_period_size_near(m_playback_handle,
                                m_params, &m_frames, &dir);
    if(rc < 0){
        fprintf(stdout, "snd_pcm_hw_params_set_period_size_near failed: %s\n", snd_strerror(rc) );
    }

    /* Write the parameters to the driver */
    rc = snd_pcm_hw_params(m_playback_handle, m_params);
    if (rc < 0) {
    fprintf(stderr,
            "unable to set hw parameters: %s %d\n",
            snd_strerror(rc), rc);
    exit(1);
    }

    //end PCM setup

Интересно то, что иногда я могу нормально запускать приложение. но примерно 1 из 4 раз я получаю сбои в функциях snd_pcm_hw_params_set_buffer_size_near и snd_pcm_hw_params_set_period_size_near с ошибкой «Неверный аргумент».

Как аргумент может быть недействительным, если иногда он успешно выполняется? Я надеюсь сделать мою программу более стабильной, чтобы ее не нужно было запускать несколько раз для успешного выполнения.

...