- if (!analog->encoding->is_float) {
- float offset = analog->encoding->offset.p / (float)analog->encoding->offset.q;
- float scale = analog->encoding->scale.p / (float)analog->encoding->scale.q;
- gboolean is_signed = analog->encoding->is_signed;
- gboolean is_bigendian = analog->encoding->is_bigendian;
- int8_t *data8 = (int8_t *)(analog->data);
- int16_t *data16 = (int16_t *)(analog->data);
- int32_t *data32 = (int32_t *)(analog->data);
-
- switch (analog->encoding->unitsize) {
- case 1:
- if (is_signed) {
- for (unsigned int i = 0; i < count; i++) {
- outbuf[i] = scale * data8[i];
- outbuf[i] += offset;
- }
- } else {
- for (unsigned int i = 0; i < count; i++) {
- outbuf[i] = scale * R8(data8 + i);
- outbuf[i] += offset;
- }
- }
- break;
- case 2:
- if (is_signed && is_bigendian) {
- for (unsigned int i = 0; i < count; i++) {
- outbuf[i] = scale * RB16S(&data16[i]);
- outbuf[i] += offset;
- }
- } else if (is_bigendian) {
- for (unsigned int i = 0; i < count; i++) {
- outbuf[i] = scale * RB16(&data16[i]);
- outbuf[i] += offset;
- }
- } else if (is_signed) {
- for (unsigned int i = 0; i < count; i++) {
- outbuf[i] = scale * RL16S(&data16[i]);
- outbuf[i] += offset;
- }
- } else {
- for (unsigned int i = 0; i < count; i++) {
- outbuf[i] = scale * RL16(&data16[i]);
- outbuf[i] += offset;
- }
- }
- break;
- case 4:
- if (is_signed && is_bigendian) {
- for (unsigned int i = 0; i < count; i++) {
- outbuf[i] = scale * RB32S(&data32[i]);
- outbuf[i] += offset;
- }
- } else if (is_bigendian) {
- for (unsigned int i = 0; i < count; i++) {
- outbuf[i] = scale * RB32(&data32[i]);
- outbuf[i] += offset;
- }
- } else if (is_signed) {
- for (unsigned int i = 0; i < count; i++) {
- outbuf[i] = scale * RL32S(&data32[i]);
- outbuf[i] += offset;
- }
- } else {
- for (unsigned int i = 0; i < count; i++) {
- outbuf[i] = scale * RL32(&data32[i]);
- outbuf[i] += offset;
- }
+ input_float = analog->encoding->is_float;
+ input_signed = analog->encoding->is_signed;
+ input_bigendian = analog->encoding->is_bigendian;
+ input_unitsize = analog->encoding->unitsize;
+
+ /*
+ * Prepare the iteration over the sample data: Get the common
+ * scale/offset factors which apply to all individual values.
+ * Position the read pointer on the first byte of input data.
+ */
+ offset = analog->encoding->offset.p;
+ offset /= analog->encoding->offset.q;
+ scale = analog->encoding->scale.p;
+ scale /= analog->encoding->scale.q;
+ data8 = analog->data;
+
+ /*
+ * Immediately handle the special case where input data needs
+ * no conversion because it already is in the application's
+ * native format. Do apply scale/offset though when applicable
+ * on our way out.
+ */
+ input_is_native = input_float &&
+ input_unitsize == sizeof(outbuf[0]) &&
+ input_bigendian == host_bigendian;
+ if (input_is_native) {
+ memcpy(outbuf, data8, count * sizeof(outbuf[0]));
+ if (scale != 1.0 || offset != 0.0) {
+ while (count--) {
+ *outbuf *= scale;
+ *outbuf += offset;
+ outbuf++;