From b40428b3fd284f172da0ae630559176727026599 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 7 Jan 2009 18:53:36 +0100 Subject: pcm_utils: moved conversion code to pcm_convert.c All what's left in pcm_utils.h is the pcm_range() utility function, which is only used internally by pcm_volume and pcm_mix. --- src/Makefile.am | 3 +- src/decoder_internal.h | 2 +- src/output/alsa_plugin.c | 2 +- src/output_control.c | 1 - src/output_internal.h | 2 +- src/pcm_convert.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++ src/pcm_convert.h | 44 +++++++++++++ src/pcm_utils.c | 158 ----------------------------------------------- src/pcm_utils.h | 26 -------- 9 files changed, 206 insertions(+), 189 deletions(-) create mode 100644 src/pcm_convert.c create mode 100644 src/pcm_convert.h delete mode 100644 src/pcm_utils.c (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 00891cfc0..75380ef2d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -50,6 +50,7 @@ mpd_headers = \ path.h \ mapper.h \ pcm_utils.h \ + pcm_convert.h \ pcm_volume.h \ pcm_mix.h \ pcm_channels.h \ @@ -131,7 +132,7 @@ mpd_SOURCES = \ pipe.c \ path.c \ mapper.c \ - pcm_utils.c \ + pcm_convert.c \ pcm_volume.c \ pcm_mix.c \ pcm_channels.c \ diff --git a/src/decoder_internal.h b/src/decoder_internal.h index bc10475b9..ea9106c8b 100644 --- a/src/decoder_internal.h +++ b/src/decoder_internal.h @@ -20,7 +20,7 @@ #define MPD_DECODER_INTERNAL_H #include "decoder_api.h" -#include "pcm_utils.h" +#include "pcm_convert.h" struct decoder { struct pcm_convert_state conv_state; diff --git a/src/output/alsa_plugin.c b/src/output/alsa_plugin.c index 0d97438eb..fc5c56c21 100644 --- a/src/output/alsa_plugin.c +++ b/src/output/alsa_plugin.c @@ -235,7 +235,7 @@ configure_hw: err = snd_pcm_hw_params_set_format(ad->pcmHandle, hwparams, bitformat); if (err == -EINVAL && audioFormat->bits != 16) { - /* fall back to 16 bit, let pcm_utils.c do the conversion */ + /* fall back to 16 bit, let pcm_convert.c do the conversion */ err = snd_pcm_hw_params_set_format(ad->pcmHandle, hwparams, SND_PCM_FORMAT_S16); if (err == 0) { diff --git a/src/output_control.c b/src/output_control.c index c0e7d001a..80cdf71d0 100644 --- a/src/output_control.c +++ b/src/output_control.c @@ -20,7 +20,6 @@ #include "output_api.h" #include "output_internal.h" #include "output_thread.h" -#include "pcm_utils.h" #include #include diff --git a/src/output_internal.h b/src/output_internal.h index 0cdbbdc2c..17209dd5a 100644 --- a/src/output_internal.h +++ b/src/output_internal.h @@ -20,7 +20,7 @@ #ifndef MPD_OUTPUT_INTERNAL_H #define MPD_OUTPUT_INTERNAL_H -#include "pcm_utils.h" +#include "pcm_convert.h" #include "notify.h" #include diff --git a/src/pcm_convert.c b/src/pcm_convert.c new file mode 100644 index 000000000..283befd8c --- /dev/null +++ b/src/pcm_convert.c @@ -0,0 +1,157 @@ +/* + * 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_convert.h" +#include "pcm_channels.h" +#include "pcm_format.h" +#include "audio_format.h" + +#include +#include +#include +#include + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "pcm" + +void pcm_convert_init(struct pcm_convert_state *state) +{ + memset(state, 0, sizeof(*state)); + + pcm_resample_init(&state->resample); + pcm_dither_24_init(&state->dither); +} + +static size_t +pcm_convert_16(const struct audio_format *src_format, + const void *src_buffer, size_t src_size, + const struct audio_format *dest_format, + int16_t *dest_buffer, + struct pcm_convert_state *state) +{ + const int16_t *buf; + size_t len; + size_t dest_size = pcm_convert_size(src_format, src_size, dest_format); + + assert(dest_format->bits == 16); + + buf = pcm_convert_to_16(&state->dither, src_format->bits, + src_buffer, src_size, &len); + if (!buf) + g_error("pcm_convert_to_16() failed"); + + if (src_format->channels != dest_format->channels) { + buf = pcm_convert_channels_16(dest_format->channels, + src_format->channels, + buf, len, &len); + if (!buf) + g_error("pcm_convert_channels_16() failed"); + } + + if (src_format->sample_rate == dest_format->sample_rate) { + assert(dest_size >= len); + memcpy(dest_buffer, buf, len); + } else { + len = pcm_resample_16(dest_format->channels, + src_format->sample_rate, buf, len, + dest_format->sample_rate, + dest_buffer, dest_size, + &state->resample); + } + + return len; +} + +static size_t +pcm_convert_24(const struct audio_format *src_format, + const void *src_buffer, size_t src_size, + const struct audio_format *dest_format, + int32_t *dest_buffer, + struct pcm_convert_state *state) +{ + const int32_t *buf; + size_t len; + size_t dest_size = pcm_convert_size(src_format, src_size, dest_format); + + assert(dest_format->bits == 24); + + buf = pcm_convert_to_24(src_format->bits, + src_buffer, src_size, &len); + if (!buf) + g_error("pcm_convert_to_24() failed"); + + if (src_format->channels != dest_format->channels) { + buf = pcm_convert_channels_24(dest_format->channels, + src_format->channels, + buf, len, &len); + if (!buf) + g_error("pcm_convert_channels_24() failed"); + } + + if (src_format->sample_rate == dest_format->sample_rate) { + assert(dest_size >= len); + memcpy(dest_buffer, buf, len); + } else { + len = pcm_resample_24(dest_format->channels, + src_format->sample_rate, buf, len, + dest_format->sample_rate, + (int32_t*)dest_buffer, dest_size, + &state->resample); + } + + return len; +} + +/* outFormat bits must be 16 and channels must be 1 or 2! */ +size_t pcm_convert(const struct audio_format *inFormat, + const char *src, size_t src_size, + const struct audio_format *outFormat, + char *outBuffer, + struct pcm_convert_state *convState) +{ + switch (outFormat->bits) { + case 16: + return pcm_convert_16(inFormat, src, src_size, + outFormat, (int16_t*)outBuffer, + convState); + case 24: + return pcm_convert_24(inFormat, src, src_size, + outFormat, (int32_t*)outBuffer, + convState); + + default: + g_error("cannot convert to %u bit\n", outFormat->bits); + } +} + +size_t pcm_convert_size(const struct audio_format *inFormat, size_t src_size, + const struct audio_format *outFormat) +{ + const double ratio = (double)outFormat->sample_rate / + (double)inFormat->sample_rate; + size_t dest_size = src_size; + + /* no partial frames allowed */ + assert((src_size % audio_format_frame_size(inFormat)) == 0); + + dest_size /= audio_format_frame_size(inFormat); + dest_size = ceil((double)dest_size * ratio); + dest_size *= audio_format_frame_size(outFormat); + + return dest_size; +} diff --git a/src/pcm_convert.h b/src/pcm_convert.h new file mode 100644 index 000000000..ac771a5c1 --- /dev/null +++ b/src/pcm_convert.h @@ -0,0 +1,44 @@ +/* + * 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_CONVERT_H +#define PCM_CONVERT_H + +#include "pcm_resample.h" +#include "pcm_dither.h" + +struct audio_format; + +struct pcm_convert_state { + struct pcm_resample_state resample; + + struct pcm_dither_24 dither; +}; + +void pcm_convert_init(struct pcm_convert_state *state); + +size_t pcm_convert(const struct audio_format *inFormat, + const char *inBuffer, size_t inSize, + const struct audio_format *outFormat, + char *outBuffer, + struct pcm_convert_state *convState); + +size_t pcm_convert_size(const struct audio_format *inFormat, size_t inSize, + const struct audio_format *outFormat); + +#endif diff --git a/src/pcm_utils.c b/src/pcm_utils.c deleted file mode 100644 index 69add6073..000000000 --- a/src/pcm_utils.c +++ /dev/null @@ -1,158 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: 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_utils.h" -#include "pcm_channels.h" -#include "pcm_format.h" -#include "conf.h" -#include "audio_format.h" - -#include -#include -#include -#include - -#undef G_LOG_DOMAIN -#define G_LOG_DOMAIN "pcm" - -void pcm_convert_init(struct pcm_convert_state *state) -{ - memset(state, 0, sizeof(*state)); - - pcm_resample_init(&state->resample); - pcm_dither_24_init(&state->dither); -} - -static size_t -pcm_convert_16(const struct audio_format *src_format, - const void *src_buffer, size_t src_size, - const struct audio_format *dest_format, - int16_t *dest_buffer, - struct pcm_convert_state *state) -{ - const int16_t *buf; - size_t len; - size_t dest_size = pcm_convert_size(src_format, src_size, dest_format); - - assert(dest_format->bits == 16); - - buf = pcm_convert_to_16(&state->dither, src_format->bits, - src_buffer, src_size, &len); - if (!buf) - g_error("pcm_convert_to_16() failed"); - - if (src_format->channels != dest_format->channels) { - buf = pcm_convert_channels_16(dest_format->channels, - src_format->channels, - buf, len, &len); - if (!buf) - g_error("pcm_convert_channels_16() failed"); - } - - if (src_format->sample_rate == dest_format->sample_rate) { - assert(dest_size >= len); - memcpy(dest_buffer, buf, len); - } else { - len = pcm_resample_16(dest_format->channels, - src_format->sample_rate, buf, len, - dest_format->sample_rate, - dest_buffer, dest_size, - &state->resample); - } - - return len; -} - -static size_t -pcm_convert_24(const struct audio_format *src_format, - const void *src_buffer, size_t src_size, - const struct audio_format *dest_format, - int32_t *dest_buffer, - struct pcm_convert_state *state) -{ - const int32_t *buf; - size_t len; - size_t dest_size = pcm_convert_size(src_format, src_size, dest_format); - - assert(dest_format->bits == 24); - - buf = pcm_convert_to_24(src_format->bits, - src_buffer, src_size, &len); - if (!buf) - g_error("pcm_convert_to_24() failed"); - - if (src_format->channels != dest_format->channels) { - buf = pcm_convert_channels_24(dest_format->channels, - src_format->channels, - buf, len, &len); - if (!buf) - g_error("pcm_convert_channels_24() failed"); - } - - if (src_format->sample_rate == dest_format->sample_rate) { - assert(dest_size >= len); - memcpy(dest_buffer, buf, len); - } else { - len = pcm_resample_24(dest_format->channels, - src_format->sample_rate, buf, len, - dest_format->sample_rate, - (int32_t*)dest_buffer, dest_size, - &state->resample); - } - - return len; -} - -/* outFormat bits must be 16 and channels must be 1 or 2! */ -size_t pcm_convert(const struct audio_format *inFormat, - const char *src, size_t src_size, - const struct audio_format *outFormat, - char *outBuffer, - struct pcm_convert_state *convState) -{ - switch (outFormat->bits) { - case 16: - return pcm_convert_16(inFormat, src, src_size, - outFormat, (int16_t*)outBuffer, - convState); - case 24: - return pcm_convert_24(inFormat, src, src_size, - outFormat, (int32_t*)outBuffer, - convState); - - default: - g_error("cannot convert to %u bit\n", outFormat->bits); - } -} - -size_t pcm_convert_size(const struct audio_format *inFormat, size_t src_size, - const struct audio_format *outFormat) -{ - const double ratio = (double)outFormat->sample_rate / - (double)inFormat->sample_rate; - size_t dest_size = src_size; - - /* no partial frames allowed */ - assert((src_size % audio_format_frame_size(inFormat)) == 0); - - dest_size /= audio_format_frame_size(inFormat); - dest_size = ceil((double)dest_size * ratio); - dest_size *= audio_format_frame_size(outFormat); - - return dest_size; -} diff --git a/src/pcm_utils.h b/src/pcm_utils.h index 5d29420f3..020cdaceb 100644 --- a/src/pcm_utils.h +++ b/src/pcm_utils.h @@ -19,24 +19,9 @@ #ifndef MPD_PCM_UTILS_H #define MPD_PCM_UTILS_H -#include "pcm_resample.h" -#include "pcm_dither.h" - #include #include -#include - -struct audio_format; - -struct pcm_convert_state { - struct pcm_resample_state resample; - - struct pcm_dither_24 dither; - - /* Strict C99 doesn't allow empty structs */ - int error; -}; /** * Check if the value is within the range of the provided bit size, @@ -52,15 +37,4 @@ pcm_range(int32_t sample, unsigned bits) return sample; } -void pcm_convert_init(struct pcm_convert_state *state); - -size_t pcm_convert(const struct audio_format *inFormat, - const char *inBuffer, size_t inSize, - const struct audio_format *outFormat, - char *outBuffer, - struct pcm_convert_state *convState); - -size_t pcm_convert_size(const struct audio_format *inFormat, size_t inSize, - const struct audio_format *outFormat); - #endif -- cgit v1.2.3