aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pcm_utils.h14
-rw-r--r--src/pcm_volume.c28
2 files changed, 42 insertions, 0 deletions
diff --git a/src/pcm_utils.h b/src/pcm_utils.h
index 93f414231..8b2259655 100644
--- a/src/pcm_utils.h
+++ b/src/pcm_utils.h
@@ -38,4 +38,18 @@ pcm_range(int32_t sample, unsigned bits)
return sample;
}
+/**
+ * Check if the value is within the range of the provided bit size,
+ * and caps it if necessary.
+ */
+static inline int64_t
+pcm_range_64(int64_t sample, unsigned bits)
+{
+ if (G_UNLIKELY(sample < ((int64_t)-1 << (bits - 1))))
+ return (int64_t)-1 << (bits - 1);
+ if (G_UNLIKELY(sample >= ((int64_t)1 << (bits - 1))))
+ return ((int64_t)1 << (bits - 1)) - 1;
+ return sample;
+}
+
#endif
diff --git a/src/pcm_volume.c b/src/pcm_volume.c
index ca720a30e..90ad17d6d 100644
--- a/src/pcm_volume.c
+++ b/src/pcm_volume.c
@@ -114,6 +114,29 @@ pcm_volume_change_24(int32_t *buffer, unsigned num_samples, int volume)
}
}
+static void
+pcm_volume_change_32(int32_t *buffer, unsigned num_samples, int volume)
+{
+ while (num_samples > 0) {
+#ifdef __i386__
+ /* assembly version for i386 */
+ int32_t sample = *buffer;
+
+ *buffer++ = pcm_volume_sample_24(sample, volume, 0);
+#else
+ /* portable version */
+ int64_t sample = *buffer;
+
+ sample = (sample * volume + pcm_volume_dither() +
+ PCM_VOLUME_1 / 2)
+ / PCM_VOLUME_1;
+ *buffer++ = pcm_range_64(sample, 32);
+#endif
+
+ --num_samples;
+ }
+}
+
bool
pcm_volume(void *buffer, int length,
const struct audio_format *format,
@@ -142,6 +165,11 @@ pcm_volume(void *buffer, int length,
volume);
return true;
+ case 32:
+ pcm_volume_change_32((int32_t*)buffer, length / 4,
+ volume);
+ return true;
+
default:
return false;
}