shithub: sox

Download patch

ref: 2c318fba9e88a35c141111aa3af0a3aaef51f3f6
parent: 69aa432c2d828aaedfa1b3d62a118e29ec469943
author: cbagwell <cbagwell>
date: Sat Sep 17 19:00:28 EDT 2005

debug code for alsa driver.

--- a/src/alsa.c
+++ b/src/alsa.c
@@ -44,11 +44,16 @@
     int err;
     alsa_priv_t alsa = (alsa_priv_t)ft->priv;
     snd_pcm_hw_params_t *hw_params;
+    snd_pcm_sw_params_t *sw_params;
     unsigned int min_rate, max_rate;
     unsigned int min_chan, max_chan;
-    unsigned int rate;
+    unsigned int rate, periods;
+    snd_pcm_uframes_t buffer_size;
+    snd_pcm_sframes_t period_size;
     int dir;
     snd_pcm_format_mask_t *fmask;
+    unsigned int buffer_time = 500000;
+    unsigned int period_time = 100000;
 
     /* Reserve buffer for 16-bit data.  FIXME: Whats a good size? */
     alsa->buf_size = ST_BUFSIZ*2;
@@ -82,6 +87,15 @@
         return ST_EOF;
     }
 
+    /* set hardware resampling */
+    rate = 0;
+    err = snd_pcm_hw_params_set_rate_resample(alsa->pcm_handle, hw_params, 
+                                              rate);
+    if (err < 0) {
+        printf("Resampling setup failed for playback: %s\n", snd_strerror(err));
+        return err;
+    }
+
     if ((err = snd_pcm_hw_params_set_access(alsa->pcm_handle, hw_params, 
                                             SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
     {
@@ -117,6 +131,7 @@
 
     snd_pcm_hw_params_get_rate_min(hw_params, &min_rate, &dir);
     snd_pcm_hw_params_get_rate_max(hw_params, &max_rate, &dir);
+    fprintf(stderr, "min_rate=%d max_rate=%d\n", min_rate, max_rate);
 
     rate = ft->info.rate;
     if (rate < min_rate) 
@@ -127,6 +142,7 @@
     if (rate != ft->info.rate)
     {
         st_warn("alsa: Hardware does not support %d.  Forcing sample rate to %d.", ft->info.rate, rate);
+        ft->info.rate = rate;
     }
 
     dir = 0;
@@ -138,6 +154,11 @@
         st_fail_errno(ft, ST_EPERM, "cannot set sample rate");
         return ST_EOF;
     }
+    snd_pcm_hw_params_get_rate(hw_params, 
+                               &rate,
+                               &dir);
+ 
+    fprintf(stderr, "new rate=%d\n", rate);
     if (rate != ft->info.rate)
     {
         st_warn("Could not set exact rate of %d.  Approximating with %d",
@@ -154,19 +175,52 @@
         return ST_EOF;
     }
 
+#if 0
+        /* set the buffer time */
+        err = snd_pcm_hw_params_set_buffer_time_near(alsa->pcm_handle, hw_params, &buffer_time, &dir);
+        if (err < 0) {
+                printf("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
+                return err;
+        }
+        err = snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size);
+        if (err < 0) {
+                printf("Unable to get buffer size for playback: %s\n", snd_strerror(err));
+                return err;
+        }
+
+    /* set the period time */
+    err = snd_pcm_hw_params_set_period_time_near(alsa->pcm_handle, hw_params, &period_time, &dir);
+    if (err < 0) {
+        printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
+        return err;
+    }
+    err = snd_pcm_hw_params_get_period_size(hw_params, &period_size, &dir);
+    if (err < 0) {
+        printf("Unable to get period size for playback: %s\n", snd_strerror(err));
+        return err;
+    }
+#endif
+
+#if 0
     /* Set number of periods. Periods used to be called fragments. */ 
-    if (snd_pcm_hw_params_set_periods(alsa->pcm_handle, hw_params, 2, 0) < 0) 
+    periods = 2;
+    if (snd_pcm_hw_params_set_periods_near(alsa->pcm_handle, hw_params, 
+                                           &periods, &dir) < 0) 
     {
         st_fail_errno(ft, ST_EPERM, "Error setting periods.");
         return ST_EOF;
     }
+    snd_pcm_hw_params_get_periods(hw_params, &periods, &dir);
 
     /* Set buffer size (in frames). The resulting latency is given by */
     /* latency = periodsize * periods / (rate * bytes_per_frame)     */
-    if (snd_pcm_hw_params_set_buffer_size(alsa->pcm_handle, hw_params, (ST_BUFSIZ * 8)>>2) < 0) {
+    buffer_size = ((ST_BUFSIZ/ft->info.channels) * periods);
+    if (snd_pcm_hw_params_set_buffer_size_near(alsa->pcm_handle, hw_params, 
+                                               &buffer_size) < 0) {
       st_fail_errno(ft, ST_EPERM, "Error setting buffersize.");
       return ST_EOF;
     }
+#endif
 
     if ((err = snd_pcm_hw_params(alsa->pcm_handle, hw_params)) < 0) 
     {
@@ -176,6 +230,49 @@
 
     snd_pcm_hw_params_free(hw_params);
 
+    if ((err = snd_pcm_sw_params_malloc(&sw_params)) < 0) 
+    {
+        st_fail_errno(ft, ST_ENOMEM, 
+                      "cannot allocate software parameter structure");
+        return ST_EOF;
+    }
+#if 0
+    /* get the current swparams */
+    err = snd_pcm_sw_params_current(alsa->pcm_handle, sw_params);
+    if (err < 0) {
+        printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
+        return err;
+    }
+    /* start the transfer when the buffer is almost full: */
+    /* (buffer_size / avail_min) * avail_min */
+    err = snd_pcm_sw_params_set_start_threshold(alsa->pcm_handle, sw_params, 
+                                                (buffer_size / period_size) * period_size);
+    if (err < 0) {
+        printf("Unable to set start threshold mode for playback: %s\n",
+               snd_strerror(err));
+        return err;
+    }
+    /* allow the transfer when at least period_size samples can be processed */
+    err = snd_pcm_sw_params_set_avail_min(alsa->pcm_handle, sw_params, period_size);
+    if (err < 0) {
+        printf("Unable to set avail min for playback: %s\n", snd_strerror(err));
+        return err;
+    }
+    /* align all transfers to 1 sample */
+    err = snd_pcm_sw_params_set_xfer_align(alsa->pcm_handle, sw_params, 1);
+    if (err < 0) {
+        printf("Unable to set transfer align for playback: %s\n", snd_strerror(err));
+        return err;
+    }
+    /* write the parameters to the playback device */
+    err = snd_pcm_sw_params(alsa->pcm_handle, sw_params);
+    if (err < 0) {
+        printf("Unable to set sw params for playback: %s\n", snd_strerror(err));
+        return err;
+    }
+#endif
+    snd_pcm_sw_params_free(sw_params);
+
     if ((err = snd_pcm_prepare(alsa->pcm_handle)) < 0) 
     {
         st_fail_errno(ft, ST_EPERM, "cannot prepare audio interface for use");
@@ -292,6 +389,8 @@
             continue;
         if (err < 0)
         {
+            if (ft->file.eof)
+                return ST_EOF;
             if (xrun_recovery(alsa->pcm_handle, err) < 0)
             {
                 st_fail_errno(ft, ST_EPERM, "ALSA write error");
@@ -323,154 +422,6 @@
 int st_alsastartwrite(ft_t ft)
 {
     return st_alsasetup(ft, SND_PCM_STREAM_PLAYBACK);
-
-    int fmt = SND_PCM_FORMAT_S16;
-    int err;
-    alsa_priv_t alsa = (alsa_priv_t)ft->priv;
-    snd_pcm_hw_params_t *hw_params;
-    unsigned int min_rate, max_rate;
-    unsigned int min_chan, max_chan;
-    unsigned int rate;
-    int dir;
-    snd_pcm_format_mask_t *fmask;
-
-    /* Reserve buffer for 16-bit data.  FIXME: Whats a good size? */
-    alsa->buf_size = ST_BUFSIZ*2;
-
-    if ((alsa->buf = malloc(alsa->buf_size)) == NULL) 
-    {
-        st_fail_errno(ft,ST_ENOMEM,
-                      "unable to allocate output buffer of size %d", 
-                      ft->file.size);
-        return(ST_EOF);
-    }
-
-    if ((err = snd_pcm_open(&(alsa->pcm_handle), ft->filename, 
-                            SND_PCM_STREAM_PLAYBACK, 0)) < 0) 
-    {
-        st_fail_errno(ft, ST_EPERM, "cannot open audio device");
-        return ST_EOF;
-    }
-
-    if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) 
-    {
-        st_fail_errno(ft, ST_ENOMEM, 
-                      "cannot allocate hardware parameter structure");
-        return ST_EOF;
-    }
-
-    if ((err = snd_pcm_hw_params_any(alsa->pcm_handle, hw_params)) < 0) 
-    {
-        st_fail_errno(ft, ST_EPERM,
-                      "cannot initialize hardware parameter structure");
-        return ST_EOF;
-    }
-
-    if ((err = snd_pcm_hw_params_set_access(alsa->pcm_handle, hw_params, 
-                                            SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
-    {
-        st_fail_errno(ft, ST_EPERM,
-                      "cannot set access type");
-        return ST_EOF;
-    }
-
-    snd_pcm_hw_params_get_channels_min(hw_params, &min_chan);
-    snd_pcm_hw_params_get_channels_max(hw_params, &max_chan);
-    if (ft->info.channels == -1) 
-        ft->info.channels = min_chan;
-    else 
-        if (ft->info.channels > max_chan) 
-            ft->info.channels = max_chan;
-        else if (ft->info.channels < min_chan) 
-            ft->info.channels = min_chan;
-
-    snd_pcm_format_mask_malloc(&fmask);
-    snd_pcm_hw_params_get_format_mask(hw_params, fmask);
-
-    if (get_format(ft, fmask, &fmt) < 0)
-        return (ST_EOF);
-
-    snd_pcm_format_mask_free(fmask);
-
-    if ((err = snd_pcm_hw_params_set_format(alsa->pcm_handle, 
-                                            hw_params, fmt)) < 0) 
-    {
-        st_fail_errno(ft, ST_EPERM, "cannot set sample format");
-        return ST_EOF;
-    }
-
-    snd_pcm_hw_params_get_rate_min(hw_params, &min_rate, &dir);
-    snd_pcm_hw_params_get_rate_max(hw_params, &max_rate, &dir);
-
-    rate = ft->info.rate;
-    if (rate < min_rate) 
-        rate = min_rate;
-    else 
-        if (rate > max_rate) 
-            rate = max_rate;
-    if (rate != ft->info.rate)
-    {
-        st_warn("alsa: Hardware does not support %d.  Forcing sample rate to %d.", ft->info.rate, rate);
-    }
-
-    dir = 0;
-    if ((err = snd_pcm_hw_params_set_rate_near(alsa->pcm_handle, 
-                                               hw_params, 
-                                               &rate,
-                                               &dir)) < 0) 
-    {
-        st_fail_errno(ft, ST_EPERM, "cannot set sample rate");
-        return ST_EOF;
-    }
-    if (rate != ft->info.rate)
-    {
-        st_warn("Could not set exact rate of %d.  Approximating with %d",
-                ft->info.rate, rate);
-    }
-
-    snd_pcm_hw_params_get_rate(hw_params, &rate, &dir);
-
-    if ((err = snd_pcm_hw_params_set_channels(alsa->pcm_handle,
-                                              hw_params, 
-                                              ft->info.channels)) < 0) 
-    {
-        st_fail_errno(ft, ST_EPERM, "cannot set channel count");
-        return ST_EOF;
-    }
-
-#if 0
-    /* Set number of periods. Periods used to be called fragments. */ 
-    if (snd_pcm_hw_params_set_periods(alsa->pcm_handle, hw_params, 2, 0) < 0) 
-    {
-        st_fail_errno(ft, ST_EPERM, "Error setting periods.");
-        return ST_EOF;
-    }
-
-    /* Set buffer size (in frames). The resulting latency is given by */
-    /* latency = periodsize * periods / (rate * bytes_per_frame)     */
-    if (snd_pcm_hw_params_set_buffer_size(alsa->pcm_handle, hw_params, (ST_BUFSIZ * 2)>>2) < 0) {
-      st_fail_errno(ft, ST_EPERM, "Error setting buffersize.");
-      return ST_EOF;
-    }
-#endif
-
-    if ((err = snd_pcm_hw_params(alsa->pcm_handle, hw_params)) < 0) 
-    {
-        st_fail_errno(ft, ST_EPERM, "cannot set parameters");
-        return ST_EOF;
-    }
-
-    snd_pcm_hw_params_free(hw_params);
-
-    if ((err = snd_pcm_prepare(alsa->pcm_handle)) < 0) 
-    {
-        st_fail_errno(ft, ST_EPERM, "cannot prepare audio interface for use");
-        return ST_EOF;
-    }
-
-    sigintreg(ft);      /* Prepare to catch SIGINT */
-
-    return (ST_SUCCESS);
 }
 
 st_ssize_t st_alsawrite(ft_t ft, st_sample_t *buf, st_ssize_t nsamp)
@@ -535,6 +486,8 @@
             continue;
         if (err < 0)
         {
+            if (ft->file.eof)
+                return ST_EOF;
             if (xrun_recovery(alsa->pcm_handle, err) < 0)
             {
                 st_fail_errno(ft, ST_EPERM, "ALSA write error\n");
--- a/src/sox.c
+++ b/src/sox.c
@@ -1190,6 +1190,11 @@
         /* left */
         idonel = (idone + 1)/2;         /* odd-length logic */
         odonel = odone/2;
+#if 0
+        fprintf(stderr, "pre %s idone=%d, odone=%d\n", efftab[e].name, idone, odone);
+        fprintf(stderr, "pre %s odone1=%d, olen1=%d odone=%d olen=%d\n", efftab[e].name, efftab[e-1].odone, efftab[e-1].olen, efftab[e].odone, efftab[e].olen); 
+#endif
+
         effstatus = (* efftab[e].h->flow)(&efftab[e],
                                           ibufl, obufl, (st_size_t *)&idonel, 
                                           (st_size_t *)&odonel);
@@ -1214,6 +1219,12 @@
         /* Don't clear since nothng has been consumed yet */
         /*efftab[e].odone = 0;*/
         efftab[e].olen += odonel + odoner;
+#if 0
+        fprintf(stderr, "post %s idone=%d, odone=%d\n", efftab[e].name, idone, odone); 
+        fprintf(stderr, "post %s odone1=%d, olen1=%d odone=%d olen=%d\n", efftab[e].name, efftab[e-1].odone, efftab[e-1].olen, efftab[e].odone, efftab[e].olen);
+#endif
+
+
         done = idonel + idoner + odonel + odoner;
     }
     if (effstatus == ST_EOF)