Merge branch 'master' of git://git.musicpd.org/metyl/mpd
This commit is contained in:
commit
7c0c8ca8d7
|
@ -504,6 +504,10 @@ if ENABLE_ENCODER
|
||||||
ENCODER_SRC += src/encoder_list.c
|
ENCODER_SRC += src/encoder_list.c
|
||||||
ENCODER_SRC += src/encoder/null_encoder.c
|
ENCODER_SRC += src/encoder/null_encoder.c
|
||||||
|
|
||||||
|
if ENABLE_WAVE_ENCODER
|
||||||
|
ENCODER_SRC += src/encoder/wave_encoder.c
|
||||||
|
endif
|
||||||
|
|
||||||
if ENABLE_VORBIS_ENCODER
|
if ENABLE_VORBIS_ENCODER
|
||||||
ENCODER_SRC += src/encoder/vorbis_encoder.c
|
ENCODER_SRC += src/encoder/vorbis_encoder.c
|
||||||
endif
|
endif
|
||||||
|
|
20
configure.ac
20
configure.ac
|
@ -659,6 +659,11 @@ AC_ARG_ENABLE(twolame-encoder,
|
||||||
[enable the TwoLAME mp2 encoder]),,
|
[enable the TwoLAME mp2 encoder]),,
|
||||||
enable_twolame_encoder=auto)
|
enable_twolame_encoder=auto)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(wave-encoder,
|
||||||
|
AS_HELP_STRING([--enable-wave-encoder],
|
||||||
|
[enable the PCM wave encoder]),,
|
||||||
|
enable_wave_encoder=yes)
|
||||||
|
|
||||||
|
|
||||||
dnl
|
dnl
|
||||||
dnl audio output plugins
|
dnl audio output plugins
|
||||||
|
@ -1078,6 +1083,7 @@ else
|
||||||
enable_vorbis_encoder=no
|
enable_vorbis_encoder=no
|
||||||
enable_lame_encoder=no
|
enable_lame_encoder=no
|
||||||
enable_twolame_encoder=no
|
enable_twolame_encoder=no
|
||||||
|
enable_wave_encoder=no
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MPD_AUTO_PKG(vorbis_encoder, VORBISENC, [vorbisenc],
|
MPD_AUTO_PKG(vorbis_encoder, VORBISENC, [vorbisenc],
|
||||||
|
@ -1097,7 +1103,8 @@ MPD_AUTO_PKG(twolame_encoder, TWOLAME, [twolame],
|
||||||
|
|
||||||
if test x$enable_vorbis_encoder != xno ||
|
if test x$enable_vorbis_encoder != xno ||
|
||||||
test x$enable_lame_encoder != xno ||
|
test x$enable_lame_encoder != xno ||
|
||||||
test x$enable_twolame_encoder != xno; then
|
test x$enable_twolame_encoder != xno ||
|
||||||
|
test x$enable_wave_encoder != xno; then
|
||||||
# at least one encoder plugin is enabled
|
# at least one encoder plugin is enabled
|
||||||
enable_encoder=yes
|
enable_encoder=yes
|
||||||
else
|
else
|
||||||
|
@ -1178,6 +1185,11 @@ if test x$enable_twolame_encoder = xyes; then
|
||||||
[Define to enable the TwoLAME encoder plugin])
|
[Define to enable the TwoLAME encoder plugin])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AM_CONDITIONAL(ENABLE_WAVE_ENCODER, test x$enable_wave_encoder = xyes)
|
||||||
|
if test x$enable_wave_encoder = xyes; then
|
||||||
|
AC_DEFINE(ENABLE_WAVE_ENCODER, 1,
|
||||||
|
[Define to enable the PCM wave encoder plugin])
|
||||||
|
fi
|
||||||
|
|
||||||
dnl
|
dnl
|
||||||
dnl Documentation
|
dnl Documentation
|
||||||
|
@ -1429,6 +1441,12 @@ if
|
||||||
echo " TwoLAME mp3 encoder ...........disabled"
|
echo " TwoLAME mp3 encoder ...........disabled"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test x$enable_wave_encoder = xyes; then
|
||||||
|
echo " PCM wave encoder ..............enabled"
|
||||||
|
else
|
||||||
|
echo " PCM wave encoder ..............disabled"
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,241 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-2009 The Music Player Daemon Project
|
||||||
|
* http://www.musicpd.org
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "encoder_api.h"
|
||||||
|
#include "encoder_plugin.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX_BUFFER 32768
|
||||||
|
|
||||||
|
struct wave_encoder {
|
||||||
|
struct encoder encoder;
|
||||||
|
unsigned bits;
|
||||||
|
|
||||||
|
uint8_t buffer[MAX_BUFFER];
|
||||||
|
size_t buffer_length;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wave_header {
|
||||||
|
uint32_t id_riff;
|
||||||
|
uint32_t riff_size;
|
||||||
|
uint32_t id_wave;
|
||||||
|
uint32_t id_fmt;
|
||||||
|
uint32_t fmt_size;
|
||||||
|
uint16_t format;
|
||||||
|
uint16_t channels;
|
||||||
|
uint32_t freq;
|
||||||
|
uint32_t byterate;
|
||||||
|
uint16_t blocksize;
|
||||||
|
uint16_t bits;
|
||||||
|
uint32_t id_data;
|
||||||
|
uint32_t data_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct encoder_plugin wave_encoder_plugin;
|
||||||
|
|
||||||
|
static inline GQuark
|
||||||
|
wave_encoder_quark(void)
|
||||||
|
{
|
||||||
|
return g_quark_from_static_string("wave_encoder");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fill_wave_header(struct wave_header *header, int channels, int bits,
|
||||||
|
int freq, int block_size)
|
||||||
|
{
|
||||||
|
int data_size = 0x0FFFFFFF;
|
||||||
|
|
||||||
|
/* constants */
|
||||||
|
header->id_riff = GUINT32_TO_LE(0x46464952);
|
||||||
|
header->id_wave = GUINT32_TO_LE(0x45564157);
|
||||||
|
header->id_fmt = GUINT32_TO_LE(0x20746d66);
|
||||||
|
header->id_data = GUINT32_TO_LE(0x61746164);
|
||||||
|
|
||||||
|
/* wave format */
|
||||||
|
header->format = GUINT16_TO_LE(1); // PCM_FORMAT
|
||||||
|
header->channels = GUINT16_TO_LE(channels);
|
||||||
|
header->bits = GUINT16_TO_LE(bits);
|
||||||
|
header->freq = GUINT32_TO_LE(freq);
|
||||||
|
header->blocksize = GUINT16_TO_LE(block_size);
|
||||||
|
header->byterate = GUINT32_TO_LE(freq * block_size);
|
||||||
|
|
||||||
|
/* chunk sizes (fake data length) */
|
||||||
|
header->fmt_size = GUINT32_TO_LE(16);
|
||||||
|
header->data_size = GUINT32_TO_LE(data_size);
|
||||||
|
header->riff_size = GUINT32_TO_LE(4 + (8 + 16) +
|
||||||
|
(8 + data_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct encoder *
|
||||||
|
wave_encoder_init(G_GNUC_UNUSED const struct config_param *param,
|
||||||
|
G_GNUC_UNUSED GError **error)
|
||||||
|
{
|
||||||
|
struct wave_encoder *encoder;
|
||||||
|
|
||||||
|
encoder = g_new(struct wave_encoder, 1);
|
||||||
|
encoder_struct_init(&encoder->encoder, &wave_encoder_plugin);
|
||||||
|
|
||||||
|
return &encoder->encoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wave_encoder_finish(struct encoder *_encoder)
|
||||||
|
{
|
||||||
|
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
|
||||||
|
|
||||||
|
g_free(encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wave_encoder_open(struct encoder *_encoder,
|
||||||
|
G_GNUC_UNUSED struct audio_format *audio_format,
|
||||||
|
G_GNUC_UNUSED GError **error)
|
||||||
|
{
|
||||||
|
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
|
||||||
|
|
||||||
|
encoder->bits = audio_format->bits;
|
||||||
|
|
||||||
|
/* create PCM wave header in initial buffer */
|
||||||
|
fill_wave_header((struct wave_header *) encoder->buffer,
|
||||||
|
audio_format->channels,
|
||||||
|
audio_format->bits,
|
||||||
|
audio_format->sample_rate,
|
||||||
|
(audio_format->bits / 8) * audio_format->channels );
|
||||||
|
|
||||||
|
encoder->buffer_length = sizeof(struct wave_header);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
pcm16_to_wave(void *dst, const void *src, size_t length)
|
||||||
|
{
|
||||||
|
uint32_t scnt;
|
||||||
|
const uint16_t *src16 = (const uint16_t *) src;
|
||||||
|
uint16_t *dst16 = (uint16_t *) dst;
|
||||||
|
|
||||||
|
for(scnt = length >> 1; scnt>0; scnt--){
|
||||||
|
*dst16++ = GUINT16_TO_LE(*src16++);
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
pcm32_to_wave(void *dst, const void *src, size_t length)
|
||||||
|
{
|
||||||
|
uint32_t scnt;
|
||||||
|
const uint32_t *src32 = (const uint32_t *) src;
|
||||||
|
uint32_t *dst32 = (uint32_t *) dst;
|
||||||
|
|
||||||
|
for(scnt = length >> 2; scnt>0; scnt--){
|
||||||
|
*dst32++ = GUINT32_TO_LE(*src32++);
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
pcm24_to_wave(void *dst, const void *src, size_t length)
|
||||||
|
{
|
||||||
|
uint32_t scnt, value;
|
||||||
|
const uint32_t *src32 = (const uint32_t *) src;
|
||||||
|
uint8_t *dst8 = (uint8_t *) dst;
|
||||||
|
|
||||||
|
for(scnt = length >> 2; scnt>0; scnt--){
|
||||||
|
value = *src32++;
|
||||||
|
*dst8++ = (value) & 0xFF;
|
||||||
|
*dst8++ = (value >> 8) & 0xFF;
|
||||||
|
*dst8++ = (value >> 16) & 0xFF;
|
||||||
|
}
|
||||||
|
//correct buffer length
|
||||||
|
length = dst8 - ((uint8_t *)dst);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wave_encoder_write(struct encoder *_encoder,
|
||||||
|
const void *src, size_t length,
|
||||||
|
G_GNUC_UNUSED GError **error)
|
||||||
|
{
|
||||||
|
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
|
||||||
|
void *dst;
|
||||||
|
|
||||||
|
assert(length + encoder->buffer_length < MAX_BUFFER);
|
||||||
|
|
||||||
|
dst = encoder->buffer + encoder->buffer_length;
|
||||||
|
|
||||||
|
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
|
||||||
|
switch (encoder->bits) {
|
||||||
|
case 8:
|
||||||
|
case 16:
|
||||||
|
case 32:// optimized cases
|
||||||
|
memcpy(dst, src, length);
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
length = pcm24_to_wave(dst, src, length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#elif (G_BYTE_ORDER == G_BIG_ENDIAN)
|
||||||
|
switch (encoder->bits) {
|
||||||
|
case 8:
|
||||||
|
memcpy(dst, src, length);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
length = pcm16_to_wave(dst, src, length);
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
length = pcm24_to_wave(dst, src, length);
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
length = pcm32_to_wave(dst, src, length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error G_BYTE_ORDER set to G_PDP_ENDIAN is not supported by wave_encoder
|
||||||
|
#endif
|
||||||
|
|
||||||
|
encoder->buffer_length += length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
wave_encoder_read(struct encoder *_encoder, void *dest, size_t length)
|
||||||
|
{
|
||||||
|
struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
|
||||||
|
|
||||||
|
if (length > encoder->buffer_length)
|
||||||
|
length = encoder->buffer_length;
|
||||||
|
|
||||||
|
memcpy(dest, encoder->buffer, length);
|
||||||
|
|
||||||
|
encoder->buffer_length -= length;
|
||||||
|
memmove(encoder->buffer, encoder->buffer + length,
|
||||||
|
encoder->buffer_length);
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct encoder_plugin wave_encoder_plugin = {
|
||||||
|
.name = "wave",
|
||||||
|
.init = wave_encoder_init,
|
||||||
|
.finish = wave_encoder_finish,
|
||||||
|
.open = wave_encoder_open,
|
||||||
|
.write = wave_encoder_write,
|
||||||
|
.read = wave_encoder_read,
|
||||||
|
};
|
|
@ -27,6 +27,7 @@ extern const struct encoder_plugin null_encoder_plugin;
|
||||||
extern const struct encoder_plugin vorbis_encoder_plugin;
|
extern const struct encoder_plugin vorbis_encoder_plugin;
|
||||||
extern const struct encoder_plugin lame_encoder_plugin;
|
extern const struct encoder_plugin lame_encoder_plugin;
|
||||||
extern const struct encoder_plugin twolame_encoder_plugin;
|
extern const struct encoder_plugin twolame_encoder_plugin;
|
||||||
|
extern const struct encoder_plugin wave_encoder_plugin;
|
||||||
|
|
||||||
static const struct encoder_plugin *encoder_plugins[] = {
|
static const struct encoder_plugin *encoder_plugins[] = {
|
||||||
&null_encoder_plugin,
|
&null_encoder_plugin,
|
||||||
|
@ -38,6 +39,9 @@ static const struct encoder_plugin *encoder_plugins[] = {
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_TWOLAME_ENCODER
|
#ifdef ENABLE_TWOLAME_ENCODER
|
||||||
&twolame_encoder_plugin,
|
&twolame_encoder_plugin,
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_WAVE_ENCODER
|
||||||
|
&wave_encoder_plugin,
|
||||||
#endif
|
#endif
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue