aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2013-04-22 21:29:49 +0200
committerAnton Khirnov <anton@khirnov.net>2015-02-20 08:56:00 +0100
commit4be49546e16eb5d7aa783285e1f0c2c5ed179d1a (patch)
treeb7bd98978651fe8fe017cd207f42b6484d585ed6
parent3756812cbc334d41421a33e54f7fa3ea6e46808c (diff)
decoder api: use AVFrame for passing data to the decoder.
Switch to libavresample for format conversion.
-rw-r--r--src/Makefile5
-rw-r--r--src/audio_format.c14
-rw-r--r--src/audio_format.h4
-rw-r--r--src/decoder/libav_decoder_plugin.c93
-rw-r--r--src/decoder_api.c48
-rw-r--r--src/decoder_api.h8
-rw-r--r--src/filter/convert_filter_plugin.c4
-rw-r--r--src/main.c7
-rw-r--r--src/pcm_channels.c246
-rw-r--r--src/pcm_channels.h80
-rw-r--r--src/pcm_convert.c385
-rw-r--r--src/pcm_convert.h29
-rw-r--r--src/pcm_format.c487
-rw-r--r--src/pcm_format.h93
-rw-r--r--src/pcm_resample.c159
-rw-r--r--src/pcm_resample.h164
-rw-r--r--src/pcm_resample_fallback.c118
-rw-r--r--src/pcm_resample_internal.h97
-rw-r--r--src/pcm_resample_libsamplerate.c312
19 files changed, 165 insertions, 2188 deletions
diff --git a/src/Makefile b/src/Makefile
index c6820dff..d62f0b9b 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -86,18 +86,13 @@ OBJS = aiff.o \
page.o \
path.o \
pcm_buffer.o \
- pcm_channels.o \
pcm_convert.o \
pcm_dither.o \
pcm_dsd.o \
pcm_dsd_usb.o \
pcm_export.o \
- pcm_format.o \
pcm_mix.o \
pcm_pack.o \
- pcm_resample.o \
- pcm_resample_fallback.o \
- pcm_resample_libsamplerate.o \
pcm_volume.o \
permission.o \
pipe.o \
diff --git a/src/audio_format.c b/src/audio_format.c
index 45d94a85..dc46604f 100644
--- a/src/audio_format.c
+++ b/src/audio_format.c
@@ -22,6 +22,8 @@
#include <assert.h>
#include <stdio.h>
+#include <libavutil/samplefmt.h>
+
void
audio_format_mask_apply(struct audio_format *af,
const struct audio_format *mask)
@@ -85,3 +87,15 @@ audio_format_to_string(const struct audio_format *af,
return s->buffer;
}
+
+enum AVSampleFormat sample_fmt_native_to_libav(enum sample_format sample_fmt)
+{
+ switch (sample_fmt) {
+ case SAMPLE_FORMAT_S8: return AV_SAMPLE_FMT_U8;
+ case SAMPLE_FORMAT_S16: return AV_SAMPLE_FMT_S16;
+ case SAMPLE_FORMAT_S24_P32:
+ case SAMPLE_FORMAT_S32: return AV_SAMPLE_FMT_S32;
+ case SAMPLE_FORMAT_FLOAT: return AV_SAMPLE_FMT_FLT;
+ default: return AV_SAMPLE_FMT_NONE;
+ }
+}
diff --git a/src/audio_format.h b/src/audio_format.h
index bf77add3..c6527e6a 100644
--- a/src/audio_format.h
+++ b/src/audio_format.h
@@ -25,6 +25,8 @@
#include <stdbool.h>
#include <assert.h>
+#include <libavutil/samplefmt.h>
+
enum sample_format {
SAMPLE_FORMAT_UNDEFINED = 0,
@@ -304,4 +306,6 @@ const char *
audio_format_to_string(const struct audio_format *af,
struct audio_format_string *s);
+enum AVSampleFormat sample_fmt_native_to_libav(enum sample_format);
+
#endif
diff --git a/src/decoder/libav_decoder_plugin.c b/src/decoder/libav_decoder_plugin.c
index 88dd4a8f..05b9b2fb 100644
--- a/src/decoder/libav_decoder_plugin.c
+++ b/src/decoder/libav_decoder_plugin.c
@@ -41,6 +41,7 @@
#include <libavutil/log.h>
#include <libavutil/mathematics.h>
#include <libavutil/dict.h>
+#include <libavutil/opt.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "libav"
@@ -159,40 +160,6 @@ static int64_t time_to_libav(double t, const AVRational time_base)
return av_rescale_q((int64_t)(t * 1024), (AVRational){1, 1024}, time_base);
}
-/**
- * Copy PCM data from a AVFrame to an interleaved buffer.
- */
-static int copy_interleave_frame(const AVCodecContext *codec_context,
- const AVFrame *frame,
- uint8_t *buffer, size_t buffer_size)
-{
- int plane_size;
- const int data_size =
- av_samples_get_buffer_size(&plane_size,
- codec_context->channels,
- frame->nb_samples,
- codec_context->sample_fmt, 1);
- uint16_t *dst = (uint16_t*)buffer;
-
- if (buffer_size < (size_t)data_size)
- /* buffer is too small - shouldn't happen */
- return AVERROR(EINVAL);
-
- if (av_sample_fmt_is_planar(codec_context->sample_fmt) &&
- codec_context->channels > 1) {
- for (int i = 0; i < frame->nb_samples; i++) {
- for (int j = 0; j < codec_context->channels; j++)
- dst[i * codec_context->channels + j] = ((uint16_t*)frame->extended_data[j])[i];
- }
- } else {
- memcpy(buffer, frame->extended_data[0], data_size);
- }
-
- return data_size;
-}
-
-#define AVCODEC_MAX_AUDIO_FRAME_SIZE 50000
-
static enum decoder_command libav_send_packet(struct decoder *decoder,
struct input_stream *is,
const AVPacket *packet,
@@ -200,9 +167,6 @@ static enum decoder_command libav_send_packet(struct decoder *decoder,
const AVRational *time_base)
{
AVPacket packet2 = *packet;
- uint8_t aligned_buffer[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2 + 16];
- const size_t buffer_size = sizeof(aligned_buffer);
-
enum decoder_command cmd = DECODE_COMMAND_NONE;
if (packet->pts != (int64_t)AV_NOPTS_VALUE)
@@ -210,37 +174,31 @@ static enum decoder_command libav_send_packet(struct decoder *decoder,
while (packet2.size > 0 &&
cmd == DECODE_COMMAND_NONE) {
- int audio_size = buffer_size;
- AVFrame frame;
+ AVFrame *frame = av_frame_alloc();
int got_frame = 0;
- int len = avcodec_decode_audio4(codec_context,
- &frame, &got_frame,
- &packet2);
- if (len >= 0 && got_frame) {
- audio_size = copy_interleave_frame(codec_context,
- &frame,
- aligned_buffer,
- buffer_size);
- if (audio_size < 0)
- len = audio_size;
- } else if (len >= 0)
- len = -1;
-
- if (len < 0) {
- /* if error, we skip the frame */
+ int ret;
+
+ if (!frame) {
+ g_warning("Error allocating a frame for decoding.\n");
+ break;
+ }
+
+ ret = avcodec_decode_audio4(codec_context, frame, &got_frame, &packet2);
+ if (ret < 0) {
g_message("decoding failed, frame skipped\n");
break;
}
- packet2.data += len;
- packet2.size -= len;
+ packet2.data += ret;
+ packet2.size -= ret;
- if (audio_size <= 0)
+ if (!got_frame) {
+ if (!ret)
+ break;
continue;
+ }
- cmd = decoder_data(decoder, is,
- aligned_buffer, audio_size,
- codec_context->bit_rate / 1000);
+ cmd = decoder_data(decoder, is, frame, codec_context->bit_rate / 1000);
}
return cmd;
}
@@ -248,17 +206,9 @@ static enum decoder_command libav_send_packet(struct decoder *decoder,
static enum sample_format libav_sample_format(const AVCodecContext *codec_context)
{
switch (codec_context->sample_fmt) {
- case AV_SAMPLE_FMT_S16:
- case AV_SAMPLE_FMT_S16P:
- return SAMPLE_FORMAT_S16;
-
- case AV_SAMPLE_FMT_S32:
- return SAMPLE_FORMAT_S32;
-
- default:
- g_warning("Unsupported libavcodec SampleFormat value: %d",
- codec_context->sample_fmt);
- return SAMPLE_FORMAT_UNDEFINED;
+ case AV_SAMPLE_FMT_S16: return SAMPLE_FORMAT_S16;
+ case AV_SAMPLE_FMT_S32: return SAMPLE_FORMAT_S32;
+ default: return SAMPLE_FORMAT_UNDEFINED;
}
}
@@ -298,6 +248,7 @@ static void libav_decode(struct decoder *decoder, struct input_stream *input)
values into AVCodecContext.channels - a change that will be
reverted later by avcodec_decode_audio3() */
+ av_opt_set_int(dec, "refcounted_frames", 1, 0);
ret = avcodec_open2(dec, codec, NULL);
if (ret < 0) {
g_warning("Could not open codec\n");
diff --git a/src/decoder_api.c b/src/decoder_api.c
index b8edb8aa..bcab6010 100644
--- a/src/decoder_api.c
+++ b/src/decoder_api.c
@@ -30,6 +30,10 @@
#include <glib.h>
+#include <libavutil/channel_layout.h>
+#include <libavutil/frame.h>
+#include <libavutil/samplefmt.h>
+
#include <assert.h>
#include <stdlib.h>
@@ -347,25 +351,24 @@ static bool update_stream_tag(struct decoder *decoder, struct input_stream *is)
enum decoder_command decoder_data(struct decoder *decoder,
struct input_stream *is,
- const void *_data, size_t length,
+ AVFrame *frame,
uint16_t kbit_rate)
{
struct decoder_control *dc = decoder->dc;
- const char *data = _data;
- GError *error = NULL;
- enum decoder_command cmd;
+ enum decoder_command cmd = DECODE_COMMAND_NONE;
+ uint8_t *data;
+ int length;
assert(dc->state == DECODE_STATE_DECODE);
assert(dc->pipe != NULL);
- assert(length % audio_format_frame_size(&dc->in_audio_format) == 0);
decoder_lock(dc);
cmd = decoder_get_virtual_command(decoder);
decoder_unlock(dc);
if (cmd == DECODE_COMMAND_STOP || cmd == DECODE_COMMAND_SEEK ||
- length == 0)
- return cmd;
+ !frame->nb_samples)
+ goto finish;
/* send stream tags */
@@ -383,23 +386,27 @@ enum decoder_command decoder_data(struct decoder *decoder,
cmd = do_send_tag(decoder, decoder->stream_tag);
if (cmd != DECODE_COMMAND_NONE)
- return cmd;
+ goto finish;
}
if (!audio_format_equals(&dc->in_audio_format, &dc->out_audio_format)) {
- data = pcm_convert(&decoder->conv_state,
- &dc->in_audio_format, data, length,
- &dc->out_audio_format, &length,
- &error);
- if (data == NULL) {
+ AVFrame *tmp = pcm_convert(&decoder->conv_state,
+ &dc->in_audio_format, &dc->out_audio_format, frame);
+ if (!tmp) {
/* the PCM conversion has failed - stop
playback, since we have no better way to
bail out */
- g_warning("%s", error->message);
- return DECODE_COMMAND_STOP;
+ g_warning("Error converting to output format.\n");
+ cmd = DECODE_COMMAND_STOP;
+ goto finish;
}
+ av_frame_free(&frame);
+ frame = tmp;
}
+ length = frame->nb_samples * av_get_bytes_per_sample(frame->format) *
+ dc->out_audio_format.channels;
+ data = frame->data[0];
while (length > 0) {
struct music_chunk *chunk;
char *dest;
@@ -409,7 +416,8 @@ enum decoder_command decoder_data(struct decoder *decoder,
chunk = decoder_get_chunk(decoder);
if (chunk == NULL) {
assert(dc->command != DECODE_COMMAND_NONE);
- return dc->command;
+ cmd = dc->command;
+ goto finish;
}
dest = music_chunk_write(chunk, &dc->out_audio_format,
@@ -448,12 +456,16 @@ enum decoder_command decoder_data(struct decoder *decoder,
audio_format_time_to_size(&dc->out_audio_format);
if (dc->end_ms > 0 &&
- decoder->timestamp >= dc->end_ms / 1000.0)
+ decoder->timestamp >= dc->end_ms / 1000.0) {
/* the end of this range has been reached:
stop decoding */
- return DECODE_COMMAND_STOP;
+ cmd = DECODE_COMMAND_STOP;
+ break;
+ }
}
+finish:
+ av_frame_free(&frame);
return DECODE_COMMAND_NONE;
}
diff --git a/src/decoder_api.h b/src/decoder_api.h
index 6e011c39..4ac00142 100644
--- a/src/decoder_api.h
+++ b/src/decoder_api.h
@@ -36,6 +36,8 @@
#include "audio_format.h"
#include "conf.h"
+#include <libavutil/frame.h>
+
#include <stdbool.h>
/**
@@ -126,10 +128,8 @@ decoder_timestamp(struct decoder *decoder, double t);
* @return the current command, or DECODE_COMMAND_NONE if there is no
* command pending
*/
-enum decoder_command
-decoder_data(struct decoder *decoder, struct input_stream *is,
- const void *data, size_t length,
- uint16_t kbit_rate);
+enum decoder_command decoder_data(struct decoder *decoder, struct input_stream *is,
+ AVFrame *frame, uint16_t kbit_rate);
/**
* This function is called by the decoder plugin when it has
diff --git a/src/filter/convert_filter_plugin.c b/src/filter/convert_filter_plugin.c
index c55b69af..40be67f6 100644
--- a/src/filter/convert_filter_plugin.c
+++ b/src/filter/convert_filter_plugin.c
@@ -111,6 +111,9 @@ convert_filter_filter(struct filter *_filter, const void *src, size_t src_size,
return src;
}
+ // FIXME
+ return NULL;
+#if 0
dest = pcm_convert(&filter->state, &filter->in_audio_format,
src, src_size,
&filter->out_audio_format, dest_size_r,
@@ -119,6 +122,7 @@ convert_filter_filter(struct filter *_filter, const void *src, size_t src_size,
return NULL;
return dest;
+#endif
}
const struct filter_plugin convert_filter_plugin = {
diff --git a/src/main.c b/src/main.c
index aa8d9e3b..aa021d64 100644
--- a/src/main.c
+++ b/src/main.c
@@ -44,7 +44,6 @@
#include "volume.h"
#include "log.h"
#include "permission.h"
-#include "pcm_resample.h"
#include "replay_gain_config.h"
#include "decoder_list.h"
#include "input_init.h"
@@ -435,12 +434,6 @@ int mpd_main(int argc, char *argv[])
archive_plugin_init_all();
#endif
- if (!pcm_resample_global_init(&error)) {
- g_warning("%s", error->message);
- g_error_free(error);
- return EXIT_FAILURE;
- }
-
decoder_plugin_init_all();
update_global_init();
diff --git a/src/pcm_channels.c b/src/pcm_channels.c
deleted file mode 100644
index ec2bd69a..00000000
--- a/src/pcm_channels.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * 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
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-#include "pcm_channels.h"
-#include "pcm_buffer.h"
-#include "pcm_utils.h"
-
-#include <assert.h>
-
-static void
-pcm_convert_channels_16_1_to_2(int16_t *restrict dest,
- const int16_t *restrict src,
- const int16_t *restrict src_end)
-{
- while (src < src_end) {
- int16_t value = *src++;
-
- *dest++ = value;
- *dest++ = value;
- }
-}
-
-static void
-pcm_convert_channels_16_2_to_1(int16_t *restrict dest,
- const int16_t *restrict src,
- const int16_t *restrict src_end)
-{
- while (src < src_end) {
- int32_t a = *src++, b = *src++;
-
- *dest++ = (a + b) / 2;
- }
-}
-
-static void
-pcm_convert_channels_16_n_to_2(int16_t *restrict dest,
- unsigned src_channels,
- const int16_t *restrict src,
- const int16_t *restrict src_end)
-{
- unsigned c;
-
- assert(src_channels > 0);
-
- while (src < src_end) {
- int32_t sum = 0;
- int16_t value;
-
- for (c = 0; c < src_channels; ++c)
- sum += *src++;
- value = sum / (int)src_channels;
-
- /* XXX this is actually only mono ... */
- *dest++ = value;
- *dest++ = value;
- }
-}
-
-const int16_t *
-pcm_convert_channels_16(struct pcm_buffer *buffer,
- unsigned dest_channels,
- unsigned src_channels, const int16_t *src,
- size_t src_size, size_t *dest_size_r)
-{
- assert(src_size % (sizeof(*src) * src_channels) == 0);
-
- size_t dest_size = src_size / src_channels * dest_channels;
- *dest_size_r = dest_size;
-
- int16_t *dest = pcm_buffer_get(buffer, dest_size);
- const int16_t *src_end = pcm_end_pointer(src, src_size);
-
- if (src_channels == 1 && dest_channels == 2)
- pcm_convert_channels_16_1_to_2(dest, src, src_end);
- else if (src_channels == 2 && dest_channels == 1)
- pcm_convert_channels_16_2_to_1(dest, src, src_end);
- else if (dest_channels == 2)
- pcm_convert_channels_16_n_to_2(dest, src_channels, src,
- src_end);
- else
- return NULL;
-
- return dest;
-}
-
-static void
-pcm_convert_channels_24_1_to_2(int32_t *restrict dest,
- const int32_t *restrict src,
- const int32_t *restrict src_end)
-{
- while (src < src_end) {
- int32_t value = *src++;
-
- *dest++ = value;
- *dest++ = value;
- }
-}
-
-static void
-pcm_convert_channels_24_2_to_1(int32_t *restrict dest,
- const int32_t *restrict src,
- const int32_t *restrict src_end)
-{
- while (src < src_end) {
- int32_t a = *src++, b = *src++;
-
- *dest++ = (a + b) / 2;
- }
-}
-
-static void
-pcm_convert_channels_24_n_to_2(int32_t *restrict dest,
- unsigned src_channels,
- const int32_t *restrict src,
- const int32_t *restrict src_end)
-{
- unsigned c;
-
- assert(src_channels > 0);
-
- while (src < src_end) {
- int32_t sum = 0;
- int32_t value;
-
- for (c = 0; c < src_channels; ++c)
- sum += *src++;
- value = sum / (int)src_channels;
-
- /* XXX this is actually only mono ... */
- *dest++ = value;
- *dest++ = value;
- }
-}
-
-const int32_t *
-pcm_convert_channels_24(struct pcm_buffer *buffer,
- unsigned dest_channels,
- unsigned src_channels, const int32_t *src,
- size_t src_size, size_t *dest_size_r)
-{
- assert(src_size % (sizeof(*src) * src_channels) == 0);
-
- size_t dest_size = src_size / src_channels * dest_channels;
- *dest_size_r = dest_size;
-
- int32_t *dest = pcm_buffer_get(buffer, dest_size);
- const int32_t *src_end = pcm_end_pointer(src, src_size);
-
- if (src_channels == 1 && dest_channels == 2)
- pcm_convert_channels_24_1_to_2(dest, src, src_end);
- else if (src_channels == 2 && dest_channels == 1)
- pcm_convert_channels_24_2_to_1(dest, src, src_end);
- else if (dest_channels == 2)
- pcm_convert_channels_24_n_to_2(dest, src_channels, src,
- src_end);
- else
- return NULL;
-
- return dest;
-}
-
-static void
-pcm_convert_channels_32_1_to_2(int32_t *dest, const int32_t *src,
- const int32_t *src_end)
-{
- pcm_convert_channels_24_1_to_2(dest, src, src_end);
-}
-
-static void
-pcm_convert_channels_32_2_to_1(int32_t *restrict dest,
- const int32_t *restrict src,
- const int32_t *restrict src_end)
-{
- while (src < src_end) {
- int64_t a = *src++, b = *src++;
-
- *dest++ = (a + b) / 2;
- }
-}
-
-static void
-pcm_convert_channels_32_n_to_2(int32_t *dest,
- unsigned src_channels, const int32_t *src,
- const int32_t *src_end)
-{
- unsigned c;
-
- assert(src_channels > 0);
-
- while (src < src_end) {
- int64_t sum = 0;
- int32_t value;
-
- for (c = 0; c < src_channels; ++c)
- sum += *src++;
- value = sum / (int64_t)src_channels;
-
- /* XXX this is actually only mono ... */
- *dest++ = value;
- *dest++ = value;
- }
-}
-
-const int32_t *
-pcm_convert_channels_32(struct pcm_buffer *buffer,
- unsigned dest_channels,
- unsigned src_channels, const int32_t *src,
- size_t src_size, size_t *dest_size_r)
-{
- assert(src_size % (sizeof(*src) * src_channels) == 0);
-
- size_t dest_size = src_size / src_channels * dest_channels;
- *dest_size_r = dest_size;
-
- int32_t *dest = pcm_buffer_get(buffer, dest_size);
- const int32_t *src_end = pcm_end_pointer(src, src_size);
-
- if (src_channels == 1 && dest_channels == 2)
- pcm_convert_channels_32_1_to_2(dest, src, src_end);
- else if (src_channels == 2 && dest_channels == 1)
- pcm_convert_channels_32_2_to_1(dest, src, src_end);
- else if (dest_channels == 2)
- pcm_convert_channels_32_n_to_2(dest, src_channels, src,
- src_end);
- else
- return NULL;
-
- return dest;
-}
diff --git a/src/pcm_channels.h b/src/pcm_channels.h
deleted file mode 100644
index 1e4a0991..00000000
--- a/src/pcm_channels.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPD_PCM_CHANNELS_H
-#define MPD_PCM_CHANNELS_H
-
-#include <stdint.h>
-#include <stddef.h>
-
-struct pcm_buffer;
-
-/**
- * Changes the number of channels in 16 bit PCM data.
- *
- * @param buffer the destination pcm_buffer object
- * @param dest_channels the number of channels requested
- * @param src_channels the number of channels in the source buffer
- * @param src the source PCM buffer
- * @param src_size the number of bytes in #src
- * @param dest_size_r returns the number of bytes of the destination buffer
- * @return the destination buffer
- */
-const int16_t *
-pcm_convert_channels_16(struct pcm_buffer *buffer,
- unsigned dest_channels,
- unsigned src_channels, const int16_t *src,
- size_t src_size, size_t *dest_size_r);
-
-/**
- * Changes the number of channels in 24 bit PCM data (aligned at 32
- * bit boundaries).
- *
- * @param buffer the destination pcm_buffer object
- * @param dest_channels the number of channels requested
- * @param src_channels the number of channels in the source buffer
- * @param src the source PCM buffer
- * @param src_size the number of bytes in #src
- * @param dest_size_r returns the number of bytes of the destination buffer
- * @return the destination buffer
- */
-const int32_t *
-pcm_convert_channels_24(struct pcm_buffer *buffer,
- unsigned dest_channels,
- unsigned src_channels, const int32_t *src,
- size_t src_size, size_t *dest_size_r);
-
-/**
- * Changes the number of channels in 32 bit PCM data.
- *
- * @param buffer the destination pcm_buffer object
- * @param dest_channels the number of channels requested
- * @param src_channels the number of channels in the source buffer
- * @param src the source PCM buffer
- * @param src_size the number of bytes in #src
- * @param dest_size_r returns the number of bytes of the destination buffer
- * @return the destination buffer
- */
-const int32_t *
-pcm_convert_channels_32(struct pcm_buffer *buffer,
- unsigned dest_channels,
- unsigned src_channels, const int32_t *src,
- size_t src_size, size_t *dest_size_r);
-
-#endif
diff --git a/src/pcm_convert.c b/src/pcm_convert.c
index 63f9a1b9..34e6c32b 100644
--- a/src/pcm_convert.c
+++ b/src/pcm_convert.c
@@ -17,19 +17,18 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "config.h"
-#include "pcm_convert.h"
-#include "pcm_channels.h"
-#include "pcm_format.h"
-#include "pcm_pack.h"
#include "audio_format.h"
-#include "glib_compat.h"
+#include "pcm_convert.h"
-#include <assert.h>
#include <string.h>
-#include <math.h>
+
#include <glib.h>
+#include <libavresample/avresample.h>
+#include <libavutil/channel_layout.h>
+#include <libavutil/frame.h>
+#include <libavutil/opt.h>
+
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "pcm"
@@ -38,292 +37,31 @@ void pcm_convert_init(struct pcm_convert_state *state)
memset(state, 0, sizeof(*state));
pcm_dsd_init(&state->dsd);
- pcm_resample_init(&state->resample);
- pcm_dither_24_init(&state->dither);
-
- pcm_buffer_init(&state->format_buffer);
- pcm_buffer_init(&state->channels_buffer);
}
void pcm_convert_deinit(struct pcm_convert_state *state)
{
pcm_dsd_deinit(&state->dsd);
- pcm_resample_deinit(&state->resample);
- pcm_buffer_deinit(&state->format_buffer);
- pcm_buffer_deinit(&state->channels_buffer);
+ avresample_free(&state->avr);
}
void
pcm_convert_reset(struct pcm_convert_state *state)
{
pcm_dsd_reset(&state->dsd);
- pcm_resample_reset(&state->resample);
-}
-
-static const void *
-pcm_convert_channels(struct pcm_buffer *buffer, enum sample_format format,
- uint8_t dest_channels,
- uint8_t src_channels, const void *src,
- size_t src_size, size_t *dest_size_r,
- GError **error_r)
-{
- const void *dest = NULL;
-
- switch (format) {
- case SAMPLE_FORMAT_UNDEFINED:
- case SAMPLE_FORMAT_S8:
- case SAMPLE_FORMAT_FLOAT:
- case SAMPLE_FORMAT_DSD:
- g_set_error(error_r, pcm_convert_quark(), 0,
- "Channel conversion not implemented for format '%s'",
- sample_format_to_string(format));
- return NULL;
-
- case SAMPLE_FORMAT_S16:
- dest = pcm_convert_channels_16(buffer, dest_channels,
- src_channels, src,
- src_size, dest_size_r);
- break;
-
- case SAMPLE_FORMAT_S24_P32:
- dest = pcm_convert_channels_24(buffer, dest_channels,
- src_channels, src,
- src_size, dest_size_r);
- break;
-
- case SAMPLE_FORMAT_S32:
- dest = pcm_convert_channels_32(buffer, dest_channels,
- src_channels, src,
- src_size, dest_size_r);
- break;
- }
-
- if (dest == NULL) {
- g_set_error(error_r, pcm_convert_quark(), 0,
- "Conversion from %u to %u channels "
- "is not implemented",
- src_channels, dest_channels);
- return NULL;
- }
-
- return dest;
-}
-
-static const int16_t *
-pcm_convert_16(struct pcm_convert_state *state,
- const struct audio_format *src_format,
- const void *src_buffer, size_t src_size,
- const struct audio_format *dest_format, size_t *dest_size_r,
- GError **error_r)
-{
- const int16_t *buf;
- size_t len;
-
- assert(dest_format->format == SAMPLE_FORMAT_S16);
-
- buf = pcm_convert_to_16(&state->format_buffer, &state->dither,
- src_format->format, src_buffer, src_size,
- &len);
- if (buf == NULL) {
- g_set_error(error_r, pcm_convert_quark(), 0,
- "Conversion from %s to 16 bit is not implemented",
- sample_format_to_string(src_format->format));
- return NULL;
- }
-
- if (src_format->channels != dest_format->channels) {
- buf = pcm_convert_channels_16(&state->channels_buffer,
- dest_format->channels,
- src_format->channels,
- buf, len, &len);
- if (buf == NULL) {
- g_set_error(error_r, pcm_convert_quark(), 0,
- "Conversion from %u to %u channels "
- "is not implemented",
- src_format->channels,
- dest_format->channels);
- return NULL;
- }
- }
-
- if (src_format->sample_rate != dest_format->sample_rate) {
- buf = pcm_resample_16(&state->resample,
- dest_format->channels,
- src_format->sample_rate, buf, len,
- dest_format->sample_rate, &len,
- error_r);
- if (buf == NULL)
- return NULL;
- }
-
- *dest_size_r = len;
- return buf;
-}
-
-static const int32_t *
-pcm_convert_24(struct pcm_convert_state *state,
- const struct audio_format *src_format,
- const void *src_buffer, size_t src_size,
- const struct audio_format *dest_format, size_t *dest_size_r,
- GError **error_r)
-{
- const int32_t *buf;
- size_t len;
-
- assert(dest_format->format == SAMPLE_FORMAT_S24_P32);
-
- buf = pcm_convert_to_24(&state->format_buffer, src_format->format,
- src_buffer, src_size, &len);
- if (buf == NULL) {
- g_set_error(error_r, pcm_convert_quark(), 0,
- "Conversion from %s to 24 bit is not implemented",
- sample_format_to_string(src_format->format));
- return NULL;
- }
-
- if (src_format->channels != dest_format->channels) {
- buf = pcm_convert_channels_24(&state->channels_buffer,
- dest_format->channels,
- src_format->channels,
- buf, len, &len);
- if (buf == NULL) {
- g_set_error(error_r, pcm_convert_quark(), 0,
- "Conversion from %u to %u channels "
- "is not implemented",
- src_format->channels,
- dest_format->channels);
- return NULL;
- }
- }
-
- if (src_format->sample_rate != dest_format->sample_rate) {
- buf = pcm_resample_24(&state->resample,
- dest_format->channels,
- src_format->sample_rate, buf, len,
- dest_format->sample_rate, &len,
- error_r);
- if (buf == NULL)
- return NULL;
- }
-
- *dest_size_r = len;
- return buf;
-}
-
-static const int32_t *
-pcm_convert_32(struct pcm_convert_state *state,
- const struct audio_format *src_format,
- const void *src_buffer, size_t src_size,
- const struct audio_format *dest_format, size_t *dest_size_r,
- GError **error_r)
-{
- const int32_t *buf;
- size_t len;
-
- assert(dest_format->format == SAMPLE_FORMAT_S32);
-
- buf = pcm_convert_to_32(&state->format_buffer, src_format->format,
- src_buffer, src_size, &len);
- if (buf == NULL) {
- g_set_error(error_r, pcm_convert_quark(), 0,
- "Conversion from %s to 32 bit is not implemented",
- sample_format_to_string(src_format->format));
- return NULL;
- }
-
- if (src_format->channels != dest_format->channels) {
- buf = pcm_convert_channels_32(&state->channels_buffer,
- dest_format->channels,
- src_format->channels,
- buf, len, &len);
- if (buf == NULL) {
- g_set_error(error_r, pcm_convert_quark(), 0,
- "Conversion from %u to %u channels "
- "is not implemented",
- src_format->channels,
- dest_format->channels);
- return NULL;
- }
- }
-
- if (src_format->sample_rate != dest_format->sample_rate) {
- buf = pcm_resample_32(&state->resample,
- dest_format->channels,
- src_format->sample_rate, buf, len,
- dest_format->sample_rate, &len,
- error_r);
- if (buf == NULL)
- return buf;
- }
-
- *dest_size_r = len;
- return buf;
+ avresample_free(&state->avr);
}
-static const float *
-pcm_convert_float(struct pcm_convert_state *state,
- const struct audio_format *src_format,
- const void *src_buffer, size_t src_size,
- const struct audio_format *dest_format, size_t *dest_size_r,
- GError **error_r)
+AVFrame *pcm_convert(struct pcm_convert_state *state,
+ const struct audio_format *src_format,
+ const struct audio_format *dest_format,
+ const AVFrame *src)
{
- const float *buffer = src_buffer;
- size_t size = src_size;
-
- assert(dest_format->format == SAMPLE_FORMAT_FLOAT);
-
- /* convert channels first, hoping the source format is
- supported (float is not) */
+ AVFrame *dst;
+ int ret;
- if (dest_format->channels != src_format->channels) {
- buffer = pcm_convert_channels(&state->channels_buffer,
- src_format->format,
- dest_format->channels,
- src_format->channels,
- buffer, size, &size, error_r);
- if (buffer == NULL)
- return NULL;
- }
-
- /* convert to float now */
-
- buffer = pcm_convert_to_float(&state->format_buffer,
- src_format->format,
- buffer, size, &size);
- if (buffer == NULL) {
- g_set_error(error_r, pcm_convert_quark(), 0,
- "Conversion from %s to float is not implemented",
- sample_format_to_string(src_format->format));
- return NULL;
- }
-
- /* resample with float, because this is the best format for
- libsamplerate */
-
- if (src_format->sample_rate != dest_format->sample_rate) {
- buffer = pcm_resample_float(&state->resample,
- dest_format->channels,
- src_format->sample_rate,
- buffer, size,
- dest_format->sample_rate, &size,
- error_r);
- if (buffer == NULL)
- return NULL;
- }
-
- *dest_size_r = size;
- return buffer;
-}
-
-const void *
-pcm_convert(struct pcm_convert_state *state,
- const struct audio_format *src_format,
- const void *src, size_t src_size,
- const struct audio_format *dest_format,
- size_t *dest_size_r,
- GError **error_r)
-{
+#if 0 // FIXME
struct audio_format float_format;
if (src_format->format == SAMPLE_FORMAT_DSD) {
size_t f_size;
@@ -344,36 +82,63 @@ pcm_convert(struct pcm_convert_state *state,
src = f;
src_size = f_size;
}
-
- switch (dest_format->format) {
- case SAMPLE_FORMAT_S16:
- return pcm_convert_16(state,
- src_format, src, src_size,
- dest_format, dest_size_r,
- error_r);
-
- case SAMPLE_FORMAT_S24_P32:
- return pcm_convert_24(state,
- src_format, src, src_size,
- dest_format, dest_size_r,
- error_r);
-
- case SAMPLE_FORMAT_S32:
- return pcm_convert_32(state,
- src_format, src, src_size,
- dest_format, dest_size_r,
- error_r);
-
- case SAMPLE_FORMAT_FLOAT:
- return pcm_convert_float(state,
- src_format, src, src_size,
- dest_format, dest_size_r,
- error_r);
-
- default:
- g_set_error(error_r, pcm_convert_quark(), 0,
- "PCM conversion to %s is not implemented",
- sample_format_to_string(dest_format->format));
- return NULL;
- }
+#endif
+
+ if (!state->avr) {
+ char in_layout[128], out_layout[128];
+ state->avr = avresample_alloc_context();
+ if (!state->avr)
+ return NULL;
+
+ state->dst_channel_layout = av_get_default_channel_layout(dest_format->channels);
+ state->dst_samplerate = dest_format->sample_rate;
+ state->dst_format = sample_fmt_native_to_libav(dest_format->format);
+
+ av_opt_set_int(state->avr, "in_channel_layout", src->channel_layout, 0);
+ av_opt_set_int(state->avr, "out_channel_layout", state->dst_channel_layout, 0);
+ av_opt_set_int(state->avr, "in_sample_rate", src->sample_rate, 0);
+ av_opt_set_int(state->avr, "out_sample_rate", state->dst_samplerate, 0);
+ av_opt_set_int(state->avr, "in_sample_fmt", src->format, 0);
+ av_opt_set_int(state->avr, "out_sample_fmt", state->dst_format, 0);
+
+ av_get_channel_layout_string(in_layout, sizeof(in_layout), -1, src->channel_layout);
+ av_get_channel_layout_string(out_layout, sizeof(out_layout), -1, state->dst_channel_layout);
+ g_debug("Opening resampling context %s:%d:%s -> %s:%d:%s\n",
+ av_get_sample_fmt_name(src->format), src->sample_rate, in_layout,
+ av_get_sample_fmt_name(state->dst_format), state->dst_samplerate, out_layout);
+
+ ret = avresample_open(state->avr);
+ if (ret < 0) {
+ g_warning("Error initializing format conversion.\n");
+ avresample_free(&state->avr);
+ return NULL;
+ }
+ }
+
+ dst = av_frame_alloc();
+ if (!dst)
+ return NULL;
+ dst->format = state->dst_format;
+ dst->channel_layout = state->dst_channel_layout;
+ dst->sample_rate = state->dst_samplerate;
+ dst->nb_samples = avresample_get_out_samples(state->avr, src->nb_samples);
+
+ ret = av_frame_get_buffer(dst, 32);
+ if (ret < 0) {
+ g_warning("Error allocating a buffer for format conversion.\n");
+ av_frame_free(&dst);
+ return NULL;
+ }
+
+ ret = avresample_convert(state->avr, dst->extended_data, dst->linesize[0],
+ dst->nb_samples, src->extended_data, src->linesize[0],
+ src->nb_samples);
+ if (ret < 0) {
+ g_warning("Error during format conversion.\n");
+ av_frame_free(&dst);
+ return NULL;
+ }
+ dst->nb_samples = ret;
+
+ return dst;
}
diff --git a/src/pcm_convert.h b/src/pcm_convert.h
index be11a6e4..b9b1af17 100644
--- a/src/pcm_convert.h
+++ b/src/pcm_convert.h
@@ -21,10 +21,13 @@
#define PCM_CONVERT_H
#include "pcm_dsd.h"
-#include "pcm_resample.h"
#include "pcm_dither.h"
#include "pcm_buffer.h"
+#include <libavutil/frame.h>
+#include <libavutil/samplefmt.h>
+#include <libavresample/avresample.h>
+
struct audio_format;
/**
@@ -35,15 +38,10 @@ struct audio_format;
struct pcm_convert_state {
struct pcm_dsd dsd;
- struct pcm_resample_state resample;
-
- struct pcm_dither dither;
-
- /** the buffer for converting the sample format */
- struct pcm_buffer format_buffer;
-
- /** the buffer for converting the channel count */
- struct pcm_buffer channels_buffer;
+ AVAudioResampleContext *avr;
+ enum AVSampleFormat dst_format;
+ int dst_samplerate;
+ uint64_t dst_channel_layout;
};
static inline GQuark
@@ -83,12 +81,9 @@ pcm_convert_reset(struct pcm_convert_state *state);
* ignore errors
* @return the destination buffer, or NULL on error
*/
-const void *
-pcm_convert(struct pcm_convert_state *state,
- const struct audio_format *src_format,
- const void *src, size_t src_size,
- const struct audio_format *dest_format,
- size_t *dest_size_r,
- GError **error_r);
+AVFrame *pcm_convert(struct pcm_convert_state *state,
+ const struct audio_format *src_format,
+ const struct audio_format *dest_format,
+ const AVFrame *src);
#endif
diff --git a/src/pcm_format.c b/src/pcm_format.c
deleted file mode 100644
index d3ea3acb..00000000
--- a/src/pcm_format.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * 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
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-#include "pcm_format.h"
-#include "pcm_dither.h"
-#include "pcm_buffer.h"
-#include "pcm_pack.h"
-#include "pcm_utils.h"
-
-static void
-pcm_convert_8_to_16(int16_t *out, const int8_t *in, const int8_t *in_end)
-{
- while (in < in_end) {
- *out++ = *in++ << 8;
- }
-}
-
-static void
-pcm_convert_24_to_16(struct pcm_dither *dither,
- int16_t *out, const int32_t *in, const int32_t *in_end)
-{
- pcm_dither_24_to_16(dither, out, in, in_end);
-}
-
-static void
-pcm_convert_32_to_16(struct pcm_dither *dither,
- int16_t *out, const int32_t *in, const int32_t *in_end)
-{
- pcm_dither_32_to_16(dither, out, in, in_end);
-}
-
-static void
-pcm_convert_float_to_16(int16_t *out, const float *in, const float *in_end)
-{
- const unsigned OUT_BITS = 16;
- const float factor = 1 << (OUT_BITS - 1);
-
- while (in < in_end) {
- int sample = *in++ * factor;
- *out++ = pcm_clamp_16(sample);
- }
-}
-
-static int16_t *
-pcm_allocate_8_to_16(struct pcm_buffer *buffer,
- const int8_t *src, size_t src_size, size_t *dest_size_r)
-{
- int16_t *dest;
- *dest_size_r = src_size / sizeof(*src) * sizeof(*dest);
- dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_8_to_16(dest, src, pcm_end_pointer(src, src_size));
- return dest;
-}
-
-static int16_t *
-pcm_allocate_24p32_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
- const int32_t *src, size_t src_size,
- size_t *dest_size_r)
-{
- int16_t *dest;
- *dest_size_r = src_size / 2;
- assert(*dest_size_r == src_size / sizeof(*src) * sizeof(*dest));
- dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_24_to_16(dither, dest, src,
- pcm_end_pointer(src, src_size));
- return dest;
-}
-
-static int16_t *
-pcm_allocate_32_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
- const int32_t *src, size_t src_size,
- size_t *dest_size_r)
-{
- int16_t *dest;
- *dest_size_r = src_size / 2;
- assert(*dest_size_r == src_size / sizeof(*src) * sizeof(*dest));
- dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_32_to_16(dither, dest, src,
- pcm_end_pointer(src, src_size));
- return dest;
-}
-
-static int16_t *
-pcm_allocate_float_to_16(struct pcm_buffer *buffer,
- const float *src, size_t src_size,
- size_t *dest_size_r)
-{
- int16_t *dest;
- *dest_size_r = src_size / 2;
- assert(*dest_size_r == src_size / sizeof(*src) * sizeof(*dest));
- dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_float_to_16(dest, src,
- pcm_end_pointer(src, src_size));
- return dest;
-}
-
-const int16_t *
-pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
- enum sample_format src_format, const void *src,
- size_t src_size, size_t *dest_size_r)
-{
- assert(src_size % sample_format_size(src_format) == 0);
-
- switch (src_format) {
- case SAMPLE_FORMAT_UNDEFINED:
- case SAMPLE_FORMAT_DSD:
- break;
-
- case SAMPLE_FORMAT_S8:
- return pcm_allocate_8_to_16(buffer,
- src, src_size, dest_size_r);
-
- case SAMPLE_FORMAT_S16:
- *dest_size_r = src_size;
- return src;
-
- case SAMPLE_FORMAT_S24_P32:
- return pcm_allocate_24p32_to_16(buffer, dither, src, src_size,
- dest_size_r);
-
- case SAMPLE_FORMAT_S32:
- return pcm_allocate_32_to_16(buffer, dither, src, src_size,
- dest_size_r);
-
- case SAMPLE_FORMAT_FLOAT:
- return pcm_allocate_float_to_16(buffer, src, src_size,
- dest_size_r);
- }
-
- return NULL;
-}
-
-static void
-pcm_convert_8_to_24(int32_t *out, const int8_t *in, const int8_t *in_end)
-{
- while (in < in_end)
- *out++ = *in++ << 16;
-}
-
-static void
-pcm_convert_16_to_24(int32_t *out, const int16_t *in, const int16_t *in_end)
-{
- while (in < in_end)
- *out++ = *in++ << 8;
-}
-
-static void
-pcm_convert_32_to_24(int32_t *restrict out,
- const int32_t *restrict in,
- const int32_t *restrict in_end)
-{
- while (in < in_end)
- *out++ = *in++ >> 8;
-}
-
-static void
-pcm_convert_float_to_24(int32_t *out, const float *in, const float *in_end)
-{
- const unsigned OUT_BITS = 24;
- const float factor = 1 << (OUT_BITS - 1);
-
- while (in < in_end) {
- int sample = *in++ * factor;
- *out++ = pcm_clamp_24(sample);
- }
-}
-
-static int32_t *
-pcm_allocate_8_to_24(struct pcm_buffer *buffer,
- const int8_t *src, size_t src_size, size_t *dest_size_r)
-{
- int32_t *dest;
- *dest_size_r = src_size / sizeof(*src) * sizeof(*dest);
- dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_8_to_24(dest, src, pcm_end_pointer(src, src_size));
- return dest;
-}
-
-static int32_t *
-pcm_allocate_16_to_24(struct pcm_buffer *buffer,
- const int16_t *src, size_t src_size, size_t *dest_size_r)
-{
- int32_t *dest;
- *dest_size_r = src_size * 2;
- assert(*dest_size_r == src_size / sizeof(*src) * sizeof(*dest));
- dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_16_to_24(dest, src, pcm_end_pointer(src, src_size));
- return dest;
-}
-
-static int32_t *
-pcm_allocate_32_to_24(struct pcm_buffer *buffer,
- const int32_t *src, size_t src_size, size_t *dest_size_r)
-{
- *dest_size_r = src_size;
- int32_t *dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_32_to_24(dest, src, pcm_end_pointer(src, src_size));
- return dest;
-}
-
-static int32_t *
-pcm_allocate_float_to_24(struct pcm_buffer *buffer,
- const float *src, size_t src_size,
- size_t *dest_size_r)
-{
- *dest_size_r = src_size;
- int32_t *dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_float_to_24(dest, src, pcm_end_pointer(src, src_size));
- return dest;
-}
-
-const int32_t *
-pcm_convert_to_24(struct pcm_buffer *buffer,
- enum sample_format src_format, const void *src,
- size_t src_size, size_t *dest_size_r)
-{
- assert(src_size % sample_format_size(src_format) == 0);
-
- switch (src_format) {
- case SAMPLE_FORMAT_UNDEFINED:
- case SAMPLE_FORMAT_DSD:
- break;
-
- case SAMPLE_FORMAT_S8:
- return pcm_allocate_8_to_24(buffer,
- src, src_size, dest_size_r);
-
- case SAMPLE_FORMAT_S16:
- return pcm_allocate_16_to_24(buffer,
- src, src_size, dest_size_r);
-
- case SAMPLE_FORMAT_S24_P32:
- *dest_size_r = src_size;
- return src;
-
- case SAMPLE_FORMAT_S32:
- return pcm_allocate_32_to_24(buffer, src, src_size,
- dest_size_r);
-
- case SAMPLE_FORMAT_FLOAT:
- return pcm_allocate_float_to_24(buffer, src, src_size,
- dest_size_r);
- }
-
- return NULL;
-}
-
-static void
-pcm_convert_8_to_32(int32_t *out, const int8_t *in, const int8_t *in_end)
-{
- while (in < in_end)
- *out++ = *in++ << 24;
-}
-
-static void
-pcm_convert_16_to_32(int32_t *out, const int16_t *in, const int16_t *in_end)
-{
- while (in < in_end)
- *out++ = *in++ << 16;
-}
-
-static void
-pcm_convert_24_to_32(int32_t *restrict out,
- const int32_t *restrict in,
- const int32_t *restrict in_end)
-{
- while (in < in_end)
- *out++ = *in++ << 8;
-}
-
-static int32_t *
-pcm_allocate_8_to_32(struct pcm_buffer *buffer,
- const int8_t *src, size_t src_size, size_t *dest_size_r)
-{
- int32_t *dest;
- *dest_size_r = src_size / sizeof(*src) * sizeof(*dest);
- dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_8_to_32(dest, src, pcm_end_pointer(src, src_size));
- return dest;
-}
-
-static int32_t *
-pcm_allocate_16_to_32(struct pcm_buffer *buffer,
- const int16_t *src, size_t src_size, size_t *dest_size_r)
-{
- int32_t *dest;
- *dest_size_r = src_size * 2;
- assert(*dest_size_r == src_size / sizeof(*src) * sizeof(*dest));
- dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_16_to_32(dest, src, pcm_end_pointer(src, src_size));
- return dest;
-}
-
-static int32_t *
-pcm_allocate_24p32_to_32(struct pcm_buffer *buffer,
- const int32_t *src, size_t src_size,
- size_t *dest_size_r)
-{
- *dest_size_r = src_size;
- int32_t *dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_24_to_32(dest, src, pcm_end_pointer(src, src_size));
- return dest;
-}
-
-static int32_t *
-pcm_allocate_float_to_32(struct pcm_buffer *buffer,
- const float *src, size_t src_size,
- size_t *dest_size_r)
-{
- /* convert to S24_P32 first */
- int32_t *dest = pcm_allocate_float_to_24(buffer, src, src_size,
- dest_size_r);
-
- /* convert to 32 bit in-place */
- pcm_convert_24_to_32(dest, dest, pcm_end_pointer(dest, *dest_size_r));
- return dest;
-}
-
-const int32_t *
-pcm_convert_to_32(struct pcm_buffer *buffer,
- enum sample_format src_format, const void *src,
- size_t src_size, size_t *dest_size_r)
-{
- assert(src_size % sample_format_size(src_format) == 0);
-
- switch (src_format) {
- case SAMPLE_FORMAT_UNDEFINED:
- case SAMPLE_FORMAT_DSD:
- break;
-
- case SAMPLE_FORMAT_S8:
- return pcm_allocate_8_to_32(buffer, src, src_size,
- dest_size_r);
-
- case SAMPLE_FORMAT_S16:
- return pcm_allocate_16_to_32(buffer, src, src_size,
- dest_size_r);
-
- case SAMPLE_FORMAT_S24_P32:
- return pcm_allocate_24p32_to_32(buffer, src, src_size,
- dest_size_r);
-
- case SAMPLE_FORMAT_S32:
- *dest_size_r = src_size;
- return src;
-
- case SAMPLE_FORMAT_FLOAT:
- return pcm_allocate_float_to_32(buffer, src, src_size,
- dest_size_r);
- }
-
- return NULL;
-}
-
-static void
-pcm_convert_8_to_float(float *out, const int8_t *in, const int8_t *in_end)
-{
- enum { in_bits = sizeof(*in) * 8 };
- static const float factor = 2.0f / (1 << in_bits);
- while (in < in_end)
- *out++ = (float)*in++ * factor;
-}
-
-static void
-pcm_convert_16_to_float(float *out, const int16_t *in, const int16_t *in_end)
-{
- enum { in_bits = sizeof(*in) * 8 };
- static const float factor = 2.0f / (1 << in_bits);
- while (in < in_end)
- *out++ = (float)*in++ * factor;
-}
-
-static void
-pcm_convert_24_to_float(float *out, const int32_t *in, const int32_t *in_end)
-{
- enum { in_bits = 24 };
- static const float factor = 2.0f / (1 << in_bits);
- while (in < in_end)
- *out++ = (float)*in++ * factor;
-}
-
-static void
-pcm_convert_32_to_float(float *out, const int32_t *in, const int32_t *in_end)
-{
- enum { in_bits = sizeof(*in) * 8 };
- static const float factor = 0.5f / (1 << (in_bits - 2));
- while (in < in_end)
- *out++ = (float)*in++ * factor;
-}
-
-static float *
-pcm_allocate_8_to_float(struct pcm_buffer *buffer,
- const int8_t *src, size_t src_size,
- size_t *dest_size_r)
-{
- float *dest;
- *dest_size_r = src_size / sizeof(*src) * sizeof(*dest);
- dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_8_to_float(dest, src, pcm_end_pointer(src, src_size));
- return dest;
-}
-
-static float *
-pcm_allocate_16_to_float(struct pcm_buffer *buffer,
- const int16_t *src, size_t src_size,
- size_t *dest_size_r)
-{
- float *dest;
- *dest_size_r = src_size * 2;
- assert(*dest_size_r == src_size / sizeof(*src) * sizeof(*dest));
- dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_16_to_float(dest, src, pcm_end_pointer(src, src_size));
- return dest;
-}
-
-static float *
-pcm_allocate_24p32_to_float(struct pcm_buffer *buffer,
- const int32_t *src, size_t src_size,
- size_t *dest_size_r)
-{
- *dest_size_r = src_size;
- float *dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_24_to_float(dest, src, pcm_end_pointer(src, src_size));
- return dest;
-}
-
-static float *
-pcm_allocate_32_to_float(struct pcm_buffer *buffer,
- const int32_t *src, size_t src_size,
- size_t *dest_size_r)
-{
- *dest_size_r = src_size;
- float *dest = pcm_buffer_get(buffer, *dest_size_r);
- pcm_convert_32_to_float(dest, src, pcm_end_pointer(src, src_size));
- return dest;
-}
-
-const float *
-pcm_convert_to_float(struct pcm_buffer *buffer,
- enum sample_format src_format, const void *src,
- size_t src_size, size_t *dest_size_r)
-{
- switch (src_format) {
- case SAMPLE_FORMAT_UNDEFINED:
- case SAMPLE_FORMAT_DSD:
- break;
-
- case SAMPLE_FORMAT_S8:
- return pcm_allocate_8_to_float(buffer,
- src, src_size, dest_size_r);
-
- case SAMPLE_FORMAT_S16:
- return pcm_allocate_16_to_float(buffer,
- src, src_size, dest_size_r);
-
- case SAMPLE_FORMAT_S24_P32:
- return pcm_allocate_24p32_to_float(buffer,
- src, src_size, dest_size_r);
-
- case SAMPLE_FORMAT_S32:
- return pcm_allocate_32_to_float(buffer,
- src, src_size, dest_size_r);
-
- case SAMPLE_FORMAT_FLOAT:
- *dest_size_r = src_size;
- return src;
- }
-
- return NULL;
-}
diff --git a/src/pcm_format.h b/src/pcm_format.h
deleted file mode 100644
index 48bcd066..00000000
--- a/src/pcm_format.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef PCM_FORMAT_H
-#define PCM_FORMAT_H
-
-#include "audio_format.h"
-
-#include <stdint.h>
-#include <stddef.h>
-
-struct pcm_buffer;
-struct pcm_dither;
-
-/**
- * Converts PCM samples to 16 bit. If the source format is 24 bit,
- * then dithering is applied.
- *
- * @param buffer a pcm_buffer object
- * @param dither a pcm_dither object for 24-to-16 conversion
- * @param bits the number of in the source buffer
- * @param src the source PCM buffer
- * @param src_size the size of #src in bytes
- * @param dest_size_r returns the number of bytes of the destination buffer
- * @return the destination buffer
- */
-const int16_t *
-pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
- enum sample_format src_format, const void *src,
- size_t src_size, size_t *dest_size_r);
-
-/**
- * Converts PCM samples to 24 bit (32 bit alignment).
- *
- * @param buffer a pcm_buffer object
- * @param bits the number of in the source buffer
- * @param src the source PCM buffer
- * @param src_size the size of #src in bytes
- * @param dest_size_r returns the number of bytes of the destination buffer
- * @return the destination buffer
- */
-const int32_t *
-pcm_convert_to_24(struct pcm_buffer *buffer,
- enum sample_format src_format, const void *src,
- size_t src_size, size_t *dest_size_r);
-
-/**
- * Converts PCM samples to 32 bit.
- *
- * @param buffer a pcm_buffer object
- * @param bits the number of in the source buffer
- * @param src the source PCM buffer
- * @param src_size the size of #src in bytes
- * @param dest_size_r returns the number of bytes of the destination buffer
- * @return the destination buffer
- */
-const int32_t *
-pcm_convert_to_32(struct pcm_buffer *buffer,
- enum sample_format src_format, const void *src,
- size_t src_size, size_t *dest_size_r);
-
-/**
- * Converts PCM samples to 32 bit floating point.
- *
- * @param buffer a pcm_buffer object
- * @param bits the number of in the source buffer
- * @param src the source PCM buffer
- * @param src_size the size of #src in bytes
- * @param dest_size_r returns the number of bytes of the destination buffer
- * @return the destination buffer
- */
-const float *
-pcm_convert_to_float(struct pcm_buffer *buffer,
- enum sample_format src_format, const void *src,
- size_t src_size, size_t *dest_size_r);
-
-#endif
diff --git a/src/pcm_resample.c b/src/pcm_resample.c
deleted file mode 100644
index bb75db6c..00000000
--- a/src/pcm_resample.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-#include "pcm_resample_internal.h"
-
-#if CONFIG_LIBSAMPLERATE
-#include "conf.h"
-#endif
-
-#include <string.h>
-
-#if CONFIG_LIBSAMPLERATE
-static bool lsr_enabled;
-#endif
-
-#if CONFIG_LIBSAMPLERATE
-static bool
-pcm_resample_lsr_enabled(void)
-{
- return lsr_enabled;
-}
-#endif
-
-bool
-pcm_resample_global_init(GError **error_r)
-{
-#if CONFIG_LIBSAMPLERATE
- const char *converter =
- config_get_string(CONF_SAMPLERATE_CONVERTER, "");
-
- lsr_enabled = strcmp(converter, "internal") != 0;
- if (lsr_enabled)
- return pcm_resample_lsr_global_init(converter, error_r);
- else
- return true;
-#else
- (void)error_r;
- return true;
-#endif
-}
-
-void pcm_resample_init(struct pcm_resample_state *state)
-{
-#if CONFIG_LIBSAMPLERATE
- if (pcm_resample_lsr_enabled())
- pcm_resample_lsr_init(state);
- else
-#endif
- pcm_resample_fallback_init(state);
-}
-
-void pcm_resample_deinit(struct pcm_resample_state *state)
-{
-#if CONFIG_LIBSAMPLERATE
- if (pcm_resample_lsr_enabled())
- pcm_resample_lsr_deinit(state);
- else
-#endif
- pcm_resample_fallback_deinit(state);
-}
-
-void
-pcm_resample_reset(struct pcm_resample_state *state)
-{
-#if CONFIG_LIBSAMPLERATE
- pcm_resample_lsr_reset(state);
-#else
- (void)state;
-#endif
-}
-
-const float *
-pcm_resample_float(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const float *src_buffer, size_t src_size,
- unsigned dest_rate, size_t *dest_size_r,
- GError **error_r)
-{
-#if CONFIG_LIBSAMPLERATE
- if (pcm_resample_lsr_enabled())
- return pcm_resample_lsr_float(state, channels,
- src_rate, src_buffer, src_size,
- dest_rate, dest_size_r,
- error_r);
-#else
- (void)error_r;
-#endif
-
- /* sizeof(float)==sizeof(int32_t); the fallback resampler does
- not do any math on the sample values, so this hack is
- possible: */
- return (const float *)
- pcm_resample_fallback_32(state, channels,
- src_rate, (const int32_t *)src_buffer,
- src_size,
- dest_rate, dest_size_r);
-}
-
-const int16_t *
-pcm_resample_16(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate, const int16_t *src_buffer, size_t src_size,
- unsigned dest_rate, size_t *dest_size_r,
- GError **error_r)
-{
-#if CONFIG_LIBSAMPLERATE
- if (pcm_resample_lsr_enabled())
- return pcm_resample_lsr_16(state, channels,
- src_rate, src_buffer, src_size,
- dest_rate, dest_size_r,
- error_r);
-#else
- (void)error_r;
-#endif
-
- return pcm_resample_fallback_16(state, channels,
- src_rate, src_buffer, src_size,
- dest_rate, dest_size_r);
-}
-
-const int32_t *
-pcm_resample_32(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate, const int32_t *src_buffer, size_t src_size,
- unsigned dest_rate, size_t *dest_size_r,
- GError **error_r)
-{
-#if CONFIG_LIBSAMPLERATE
- if (pcm_resample_lsr_enabled())
- return pcm_resample_lsr_32(state, channels,
- src_rate, src_buffer, src_size,
- dest_rate, dest_size_r,
- error_r);
-#else
- (void)error_r;
-#endif
-
- return pcm_resample_fallback_32(state, channels,
- src_rate, src_buffer, src_size,
- dest_rate, dest_size_r);
-}
diff --git a/src/pcm_resample.h b/src/pcm_resample.h
deleted file mode 100644
index 8e73659d..00000000
--- a/src/pcm_resample.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef MPD_PCM_RESAMPLE_H
-#define MPD_PCM_RESAMPLE_H
-
-#include "check.h"
-#include "pcm_buffer.h"
-
-#include <stdint.h>
-#include <stddef.h>
-#include <stdbool.h>
-
-#if CONFIG_LIBSAMPLERATE
-#include <samplerate.h>
-#endif
-
-/**
- * This object is statically allocated (within another struct), and
- * holds buffer allocations and the state for the resampler.
- */
-struct pcm_resample_state {
-#if CONFIG_LIBSAMPLERATE
- SRC_STATE *state;
- SRC_DATA data;
-
- struct pcm_buffer in, out;
-
- struct {
- unsigned src_rate;
- unsigned dest_rate;
- unsigned channels;
- } prev;
-
- int error;
-#endif
-
- struct pcm_buffer buffer;
-};
-
-bool
-pcm_resample_global_init(GError **error_r);
-
-/**
- * Initializes a pcm_resample_state object.
- */
-void pcm_resample_init(struct pcm_resample_state *state);
-
-/**
- * Deinitializes a pcm_resample_state object and frees allocated
- * memory.
- */
-void pcm_resample_deinit(struct pcm_resample_state *state);
-
-/**
- * @see pcm_convert_reset()
- */
-void
-pcm_resample_reset(struct pcm_resample_state *state);
-
-/**
- * Resamples 32 bit float data.
- *
- * @param state an initialized pcm_resample_state object
- * @param channels the number of channels
- * @param src_rate the source sample rate
- * @param src the source PCM buffer
- * @param src_size the size of #src in bytes
- * @param dest_rate the requested destination sample rate
- * @param dest_size_r returns the number of bytes of the destination buffer
- * @return the destination buffer
- */
-const float *
-pcm_resample_float(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const float *src_buffer, size_t src_size,
- unsigned dest_rate, size_t *dest_size_r,
- GError **error_r);
-
-/**
- * Resamples 16 bit PCM data.
- *
- * @param state an initialized pcm_resample_state object
- * @param channels the number of channels
- * @param src_rate the source sample rate
- * @param src the source PCM buffer
- * @param src_size the size of #src in bytes
- * @param dest_rate the requested destination sample rate
- * @param dest_size_r returns the number of bytes of the destination buffer
- * @return the destination buffer
- */
-const int16_t *
-pcm_resample_16(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const int16_t *src_buffer, size_t src_size,
- unsigned dest_rate, size_t *dest_size_r,
- GError **error_r);
-
-/**
- * Resamples 32 bit PCM data.
- *
- * @param state an initialized pcm_resample_state object
- * @param channels the number of channels
- * @param src_rate the source sample rate
- * @param src the source PCM buffer
- * @param src_size the size of #src in bytes
- * @param dest_rate the requested destination sample rate
- * @param dest_size_r returns the number of bytes of the destination buffer
- * @return the destination buffer
- */
-const int32_t *
-pcm_resample_32(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const int32_t *src_buffer, size_t src_size,
- unsigned dest_rate, size_t *dest_size_r,
- GError **error_r);
-
-/**
- * Resamples 24 bit PCM data.
- *
- * @param state an initialized pcm_resample_state object
- * @param channels the number of channels
- * @param src_rate the source sample rate
- * @param src the source PCM buffer
- * @param src_size the size of #src in bytes
- * @param dest_rate the requested destination sample rate
- * @param dest_size_r returns the number of bytes of the destination buffer
- * @return the destination buffer
- */
-static inline const int32_t *
-pcm_resample_24(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const int32_t *src_buffer, size_t src_size,
- unsigned dest_rate, size_t *dest_size_r,
- GError **error_r)
-{
- /* reuse the 32 bit code - the resampler code doesn't care if
- the upper 8 bits are actually used */
- return pcm_resample_32(state, channels,
- src_rate, src_buffer, src_size,
- dest_rate, dest_size_r, error_r);
-}
-
-#endif
diff --git a/src/pcm_resample_fallback.c b/src/pcm_resample_fallback.c
deleted file mode 100644
index 1d1dfdf5..00000000
--- a/src/pcm_resample_fallback.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-#include "pcm_resample_internal.h"
-
-#include <assert.h>
-
-void
-pcm_resample_fallback_init(struct pcm_resample_state *state)
-{
- pcm_buffer_init(&state->buffer);
-}
-
-void
-pcm_resample_fallback_deinit(struct pcm_resample_state *state)
-{
- pcm_buffer_deinit(&state->buffer);
-}
-
-/* resampling code blatantly ripped from ESD */
-const int16_t *
-pcm_resample_fallback_16(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const int16_t *src_buffer, size_t src_size,
- unsigned dest_rate,
- size_t *dest_size_r)
-{
- unsigned src_pos, dest_pos = 0;
- unsigned src_frames = src_size / channels / sizeof(*src_buffer);
- unsigned dest_frames =
- (src_frames * dest_rate + src_rate - 1) / src_rate;
- unsigned dest_samples = dest_frames * channels;
- size_t dest_size = dest_samples * sizeof(*src_buffer);
- int16_t *dest_buffer = pcm_buffer_get(&state->buffer, dest_size);
-
- assert((src_size % (sizeof(*src_buffer) * channels)) == 0);
-
- switch (channels) {
- case 1:
- while (dest_pos < dest_samples) {
- src_pos = dest_pos * src_rate / dest_rate;
-
- dest_buffer[dest_pos++] = src_buffer[src_pos];
- }
- break;
- case 2:
- while (dest_pos < dest_samples) {
- src_pos = dest_pos * src_rate / dest_rate;
- src_pos &= ~1;
-
- dest_buffer[dest_pos++] = src_buffer[src_pos];
- dest_buffer[dest_pos++] = src_buffer[src_pos + 1];
- }
- break;
- }
-
- *dest_size_r = dest_size;
- return dest_buffer;
-}
-
-const int32_t *
-pcm_resample_fallback_32(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const int32_t *src_buffer, size_t src_size,
- unsigned dest_rate,
- size_t *dest_size_r)
-{
- unsigned src_pos, dest_pos = 0;
- unsigned src_frames = src_size / channels / sizeof(*src_buffer);
- unsigned dest_frames =
- (src_frames * dest_rate + src_rate - 1) / src_rate;
- unsigned dest_samples = dest_frames * channels;
- size_t dest_size = dest_samples * sizeof(*src_buffer);
- int32_t *dest_buffer = pcm_buffer_get(&state->buffer, dest_size);
-
- assert((src_size % (sizeof(*src_buffer) * channels)) == 0);
-
- switch (channels) {
- case 1:
- while (dest_pos < dest_samples) {
- src_pos = dest_pos * src_rate / dest_rate;
-
- dest_buffer[dest_pos++] = src_buffer[src_pos];
- }
- break;
- case 2:
- while (dest_pos < dest_samples) {
- src_pos = dest_pos * src_rate / dest_rate;
- src_pos &= ~1;
-
- dest_buffer[dest_pos++] = src_buffer[src_pos];
- dest_buffer[dest_pos++] = src_buffer[src_pos + 1];
- }
- break;
- }
-
- *dest_size_r = dest_size;
- return dest_buffer;
-}
diff --git a/src/pcm_resample_internal.h b/src/pcm_resample_internal.h
deleted file mode 100644
index 528ea2d6..00000000
--- a/src/pcm_resample_internal.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/** \file
- *
- * Internal declarations for the pcm_resample library. The "internal"
- * resampler is called "fallback" in the MPD source, so the file name
- * of this header is somewhat unrelated to it.
- */
-
-#ifndef MPD_PCM_RESAMPLE_INTERNAL_H
-#define MPD_PCM_RESAMPLE_INTERNAL_H
-
-#include "check.h"
-#include "pcm_resample.h"
-
-#if CONFIG_LIBSAMPLERATE
-
-bool
-pcm_resample_lsr_global_init(const char *converter, GError **error_r);
-
-void
-pcm_resample_lsr_init(struct pcm_resample_state *state);
-
-void
-pcm_resample_lsr_deinit(struct pcm_resample_state *state);
-
-void
-pcm_resample_lsr_reset(struct pcm_resample_state *state);
-
-const float *
-pcm_resample_lsr_float(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const float *src_buffer, size_t src_size,
- unsigned dest_rate, size_t *dest_size_r,
- GError **error_r);
-
-const int16_t *
-pcm_resample_lsr_16(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const int16_t *src_buffer, size_t src_size,
- unsigned dest_rate, size_t *dest_size_r,
- GError **error_r);
-
-const int32_t *
-pcm_resample_lsr_32(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const int32_t *src_buffer,
- G_GNUC_UNUSED size_t src_size,
- unsigned dest_rate, size_t *dest_size_r,
- GError **error_r);
-
-#endif
-
-void
-pcm_resample_fallback_init(struct pcm_resample_state *state);
-
-void
-pcm_resample_fallback_deinit(struct pcm_resample_state *state);
-
-const int16_t *
-pcm_resample_fallback_16(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const int16_t *src_buffer, size_t src_size,
- unsigned dest_rate,
- size_t *dest_size_r);
-
-const int32_t *
-pcm_resample_fallback_32(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const int32_t *src_buffer,
- G_GNUC_UNUSED size_t src_size,
- unsigned dest_rate,
- size_t *dest_size_r);
-
-#endif
diff --git a/src/pcm_resample_libsamplerate.c b/src/pcm_resample_libsamplerate.c
deleted file mode 100644
index f957e515..00000000
--- a/src/pcm_resample_libsamplerate.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * 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
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-#include "pcm_resample_internal.h"
-#include "conf.h"
-
-#include <glib.h>
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "pcm"
-
-static int lsr_converter = SRC_SINC_FASTEST;
-
-static inline GQuark
-libsamplerate_quark(void)
-{
- return g_quark_from_static_string("libsamplerate");
-}
-
-static bool
-lsr_parse_converter(const char *s)
-{
- assert(s != NULL);
-
- if (*s == 0)
- return true;
-
- char *endptr;
- long l = strtol(s, &endptr, 10);
- if (*endptr == 0 && src_get_name(l) != NULL) {
- lsr_converter = l;
- return true;
- }
-
- size_t length = strlen(s);
- for (int i = 0;; ++i) {
- const char *name = src_get_name(i);
- if (name == NULL)
- break;
-
- if (g_ascii_strncasecmp(s, name, length) == 0) {
- lsr_converter = i;
- return true;
- }
- }
-
- return false;
-}
-
-bool
-pcm_resample_lsr_global_init(const char *converter, GError **error_r)
-{
- if (!lsr_parse_converter(converter)) {
- g_set_error(error_r, libsamplerate_quark(), 0,
- "unknown samplerate converter '%s'", converter);
- return false;
- }
-
- g_debug("libsamplerate converter '%s'",
- src_get_name(lsr_converter));
-
- return true;
-}
-
-void
-pcm_resample_lsr_init(struct pcm_resample_state *state)
-{
- memset(state, 0, sizeof(*state));
-
- pcm_buffer_init(&state->in);
- pcm_buffer_init(&state->out);
- pcm_buffer_init(&state->buffer);
-}
-
-void
-pcm_resample_lsr_deinit(struct pcm_resample_state *state)
-{
- if (state->state != NULL)
- state->state = src_delete(state->state);
-
- pcm_buffer_deinit(&state->in);
- pcm_buffer_deinit(&state->out);
- pcm_buffer_deinit(&state->buffer);
-}
-
-void
-pcm_resample_lsr_reset(struct pcm_resample_state *state)
-{
- if (state->state != NULL)
- src_reset(state->state);
-}
-
-static bool
-pcm_resample_set(struct pcm_resample_state *state,
- unsigned channels, unsigned src_rate, unsigned dest_rate,
- GError **error_r)
-{
- int error;
- SRC_DATA *data = &state->data;
-
- /* (re)set the state/ratio if the in or out format changed */
- if (channels == state->prev.channels &&
- src_rate == state->prev.src_rate &&
- dest_rate == state->prev.dest_rate)
- return true;
-
- state->error = 0;
- state->prev.channels = channels;
- state->prev.src_rate = src_rate;
- state->prev.dest_rate = dest_rate;
-
- if (state->state)
- state->state = src_delete(state->state);
-
- state->state = src_new(lsr_converter, channels, &error);
- if (!state->state) {
- g_set_error(error_r, libsamplerate_quark(), state->error,
- "libsamplerate initialization has failed: %s",
- src_strerror(error));
- return false;
- }
-
- data->src_ratio = (double)dest_rate / (double)src_rate;
- g_debug("setting samplerate conversion ratio to %.2lf",
- data->src_ratio);
- src_set_ratio(state->state, data->src_ratio);
-
- return true;
-}
-
-static bool
-lsr_process(struct pcm_resample_state *state, GError **error_r)
-{
- if (state->error == 0)
- state->error = src_process(state->state, &state->data);
- if (state->error) {
- g_set_error(error_r, libsamplerate_quark(), state->error,
- "libsamplerate has failed: %s",
- src_strerror(state->error));
- return false;
- }
-
- return true;
-}
-
-static float *
-deconst_float_buffer(const float *in)
-{
- union {
- const float *in;
- float *out;
- } u = { .in = in };
- return u.out;
-}
-
-const float *
-pcm_resample_lsr_float(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const float *src_buffer, size_t src_size,
- unsigned dest_rate, size_t *dest_size_r,
- GError **error_r)
-{
- assert((src_size % (sizeof(*src_buffer) * channels)) == 0);
-
- if (!pcm_resample_set(state, channels, src_rate, dest_rate, error_r))
- return NULL;
-
- SRC_DATA *data = &state->data;
- data->input_frames = src_size / sizeof(*src_buffer) / channels;
- data->data_in = deconst_float_buffer(src_buffer);
-
- data->output_frames = (src_size * dest_rate + src_rate - 1) / src_rate;
- size_t data_out_size = data->output_frames * sizeof(float) * channels;
- data->data_out = pcm_buffer_get(&state->out, data_out_size);
-
- if (!lsr_process(state, error_r))
- return NULL;
-
- *dest_size_r = data->output_frames_gen *
- sizeof(*data->data_out) * channels;
- return data->data_out;
-}
-
-const int16_t *
-pcm_resample_lsr_16(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const int16_t *src_buffer, size_t src_size,
- unsigned dest_rate, size_t *dest_size_r,
- GError **error_r)
-{
- bool success;
- SRC_DATA *data = &state->data;
- size_t data_in_size;
- size_t data_out_size;
- int16_t *dest_buffer;
-
- assert((src_size % (sizeof(*src_buffer) * channels)) == 0);
-
- success = pcm_resample_set(state, channels, src_rate, dest_rate,
- error_r);
- if (!success)
- return NULL;
-
- data->input_frames = src_size / sizeof(*src_buffer) / channels;
- data_in_size = data->input_frames * sizeof(float) * channels;
- data->data_in = pcm_buffer_get(&state->in, data_in_size);
-
- data->output_frames = (src_size * dest_rate + src_rate - 1) / src_rate;
- data_out_size = data->output_frames * sizeof(float) * channels;
- data->data_out = pcm_buffer_get(&state->out, data_out_size);
-
- src_short_to_float_array(src_buffer, data->data_in,
- data->input_frames * channels);
-
- if (!lsr_process(state, error_r))
- return NULL;
-
- *dest_size_r = data->output_frames_gen *
- sizeof(*dest_buffer) * channels;
- dest_buffer = pcm_buffer_get(&state->buffer, *dest_size_r);
- src_float_to_short_array(data->data_out, dest_buffer,
- data->output_frames_gen * channels);
-
- return dest_buffer;
-}
-
-#ifdef HAVE_LIBSAMPLERATE_NOINT
-
-/* libsamplerate introduced these functions in v0.1.3 */
-
-static void
-src_int_to_float_array(const int *in, float *out, int len)
-{
- while (len-- > 0)
- *out++ = *in++ / (float)(1 << (24 - 1));
-}
-
-static void
-src_float_to_int_array (const float *in, int *out, int len)
-{
- while (len-- > 0)
- *out++ = *in++ * (float)(1 << (24 - 1));
-}
-
-#endif
-
-const int32_t *
-pcm_resample_lsr_32(struct pcm_resample_state *state,
- unsigned channels,
- unsigned src_rate,
- const int32_t *src_buffer, size_t src_size,
- unsigned dest_rate, size_t *dest_size_r,
- GError **error_r)
-{
- bool success;
- SRC_DATA *data = &state->data;
- size_t data_in_size;
- size_t data_out_size;
- int32_t *dest_buffer;
-
- assert((src_size % (sizeof(*src_buffer) * channels)) == 0);
-
- success = pcm_resample_set(state, channels, src_rate, dest_rate,
- error_r);
- if (!success)
- return NULL;
-
- data->input_frames = src_size / sizeof(*src_buffer) / channels;
- data_in_size = data->input_frames * sizeof(float) * channels;
- data->data_in = pcm_buffer_get(&state->in, data_in_size);
-
- data->output_frames = (src_size * dest_rate + src_rate - 1) / src_rate;
- data_out_size = data->output_frames * sizeof(float) * channels;
- data->data_out = pcm_buffer_get(&state->out, data_out_size);
-
- src_int_to_float_array(src_buffer, data->data_in,
- data->input_frames * channels);
-
- if (!lsr_process(state, error_r))
- return NULL;
-
- *dest_size_r = data->output_frames_gen *
- sizeof(*dest_buffer) * channels;
- dest_buffer = pcm_buffer_get(&state->buffer, *dest_size_r);
- src_float_to_int_array(data->data_out, dest_buffer,
- data->output_frames_gen * channels);
-
- return dest_buffer;
-}