]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Added snd_pcm_hw_params_set_rate_resample function
authorJaroslav Kysela <perex@perex.cz>
Tue, 12 Apr 2005 12:09:55 +0000 (12:09 +0000)
committerJaroslav Kysela <perex@perex.cz>
Tue, 12 Apr 2005 12:09:55 +0000 (12:09 +0000)
- snd_pcm_hw_params_set_rate_resample()
- snd_pcm_hw_params_get_rate_resample()

include/pcm.h
include/sound/asound.h
src/Versions
src/pcm/pcm.c
src/pcm/pcm_local.h
src/pcm/pcm_params.c
src/pcm/pcm_plug.c
test/latency.c
test/pcm.c

index 5224bb3cb22b58db7622c19812a00072dfc24321..a152683f5843169891ef4100c5424e862108b538 100644 (file)
@@ -585,6 +585,8 @@ int snd_pcm_hw_params_set_rate_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *param
 int snd_pcm_hw_params_set_rate_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
 int snd_pcm_hw_params_set_rate_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
 int snd_pcm_hw_params_set_rate_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
+int snd_pcm_hw_params_set_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val);
+int snd_pcm_hw_params_get_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val);
 
 int snd_pcm_hw_params_get_period_time(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
 int snd_pcm_hw_params_get_period_time_min(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
@@ -735,6 +737,8 @@ int snd_pcm_hw_params_set_rate_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *param
 unsigned int snd_pcm_hw_params_set_rate_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int *dir);
 unsigned int snd_pcm_hw_params_set_rate_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
 unsigned int snd_pcm_hw_params_set_rate_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir);
+int snd_pcm_hw_params_set_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val);
+int snd_pcm_hw_params_get_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val);
 
 asm(".symver snd_pcm_hw_params_get_period_time,snd_pcm_hw_params_get_period_time@ALSA_0.9");
 asm(".symver snd_pcm_hw_params_get_period_time_min,snd_pcm_hw_params_get_period_time_min@ALSA_0.9");
index 42c586ef76e69fadd684e9e73904b38bc114d9eb..4df0483131f0861f7fa3b06a6bfde51c2ca3d7e0 100644 (file)
@@ -340,7 +340,7 @@ enum sndrv_pcm_hw_param {
        SNDRV_PCM_HW_PARAM_LAST_INTERVAL = SNDRV_PCM_HW_PARAM_TICK_TIME
 };
 
-#define SNDRV_PCM_HW_PARAMS_RUNTIME            (1<<0)
+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0)  /* avoid rate resampling */
 
 struct sndrv_interval {
        unsigned int min, max;
index 1e2b1a4b210964a381f326cfd6dd1896c9402061..24ecb1ed76fd0ed468b9535e69dedd1bac3d93ef 100644 (file)
@@ -174,6 +174,9 @@ ALSA_1.0.8 {
 ALSA_1.0.9 {
   global:
 
+    snd_pcm_hw_params_set_rate_resample;
+    snd_pcm_hw_params_get_rate_resample;
+
     snd_pcm_ioplug_create;
     snd_pcm_ioplug_delete;
     snd_pcm_ioplug_reinit_status;
index 7a3a5b77526b06110a3cc13055410d64f73b6cc0..acc5e5e6769e792fa594d74e703e66af40fec03d 100644 (file)
@@ -744,6 +744,7 @@ int snd_pcm_hw_params_current(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
        if (!pcm->setup)
                return -EBADFD;
        memset(params, 0, snd_pcm_hw_params_sizeof());
+       params->flags = pcm->hw_flags;
        snd_mask_copy(&params->masks[SND_PCM_HW_PARAM_ACCESS - SND_PCM_HW_PARAM_FIRST_MASK], (snd_mask_t *)&pcm->access);
        snd_mask_copy(&params->masks[SND_PCM_HW_PARAM_FORMAT - SND_PCM_HW_PARAM_FIRST_MASK], (snd_mask_t *)&pcm->format);
        snd_mask_copy(&params->masks[SND_PCM_HW_PARAM_SUBFORMAT - SND_PCM_HW_PARAM_FIRST_MASK], (snd_mask_t *)&pcm->subformat);
@@ -3909,6 +3910,35 @@ int snd_pcm_hw_params_set_rate_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
        return snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_RATE, val, dir);
 }
 
+/**
+ * \brief Restrict a configuration space to contain only real hardware rates
+ * \param pcm PCM handle
+ * \param params Configuration space
+ * \param val 0 = disable, 1 = enable (default) rate resampling
+ * \return 0 otherwise a negative error code
+ */
+int snd_pcm_hw_params_set_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val)
+{
+       assert(pcm && params);
+       if (!val)
+               params->flags |= SND_PCM_HW_PARAMS_NORESAMPLE;
+       else
+               params->flags &= ~SND_PCM_HW_PARAMS_NORESAMPLE;
+       return snd_pcm_hw_refine(pcm, params);
+}
+
+/**
+ * \brief Extract resample state from a configuration space
+ * \param pcm PCM handle
+ * \param *val 0 = disable, 1 = enable rate resampling
+ * \return 0 otherwise a negative error code
+ */
+int snd_pcm_hw_params_get_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val)
+{
+       assert(pcm && params && val);
+       *val = params->flags & SND_PCM_HW_PARAMS_NORESAMPLE ? 0 : 1;
+       return 0;
+}
 
 /**
  * \brief Extract period time from a configuration space
index bd8838a5eeef188dd7f409d3531dc98a3bac1304..948e0f06989f4051827d61847d82adcfa2d965b9 100644 (file)
@@ -58,7 +58,6 @@ typedef enum sndrv_pcm_hw_param snd_pcm_hw_param_t;
 #define SND_PCM_HW_PARAM_BUFFER_BYTES SNDRV_PCM_HW_PARAM_BUFFER_BYTES
 #define SND_PCM_HW_PARAM_TICK_TIME SNDRV_PCM_HW_PARAM_TICK_TIME
 #define SND_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_LAST_INTERVAL
-#define SND_PCM_HW_PARAMS_RUNTIME SNDRV_PCM_HW_PARAMS_RUNTIME
 #define SND_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_LAST_MASK
 #define SND_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_FIRST_MASK
 #define SND_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_LAST_INTERVAL
@@ -93,6 +92,12 @@ typedef enum sndrv_pcm_hw_param snd_pcm_hw_param_t;
 /** device can do a kind of synchronized start */
 #define SND_PCM_INFO_SYNC_START SNDRV_PCM_INFO_SYNC_START
 
+#ifndef SNDRV_PCM_HW_PARAMS_NORESAMPLE
+#define SND_PCM_HW_PARAMS_NORESAMPLE (1<<0)
+#else
+#define SND_PCM_HW_PARAMS_NORESAMPLE SNDRV_PCM_HW_PARAMS_NORESAMPLE
+#endif
+
 typedef struct _snd_pcm_rbptr {
        snd_pcm_t *master;
        volatile snd_pcm_uframes_t *ptr;
@@ -199,6 +204,7 @@ struct _snd_pcm {
        unsigned int msbits;            /* used most significant bits */
        unsigned int rate_num;          /* rate numerator */
        unsigned int rate_den;          /* rate denominator */
+       unsigned int hw_flags;          /* actual hardware flags */
        snd_pcm_uframes_t fifo_size;    /* chip FIFO size in frames */
        snd_pcm_uframes_t buffer_size;
        snd_interval_t buffer_time;
index 631e2652f99f71531d7ab5e13dc7ace46c549525..c62d1c2b600ecc0918683042896fedfc2b4a601c 100644 (file)
@@ -2281,6 +2281,7 @@ int _snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
        }
        pcm->min_align = min_align;
        
+       pcm->hw_flags = params->flags;
        pcm->info = params->info;
        pcm->msbits = params->msbits;
        pcm->rate_num = params->rate_num;
index 7ff34ff7b5d23e30719c99eb9e404e490e6e61be..e71102a8272bdda96eed6a5aae4d9e2cbe4e4e4a 100644 (file)
@@ -728,6 +728,8 @@ static int snd_pcm_plug_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *p
        err = _snd_pcm_hw_params_refine(sparams, links, params);
        if (err < 0)
                return err;
+       if (params->flags & SND_PCM_HW_PARAMS_NORESAMPLE)
+               snd_interval_copy((snd_interval_t *)snd_pcm_hw_param_get_interval(params, SND_PCM_HW_PARAM_RATE), snd_pcm_hw_param_get_interval(sparams, SND_PCM_HW_PARAM_RATE));
        return 0;
 }
        
@@ -830,6 +832,8 @@ static int snd_pcm_plug_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
        err = _snd_pcm_hw_params_refine(params, links, sparams);
        if (err < 0)
                return err;
+       if (params->flags & SND_PCM_HW_PARAMS_NORESAMPLE)
+               snd_interval_copy((snd_interval_t *)snd_pcm_hw_param_get_interval(params, SND_PCM_HW_PARAM_RATE), snd_pcm_hw_param_get_interval(sparams, SND_PCM_HW_PARAM_RATE));
        /* FIXME */
        params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
        return 0;
index eb7292f9e3623254b50103f9248ea18a04ee0d8d..a135da874088513ce3bb0334c637b37f37f554cb 100644 (file)
@@ -51,6 +51,7 @@ int block = 0;                        /* block mode */
 int tick_time = 0;             /* disabled, otherwise in us */
 int tick_time_ok = 0;
 int use_poll = 0;
+int resample = 1;
 unsigned long loop_limit;
 
 snd_output_t *output = NULL;
@@ -67,6 +68,11 @@ int setparams_stream(snd_pcm_t *handle,
                printf("Broken configuration for %s PCM: no configurations available: %s\n", snd_strerror(err), id);
                return err;
        }
+       err = snd_pcm_hw_params_set_rate_resample(handle, params, resample);
+       if (err < 0) {
+               printf("Resample setup failed for %s (val %i): %s\n", id, resample, snd_strerror(err));
+               return err;
+       }
        err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
        if (err < 0) {
                printf("Access type not available for %s: %s\n", id, snd_strerror(err));
@@ -518,7 +524,7 @@ int main(int argc, char *argv[])
        morehelp = 0;
        while (1) {
                int c;
-               if ((c = getopt_long(argc, argv, "hP:C:m:M:F:f:c:r:s:bt:pe", long_option, NULL)) < 0)
+               if ((c = getopt_long(argc, argv, "hP:C:m:M:F:f:c:r:s:bt:pen", long_option, NULL)) < 0)
                        break;
                switch (c) {
                case 'h':
@@ -580,6 +586,9 @@ int main(int argc, char *argv[])
                case 'e':
                        effect = 1;
                        break;
+               case 'n':
+                       resample = 0;
+                       break;
                }
        }
 
index 1c215994a0c29c246351d03c6f3a28a5fb0bd27c..47acf733b612cda660517aaa3e671207bee85a87 100644 (file)
@@ -20,6 +20,7 @@ unsigned int buffer_time = 500000;            /* ring buffer length in us */
 unsigned int period_time = 100000;             /* period time in us */
 double freq = 440;                             /* sinusoidal wave frequency in Hz */
 int verbose = 0;                               /* verbose flag */
+int resample = 1;                              /* enable alsa-lib resampling */
 
 snd_pcm_sframes_t buffer_size;
 snd_pcm_sframes_t period_size;
@@ -80,6 +81,12 @@ static int set_hwparams(snd_pcm_t *handle,
                printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
                return err;
        }
+       /* set hardware resampling */
+       err = snd_pcm_hw_params_set_rate_resample(handle, params, resample);
+       if (err < 0) {
+               printf("Resampling setup failed for playback: %s\n", snd_strerror(err));
+               return err;
+       }
        /* set the interleaved read/write format */
        err = snd_pcm_hw_params_set_access(handle, params, access);
        if (err < 0) {
@@ -729,6 +736,7 @@ int main(int argc, char *argv[])
                {"period", 1, NULL, 'p'},
                {"method", 1, NULL, 'm'},
                {"verbose", 1, NULL, 'v'},
+               {"noresample", 1, NULL, 'n'},
                {NULL, 0, NULL, 0},
        };
        snd_pcm_t *handle;
@@ -746,7 +754,7 @@ int main(int argc, char *argv[])
        morehelp = 0;
        while (1) {
                int c;
-               if ((c = getopt_long(argc, argv, "hD:r:c:f:b:p:m:v", long_option, NULL)) < 0)
+               if ((c = getopt_long(argc, argv, "hD:r:c:f:b:p:m:vn", long_option, NULL)) < 0)
                        break;
                switch (c) {
                case 'h':
@@ -790,6 +798,9 @@ int main(int argc, char *argv[])
                case 'v':
                        verbose = 1;
                        break;
+               case 'n':
+                       resample = 0;
+                       break;
                }
        }