snd_pcm_t *req_slave;
int close_slave;
snd_pcm_t *slave;
+ snd_pcm_format_t sformat;
+ int schannels;
+ int srate;
snd_pcm_route_ttable_entry_t *ttable;
unsigned int tt_ssize, tt_cused, tt_sused;
} snd_pcm_plug_t;
return 0;
}
-static int snd_pcm_plug_hw_refine_sprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *sparams)
+static int snd_pcm_plug_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
{
+ snd_pcm_plug_t *plug = pcm->private_data;
_snd_pcm_hw_params_any(sparams);
+ if (plug->sformat >= 0) {
+ _snd_pcm_hw_params_set_format(sparams, plug->sformat);
+ _snd_pcm_hw_params_set_subformat(sparams, SND_PCM_SUBFORMAT_STD);
+ }
+ if (plug->schannels > 0)
+ _snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_CHANNELS,
+ plug->schannels, 0);
+ if (plug->srate > 0)
+ _snd_pcm_hw_param_set_minmax(sparams, SND_PCM_HW_PARAM_RATE,
+ plug->srate, 0, plug->srate + 1, -1);
+ if (plug->sformat >= 0 || plug->schannels > 0 || plug->srate > 0) {
+ int err = snd_pcm_hw_refine(plug->req_slave, sparams);
+ if (err < 0)
+ return err;
+ }
return 0;
}
snd_pcm_format_t format;
snd_interval_t t, buffer_size;
const snd_interval_t *srate, *crate;
- snd_pcm_hw_param_refine_near(slave, sparams, SND_PCM_HW_PARAM_RATE,
- params);
- snd_pcm_hw_param_refine_near(slave, sparams, SND_PCM_HW_PARAM_CHANNELS,
- params);
- format_mask = snd_pcm_hw_param_get_mask(params,
- SND_PCM_HW_PARAM_FORMAT);
- sformat_mask = snd_pcm_hw_param_get_mask(sparams,
- SND_PCM_HW_PARAM_FORMAT);
- snd_mask_none(&sfmt_mask);
- for (format = 0; format <= SND_PCM_FORMAT_LAST; snd_enum_incr(format)) {
- snd_pcm_format_t f;
- if (!snd_pcm_format_mask_test(format_mask, format))
- continue;
- if (snd_pcm_format_mask_test(sformat_mask, format))
- f = format;
- else {
- f = snd_pcm_plug_slave_format(format, sformat_mask);
- if (f == SND_PCM_FORMAT_UNKNOWN)
+ if (plug->srate == -2)
+ links |= SND_PCM_HW_PARBIT_RATE;
+ else
+ snd_pcm_hw_param_refine_near(slave, sparams, SND_PCM_HW_PARAM_RATE,
+ params);
+ if (plug->schannels == -2)
+ links |= SND_PCM_HW_PARBIT_CHANNELS;
+ else
+ snd_pcm_hw_param_refine_near(slave, sparams, SND_PCM_HW_PARAM_CHANNELS,
+ params);
+ if (plug->sformat == -2)
+ links |= SND_PCM_HW_PARBIT_FORMAT;
+ else {
+ format_mask = snd_pcm_hw_param_get_mask(params,
+ SND_PCM_HW_PARAM_FORMAT);
+ sformat_mask = snd_pcm_hw_param_get_mask(sparams,
+ SND_PCM_HW_PARAM_FORMAT);
+ snd_mask_none(&sfmt_mask);
+ for (format = 0; format <= SND_PCM_FORMAT_LAST; snd_enum_incr(format)) {
+ snd_pcm_format_t f;
+ if (!snd_pcm_format_mask_test(format_mask, format))
continue;
+ if (snd_pcm_format_mask_test(sformat_mask, format))
+ f = format;
+ else {
+ f = snd_pcm_plug_slave_format(format, sformat_mask);
+ if (f == SND_PCM_FORMAT_UNKNOWN)
+ continue;
+ }
+ snd_pcm_format_mask_set(&sfmt_mask, f);
}
- snd_pcm_format_mask_set(&sfmt_mask, f);
- }
- err = snd_pcm_hw_param_set_mask(slave, sparams, SND_CHANGE,
- SND_PCM_HW_PARAM_FORMAT, &sfmt_mask);
- assert(err >= 0);
+ err = snd_pcm_hw_param_set_mask(slave, sparams, SND_CHANGE,
+ SND_PCM_HW_PARAM_FORMAT, &sfmt_mask);
+ assert(err >= 0);
+ }
if (snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_FORMAT, sparams) ||
snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_CHANNELS, sparams) ||
_snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
&access_mask);
}
- if (snd_pcm_hw_param_always_eq(params, SND_PCM_HW_PARAM_RATE, sparams))
+ if ((links & SND_PCM_HW_PARBIT_RATE) ||
+ snd_pcm_hw_param_always_eq(params, SND_PCM_HW_PARAM_RATE, sparams))
links |= (SND_PCM_HW_PARBIT_PERIOD_SIZE |
SND_PCM_HW_PARBIT_BUFFER_SIZE);
else {
snd_pcm_hw_params_t *params,
snd_pcm_hw_params_t *sparams)
{
+ snd_pcm_plug_t *plug = pcm->private_data;
unsigned int links = (SND_PCM_HW_PARBIT_PERIOD_TIME |
SND_PCM_HW_PARBIT_TICK_TIME);
const snd_pcm_format_mask_t *format_mask, *sformat_mask;
const snd_interval_t *srate, *crate;
unsigned int rate_min, srate_min;
int rate_mindir, srate_mindir;
- format_mask = snd_pcm_hw_param_get_mask(params,
- SND_PCM_HW_PARAM_FORMAT);
- sformat_mask = snd_pcm_hw_param_get_mask(sparams,
- SND_PCM_HW_PARAM_FORMAT);
- snd_mask_none(&fmt_mask);
- for (format = 0; format <= SND_PCM_FORMAT_LAST; snd_enum_incr(format)) {
- snd_pcm_format_t f;
- if (!snd_pcm_format_mask_test(format_mask, format))
- continue;
- if (snd_pcm_format_mask_test(sformat_mask, format))
- f = format;
- else {
- f = snd_pcm_plug_slave_format(format, sformat_mask);
- if (f == SND_PCM_FORMAT_UNKNOWN)
+
+ if (plug->schannels == -2)
+ links |= SND_PCM_HW_PARBIT_CHANNELS;
+
+ if (plug->sformat == -2)
+ links |= SND_PCM_HW_PARBIT_FORMAT;
+ else {
+ format_mask = snd_pcm_hw_param_get_mask(params,
+ SND_PCM_HW_PARAM_FORMAT);
+ sformat_mask = snd_pcm_hw_param_get_mask(sparams,
+ SND_PCM_HW_PARAM_FORMAT);
+ snd_mask_none(&fmt_mask);
+ for (format = 0; format <= SND_PCM_FORMAT_LAST; snd_enum_incr(format)) {
+ snd_pcm_format_t f;
+ if (!snd_pcm_format_mask_test(format_mask, format))
continue;
+ if (snd_pcm_format_mask_test(sformat_mask, format))
+ f = format;
+ else {
+ f = snd_pcm_plug_slave_format(format, sformat_mask);
+ if (f == SND_PCM_FORMAT_UNKNOWN)
+ continue;
+ }
+ snd_pcm_format_mask_set(&fmt_mask, format);
}
- snd_pcm_format_mask_set(&fmt_mask, format);
- }
-
- err = _snd_pcm_hw_param_set_mask(params,
- SND_PCM_HW_PARAM_FORMAT, &fmt_mask);
- if (err < 0)
- return err;
- /* This is a temporary hack, waiting for a better solution */
- rate_min = snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_RATE, &rate_mindir);
- srate_min = snd_pcm_hw_param_get_min(sparams, SND_PCM_HW_PARAM_RATE, &srate_mindir);
- if (rate_min == srate_min && srate_mindir > rate_mindir) {
- err = _snd_pcm_hw_param_set_min(params, SND_PCM_HW_PARAM_RATE, srate_min, srate_mindir);
+ err = _snd_pcm_hw_param_set_mask(params,
+ SND_PCM_HW_PARAM_FORMAT, &fmt_mask);
if (err < 0)
return err;
}
- if (snd_pcm_hw_param_always_eq(params, SND_PCM_HW_PARAM_RATE, sparams))
+ if (plug->srate == -2)
+ links |= SND_PCM_HW_PARBIT_RATE;
+ else {
+ /* This is a temporary hack, waiting for a better solution */
+ rate_min = snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_RATE, &rate_mindir);
+ srate_min = snd_pcm_hw_param_get_min(sparams, SND_PCM_HW_PARAM_RATE, &srate_mindir);
+ if (rate_min == srate_min && srate_mindir > rate_mindir) {
+ err = _snd_pcm_hw_param_set_min(params, SND_PCM_HW_PARAM_RATE, srate_min, srate_mindir);
+ if (err < 0)
+ return err;
+ }
+ }
+ if ((links & SND_PCM_HW_PARBIT_RATE) ||
+ snd_pcm_hw_param_always_eq(params, SND_PCM_HW_PARAM_RATE, sparams))
links |= (SND_PCM_HW_PARBIT_PERIOD_SIZE |
SND_PCM_HW_PARBIT_BUFFER_SIZE);
else {
int snd_pcm_plug_open(snd_pcm_t **pcmp,
const char *name,
+ snd_pcm_format_t sformat, int schannels, int srate,
snd_pcm_route_ttable_entry_t *ttable,
unsigned int tt_ssize,
unsigned int tt_cused, unsigned int tt_sused,
plug = calloc(1, sizeof(snd_pcm_plug_t));
if (!plug)
return -ENOMEM;
+ plug->sformat = sformat;
+ plug->schannels = schannels;
+ plug->srate = srate;
plug->slave = plug->req_slave = slave;
plug->close_slave = close_slave;
plug->ttable = ttable;
return 0;
}
-int snd_pcm_plug_open_hw(snd_pcm_t **pcmp, const char *name, int card, int device, int subdevice, snd_pcm_stream_t stream, int mode)
-{
- snd_pcm_t *slave;
- int err;
- err = snd_pcm_hw_open(&slave, NULL, card, device, subdevice, stream, mode);
- if (err < 0)
- return err;
- return snd_pcm_plug_open(pcmp, name, 0, 0, 0, 0, slave, 1);
-}
-
-#define MAX_CHANNELS 32
+#define MAX_CHANNELS 64
int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
snd_config_t *root, snd_config_t *conf,
snd_config_t *tt = NULL;
snd_pcm_route_ttable_entry_t *ttable = NULL;
unsigned int cused, sused;
+ snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
+ int schannels = -1, srate = -1;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id = snd_config_get_id(n);
SNDERR("slave is not defined");
return -EINVAL;
}
- err = snd_pcm_slave_conf(root, slave, &sconf, 0);
+ err = snd_pcm_slave_conf(root, slave, &sconf, 3,
+ SND_PCM_HW_PARAM_FORMAT, SCONF_UNCHANGED, &sformat,
+ SND_PCM_HW_PARAM_CHANNELS, SCONF_UNCHANGED, &schannels,
+ SND_PCM_HW_PARAM_RATE, SCONF_UNCHANGED, &srate);
if (err < 0)
return err;
if (tt) {
snd_config_delete(sconf);
if (err < 0)
return err;
- err = snd_pcm_plug_open(pcmp, name, ttable, MAX_CHANNELS, cused, sused, spcm, 1);
+ err = snd_pcm_plug_open(pcmp, name, sformat, schannels, srate,
+ ttable, MAX_CHANNELS, cused, sused, spcm, 1);
if (err < 0)
snd_pcm_close(spcm);
return err;
#endif
#ifdef GETS_LABELS
-static inline int32_t getS(const void *src, int src_sign, int src_wid, int src_end,
- int dst_wid)
+static inline int32_t _gets(const void *src,
+ int src_sign, int src_wid, int src_end,
+ int dst_wid)
{
int32_t s;
switch (src_wid) {
s -= 1U << (src_wid - 1);
if (src_wid < dst_wid)
return s * (1 << (dst_wid - src_wid));
- else
+ else if (src_wid > dst_wid)
return s / (1 << (src_wid - dst_wid));
+ return s;
}
/* src_sign src_wid src_end dst_wid */
#endif
#ifdef GETS_END
-gets_u8_8: sample = getS(src, 0, 8, 0, 8); goto GETS_END;
-gets_u8_16: sample = getS(src, 0, 8, 0, 16); goto GETS_END;
-gets_u8_24: sample = getS(src, 0, 8, 0, 24); goto GETS_END;
-gets_u8_32: sample = getS(src, 0, 8, 0, 32); goto GETS_END;
-gets_u16h_8: sample = getS(src, 0, 16, 0, 8); goto GETS_END;
-gets_u16h_16: sample = getS(src, 0, 16, 0, 16); goto GETS_END;
-gets_u16h_24: sample = getS(src, 0, 16, 0, 24); goto GETS_END;
-gets_u16h_32: sample = getS(src, 0, 16, 0, 32); goto GETS_END;
-gets_u16s_8: sample = getS(src, 0, 16, 1, 8); goto GETS_END;
-gets_u16s_16: sample = getS(src, 0, 16, 1, 16); goto GETS_END;
-gets_u16s_24: sample = getS(src, 0, 16, 1, 24); goto GETS_END;
-gets_u16s_32: sample = getS(src, 0, 16, 1, 32); goto GETS_END;
-gets_u24h_8: sample = getS(src, 0, 24, 0, 8); goto GETS_END;
-gets_u24h_16: sample = getS(src, 0, 24, 0, 16); goto GETS_END;
-gets_u24h_24: sample = getS(src, 0, 24, 0, 24); goto GETS_END;
-gets_u24h_32: sample = getS(src, 0, 24, 0, 32); goto GETS_END;
-gets_u24s_8: sample = getS(src, 0, 24, 1, 8); goto GETS_END;
-gets_u24s_16: sample = getS(src, 0, 24, 1, 16); goto GETS_END;
-gets_u24s_24: sample = getS(src, 0, 24, 1, 24); goto GETS_END;
-gets_u24s_32: sample = getS(src, 0, 24, 1, 32); goto GETS_END;
-gets_u32h_8: sample = getS(src, 0, 32, 0, 8); goto GETS_END;
-gets_u32h_16: sample = getS(src, 0, 32, 0, 16); goto GETS_END;
-gets_u32h_24: sample = getS(src, 0, 32, 0, 24); goto GETS_END;
-gets_u32h_32: sample = getS(src, 0, 32, 0, 32); goto GETS_END;
-gets_u32s_8: sample = getS(src, 0, 32, 1, 8); goto GETS_END;
-gets_u32s_16: sample = getS(src, 0, 32, 1, 16); goto GETS_END;
-gets_u32s_24: sample = getS(src, 0, 32, 1, 24); goto GETS_END;
-gets_u32s_32: sample = getS(src, 0, 32, 1, 32); goto GETS_END;
-gets_s8_8: sample = getS(src, 1, 8, 0, 8); goto GETS_END;
-gets_s8_16: sample = getS(src, 1, 8, 0, 16); goto GETS_END;
-gets_s8_24: sample = getS(src, 1, 8, 0, 24); goto GETS_END;
-gets_s8_32: sample = getS(src, 1, 8, 0, 32); goto GETS_END;
-gets_s16h_8: sample = getS(src, 1, 16, 0, 8); goto GETS_END;
-gets_s16h_16: sample = getS(src, 1, 16, 0, 16); goto GETS_END;
-gets_s16h_24: sample = getS(src, 1, 16, 0, 24); goto GETS_END;
-gets_s16h_32: sample = getS(src, 1, 16, 0, 32); goto GETS_END;
-gets_s16s_8: sample = getS(src, 1, 16, 1, 8); goto GETS_END;
-gets_s16s_16: sample = getS(src, 1, 16, 1, 16); goto GETS_END;
-gets_s16s_24: sample = getS(src, 1, 16, 1, 24); goto GETS_END;
-gets_s16s_32: sample = getS(src, 1, 16, 1, 32); goto GETS_END;
-gets_s24h_8: sample = getS(src, 1, 24, 0, 8); goto GETS_END;
-gets_s24h_16: sample = getS(src, 1, 24, 0, 16); goto GETS_END;
-gets_s24h_24: sample = getS(src, 1, 24, 0, 24); goto GETS_END;
-gets_s24h_32: sample = getS(src, 1, 24, 0, 32); goto GETS_END;
-gets_s24s_8: sample = getS(src, 1, 24, 1, 8); goto GETS_END;
-gets_s24s_16: sample = getS(src, 1, 24, 1, 16); goto GETS_END;
-gets_s24s_24: sample = getS(src, 1, 24, 1, 24); goto GETS_END;
-gets_s24s_32: sample = getS(src, 1, 24, 1, 32); goto GETS_END;
-gets_s32h_8: sample = getS(src, 1, 32, 0, 8); goto GETS_END;
-gets_s32h_16: sample = getS(src, 1, 32, 0, 16); goto GETS_END;
-gets_s32h_24: sample = getS(src, 1, 32, 0, 24); goto GETS_END;
-gets_s32h_32: sample = getS(src, 1, 32, 0, 32); goto GETS_END;
-gets_s32s_8: sample = getS(src, 1, 32, 1, 8); goto GETS_END;
-gets_s32s_16: sample = getS(src, 1, 32, 1, 16); goto GETS_END;
-gets_s32s_24: sample = getS(src, 1, 32, 1, 24); goto GETS_END;
-gets_s32s_32: sample = getS(src, 1, 32, 1, 32); goto GETS_END;
+gets_u8_8: sample = _gets(src, 0, 8, 0, 8); goto GETS_END;
+gets_u8_16: sample = _gets(src, 0, 8, 0, 16); goto GETS_END;
+gets_u8_24: sample = _gets(src, 0, 8, 0, 24); goto GETS_END;
+gets_u8_32: sample = _gets(src, 0, 8, 0, 32); goto GETS_END;
+gets_u16h_8: sample = _gets(src, 0, 16, 0, 8); goto GETS_END;
+gets_u16h_16: sample = _gets(src, 0, 16, 0, 16); goto GETS_END;
+gets_u16h_24: sample = _gets(src, 0, 16, 0, 24); goto GETS_END;
+gets_u16h_32: sample = _gets(src, 0, 16, 0, 32); goto GETS_END;
+gets_u16s_8: sample = _gets(src, 0, 16, 1, 8); goto GETS_END;
+gets_u16s_16: sample = _gets(src, 0, 16, 1, 16); goto GETS_END;
+gets_u16s_24: sample = _gets(src, 0, 16, 1, 24); goto GETS_END;
+gets_u16s_32: sample = _gets(src, 0, 16, 1, 32); goto GETS_END;
+gets_u24h_8: sample = _gets(src, 0, 24, 0, 8); goto GETS_END;
+gets_u24h_16: sample = _gets(src, 0, 24, 0, 16); goto GETS_END;
+gets_u24h_24: sample = _gets(src, 0, 24, 0, 24); goto GETS_END;
+gets_u24h_32: sample = _gets(src, 0, 24, 0, 32); goto GETS_END;
+gets_u24s_8: sample = _gets(src, 0, 24, 1, 8); goto GETS_END;
+gets_u24s_16: sample = _gets(src, 0, 24, 1, 16); goto GETS_END;
+gets_u24s_24: sample = _gets(src, 0, 24, 1, 24); goto GETS_END;
+gets_u24s_32: sample = _gets(src, 0, 24, 1, 32); goto GETS_END;
+gets_u32h_8: sample = _gets(src, 0, 32, 0, 8); goto GETS_END;
+gets_u32h_16: sample = _gets(src, 0, 32, 0, 16); goto GETS_END;
+gets_u32h_24: sample = _gets(src, 0, 32, 0, 24); goto GETS_END;
+gets_u32h_32: sample = _gets(src, 0, 32, 0, 32); goto GETS_END;
+gets_u32s_8: sample = _gets(src, 0, 32, 1, 8); goto GETS_END;
+gets_u32s_16: sample = _gets(src, 0, 32, 1, 16); goto GETS_END;
+gets_u32s_24: sample = _gets(src, 0, 32, 1, 24); goto GETS_END;
+gets_u32s_32: sample = _gets(src, 0, 32, 1, 32); goto GETS_END;
+gets_s8_8: sample = _gets(src, 1, 8, 0, 8); goto GETS_END;
+gets_s8_16: sample = _gets(src, 1, 8, 0, 16); goto GETS_END;
+gets_s8_24: sample = _gets(src, 1, 8, 0, 24); goto GETS_END;
+gets_s8_32: sample = _gets(src, 1, 8, 0, 32); goto GETS_END;
+gets_s16h_8: sample = _gets(src, 1, 16, 0, 8); goto GETS_END;
+gets_s16h_16: sample = _gets(src, 1, 16, 0, 16); goto GETS_END;
+gets_s16h_24: sample = _gets(src, 1, 16, 0, 24); goto GETS_END;
+gets_s16h_32: sample = _gets(src, 1, 16, 0, 32); goto GETS_END;
+gets_s16s_8: sample = _gets(src, 1, 16, 1, 8); goto GETS_END;
+gets_s16s_16: sample = _gets(src, 1, 16, 1, 16); goto GETS_END;
+gets_s16s_24: sample = _gets(src, 1, 16, 1, 24); goto GETS_END;
+gets_s16s_32: sample = _gets(src, 1, 16, 1, 32); goto GETS_END;
+gets_s24h_8: sample = _gets(src, 1, 24, 0, 8); goto GETS_END;
+gets_s24h_16: sample = _gets(src, 1, 24, 0, 16); goto GETS_END;
+gets_s24h_24: sample = _gets(src, 1, 24, 0, 24); goto GETS_END;
+gets_s24h_32: sample = _gets(src, 1, 24, 0, 32); goto GETS_END;
+gets_s24s_8: sample = _gets(src, 1, 24, 1, 8); goto GETS_END;
+gets_s24s_16: sample = _gets(src, 1, 24, 1, 16); goto GETS_END;
+gets_s24s_24: sample = _gets(src, 1, 24, 1, 24); goto GETS_END;
+gets_s24s_32: sample = _gets(src, 1, 24, 1, 32); goto GETS_END;
+gets_s32h_8: sample = _gets(src, 1, 32, 0, 8); goto GETS_END;
+gets_s32h_16: sample = _gets(src, 1, 32, 0, 16); goto GETS_END;
+gets_s32h_24: sample = _gets(src, 1, 32, 0, 24); goto GETS_END;
+gets_s32h_32: sample = _gets(src, 1, 32, 0, 32); goto GETS_END;
+gets_s32s_8: sample = _gets(src, 1, 32, 1, 8); goto GETS_END;
+gets_s32s_16: sample = _gets(src, 1, 32, 1, 16); goto GETS_END;
+gets_s32s_24: sample = _gets(src, 1, 32, 1, 24); goto GETS_END;
+gets_s32s_32: sample = _gets(src, 1, 32, 1, 32); goto GETS_END;
+#endif
+
+#ifdef NORMS_LABELS
+static inline void _norms(const void *src, void *dst,
+ int src_wid,
+ int dst_sign, int dst_wid, int dst_end)
+{
+ int32_t s;
+ switch (src_wid) {
+ case 8:
+ s = *(int8_t*)src;
+ if (s >= 0x7f)
+ goto _min;
+ else if (s <= -0x80)
+ goto _max;
+ break;
+ case 16:
+ s = *(int16_t*)src;
+ if (s >= 0x7fff)
+ goto _min;
+ else if (s <= -0x8000)
+ goto _max;
+ break;
+ case 24:
+ s = *(int32_t*)src;
+ if (s >= 0x7fffff)
+ goto _min;
+ else if (s <= -0x800000)
+ goto _max;
+ break;
+ case 32:
+ {
+ int64_t s64;
+ s64 = *(int64_t*)src;
+ if (s64 >= 0x7fffffff)
+ goto _min;
+ else if (s64 <= -0x80000000)
+ goto _max;
+ s = s64;
+ break;
+ }
+ default:
+ assert(0);
+ return;
+ }
+ if (src_wid < dst_wid) {
+ unsigned int bits = dst_wid - src_wid;
+ s *= 1 << bits;
+ } else if (src_wid > dst_wid) {
+ unsigned int bits = src_wid - dst_wid;
+ s = (s + (1 << (bits - 1)))/ (1 << bits);
+ }
+ if (!dst_sign)
+ s += (1U << (dst_wid - 1));
+ switch (dst_wid) {
+ case 8:
+ *(u_int8_t*)dst = s;
+ break;
+ case 16:
+ if (dst_end)
+ s = bswap_16(s);
+ *(u_int16_t*)dst = s;
+ break;
+ case 24:
+ case 32:
+ if (dst_end)
+ s = bswap_32(s);
+ *(u_int32_t*)dst = s;
+ break;
+ }
+ return;
+
+ _min:
+ switch (dst_wid) {
+ case 8:
+ if (dst_sign)
+ *(u_int8_t*)dst = 0x80;
+ else
+ *(u_int8_t*)dst = 0;
+ break;
+ case 16:
+ if (dst_sign)
+ *(u_int16_t*)dst = dst_end ? 0x0080 : 0x8000;
+ else
+ *(u_int16_t*)dst = 0;
+ break;
+ case 24:
+ if (dst_sign)
+ *(u_int32_t*)dst = dst_end ? 0x00008000 : 0x00800000;
+ else
+ *(u_int32_t*)dst = 0;
+ break;
+ case 32:
+ if (dst_sign)
+ *(u_int32_t*)dst = dst_end ? 0x00000080 : 0x80000000;
+ else
+ *(u_int32_t*)dst = 0;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ return;
+
+ _max:
+ switch (dst_wid) {
+ case 8:
+ if (dst_sign)
+ *(u_int8_t*)dst = 0x7f;
+ else
+ *(u_int8_t*)dst = 0xff;
+ break;
+ case 16:
+ if (dst_sign)
+ *(u_int16_t*)dst = dst_end ? 0xff7f : 0x7fff;
+ else
+ *(u_int16_t*)dst = 0;
+ break;
+ case 24:
+ if (dst_sign)
+ *(u_int32_t*)dst = dst_end ? 0xffff7f00 : 0x007fffff;
+ else
+ *(u_int32_t*)dst = 0;
+ break;
+ case 32:
+ if (dst_sign)
+ *(u_int32_t*)dst = dst_end ? 0xffffff7f : 0x7fffffff;
+ else
+ *(u_int32_t*)dst = 0;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ return;
+}
+
+/* src_wid dst_sign dst_wid dst_end */
+static void *norms_labels[4 * 2 * 4 * 2] = {
+ &&norms_8_u8, /* s8 -> u8 */
+ &&norms_8_u8, /* s8 -> u8 */
+ &&norms_8_u16h, /* s8 -> u16h */
+ &&norms_8_u16s, /* s8 -> u16s */
+ &&norms_8_u24h, /* s8 -> u24h */
+ &&norms_8_u24s, /* s8 -> u24s */
+ &&norms_8_u32h, /* s8 -> u32h */
+ &&norms_8_u32s, /* s8 -> u32s */
+ &&norms_8_s8, /* s8 -> s8 */
+ &&norms_8_s8, /* s8 -> s8 */
+ &&norms_8_s16h, /* s8 -> s16h */
+ &&norms_8_s16s, /* s8 -> s16s */
+ &&norms_8_s24h, /* s8 -> s24h */
+ &&norms_8_s24s, /* s8 -> s24s */
+ &&norms_8_s32h, /* s8 -> s32h */
+ &&norms_8_s32s, /* s8 -> s32s */
+ &&norms_16_u8, /* s16 -> u8 */
+ &&norms_16_u8, /* s16 -> u8 */
+ &&norms_16_u16h, /* s16 -> u16h */
+ &&norms_16_u16s, /* s16 -> u16s */
+ &&norms_16_u24h, /* s16 -> u24h */
+ &&norms_16_u24s, /* s16 -> u24s */
+ &&norms_16_u32h, /* s16 -> u32h */
+ &&norms_16_u32s, /* s16 -> u32s */
+ &&norms_16_s8, /* s16 -> s8 h*/
+ &&norms_16_s8, /* s16 -> s8 */
+ &&norms_16_s16h, /* s16 -> s16h */
+ &&norms_16_s16s, /* s16 -> s16s */
+ &&norms_16_s24h, /* s16 -> s24h */
+ &&norms_16_s24s, /* s16 -> s24s */
+ &&norms_16_s32h, /* s16 -> s32h */
+ &&norms_16_s32s, /* s16 -> s32s */
+ &&norms_24_u8, /* s24 -> u8 */
+ &&norms_24_u8, /* s24 -> u8 */
+ &&norms_24_u16h, /* s24 -> u16h */
+ &&norms_24_u16s, /* s24 -> u16s */
+ &&norms_24_u24h, /* s24 -> u24h */
+ &&norms_24_u24s, /* s24 -> u24s */
+ &&norms_24_u32h, /* s24 -> u32h */
+ &&norms_24_u32s, /* s24 -> u32s */
+ &&norms_24_s8, /* s24 -> s8 */
+ &&norms_24_s8, /* s24 -> s8 */
+ &&norms_24_s16h, /* s24 -> s16h */
+ &&norms_24_s16s, /* s24 -> s16s */
+ &&norms_24_s24h, /* s24 -> s24h */
+ &&norms_24_s24s, /* s24 -> s24s */
+ &&norms_24_s32h, /* s24 -> s32h */
+ &&norms_24_s32s, /* s24 -> s32s */
+ &&norms_32_u8, /* s32 -> u8 */
+ &&norms_32_u8, /* s32 -> u8 */
+ &&norms_32_u16h, /* s32 -> u16h */
+ &&norms_32_u16s, /* s32 -> u16s */
+ &&norms_32_u24h, /* s32 -> u24h */
+ &&norms_32_u24s, /* s32 -> u24s */
+ &&norms_32_u32h, /* s32 -> u32h */
+ &&norms_32_u32s, /* s32 -> u32s */
+ &&norms_32_s8, /* s32 -> s8 */
+ &&norms_32_s8, /* s32 -> s8 */
+ &&norms_32_s16h, /* s32 -> s16h */
+ &&norms_32_s16s, /* s32 -> s16s */
+ &&norms_32_s24h, /* s32 -> s24h */
+ &&norms_32_s24s, /* s32 -> s24s */
+ &&norms_32_s32h, /* s32 -> s32h */
+ &&norms_32_s32s, /* s32 -> s32s */
+};
+#endif
+
+#ifdef NORMS_END
+norms_8_u8: _norms(src, dst, 8, 0, 8, 0); goto NORMS_END;
+norms_8_u16h: _norms(src, dst, 8, 0, 16, 0); goto NORMS_END;
+norms_8_u16s: _norms(src, dst, 8, 0, 16, 1); goto NORMS_END;
+norms_8_u24h: _norms(src, dst, 8, 0, 24, 0); goto NORMS_END;
+norms_8_u24s: _norms(src, dst, 8, 0, 24, 1); goto NORMS_END;
+norms_8_u32h: _norms(src, dst, 8, 0, 32, 0); goto NORMS_END;
+norms_8_u32s: _norms(src, dst, 8, 0, 32, 1); goto NORMS_END;
+norms_8_s8: _norms(src, dst, 8, 1, 8, 0); goto NORMS_END;
+norms_8_s16h: _norms(src, dst, 8, 1, 16, 0); goto NORMS_END;
+norms_8_s16s: _norms(src, dst, 8, 1, 16, 1); goto NORMS_END;
+norms_8_s24h: _norms(src, dst, 8, 1, 24, 0); goto NORMS_END;
+norms_8_s24s: _norms(src, dst, 8, 1, 24, 1); goto NORMS_END;
+norms_8_s32h: _norms(src, dst, 8, 1, 32, 0); goto NORMS_END;
+norms_8_s32s: _norms(src, dst, 8, 1, 32, 1); goto NORMS_END;
+norms_16_u8: _norms(src, dst, 16, 0, 8, 0); goto NORMS_END;
+norms_16_u16h: _norms(src, dst, 16, 0, 16, 0); goto NORMS_END;
+norms_16_u16s: _norms(src, dst, 16, 0, 16, 1); goto NORMS_END;
+norms_16_u24h: _norms(src, dst, 16, 0, 24, 0); goto NORMS_END;
+norms_16_u24s: _norms(src, dst, 16, 0, 24, 1); goto NORMS_END;
+norms_16_u32h: _norms(src, dst, 16, 0, 32, 0); goto NORMS_END;
+norms_16_u32s: _norms(src, dst, 16, 0, 32, 1); goto NORMS_END;
+norms_16_s8: _norms(src, dst, 16, 1, 8, 0); goto NORMS_END;
+norms_16_s16h: _norms(src, dst, 16, 1, 16, 0); goto NORMS_END;
+norms_16_s16s: _norms(src, dst, 16, 1, 16, 1); goto NORMS_END;
+norms_16_s24h: _norms(src, dst, 16, 1, 24, 0); goto NORMS_END;
+norms_16_s24s: _norms(src, dst, 16, 1, 24, 1); goto NORMS_END;
+norms_16_s32h: _norms(src, dst, 16, 1, 32, 0); goto NORMS_END;
+norms_16_s32s: _norms(src, dst, 16, 1, 32, 1); goto NORMS_END;
+norms_24_u8: _norms(src, dst, 24, 0, 8, 0); goto NORMS_END;
+norms_24_u16h: _norms(src, dst, 24, 0, 16, 0); goto NORMS_END;
+norms_24_u16s: _norms(src, dst, 24, 0, 16, 1); goto NORMS_END;
+norms_24_u24h: _norms(src, dst, 24, 0, 24, 0); goto NORMS_END;
+norms_24_u24s: _norms(src, dst, 24, 0, 24, 1); goto NORMS_END;
+norms_24_u32h: _norms(src, dst, 24, 0, 32, 0); goto NORMS_END;
+norms_24_u32s: _norms(src, dst, 24, 0, 32, 1); goto NORMS_END;
+norms_24_s8: _norms(src, dst, 24, 1, 8, 0); goto NORMS_END;
+norms_24_s16h: _norms(src, dst, 24, 1, 16, 0); goto NORMS_END;
+norms_24_s16s: _norms(src, dst, 24, 1, 16, 1); goto NORMS_END;
+norms_24_s24h: _norms(src, dst, 24, 1, 24, 0); goto NORMS_END;
+norms_24_s24s: _norms(src, dst, 24, 1, 24, 1); goto NORMS_END;
+norms_24_s32h: _norms(src, dst, 24, 1, 32, 0); goto NORMS_END;
+norms_24_s32s: _norms(src, dst, 24, 1, 32, 1); goto NORMS_END;
+norms_32_u8: _norms(src, dst, 32, 0, 8, 0); goto NORMS_END;
+norms_32_u16h: _norms(src, dst, 32, 0, 16, 0); goto NORMS_END;
+norms_32_u16s: _norms(src, dst, 32, 0, 16, 1); goto NORMS_END;
+norms_32_u24h: _norms(src, dst, 32, 0, 24, 0); goto NORMS_END;
+norms_32_u24s: _norms(src, dst, 32, 0, 24, 1); goto NORMS_END;
+norms_32_u32h: _norms(src, dst, 32, 0, 32, 0); goto NORMS_END;
+norms_32_u32s: _norms(src, dst, 32, 0, 32, 1); goto NORMS_END;
+norms_32_s8: _norms(src, dst, 32, 1, 8, 0); goto NORMS_END;
+norms_32_s16h: _norms(src, dst, 32, 1, 16, 0); goto NORMS_END;
+norms_32_s16s: _norms(src, dst, 32, 1, 16, 1); goto NORMS_END;
+norms_32_s24h: _norms(src, dst, 32, 1, 24, 0); goto NORMS_END;
+norms_32_s24s: _norms(src, dst, 32, 1, 24, 1); goto NORMS_END;
+norms_32_s32h: _norms(src, dst, 32, 1, 32, 0); goto NORMS_END;
+norms_32_s32s: _norms(src, dst, 32, 1, 32, 1); goto NORMS_END;
#endif
#undef as_u8