pcm_utils: moved code to pcm_resample.c
Separate the resampling code from the rest of pcm_utils.c. Create two sub-libraries: pcm_resample_libsamplerate.c and pcm_resample_fallback.c.
This commit is contained in:
parent
098991f8e8
commit
6b1c54ef96
@ -390,6 +390,8 @@ if test x$enable_lsr = xyes; then
|
|||||||
[enable_lsr=no;AC_MSG_WARN([libsamplerate not found -- disabling])])
|
[enable_lsr=no;AC_MSG_WARN([libsamplerate not found -- disabling])])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AM_CONDITIONAL(HAVE_LIBSAMPLERATE, test x$enable_lsr = xyes)
|
||||||
|
|
||||||
if test x$enable_fifo = xyes; then
|
if test x$enable_fifo = xyes; then
|
||||||
AC_CHECK_FUNC([mkfifo],
|
AC_CHECK_FUNC([mkfifo],
|
||||||
[enable_fifo=yes;AC_DEFINE([HAVE_FIFO], 1, [Define to enable support for writing audio to a FIFO])],
|
[enable_fifo=yes;AC_DEFINE([HAVE_FIFO], 1, [Define to enable support for writing audio to a FIFO])],
|
||||||
|
@ -66,6 +66,7 @@ mpd_headers = \
|
|||||||
path.h \
|
path.h \
|
||||||
mapper.h \
|
mapper.h \
|
||||||
pcm_utils.h \
|
pcm_utils.h \
|
||||||
|
pcm_resample.h \
|
||||||
pcm_dither.h \
|
pcm_dither.h \
|
||||||
permission.h \
|
permission.h \
|
||||||
player_thread.h \
|
player_thread.h \
|
||||||
@ -146,6 +147,7 @@ mpd_SOURCES = \
|
|||||||
path.c \
|
path.c \
|
||||||
mapper.c \
|
mapper.c \
|
||||||
pcm_utils.c \
|
pcm_utils.c \
|
||||||
|
pcm_resample.c \
|
||||||
pcm_dither.c \
|
pcm_dither.c \
|
||||||
permission.c \
|
permission.c \
|
||||||
player_thread.c \
|
player_thread.c \
|
||||||
@ -176,6 +178,12 @@ mpd_SOURCES = \
|
|||||||
stored_playlist.c \
|
stored_playlist.c \
|
||||||
timer.c
|
timer.c
|
||||||
|
|
||||||
|
if HAVE_LIBSAMPLERATE
|
||||||
|
mpd_SOURCES += pcm_resample_libsamplerate.c
|
||||||
|
else
|
||||||
|
mpd_SOURCES += pcm_resample_fallback.c
|
||||||
|
endif
|
||||||
|
|
||||||
if HAVE_ID3TAG
|
if HAVE_ID3TAG
|
||||||
mpd_SOURCES += tag_id3.c
|
mpd_SOURCES += tag_id3.c
|
||||||
endif
|
endif
|
||||||
|
26
src/pcm_resample.c
Normal file
26
src/pcm_resample.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/* the Music Player Daemon (MPD)
|
||||||
|
* Copyright (C) 2008 Max Kellermann <max@duempel.org>
|
||||||
|
* 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_resample.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void pcm_resample_init(struct pcm_resample_state *state)
|
||||||
|
{
|
||||||
|
memset(state, 0, sizeof(*state));
|
||||||
|
}
|
63
src/pcm_resample.h
Normal file
63
src/pcm_resample.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* the Music Player Daemon (MPD)
|
||||||
|
* Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
|
||||||
|
* Copyright (C) 2008 Max Kellermann <max@duempel.org>
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MPD_PCM_RESAMPLE_H
|
||||||
|
#define MPD_PCM_RESAMPLE_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSAMPLERATE
|
||||||
|
#include <samplerate.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct pcm_resample_state {
|
||||||
|
#ifdef HAVE_LIBSAMPLERATE
|
||||||
|
SRC_STATE *state;
|
||||||
|
SRC_DATA data;
|
||||||
|
size_t data_in_size;
|
||||||
|
size_t data_out_size;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned src_rate;
|
||||||
|
unsigned dest_rate;
|
||||||
|
uint8_t channels;
|
||||||
|
} prev;
|
||||||
|
|
||||||
|
bool error;
|
||||||
|
#else
|
||||||
|
/* struct must not be empty */
|
||||||
|
int dummy;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
void pcm_resample_init(struct pcm_resample_state *state);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
pcm_resample_16(uint8_t channels,
|
||||||
|
unsigned src_rate,
|
||||||
|
const int16_t *src_buffer, size_t src_size,
|
||||||
|
unsigned dest_rate,
|
||||||
|
int16_t *dest_buffer, size_t dest_size,
|
||||||
|
struct pcm_resample_state *state);
|
||||||
|
|
||||||
|
#endif
|
61
src/pcm_resample_fallback.c
Normal file
61
src/pcm_resample_fallback.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* the Music Player Daemon (MPD)
|
||||||
|
* Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
|
||||||
|
* Copyright (C) 2008 Max Kellermann <max@duempel.org>
|
||||||
|
* 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_resample.h"
|
||||||
|
#include "gcc.h"
|
||||||
|
|
||||||
|
/* resampling code blatantly ripped from ESD */
|
||||||
|
size_t
|
||||||
|
pcm_resample_16(uint8_t channels,
|
||||||
|
unsigned src_rate,
|
||||||
|
const int16_t *src_buffer, mpd_unused size_t src_size,
|
||||||
|
unsigned dest_rate,
|
||||||
|
int16_t *dest_buffer, size_t dest_size,
|
||||||
|
mpd_unused struct pcm_resample_state *state)
|
||||||
|
{
|
||||||
|
unsigned src_pos, dest_pos = 0;
|
||||||
|
unsigned dest_samples = dest_size / 2;
|
||||||
|
int16_t lsample, rsample;
|
||||||
|
|
||||||
|
switch (channels) {
|
||||||
|
case 1:
|
||||||
|
while (dest_pos < dest_samples) {
|
||||||
|
src_pos = dest_pos * src_rate / dest_rate;
|
||||||
|
|
||||||
|
lsample = src_buffer[src_pos++];
|
||||||
|
|
||||||
|
dest_buffer[dest_pos++] = lsample;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
while (dest_pos < dest_samples) {
|
||||||
|
src_pos = dest_pos * src_rate / dest_rate;
|
||||||
|
src_pos &= ~1;
|
||||||
|
|
||||||
|
lsample = src_buffer[src_pos++];
|
||||||
|
rsample = src_buffer[src_pos++];
|
||||||
|
|
||||||
|
dest_buffer[dest_pos++] = lsample;
|
||||||
|
dest_buffer[dest_pos++] = rsample;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest_size;
|
||||||
|
}
|
140
src/pcm_resample_libsamplerate.c
Normal file
140
src/pcm_resample_libsamplerate.c
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/* the Music Player Daemon (MPD)
|
||||||
|
* Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
|
||||||
|
* Copyright (C) 2008 Max Kellermann <max@duempel.org>
|
||||||
|
* 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_resample.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static int pcm_resample_get_converter(void)
|
||||||
|
{
|
||||||
|
const char *conf = getConfigParamValue(CONF_SAMPLERATE_CONVERTER);
|
||||||
|
long convalgo;
|
||||||
|
char *test;
|
||||||
|
const char *test2;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (!conf) {
|
||||||
|
convalgo = SRC_SINC_FASTEST;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
convalgo = strtol(conf, &test, 10);
|
||||||
|
if (*test == '\0' && src_get_name(convalgo))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
len = strlen(conf);
|
||||||
|
for (convalgo = 0 ; ; convalgo++) {
|
||||||
|
test2 = src_get_name(convalgo);
|
||||||
|
if (!test2) {
|
||||||
|
convalgo = SRC_SINC_FASTEST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (strncasecmp(test2, conf, len) == 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ERROR("unknown samplerate converter \"%s\"\n", conf);
|
||||||
|
out:
|
||||||
|
DEBUG("selecting samplerate converter \"%s\"\n",
|
||||||
|
src_get_name(convalgo));
|
||||||
|
|
||||||
|
return convalgo;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
pcm_resample_16(uint8_t channels,
|
||||||
|
unsigned src_rate,
|
||||||
|
const int16_t *src_buffer, size_t src_size,
|
||||||
|
unsigned dest_rate,
|
||||||
|
int16_t *dest_buffer, size_t dest_size,
|
||||||
|
struct pcm_resample_state *state)
|
||||||
|
{
|
||||||
|
static int convalgo = -1;
|
||||||
|
SRC_DATA *data = &state->data;
|
||||||
|
size_t data_in_size;
|
||||||
|
size_t data_out_size;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (convalgo < 0)
|
||||||
|
convalgo = pcm_resample_get_converter();
|
||||||
|
|
||||||
|
/* (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) {
|
||||||
|
state->error = false;
|
||||||
|
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(convalgo, channels, &error);
|
||||||
|
if (!state->state) {
|
||||||
|
ERROR("cannot create new libsamplerate state: %s\n",
|
||||||
|
src_strerror(error));
|
||||||
|
state->error = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->src_ratio = (double)dest_rate / (double)src_rate;
|
||||||
|
DEBUG("setting samplerate conversion ratio to %.2lf\n",
|
||||||
|
data->src_ratio);
|
||||||
|
src_set_ratio(state->state, data->src_ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* there was an error previously, and nothing has changed */
|
||||||
|
if (state->error)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
data->input_frames = src_size / 2 / channels;
|
||||||
|
data_in_size = data->input_frames * sizeof(float) * channels;
|
||||||
|
if (data_in_size > state->data_in_size) {
|
||||||
|
state->data_in_size = data_in_size;
|
||||||
|
data->data_in = xrealloc(data->data_in, data_in_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
data->output_frames = dest_size / 2 / channels;
|
||||||
|
data_out_size = data->output_frames * sizeof(float) * channels;
|
||||||
|
if (data_out_size > state->data_out_size) {
|
||||||
|
state->data_out_size = data_out_size;
|
||||||
|
data->data_out = xrealloc(data->data_out, data_out_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
src_short_to_float_array(src_buffer, data->data_in,
|
||||||
|
data->input_frames * channels);
|
||||||
|
|
||||||
|
error = src_process(state->state, data);
|
||||||
|
if (error) {
|
||||||
|
ERROR("error processing samples with libsamplerate: %s\n",
|
||||||
|
src_strerror(error));
|
||||||
|
state->error = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
src_float_to_short_array(data->data_out, dest_buffer,
|
||||||
|
data->output_frames_gen * channels);
|
||||||
|
|
||||||
|
return data->output_frames_gen * 2 * channels;
|
||||||
|
}
|
168
src/pcm_utils.c
168
src/pcm_utils.c
@ -209,166 +209,10 @@ void pcm_convert_init(struct pcm_convert_state *state)
|
|||||||
{
|
{
|
||||||
memset(state, 0, sizeof(*state));
|
memset(state, 0, sizeof(*state));
|
||||||
|
|
||||||
|
pcm_resample_init(&state->resample);
|
||||||
pcm_dither_24_init(&state->dither);
|
pcm_dither_24_init(&state->dither);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LIBSAMPLERATE
|
|
||||||
static int pcm_resample_get_converter(void)
|
|
||||||
{
|
|
||||||
const char *conf = getConfigParamValue(CONF_SAMPLERATE_CONVERTER);
|
|
||||||
long convalgo;
|
|
||||||
char *test;
|
|
||||||
const char *test2;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (!conf) {
|
|
||||||
convalgo = SRC_SINC_FASTEST;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
convalgo = strtol(conf, &test, 10);
|
|
||||||
if (*test == '\0' && src_get_name(convalgo))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
len = strlen(conf);
|
|
||||||
for (convalgo = 0 ; ; convalgo++) {
|
|
||||||
test2 = src_get_name(convalgo);
|
|
||||||
if (!test2) {
|
|
||||||
convalgo = SRC_SINC_FASTEST;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (strncasecmp(test2, conf, len) == 0)
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERROR("unknown samplerate converter \"%s\"\n", conf);
|
|
||||||
out:
|
|
||||||
DEBUG("selecting samplerate converter \"%s\"\n",
|
|
||||||
src_get_name(convalgo));
|
|
||||||
|
|
||||||
return convalgo;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBSAMPLERATE
|
|
||||||
static size_t pcm_resample(int8_t channels, uint32_t inSampleRate,
|
|
||||||
const int16_t *src, size_t src_size,
|
|
||||||
uint32_t outSampleRate, int16_t *outBuffer,
|
|
||||||
size_t outSize,
|
|
||||||
struct pcm_convert_state *convState)
|
|
||||||
{
|
|
||||||
static int convalgo = -1;
|
|
||||||
SRC_DATA *data = &convState->data;
|
|
||||||
size_t dataInSize;
|
|
||||||
size_t dataOutSize;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if (convalgo < 0)
|
|
||||||
convalgo = pcm_resample_get_converter();
|
|
||||||
|
|
||||||
/* (re)set the state/ratio if the in or out format changed */
|
|
||||||
if ((channels != convState->lastChannels) ||
|
|
||||||
(inSampleRate != convState->lastInSampleRate) ||
|
|
||||||
(outSampleRate != convState->lastOutSampleRate)) {
|
|
||||||
convState->error = 0;
|
|
||||||
convState->lastChannels = channels;
|
|
||||||
convState->lastInSampleRate = inSampleRate;
|
|
||||||
convState->lastOutSampleRate = outSampleRate;
|
|
||||||
|
|
||||||
if (convState->state)
|
|
||||||
convState->state = src_delete(convState->state);
|
|
||||||
|
|
||||||
convState->state = src_new(convalgo, channels, &error);
|
|
||||||
if (!convState->state) {
|
|
||||||
ERROR("cannot create new libsamplerate state: %s\n",
|
|
||||||
src_strerror(error));
|
|
||||||
convState->error = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->src_ratio = (double)outSampleRate / (double)inSampleRate;
|
|
||||||
DEBUG("setting samplerate conversion ratio to %.2lf\n",
|
|
||||||
data->src_ratio);
|
|
||||||
src_set_ratio(convState->state, data->src_ratio);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* there was an error previously, and nothing has changed */
|
|
||||||
if (convState->error)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
data->input_frames = src_size / 2 / channels;
|
|
||||||
dataInSize = data->input_frames * sizeof(float) * channels;
|
|
||||||
if (dataInSize > convState->dataInSize) {
|
|
||||||
convState->dataInSize = dataInSize;
|
|
||||||
data->data_in = xrealloc(data->data_in, dataInSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
data->output_frames = outSize / 2 / channels;
|
|
||||||
dataOutSize = data->output_frames * sizeof(float) * channels;
|
|
||||||
if (dataOutSize > convState->dataOutSize) {
|
|
||||||
convState->dataOutSize = dataOutSize;
|
|
||||||
data->data_out = xrealloc(data->data_out, dataOutSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
src_short_to_float_array((const short *)src, data->data_in,
|
|
||||||
data->input_frames * channels);
|
|
||||||
|
|
||||||
error = src_process(convState->state, data);
|
|
||||||
if (error) {
|
|
||||||
ERROR("error processing samples with libsamplerate: %s\n",
|
|
||||||
src_strerror(error));
|
|
||||||
convState->error = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
src_float_to_short_array(data->data_out, (short *)outBuffer,
|
|
||||||
data->output_frames_gen * channels);
|
|
||||||
|
|
||||||
return data->output_frames_gen * 2 * channels;
|
|
||||||
}
|
|
||||||
#else /* !HAVE_LIBSAMPLERATE */
|
|
||||||
/* resampling code blatantly ripped from ESD */
|
|
||||||
static size_t pcm_resample(int8_t channels, uint32_t inSampleRate,
|
|
||||||
const int16_t *src, mpd_unused size_t src_size,
|
|
||||||
uint32_t outSampleRate, char *outBuffer,
|
|
||||||
size_t outSize,
|
|
||||||
mpd_unused struct pcm_convert_state *convState)
|
|
||||||
{
|
|
||||||
uint32_t rd_dat = 0;
|
|
||||||
uint32_t wr_dat = 0;
|
|
||||||
const int16_t *in = (const int16_t *)src;
|
|
||||||
int16_t *out = (int16_t *)outBuffer;
|
|
||||||
uint32_t nlen = outSize / 2;
|
|
||||||
int16_t lsample, rsample;
|
|
||||||
|
|
||||||
switch (channels) {
|
|
||||||
case 1:
|
|
||||||
while (wr_dat < nlen) {
|
|
||||||
rd_dat = wr_dat * inSampleRate / outSampleRate;
|
|
||||||
|
|
||||||
lsample = in[rd_dat++];
|
|
||||||
|
|
||||||
out[wr_dat++] = lsample;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
while (wr_dat < nlen) {
|
|
||||||
rd_dat = wr_dat * inSampleRate / outSampleRate;
|
|
||||||
rd_dat &= ~1;
|
|
||||||
|
|
||||||
lsample = in[rd_dat++];
|
|
||||||
rsample = in[rd_dat++];
|
|
||||||
|
|
||||||
out[wr_dat++] = lsample;
|
|
||||||
out[wr_dat++] = rsample;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return outSize;
|
|
||||||
}
|
|
||||||
#endif /* !HAVE_LIBSAMPLERATE */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pcm_convert_channels_1_to_2(int16_t *dest, const int16_t *src,
|
pcm_convert_channels_1_to_2(int16_t *dest, const int16_t *src,
|
||||||
unsigned num_frames)
|
unsigned num_frames)
|
||||||
@ -542,11 +386,11 @@ size_t pcm_convert(const struct audio_format *inFormat,
|
|||||||
assert(dest_size >= len);
|
assert(dest_size >= len);
|
||||||
memcpy(outBuffer, buf, len);
|
memcpy(outBuffer, buf, len);
|
||||||
} else {
|
} else {
|
||||||
len = pcm_resample(outFormat->channels,
|
len = pcm_resample_16(outFormat->channels,
|
||||||
inFormat->sample_rate, buf, len,
|
inFormat->sample_rate, buf, len,
|
||||||
outFormat->sample_rate,
|
outFormat->sample_rate,
|
||||||
(int16_t*)outBuffer,
|
(int16_t*)outBuffer,
|
||||||
dest_size, convState);
|
dest_size, &convState->resample);
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -19,28 +19,16 @@
|
|||||||
#ifndef PCM_UTILS_H
|
#ifndef PCM_UTILS_H
|
||||||
#define PCM_UTILS_H
|
#define PCM_UTILS_H
|
||||||
|
|
||||||
#include "../config.h"
|
#include "pcm_resample.h"
|
||||||
#include "pcm_dither.h"
|
#include "pcm_dither.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#ifdef HAVE_LIBSAMPLERATE
|
|
||||||
#include <samplerate.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct audio_format;
|
struct audio_format;
|
||||||
|
|
||||||
struct pcm_convert_state {
|
struct pcm_convert_state {
|
||||||
#ifdef HAVE_LIBSAMPLERATE
|
struct pcm_resample_state resample;
|
||||||
SRC_STATE *state;
|
|
||||||
SRC_DATA data;
|
|
||||||
size_t dataInSize;
|
|
||||||
size_t dataOutSize;
|
|
||||||
int8_t lastChannels;
|
|
||||||
uint32_t lastInSampleRate;
|
|
||||||
uint32_t lastOutSampleRate;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct pcm_dither_24 dither;
|
struct pcm_dither_24 dither;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user