From: Jaroslav Kysela Date: Tue, 12 Apr 2005 12:09:55 +0000 (+0000) Subject: Added snd_pcm_hw_params_set_rate_resample function X-Git-Tag: v1.0.9rc3~17 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=f65d9f31083661f16e72fcace5bd111a1e90f290;p=alsa-lib.git Added snd_pcm_hw_params_set_rate_resample function - snd_pcm_hw_params_set_rate_resample() - snd_pcm_hw_params_get_rate_resample() --- diff --git a/include/pcm.h b/include/pcm.h index 5224bb3c..a152683f 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -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"); diff --git a/include/sound/asound.h b/include/sound/asound.h index 42c586ef..4df04831 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -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; diff --git a/src/Versions b/src/Versions index 1e2b1a4b..24ecb1ed 100644 --- a/src/Versions +++ b/src/Versions @@ -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; diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 7a3a5b77..acc5e5e6 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -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(¶ms->masks[SND_PCM_HW_PARAM_ACCESS - SND_PCM_HW_PARAM_FIRST_MASK], (snd_mask_t *)&pcm->access); snd_mask_copy(¶ms->masks[SND_PCM_HW_PARAM_FORMAT - SND_PCM_HW_PARAM_FIRST_MASK], (snd_mask_t *)&pcm->format); snd_mask_copy(¶ms->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 diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index bd8838a5..948e0f06 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -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; diff --git a/src/pcm/pcm_params.c b/src/pcm/pcm_params.c index 631e2652..c62d1c2b 100644 --- a/src/pcm/pcm_params.c +++ b/src/pcm/pcm_params.c @@ -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; diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index 7ff34ff7..e71102a8 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -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; diff --git a/test/latency.c b/test/latency.c index eb7292f9..a135da87 100644 --- a/test/latency.c +++ b/test/latency.c @@ -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; } } diff --git a/test/pcm.c b/test/pcm.c index 1c215994..47acf733 100644 --- a/test/pcm.c +++ b/test/pcm.c @@ -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; } }