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);
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");
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;
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;
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);
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
#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
/** 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;
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;
}
pcm->min_align = min_align;
+ pcm->hw_flags = params->flags;
pcm->info = params->info;
pcm->msbits = params->msbits;
pcm->rate_num = params->rate_num;
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;
}
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;
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;
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));
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':
case 'e':
effect = 1;
break;
+ case 'n':
+ resample = 0;
+ break;
}
}
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;
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) {
{"period", 1, NULL, 'p'},
{"method", 1, NULL, 'm'},
{"verbose", 1, NULL, 'v'},
+ {"noresample", 1, NULL, 'n'},
{NULL, 0, NULL, 0},
};
snd_pcm_t *handle;
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':
case 'v':
verbose = 1;
break;
+ case 'n':
+ resample = 0;
+ break;
}
}