aboutsummaryrefslogtreecommitdiffstats
path: root/src/pcm_volume.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pcm_volume.c')
-rw-r--r--src/pcm_volume.c64
1 files changed, 39 insertions, 25 deletions
diff --git a/src/pcm_volume.c b/src/pcm_volume.c
index 240c779d8..49c86026f 100644
--- a/src/pcm_volume.c
+++ b/src/pcm_volume.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2010 The Music Player Daemon Project
+ * Copyright (C) 2003-2011 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -31,9 +31,9 @@
#define G_LOG_DOMAIN "pcm_volume"
static void
-pcm_volume_change_8(int8_t *buffer, unsigned num_samples, int volume)
+pcm_volume_change_8(int8_t *buffer, const int8_t *end, int volume)
{
- while (num_samples > 0) {
+ while (buffer < end) {
int32_t sample = *buffer;
sample = (sample * volume + pcm_volume_dither() +
@@ -41,14 +41,13 @@ pcm_volume_change_8(int8_t *buffer, unsigned num_samples, int volume)
/ PCM_VOLUME_1;
*buffer++ = pcm_range(sample, 8);
- --num_samples;
}
}
static void
-pcm_volume_change_16(int16_t *buffer, unsigned num_samples, int volume)
+pcm_volume_change_16(int16_t *buffer, const int16_t *end, int volume)
{
- while (num_samples > 0) {
+ while (buffer < end) {
int32_t sample = *buffer;
sample = (sample * volume + pcm_volume_dither() +
@@ -56,7 +55,6 @@ pcm_volume_change_16(int16_t *buffer, unsigned num_samples, int volume)
/ PCM_VOLUME_1;
*buffer++ = pcm_range(sample, 16);
- --num_samples;
}
}
@@ -92,9 +90,9 @@ pcm_volume_sample_24(int32_t sample, int32_t volume, G_GNUC_UNUSED int32_t dithe
#endif
static void
-pcm_volume_change_24(int32_t *buffer, unsigned num_samples, int volume)
+pcm_volume_change_24(int32_t *buffer, const int32_t *end, int volume)
{
- while (num_samples > 0) {
+ while (buffer < end) {
#ifdef __i386__
/* assembly version for i386 */
int32_t sample = *buffer;
@@ -110,14 +108,13 @@ pcm_volume_change_24(int32_t *buffer, unsigned num_samples, int volume)
/ PCM_VOLUME_1;
#endif
*buffer++ = pcm_range(sample, 24);
- --num_samples;
}
}
static void
-pcm_volume_change_32(int32_t *buffer, unsigned num_samples, int volume)
+pcm_volume_change_32(int32_t *buffer, const int32_t *end, int volume)
{
- while (num_samples > 0) {
+ while (buffer < end) {
#ifdef __i386__
/* assembly version for i386 */
int32_t sample = *buffer;
@@ -132,14 +129,22 @@ pcm_volume_change_32(int32_t *buffer, unsigned num_samples, int volume)
/ PCM_VOLUME_1;
*buffer++ = pcm_range_64(sample, 32);
#endif
+ }
+}
- --num_samples;
+static void
+pcm_volume_change_float(float *buffer, const float *end, float volume)
+{
+ while (buffer < end) {
+ float sample = *buffer;
+ sample *= volume;
+ *buffer++ = sample;
}
}
bool
-pcm_volume(void *buffer, int length,
- const struct audio_format *format,
+pcm_volume(void *buffer, size_t length,
+ enum sample_format format,
int volume)
{
if (volume == PCM_VOLUME_1)
@@ -150,27 +155,36 @@ pcm_volume(void *buffer, int length,
return true;
}
- switch (format->format) {
+ const void *end = pcm_end_pointer(buffer, length);
+ switch (format) {
+ case SAMPLE_FORMAT_UNDEFINED:
+ case SAMPLE_FORMAT_DSD:
+ /* not implemented */
+ return false;
+
case SAMPLE_FORMAT_S8:
- pcm_volume_change_8((int8_t *)buffer, length, volume);
+ pcm_volume_change_8(buffer, end, volume);
return true;
case SAMPLE_FORMAT_S16:
- pcm_volume_change_16((int16_t *)buffer, length / 2,
- volume);
+ pcm_volume_change_16(buffer, end, volume);
return true;
case SAMPLE_FORMAT_S24_P32:
- pcm_volume_change_24((int32_t*)buffer, length / 4,
- volume);
+ pcm_volume_change_24(buffer, end, volume);
return true;
case SAMPLE_FORMAT_S32:
- pcm_volume_change_32((int32_t*)buffer, length / 4,
- volume);
+ pcm_volume_change_32(buffer, end, volume);
return true;
- default:
- return false;
+ case SAMPLE_FORMAT_FLOAT:
+ pcm_volume_change_float(buffer, end,
+ pcm_volume_to_float(volume));
+ return true;
}
+
+ /* unreachable */
+ assert(false);
+ return false;
}