'ALSA driver's buffer is TOO large

I'm using a USB sound card to create a real-time Linux player. The APP is developed based on ALSA's API.

I found that the driver's buffer is too large. I don't know how to reduce the buffer size via userspace.

For example, when I initialize ALSA by 16-bit stereo 44100Hz, the total buffer size will be 256 frames(snd_pcm_hw_params_get_period_size) * 1024 periods(snd_pcm_hw_params_get_periods). So that the total buffer time is 256*1024/44100=5.94(seconds). That's too large for my REAL-TIME use case!


my exp 01: I've been trying to reduce to periods counts by snd_pcm_hw_params_test_periods, but the driver's buffer size (frames*periods) is ALL THE SAME!


here's my sample code

    bool init(const std::string &PCM_DEVICE, const int channels, const int rate) {
        unsigned int pcm;
        unsigned int tmp;
        snd_pcm_hw_params_t* params = nullptr;

        /* Open the PCM device in playback mode */
        if (pcm = snd_pcm_open(&pcm_handle_, PCM_DEVICE.c_str(), SND_PCM_STREAM_PLAYBACK, 0) < 0) {
            printf("ERROR: Can't open \"%s\" PCM device. %s\n", PCM_DEVICE, snd_strerror(pcm));
            return false;
        }

        /* Allocate parameters object and fill it with default values*/
        snd_pcm_hw_params_alloca(&params);

        snd_pcm_hw_params_any(pcm_handle_, params);

        /* Set parameters */
        if (pcm = snd_pcm_hw_params_set_access(pcm_handle_, params,
                                               SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
            printf("ERROR: Can't set interleaved mode. %s\n", snd_strerror(pcm));

        if (pcm = snd_pcm_hw_params_set_format(pcm_handle_, params,
                                               SND_PCM_FORMAT_S16_LE) < 0)
            printf("ERROR: Can't set format. %s\n", snd_strerror(pcm));

        if (pcm = snd_pcm_hw_params_set_channels(pcm_handle_, params, channels) < 0)
            printf("ERROR: Can't set channels number. %s\n", snd_strerror(pcm));

        if (pcm = snd_pcm_hw_params_set_rate_near(pcm_handle_, params, (unsigned int*)&rate, 0) < 0)
            printf("ERROR: Can't set rate. %s\n", snd_strerror(pcm));

        /* Write parameters */
        if (pcm = snd_pcm_hw_params(pcm_handle_, params) < 0)
            printf("ERROR: Can't set harware parameters. %s\n", snd_strerror(pcm));

        /* Resume information */
        printf("PCM name: '%s'\n", snd_pcm_name(pcm_handle_));

        printf("PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(pcm_handle_)));

        snd_pcm_hw_params_get_channels(params, &tmp);
        printf("channels: %i ", tmp);

        if (tmp == 1)
            printf("(mono)\n");
        else if (tmp == 2)
            printf("(stereo)\n");

        snd_pcm_hw_params_get_rate(params, &tmp, 0);
        printf("rate: %d bps\n", tmp);


        /* Allocate buffer to hold single period */
        snd_pcm_hw_params_get_period_size(params, &frames_, 0);
        LOGI << "frames_ = " << frames_;

        buffSize_ = frames_ * channels * 2 /* 2 -> sample size */;
        buff_.resize(buffSize_);

        snd_pcm_hw_params_get_period_time(params, &tmp, NULL);

        snd_pcm_hw_params_get_periods(params, &tmp, NULL); // https://www.alsa-project.org/wiki/FramesPeriods
        LOGI << "periods_ =" << tmp;

        return true;
    }


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source