]> git.sesse.net Git - nageru/blobdiff - alsa_output.cpp
Write 1.4.0 changelog.
[nageru] / alsa_output.cpp
index 52f4936924f7a84570b92aa168af9a79321a735d..7dd10244b094d83b9f93c65af0b8e87dc4e5a5c6 100644 (file)
@@ -1,5 +1,9 @@
 #include "alsa_output.h"
 
+#include <alsa/asoundlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <vector>
 
 using namespace std;
@@ -17,7 +21,7 @@ void die_on_error(const char *func_name, int err)
 }  // namespace
 
 ALSAOutput::ALSAOutput(int sample_rate, int num_channels)
-       : num_channels(num_channels)
+       : sample_rate(sample_rate), num_channels(num_channels)
 {
        die_on_error("snd_pcm_open()", snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0));
 
@@ -31,17 +35,24 @@ ALSAOutput::ALSAOutput(int sample_rate, int num_channels)
        die_on_error("snd_pcm_hw_params_set_channels", snd_pcm_hw_params_set_channels(pcm_handle, hw_params, num_channels));
 
        // Fragment size of 512 samples. (A frame at 60 fps/48 kHz is 800 samples.)
-       // We ask for four such periods.
-       unsigned int num_periods = 4;
+       // We ask for 16 such periods (~170 ms buffer).
+       unsigned int num_periods = 16;
        int dir = 0;
-       die_on_error("snd_pcm_hw_params_set_periods_near", snd_pcm_hw_params_set_periods_near(pcm_handle, hw_params, &num_periods, &dir));
+       die_on_error("snd_pcm_hw_params_set_periods_near()", snd_pcm_hw_params_set_periods_near(pcm_handle, hw_params, &num_periods, &dir));
        period_size = 512;
        dir = 0;
-       die_on_error("snd_pcm_hw_params_set_period_size_near", snd_pcm_hw_params_set_period_size_near(pcm_handle, hw_params, &period_size, &dir));
-       die_on_error("snd_pcm_hw_params", snd_pcm_hw_params(pcm_handle, hw_params));
+       die_on_error("snd_pcm_hw_params_set_period_size_near()", snd_pcm_hw_params_set_period_size_near(pcm_handle, hw_params, &period_size, &dir));
+       die_on_error("snd_pcm_hw_params()", snd_pcm_hw_params(pcm_handle, hw_params));
        //snd_pcm_hw_params_free(hw_params);
 
+       snd_pcm_sw_params_t *sw_params;
+       snd_pcm_sw_params_alloca(&sw_params);
+       die_on_error("snd_pcm_sw_params_current()", snd_pcm_sw_params_current(pcm_handle, sw_params));
+       die_on_error("snd_pcm_sw_params_set_start_threshold", snd_pcm_sw_params_set_start_threshold(pcm_handle, sw_params, num_periods * period_size / 2));
+       die_on_error("snd_pcm_sw_params()", snd_pcm_sw_params(pcm_handle, sw_params));
+
        die_on_error("snd_pcm_nonblock", snd_pcm_nonblock(pcm_handle, 1));
+       die_on_error("snd_pcm_prepare()", snd_pcm_prepare(pcm_handle));
 }
 
 void ALSAOutput::write(const vector<float> &samples)
@@ -72,7 +83,8 @@ try_again:
                if (ret == 0) {
                        if (buffer.size() >= period_size * num_channels * 8) {
                                // OK, almost 100 ms. Giving up.
-                               fprintf(stderr, "warning: ALSA overrun, dropping some audio\n");
+                               fprintf(stderr, "warning: ALSA overrun, dropping some audio (%d ms)\n",
+                                       int(buffer.size() * 1000 / (num_channels * sample_rate)));
                                buffer.clear();
                        }
                } else if (ret > 0) {