Merge branch 'master' of git://git.musicpd.org/metyl/mpd

This commit is contained in:
Max Kellermann 2009-11-11 06:45:23 +01:00
commit 7c0c8ca8d7
4 changed files with 268 additions and 1 deletions

View File

@ -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

View File

@ -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

241
src/encoder/wave_encoder.c Normal file
View File

@ -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,
};

View File

@ -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
}; };