diff options
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/pcm_utils.c | 87 | ||||
-rw-r--r-- | src/pcm_utils.h | 19 | ||||
-rw-r--r-- | src/pcm_volume.c | 105 | ||||
-rw-r--r-- | src/pcm_volume.h | 59 | ||||
-rw-r--r-- | src/player_control.c | 2 | ||||
-rw-r--r-- | src/player_thread.c | 2 | ||||
-rw-r--r-- | src/replay_gain.c | 2 | ||||
-rw-r--r-- | src/volume.c | 2 |
9 files changed, 171 insertions, 109 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 7337d9150..2c2b14665 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -50,6 +50,7 @@ mpd_headers = \ path.h \ mapper.h \ pcm_utils.h \ + pcm_volume.h \ pcm_channels.h \ pcm_resample.h \ pcm_dither.h \ @@ -129,6 +130,7 @@ mpd_SOURCES = \ path.c \ mapper.c \ pcm_utils.c \ + pcm_volume.c \ pcm_channels.c \ pcm_resample.c \ pcm_dither.c \ diff --git a/src/pcm_utils.c b/src/pcm_utils.c index 43690ef89..d619c9dd7 100644 --- a/src/pcm_utils.c +++ b/src/pcm_utils.c @@ -19,6 +19,7 @@ #include "pcm_utils.h" #include "pcm_channels.h" #include "pcm_prng.h" +#include "pcm_volume.h" #include "conf.h" #include "audio_format.h" @@ -30,92 +31,6 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "pcm" -static inline int -pcm_dither(void) -{ - static unsigned long state; - uint32_t r; - - r = state = prng(state); - - return (r & 511) - ((r >> 9) & 511); -} - -static void -pcm_volume_change_8(int8_t *buffer, unsigned num_samples, int volume) -{ - while (num_samples > 0) { - int32_t sample = *buffer; - - sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2) - / PCM_VOLUME_1; - - *buffer++ = pcm_range(sample, 8); - --num_samples; - } -} - -static void -pcm_volume_change_16(int16_t *buffer, unsigned num_samples, int volume) -{ - while (num_samples > 0) { - int32_t sample = *buffer; - - sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2) - / PCM_VOLUME_1; - - *buffer++ = pcm_range(sample, 16); - --num_samples; - } -} - -static void -pcm_volume_change_24(int32_t *buffer, unsigned num_samples, int volume) -{ - while (num_samples > 0) { - int64_t sample = *buffer; - - sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2) - / PCM_VOLUME_1; - - *buffer++ = pcm_range(sample, 24); - --num_samples; - } -} - -void pcm_volume(char *buffer, int bufferSize, - const struct audio_format *format, - int volume) -{ - if (volume == PCM_VOLUME_1) - return; - - if (volume <= 0) { - memset(buffer, 0, bufferSize); - return; - } - - switch (format->bits) { - case 8: - pcm_volume_change_8((int8_t *)buffer, bufferSize, volume); - break; - - case 16: - pcm_volume_change_16((int16_t *)buffer, bufferSize / 2, - volume); - break; - - case 24: - pcm_volume_change_24((int32_t*)buffer, bufferSize / 4, - volume); - break; - - default: - g_error("%u bits not supported by pcm_volume!\n", - format->bits); - } -} - static void pcm_add_8(int8_t *buffer1, const int8_t *buffer2, unsigned num_samples, int volume1, int volume2) diff --git a/src/pcm_utils.h b/src/pcm_utils.h index 44ea5aa16..61262048f 100644 --- a/src/pcm_utils.h +++ b/src/pcm_utils.h @@ -29,11 +29,6 @@ struct audio_format; -enum { - /** this value means "100% volume" */ - PCM_VOLUME_1 = 1000, -}; - struct pcm_convert_state { struct pcm_resample_state resample; @@ -57,20 +52,6 @@ pcm_range(int32_t sample, unsigned bits) return sample; } -/** - * Converts a float value (0.0 = silence, 1.0 = 100% volume) to an - * integer volume value (1000 = 100%). - */ -static inline int -pcm_float_to_volume(float volume) -{ - return volume * PCM_VOLUME_1 + 0.5; -} - -void pcm_volume(char *buffer, int bufferSize, - const struct audio_format *format, - int volume); - void pcm_mix(char *buffer1, const char *buffer2, size_t size, const struct audio_format *format, float portion1); diff --git a/src/pcm_volume.c b/src/pcm_volume.c new file mode 100644 index 000000000..af7916b1f --- /dev/null +++ b/src/pcm_volume.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2003-2009 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "pcm_volume.h" +#include "pcm_utils.h" +#include "audio_format.h" + +#include <glib.h> + +#include <stdint.h> +#include <string.h> + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "pcm_volume" + +static void +pcm_volume_change_8(int8_t *buffer, unsigned num_samples, int volume) +{ + while (num_samples > 0) { + int32_t sample = *buffer; + + sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2) + / PCM_VOLUME_1; + + *buffer++ = pcm_range(sample, 8); + --num_samples; + } +} + +static void +pcm_volume_change_16(int16_t *buffer, unsigned num_samples, int volume) +{ + while (num_samples > 0) { + int32_t sample = *buffer; + + sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2) + / PCM_VOLUME_1; + + *buffer++ = pcm_range(sample, 16); + --num_samples; + } +} + +static void +pcm_volume_change_24(int32_t *buffer, unsigned num_samples, int volume) +{ + while (num_samples > 0) { + int64_t sample = *buffer; + + sample = (sample * volume + pcm_dither() + PCM_VOLUME_1 / 2) + / PCM_VOLUME_1; + + *buffer++ = pcm_range(sample, 24); + --num_samples; + } +} + +void +pcm_volume(char *buffer, int bufferSize, + const struct audio_format *format, + int volume) +{ + if (volume == PCM_VOLUME_1) + return; + + if (volume <= 0) { + memset(buffer, 0, bufferSize); + return; + } + + switch (format->bits) { + case 8: + pcm_volume_change_8((int8_t *)buffer, bufferSize, volume); + break; + + case 16: + pcm_volume_change_16((int16_t *)buffer, bufferSize / 2, + volume); + break; + + case 24: + pcm_volume_change_24((int32_t*)buffer, bufferSize / 4, + volume); + break; + + default: + g_error("%u bits not supported by pcm_volume!\n", + format->bits); + } +} diff --git a/src/pcm_volume.h b/src/pcm_volume.h new file mode 100644 index 000000000..eb3f8d6ee --- /dev/null +++ b/src/pcm_volume.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2003-2009 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PCM_VOLUME_H +#define PCM_VOLUME_H + +#include "pcm_prng.h" + +#include <stdint.h> + +enum { + /** this value means "100% volume" */ + PCM_VOLUME_1 = 1000, +}; + +struct audio_format; + +/** + * Converts a float value (0.0 = silence, 1.0 = 100% volume) to an + * integer volume value (1000 = 100%). + */ +static inline int +pcm_float_to_volume(float volume) +{ + return volume * PCM_VOLUME_1 + 0.5; +} + +static inline int +pcm_dither(void) +{ + static unsigned long state; + uint32_t r; + + r = state = prng(state); + + return (r & 511) - ((r >> 9) & 511); +} + +void +pcm_volume(char *buffer, int bufferSize, + const struct audio_format *format, + int volume); + +#endif diff --git a/src/player_control.c b/src/player_control.c index e30ce6ec4..60b5b8350 100644 --- a/src/player_control.c +++ b/src/player_control.c @@ -22,7 +22,7 @@ #include "tag.h" #include "song.h" #include "idle.h" -#include "pcm_utils.h" +#include "pcm_volume.h" #include "main.h" #include <assert.h> diff --git a/src/player_thread.c b/src/player_thread.c index bdf36f43f..5c187ccd7 100644 --- a/src/player_thread.c +++ b/src/player_thread.c @@ -20,7 +20,7 @@ #include "player_control.h" #include "decoder_control.h" #include "audio.h" -#include "pcm_utils.h" +#include "pcm_volume.h" #include "path.h" #include "event_pipe.h" #include "crossfade.h" diff --git a/src/replay_gain.c b/src/replay_gain.c index 74b7c7f34..cc2397b08 100644 --- a/src/replay_gain.c +++ b/src/replay_gain.c @@ -20,7 +20,7 @@ #include "replay_gain.h" #include "conf.h" #include "audio_format.h" -#include "pcm_utils.h" +#include "pcm_volume.h" #include <glib.h> #include <stdlib.h> diff --git a/src/volume.c b/src/volume.c index e76528d72..97b1ccd2b 100644 --- a/src/volume.c +++ b/src/volume.c @@ -20,7 +20,7 @@ #include "conf.h" #include "player_control.h" #include "idle.h" -#include "pcm_utils.h" +#include "pcm_volume.h" #include "config.h" #include "audio.h" |