Commit c412d625 authored by Max Kellermann's avatar Max Kellermann

audio_format: changed "bits" to "enum sample_format"

This patch prepares support for floating point samples (and probably other formats). It changes the meaning of the "bits" attribute from a bit count to a symbolic value.
parent 68c2cfbb
...@@ -877,6 +877,7 @@ test_run_normalize_LDADD = \ ...@@ -877,6 +877,7 @@ test_run_normalize_LDADD = \
$(GLIB_LIBS) $(GLIB_LIBS)
test_run_convert_SOURCES = test/run_convert.c \ test_run_convert_SOURCES = test/run_convert.c \
src/audio_format.c \
src/audio_check.c \ src/audio_check.c \
src/audio_parser.c \ src/audio_parser.c \
src/pcm_channels.c \ src/pcm_channels.c \
......
...@@ -35,7 +35,7 @@ audio_check_sample_rate(unsigned long sample_rate, GError **error_r) ...@@ -35,7 +35,7 @@ audio_check_sample_rate(unsigned long sample_rate, GError **error_r)
} }
bool bool
audio_check_sample_format(unsigned sample_format, GError **error_r) audio_check_sample_format(enum sample_format sample_format, GError **error_r)
{ {
if (!audio_valid_sample_format(sample_format)) { if (!audio_valid_sample_format(sample_format)) {
g_set_error(error_r, audio_format_quark(), 0, g_set_error(error_r, audio_format_quark(), 0,
...@@ -60,7 +60,7 @@ audio_check_channel_count(unsigned channels, GError **error_r) ...@@ -60,7 +60,7 @@ audio_check_channel_count(unsigned channels, GError **error_r)
bool bool
audio_format_init_checked(struct audio_format *af, unsigned long sample_rate, audio_format_init_checked(struct audio_format *af, unsigned long sample_rate,
unsigned sample_format, unsigned channels, enum sample_format sample_format, unsigned channels,
GError **error_r) GError **error_r)
{ {
if (audio_check_sample_rate(sample_rate, error_r) && if (audio_check_sample_rate(sample_rate, error_r) &&
......
...@@ -20,11 +20,11 @@ ...@@ -20,11 +20,11 @@
#ifndef MPD_AUDIO_CHECK_H #ifndef MPD_AUDIO_CHECK_H
#define MPD_AUDIO_CHECK_H #define MPD_AUDIO_CHECK_H
#include "audio_format.h"
#include <glib.h> #include <glib.h>
#include <stdbool.h> #include <stdbool.h>
struct audio_format;
/** /**
* The GLib quark used for errors reported by this library. * The GLib quark used for errors reported by this library.
*/ */
...@@ -48,7 +48,7 @@ audio_check_channel_count(unsigned sample_format, GError **error_r); ...@@ -48,7 +48,7 @@ audio_check_channel_count(unsigned sample_format, GError **error_r);
*/ */
bool bool
audio_format_init_checked(struct audio_format *af, unsigned long sample_rate, audio_format_init_checked(struct audio_format *af, unsigned long sample_rate,
unsigned sample_format, unsigned channels, enum sample_format sample_format, unsigned channels,
GError **error_r); GError **error_r);
#endif #endif
...@@ -29,14 +29,39 @@ ...@@ -29,14 +29,39 @@
#endif #endif
const char * const char *
sample_format_to_string(enum sample_format format)
{
switch (format) {
case SAMPLE_FORMAT_UNDEFINED:
return "?";
case SAMPLE_FORMAT_S8:
return "8";
case SAMPLE_FORMAT_S16:
return "16";
case SAMPLE_FORMAT_S24_P32:
return "24";
case SAMPLE_FORMAT_S32:
return "32";
}
/* unreachable */
assert(false);
return "?";
}
const char *
audio_format_to_string(const struct audio_format *af, audio_format_to_string(const struct audio_format *af,
struct audio_format_string *s) struct audio_format_string *s)
{ {
assert(af != NULL); assert(af != NULL);
assert(s != NULL); assert(s != NULL);
snprintf(s->buffer, sizeof(s->buffer), "%u:%u%s:%u", snprintf(s->buffer, sizeof(s->buffer), "%u:%s%s:%u",
af->sample_rate, af->bits, af->sample_rate, sample_format_to_string(af->format),
af->reverse_endian ? REVERSE_ENDIAN_SUFFIX : "", af->reverse_endian ? REVERSE_ENDIAN_SUFFIX : "",
af->channels); af->channels);
......
...@@ -23,6 +23,21 @@ ...@@ -23,6 +23,21 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
enum sample_format {
SAMPLE_FORMAT_UNDEFINED = 0,
SAMPLE_FORMAT_S8,
SAMPLE_FORMAT_S16,
/**
* Signed 24 bit integer samples, packed in 32 bit integers
* (the most significant byte is filled with the sign bit).
*/
SAMPLE_FORMAT_S24_P32,
SAMPLE_FORMAT_S32,
};
/** /**
* This structure describes the format of a raw PCM stream. * This structure describes the format of a raw PCM stream.
*/ */
...@@ -35,11 +50,10 @@ struct audio_format { ...@@ -35,11 +50,10 @@ struct audio_format {
uint32_t sample_rate; uint32_t sample_rate;
/** /**
* The number of significant bits per sample. Samples are * The format samples are stored in. See the #sample_format
* currently always signed. Supported values are 8, 16, 24, * enum for valid values.
* 32. 24 bit samples are packed in 32 bit integers.
*/ */
uint8_t bits; uint8_t format;
/** /**
* The number of channels. Only mono (1) and stereo (2) are * The number of channels. Only mono (1) and stereo (2) are
...@@ -69,7 +83,7 @@ struct audio_format_string { ...@@ -69,7 +83,7 @@ struct audio_format_string {
static inline void audio_format_clear(struct audio_format *af) static inline void audio_format_clear(struct audio_format *af)
{ {
af->sample_rate = 0; af->sample_rate = 0;
af->bits = 0; af->format = SAMPLE_FORMAT_UNDEFINED;
af->channels = 0; af->channels = 0;
af->reverse_endian = 0; af->reverse_endian = 0;
} }
...@@ -80,10 +94,10 @@ static inline void audio_format_clear(struct audio_format *af) ...@@ -80,10 +94,10 @@ static inline void audio_format_clear(struct audio_format *af)
*/ */
static inline void audio_format_init(struct audio_format *af, static inline void audio_format_init(struct audio_format *af,
uint32_t sample_rate, uint32_t sample_rate,
uint8_t bits, uint8_t channels) enum sample_format format, uint8_t channels)
{ {
af->sample_rate = sample_rate; af->sample_rate = sample_rate;
af->bits = bits; af->format = (uint8_t)format;
af->channels = channels; af->channels = channels;
af->reverse_endian = 0; af->reverse_endian = 0;
} }
...@@ -105,7 +119,8 @@ static inline bool audio_format_defined(const struct audio_format *af) ...@@ -105,7 +119,8 @@ static inline bool audio_format_defined(const struct audio_format *af)
static inline bool static inline bool
audio_format_fully_defined(const struct audio_format *af) audio_format_fully_defined(const struct audio_format *af)
{ {
return af->sample_rate != 0 && af->bits != 0 && af->channels != 0; return af->sample_rate != 0 && af->format != SAMPLE_FORMAT_UNDEFINED &&
af->channels != 0;
} }
/** /**
...@@ -115,7 +130,8 @@ audio_format_fully_defined(const struct audio_format *af) ...@@ -115,7 +130,8 @@ audio_format_fully_defined(const struct audio_format *af)
static inline bool static inline bool
audio_format_mask_defined(const struct audio_format *af) audio_format_mask_defined(const struct audio_format *af)
{ {
return af->sample_rate != 0 || af->bits != 0 || af->channels != 0; return af->sample_rate != 0 || af->format != SAMPLE_FORMAT_UNDEFINED ||
af->channels != 0;
} }
/** /**
...@@ -135,9 +151,20 @@ audio_valid_sample_rate(unsigned sample_rate) ...@@ -135,9 +151,20 @@ audio_valid_sample_rate(unsigned sample_rate)
* @param bits the number of significant bits per sample * @param bits the number of significant bits per sample
*/ */
static inline bool static inline bool
audio_valid_sample_format(unsigned bits) audio_valid_sample_format(enum sample_format format)
{ {
return bits == 16 || bits == 24 || bits == 32 || bits == 8; switch (format) {
case SAMPLE_FORMAT_S8:
case SAMPLE_FORMAT_S16:
case SAMPLE_FORMAT_S24_P32:
case SAMPLE_FORMAT_S32:
return true;
case SAMPLE_FORMAT_UNDEFINED:
break;
}
return false;
} }
/** /**
...@@ -156,7 +183,7 @@ audio_valid_channel_count(unsigned channels) ...@@ -156,7 +183,7 @@ audio_valid_channel_count(unsigned channels)
static inline bool audio_format_valid(const struct audio_format *af) static inline bool audio_format_valid(const struct audio_format *af)
{ {
return audio_valid_sample_rate(af->sample_rate) && return audio_valid_sample_rate(af->sample_rate) &&
audio_valid_sample_format(af->bits) && audio_valid_sample_format((enum sample_format)af->format) &&
audio_valid_channel_count(af->channels); audio_valid_channel_count(af->channels);
} }
...@@ -168,7 +195,8 @@ static inline bool audio_format_mask_valid(const struct audio_format *af) ...@@ -168,7 +195,8 @@ static inline bool audio_format_mask_valid(const struct audio_format *af)
{ {
return (af->sample_rate == 0 || return (af->sample_rate == 0 ||
audio_valid_sample_rate(af->sample_rate)) && audio_valid_sample_rate(af->sample_rate)) &&
(af->bits == 0 || audio_valid_sample_format(af->bits)) && (af->format == SAMPLE_FORMAT_UNDEFINED ||
audio_valid_sample_format((enum sample_format)af->format)) &&
(af->channels == 0 || audio_valid_channel_count(af->channels)); (af->channels == 0 || audio_valid_channel_count(af->channels));
} }
...@@ -176,7 +204,7 @@ static inline bool audio_format_equals(const struct audio_format *a, ...@@ -176,7 +204,7 @@ static inline bool audio_format_equals(const struct audio_format *a,
const struct audio_format *b) const struct audio_format *b)
{ {
return a->sample_rate == b->sample_rate && return a->sample_rate == b->sample_rate &&
a->bits == b->bits && a->format == b->format &&
a->channels == b->channels && a->channels == b->channels &&
a->reverse_endian == b->reverse_endian; a->reverse_endian == b->reverse_endian;
} }
...@@ -188,8 +216,8 @@ audio_format_mask_apply(struct audio_format *af, ...@@ -188,8 +216,8 @@ audio_format_mask_apply(struct audio_format *af,
if (mask->sample_rate != 0) if (mask->sample_rate != 0)
af->sample_rate = mask->sample_rate; af->sample_rate = mask->sample_rate;
if (mask->bits != 0) if (mask->format != SAMPLE_FORMAT_UNDEFINED)
af->bits = mask->bits; af->format = mask->format;
if (mask->channels != 0) if (mask->channels != 0)
af->channels = mask->channels; af->channels = mask->channels;
...@@ -200,12 +228,22 @@ audio_format_mask_apply(struct audio_format *af, ...@@ -200,12 +228,22 @@ audio_format_mask_apply(struct audio_format *af,
*/ */
static inline unsigned audio_format_sample_size(const struct audio_format *af) static inline unsigned audio_format_sample_size(const struct audio_format *af)
{ {
if (af->bits <= 8) switch (af->format) {
case SAMPLE_FORMAT_S8:
return 1; return 1;
else if (af->bits <= 16)
case SAMPLE_FORMAT_S16:
return 2; return 2;
else
case SAMPLE_FORMAT_S24_P32:
case SAMPLE_FORMAT_S32:
return 4; return 4;
case SAMPLE_FORMAT_UNDEFINED:
break;
}
return 0;
} }
/** /**
...@@ -227,6 +265,16 @@ static inline double audio_format_time_to_size(const struct audio_format *af) ...@@ -227,6 +265,16 @@ static inline double audio_format_time_to_size(const struct audio_format *af)
} }
/** /**
* Renders a #sample_format enum into a string, e.g. for printing it
* in a log file.
*
* @param format a #sample_format enum value
* @return the string
*/
const char *
sample_format_to_string(enum sample_format format);
/**
* Renders the #audio_format object into a string, e.g. for printing * Renders the #audio_format object into a string, e.g. for printing
* it in a log file. * it in a log file.
* *
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "audio_format.h" #include "audio_format.h"
#include "audio_check.h" #include "audio_check.h"
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
/** /**
...@@ -65,14 +66,16 @@ parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r, ...@@ -65,14 +66,16 @@ parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r,
} }
static bool static bool
parse_sample_format(const char *src, bool mask, uint8_t *bits_r, parse_sample_format(const char *src, bool mask,
enum sample_format *sample_format_r,
const char **endptr_r, GError **error_r) const char **endptr_r, GError **error_r)
{ {
unsigned long value; unsigned long value;
char *endptr; char *endptr;
enum sample_format sample_format;
if (mask && *src == '*') { if (mask && *src == '*') {
*bits_r = 0; *sample_format_r = SAMPLE_FORMAT_UNDEFINED;
*endptr_r = src + 1; *endptr_r = src + 1;
return true; return true;
} }
...@@ -82,10 +85,34 @@ parse_sample_format(const char *src, bool mask, uint8_t *bits_r, ...@@ -82,10 +85,34 @@ parse_sample_format(const char *src, bool mask, uint8_t *bits_r,
g_set_error(error_r, audio_parser_quark(), 0, g_set_error(error_r, audio_parser_quark(), 0,
"Failed to parse the sample format"); "Failed to parse the sample format");
return false; return false;
} else if (!audio_check_sample_format(value, error_r)) }
switch (value) {
case 8:
sample_format = SAMPLE_FORMAT_S8;
break;
case 16:
sample_format = SAMPLE_FORMAT_S16;
break;
case 24:
sample_format = SAMPLE_FORMAT_S24_P32;
break;
case 32:
sample_format = SAMPLE_FORMAT_S32;
break;
default:
g_set_error(error_r, audio_parser_quark(), 0,
"Invalid sample format: %lu", value);
return false; return false;
}
assert(audio_valid_sample_format(sample_format));
*bits_r = value; *sample_format_r = sample_format;
*endptr_r = endptr; *endptr_r = endptr;
return true; return true;
} }
...@@ -121,7 +148,8 @@ audio_format_parse(struct audio_format *dest, const char *src, ...@@ -121,7 +148,8 @@ audio_format_parse(struct audio_format *dest, const char *src,
bool mask, GError **error_r) bool mask, GError **error_r)
{ {
uint32_t rate; uint32_t rate;
uint8_t bits, channels; enum sample_format sample_format;
uint8_t channels;
audio_format_clear(dest); audio_format_clear(dest);
...@@ -138,7 +166,7 @@ audio_format_parse(struct audio_format *dest, const char *src, ...@@ -138,7 +166,7 @@ audio_format_parse(struct audio_format *dest, const char *src,
/* parse sample format */ /* parse sample format */
if (!parse_sample_format(src, mask, &bits, &src, error_r)) if (!parse_sample_format(src, mask, &sample_format, &src, error_r))
return false; return false;
if (*src++ != ':') { if (*src++ != ':') {
...@@ -158,7 +186,7 @@ audio_format_parse(struct audio_format *dest, const char *src, ...@@ -158,7 +186,7 @@ audio_format_parse(struct audio_format *dest, const char *src,
return false; return false;
} }
audio_format_init(dest, rate, bits, channels); audio_format_init(dest, rate, sample_format, channels);
return true; return true;
} }
...@@ -60,6 +60,27 @@ flac_data_deinit(struct flac_data *data) ...@@ -60,6 +60,27 @@ flac_data_deinit(struct flac_data *data)
tag_free(data->tag); tag_free(data->tag);
} }
static enum sample_format
flac_sample_format(const FLAC__StreamMetadata_StreamInfo *si)
{
switch (si->bits_per_sample) {
case 8:
return SAMPLE_FORMAT_S8;
case 16:
return SAMPLE_FORMAT_S16;
case 24:
return SAMPLE_FORMAT_S24_P32;
case 32:
return SAMPLE_FORMAT_S32;
default:
return SAMPLE_FORMAT_UNDEFINED;
}
}
bool bool
flac_data_get_audio_format(struct flac_data *data, flac_data_get_audio_format(struct flac_data *data,
struct audio_format *audio_format) struct audio_format *audio_format)
...@@ -71,9 +92,11 @@ flac_data_get_audio_format(struct flac_data *data, ...@@ -71,9 +92,11 @@ flac_data_get_audio_format(struct flac_data *data,
return false; return false;
} }
data->sample_format = flac_sample_format(&data->stream_info);
if (!audio_format_init_checked(audio_format, if (!audio_format_init_checked(audio_format,
data->stream_info.sample_rate, data->stream_info.sample_rate,
data->stream_info.bits_per_sample, data->sample_format,
data->stream_info.channels, &error)) { data->stream_info.channels, &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
...@@ -144,7 +167,7 @@ flac_common_write(struct flac_data *data, const FLAC__Frame * frame, ...@@ -144,7 +167,7 @@ flac_common_write(struct flac_data *data, const FLAC__Frame * frame,
buffer = pcm_buffer_get(&data->buffer, buffer_size); buffer = pcm_buffer_get(&data->buffer, buffer_size);
flac_convert(buffer, frame->header.channels, flac_convert(buffer, frame->header.channels,
frame->header.bits_per_sample, buf, data->sample_format, buf,
0, frame->header.blocksize); 0, frame->header.blocksize);
if (data->next_frame >= data->first_frame) if (data->next_frame >= data->first_frame)
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
struct flac_data { struct flac_data {
struct pcm_buffer buffer; struct pcm_buffer buffer;
enum sample_format sample_format;
/** /**
* The size of one frame in the output buffer. * The size of one frame in the output buffer.
*/ */
......
...@@ -101,13 +101,33 @@ setup_virtual_fops(struct input_stream *stream) ...@@ -101,13 +101,33 @@ setup_virtual_fops(struct input_stream *stream)
return vf; return vf;
} }
static uint8_t static enum sample_format
audiofile_bits_to_sample_format(int bits)
{
switch (bits) {
case 8:
return SAMPLE_FORMAT_S8;
case 16:
return SAMPLE_FORMAT_S16;
case 24:
return SAMPLE_FORMAT_S24_P32;
case 32:
return SAMPLE_FORMAT_S32;
}
return SAMPLE_FORMAT_UNDEFINED;
}
static enum sample_format
audiofile_setup_sample_format(AFfilehandle af_fp) audiofile_setup_sample_format(AFfilehandle af_fp)
{ {
int fs, bits; int fs, bits;
afGetSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits); afGetSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits);
if (!audio_valid_sample_format(bits)) { if (!audio_valid_sample_format(audiofile_bits_to_sample_format(bits))) {
g_debug("input file has %d bit samples, converting to 16", g_debug("input file has %d bit samples, converting to 16",
bits); bits);
bits = 16; bits = 16;
...@@ -117,7 +137,7 @@ audiofile_setup_sample_format(AFfilehandle af_fp) ...@@ -117,7 +137,7 @@ audiofile_setup_sample_format(AFfilehandle af_fp)
AF_SAMPFMT_TWOSCOMP, bits); AF_SAMPFMT_TWOSCOMP, bits);
afGetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits); afGetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits);
return bits; return audiofile_bits_to_sample_format(bits);
} }
static void static void
......
...@@ -283,7 +283,7 @@ faad_decoder_init(faacDecHandle decoder, struct decoder_buffer *buffer, ...@@ -283,7 +283,7 @@ faad_decoder_init(faacDecHandle decoder, struct decoder_buffer *buffer,
decoder_buffer_consume(buffer, nbytes); decoder_buffer_consume(buffer, nbytes);
return audio_format_init_checked(audio_format, sample_rate, return audio_format_init_checked(audio_format, sample_rate,
16, channels, error_r); SAMPLE_FORMAT_S16, channels, error_r);
} }
/** /**
......
...@@ -277,6 +277,26 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is, ...@@ -277,6 +277,26 @@ ffmpeg_send_packet(struct decoder *decoder, struct input_stream *is,
return cmd; return cmd;
} }
static enum sample_format
ffmpeg_sample_format(G_GNUC_UNUSED const AVCodecContext *codec_context)
{
#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(41<<8)+0)
int bits = (uint8_t) av_get_bits_per_sample_format(codec_context->sample_fmt);
/* XXX implement & test other sample formats */
switch (bits) {
case 16:
return SAMPLE_FORMAT_S16;
}
return SAMPLE_FORMAT_UNDEFINED;
#else
/* XXX fixme 16-bit for older ffmpeg (13 Aug 2007) */
return SAMPLE_FORMAT_S16;
#endif
}
static bool static bool
ffmpeg_decode_internal(struct ffmpeg_context *ctx) ffmpeg_decode_internal(struct ffmpeg_context *ctx)
{ {
...@@ -288,7 +308,6 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx) ...@@ -288,7 +308,6 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx)
struct audio_format audio_format; struct audio_format audio_format;
enum decoder_command cmd; enum decoder_command cmd;
int total_time; int total_time;
uint8_t bits;
total_time = 0; total_time = 0;
...@@ -296,14 +315,9 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx) ...@@ -296,14 +315,9 @@ ffmpeg_decode_internal(struct ffmpeg_context *ctx)
codec_context->channels = 2; codec_context->channels = 2;
} }
#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(41<<8)+0)
bits = (uint8_t) av_get_bits_per_sample_format(codec_context->sample_fmt);
#else
/* XXX fixme 16-bit for older ffmpeg (13 Aug 2007) */
bits = (uint8_t) 16;
#endif
if (!audio_format_init_checked(&audio_format, if (!audio_format_init_checked(&audio_format,
codec_context->sample_rate, bits, codec_context->sample_rate,
ffmpeg_sample_format(codec_context),
codec_context->channels, &error)) { codec_context->channels, &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include "config.h" #include "config.h"
#include "flac_pcm.h" #include "flac_pcm.h"
#include <assert.h>
static void flac_convert_stereo16(int16_t *dest, static void flac_convert_stereo16(int16_t *dest,
const FLAC__int32 * const buf[], const FLAC__int32 * const buf[],
unsigned int position, unsigned int end) unsigned int position, unsigned int end)
...@@ -74,12 +76,12 @@ flac_convert_8(int8_t *dest, ...@@ -74,12 +76,12 @@ flac_convert_8(int8_t *dest,
void void
flac_convert(void *dest, flac_convert(void *dest,
unsigned int num_channels, unsigned sample_format, unsigned int num_channels, enum sample_format sample_format,
const FLAC__int32 *const buf[], const FLAC__int32 *const buf[],
unsigned int position, unsigned int end) unsigned int position, unsigned int end)
{ {
switch (sample_format) { switch (sample_format) {
case 16: case SAMPLE_FORMAT_S16:
if (num_channels == 2) if (num_channels == 2)
flac_convert_stereo16((int16_t*)dest, buf, flac_convert_stereo16((int16_t*)dest, buf,
position, end); position, end);
...@@ -88,15 +90,19 @@ flac_convert(void *dest, ...@@ -88,15 +90,19 @@ flac_convert(void *dest,
position, end); position, end);
break; break;
case 24: case SAMPLE_FORMAT_S24_P32:
case 32: case SAMPLE_FORMAT_S32:
flac_convert_32((int32_t*)dest, num_channels, buf, flac_convert_32((int32_t*)dest, num_channels, buf,
position, end); position, end);
break; break;
case 8: case SAMPLE_FORMAT_S8:
flac_convert_8((int8_t*)dest, num_channels, buf, flac_convert_8((int8_t*)dest, num_channels, buf,
position, end); position, end);
break; break;
case SAMPLE_FORMAT_UNDEFINED:
/* unreachable */
assert(false);
} }
} }
...@@ -20,11 +20,13 @@ ...@@ -20,11 +20,13 @@
#ifndef MPD_FLAC_PCM_H #ifndef MPD_FLAC_PCM_H
#define MPD_FLAC_PCM_H #define MPD_FLAC_PCM_H
#include "audio_format.h"
#include <FLAC/ordinals.h> #include <FLAC/ordinals.h>
void void
flac_convert(void *dest, flac_convert(void *dest,
unsigned int num_channels, unsigned sample_format, unsigned int num_channels, enum sample_format sample_format,
const FLAC__int32 *const buf[], const FLAC__int32 *const buf[],
unsigned int position, unsigned int end); unsigned int position, unsigned int end);
......
...@@ -88,7 +88,7 @@ fluidsynth_file_decode(struct decoder *decoder, const char *path_fs) ...@@ -88,7 +88,7 @@ fluidsynth_file_decode(struct decoder *decoder, const char *path_fs)
{ {
static const struct audio_format audio_format = { static const struct audio_format audio_format = {
.sample_rate = 48000, .sample_rate = 48000,
.bits = 16, .format = SAMPLE_FORMAT_S16,
.channels = 2, .channels = 2,
}; };
char setting_sample_rate[] = "synth.sample-rate"; char setting_sample_rate[] = "synth.sample-rate";
......
...@@ -1188,7 +1188,8 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream) ...@@ -1188,7 +1188,8 @@ mp3_decode(struct decoder *decoder, struct input_stream *input_stream)
} }
if (!audio_format_init_checked(&audio_format, if (!audio_format_init_checked(&audio_format,
data.frame.header.samplerate, 24, data.frame.header.samplerate,
SAMPLE_FORMAT_S24_P32,
MAD_NCHANNELS(&data.frame.header), MAD_NCHANNELS(&data.frame.header),
&error)) { &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
......
...@@ -163,7 +163,7 @@ mikmod_decoder_file_decode(struct decoder *decoder, const char *path_fs) ...@@ -163,7 +163,7 @@ mikmod_decoder_file_decode(struct decoder *decoder, const char *path_fs)
/* Prevent module from looping forever */ /* Prevent module from looping forever */
handle->loop = 0; handle->loop = 0;
audio_format_init(&audio_format, mikmod_sample_rate, 16, 2); audio_format_init(&audio_format, mikmod_sample_rate, SAMPLE_FORMAT_S16, 2);
assert(audio_format_valid(&audio_format)); assert(audio_format_valid(&audio_format));
decoder_initialized(decoder, &audio_format, false, 0); decoder_initialized(decoder, &audio_format, false, 0);
......
...@@ -122,7 +122,7 @@ mod_decode(struct decoder *decoder, struct input_stream *is) ...@@ -122,7 +122,7 @@ mod_decode(struct decoder *decoder, struct input_stream *is)
return; return;
} }
audio_format_init(&audio_format, 44100, 16, 2); audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2);
assert(audio_format_valid(&audio_format)); assert(audio_format_valid(&audio_format));
decoder_initialized(decoder, &audio_format, decoder_initialized(decoder, &audio_format,
......
...@@ -132,7 +132,8 @@ mp4_faad_new(mp4ff_t *mp4fh, int *track_r, struct audio_format *audio_format) ...@@ -132,7 +132,8 @@ mp4_faad_new(mp4ff_t *mp4fh, int *track_r, struct audio_format *audio_format)
return NULL; return NULL;
} }
if (!audio_format_init_checked(audio_format, sample_rate, 16, channels, if (!audio_format_init_checked(audio_format, sample_rate,
SAMPLE_FORMAT_S16, channels,
&error)) { &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
......
...@@ -196,7 +196,8 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is) ...@@ -196,7 +196,8 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is)
mpc_demux_get_info(demux, &info); mpc_demux_get_info(demux, &info);
#endif #endif
if (!audio_format_init_checked(&audio_format, info.sample_freq, 24, if (!audio_format_init_checked(&audio_format, info.sample_freq,
SAMPLE_FORMAT_S24_P32,
info.channels, &error)) { info.channels, &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
......
...@@ -87,7 +87,7 @@ mpd_mpg123_open(mpg123_handle *handle, const char *path_fs, ...@@ -87,7 +87,7 @@ mpd_mpg123_open(mpg123_handle *handle, const char *path_fs,
return false; return false;
} }
if (!audio_format_init_checked(audio_format, rate, 16, if (!audio_format_init_checked(audio_format, rate, SAMPLE_FORMAT_S16,
channels, &gerror)) { channels, &gerror)) {
g_warning("%s", gerror->message); g_warning("%s", gerror->message);
g_error_free(gerror); g_error_free(gerror);
......
...@@ -277,7 +277,7 @@ sidplay_file_decode(struct decoder *decoder, const char *path_fs) ...@@ -277,7 +277,7 @@ sidplay_file_decode(struct decoder *decoder, const char *path_fs)
/* initialize the MPD decoder */ /* initialize the MPD decoder */
struct audio_format audio_format; struct audio_format audio_format;
audio_format_init(&audio_format, 48000, 16, 2); audio_format_init(&audio_format, 48000, SAMPLE_FORMAT_S16, 2);
assert(audio_format_valid(&audio_format)); assert(audio_format_valid(&audio_format));
decoder_initialized(decoder, &audio_format, true, (float)song_len); decoder_initialized(decoder, &audio_format, true, (float)song_len);
......
...@@ -130,7 +130,8 @@ sndfile_stream_decode(struct decoder *decoder, struct input_stream *is) ...@@ -130,7 +130,8 @@ sndfile_stream_decode(struct decoder *decoder, struct input_stream *is)
/* for now, always read 32 bit samples. Later, we could lower /* for now, always read 32 bit samples. Later, we could lower
MPD's CPU usage by reading 16 bit samples with MPD's CPU usage by reading 16 bit samples with
sf_readf_short() on low-quality source files. */ sf_readf_short() on low-quality source files. */
if (!audio_format_init_checked(&audio_format, info.samplerate, 32, if (!audio_format_init_checked(&audio_format, info.samplerate,
SAMPLE_FORMAT_S32,
info.channels, &error)) { info.channels, &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
......
...@@ -311,7 +311,8 @@ vorbis_stream_decode(struct decoder *decoder, ...@@ -311,7 +311,8 @@ vorbis_stream_decode(struct decoder *decoder,
return; return;
} }
if (!audio_format_init_checked(&audio_format, vi->rate, 16, if (!audio_format_init_checked(&audio_format, vi->rate,
SAMPLE_FORMAT_S16,
vi->channels, &error)) { vi->channels, &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
......
...@@ -123,6 +123,33 @@ format_samples_float(G_GNUC_UNUSED int bytes_per_sample, void *buffer, ...@@ -123,6 +123,33 @@ format_samples_float(G_GNUC_UNUSED int bytes_per_sample, void *buffer,
} }
} }
/**
* Choose a MPD sample format from libwavpacks' number of bits.
*/
static enum sample_format
wavpack_bits_to_sample_format(bool is_float, int bytes_per_sample)
{
if (is_float)
return SAMPLE_FORMAT_S24_P32;
switch (bytes_per_sample) {
case 1:
return SAMPLE_FORMAT_S8;
case 2:
return SAMPLE_FORMAT_S16;
case 3:
return SAMPLE_FORMAT_S24_P32;
case 4:
return SAMPLE_FORMAT_S32;
default:
return SAMPLE_FORMAT_UNDEFINED;
}
}
/* /*
* This does the main decoding thing. * This does the main decoding thing.
* Requires an already opened WavpackContext. * Requires an already opened WavpackContext.
...@@ -132,7 +159,8 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, ...@@ -132,7 +159,8 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek,
struct replay_gain_info *replay_gain_info) struct replay_gain_info *replay_gain_info)
{ {
GError *error = NULL; GError *error = NULL;
unsigned bits; bool is_float;
enum sample_format sample_format;
struct audio_format audio_format; struct audio_format audio_format;
format_samples_t format_samples; format_samples_t format_samples;
char chunk[CHUNK_SIZE]; char chunk[CHUNK_SIZE];
...@@ -141,19 +169,14 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek, ...@@ -141,19 +169,14 @@ wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek,
int bytes_per_sample, output_sample_size; int bytes_per_sample, output_sample_size;
int position; int position;
bits = WavpackGetBitsPerSample(wpc); is_float = (WavpackGetMode(wpc) & MODE_FLOAT) != 0;
sample_format =
/* round bitwidth to 8-bit units */ wavpack_bits_to_sample_format(is_float,
bits = (bits + 7) & (~7); WavpackGetBytesPerSample(wpc));
/* MPD handles max 32-bit samples */
if (bits > 32)
bits = 32;
if ((WavpackGetMode(wpc) & MODE_FLOAT) == MODE_FLOAT)
bits = 24;
if (!audio_format_init_checked(&audio_format, if (!audio_format_init_checked(&audio_format,
WavpackGetSampleRate(wpc), bits, WavpackGetSampleRate(wpc),
sample_format,
WavpackGetNumChannels(wpc), &error)) { WavpackGetNumChannels(wpc), &error)) {
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
......
...@@ -59,7 +59,7 @@ wildmidi_file_decode(struct decoder *decoder, const char *path_fs) ...@@ -59,7 +59,7 @@ wildmidi_file_decode(struct decoder *decoder, const char *path_fs)
{ {
static const struct audio_format audio_format = { static const struct audio_format audio_format = {
.sample_rate = WILDMIDI_SAMPLE_RATE, .sample_rate = WILDMIDI_SAMPLE_RATE,
.bits = 16, .format = SAMPLE_FORMAT_S16,
.channels = 2, .channels = 2,
}; };
midi *wm; midi *wm;
......
...@@ -89,7 +89,8 @@ flac_encoder_finish(struct encoder *_encoder) ...@@ -89,7 +89,8 @@ flac_encoder_finish(struct encoder *_encoder)
} }
static bool static bool
flac_encoder_setup(struct flac_encoder *encoder, GError **error) flac_encoder_setup(struct flac_encoder *encoder, unsigned bits_per_sample,
GError **error)
{ {
if ( !FLAC__stream_encoder_set_compression_level(encoder->fse, if ( !FLAC__stream_encoder_set_compression_level(encoder->fse,
encoder->compression)) { encoder->compression)) {
...@@ -106,10 +107,10 @@ flac_encoder_setup(struct flac_encoder *encoder, GError **error) ...@@ -106,10 +107,10 @@ flac_encoder_setup(struct flac_encoder *encoder, GError **error)
return false; return false;
} }
if ( !FLAC__stream_encoder_set_bits_per_sample(encoder->fse, if ( !FLAC__stream_encoder_set_bits_per_sample(encoder->fse,
encoder->audio_format.bits)) { bits_per_sample)) {
g_set_error(error, flac_encoder_quark(), 0, g_set_error(error, flac_encoder_quark(), 0,
"error setting flac bit format to %d", "error setting flac bit format to %d",
encoder->audio_format.bits); bits_per_sample);
return false; return false;
} }
if ( !FLAC__stream_encoder_set_sample_rate(encoder->fse, if ( !FLAC__stream_encoder_set_sample_rate(encoder->fse,
...@@ -143,13 +144,29 @@ flac_encoder_open(struct encoder *_encoder, struct audio_format *audio_format, ...@@ -143,13 +144,29 @@ flac_encoder_open(struct encoder *_encoder, struct audio_format *audio_format,
GError **error) GError **error)
{ {
struct flac_encoder *encoder = (struct flac_encoder *)_encoder; struct flac_encoder *encoder = (struct flac_encoder *)_encoder;
unsigned bits_per_sample;
FLAC__StreamEncoderInitStatus init_status; FLAC__StreamEncoderInitStatus init_status;
encoder->audio_format = *audio_format; encoder->audio_format = *audio_format;
/* FIXME: flac should support 32bit as well */ /* FIXME: flac should support 32bit as well */
if (audio_format->bits > 24) switch (audio_format->format) {
audio_format->bits = 24; case SAMPLE_FORMAT_S8:
bits_per_sample = 8;
break;
case SAMPLE_FORMAT_S16:
bits_per_sample = 16;
break;
case SAMPLE_FORMAT_S24_P32:
bits_per_sample = 24;
break;
default:
bits_per_sample = 24;
audio_format->format = SAMPLE_FORMAT_S24_P32;
}
/* allocate the encoder */ /* allocate the encoder */
encoder->fse = FLAC__stream_encoder_new(); encoder->fse = FLAC__stream_encoder_new();
...@@ -159,7 +176,7 @@ flac_encoder_open(struct encoder *_encoder, struct audio_format *audio_format, ...@@ -159,7 +176,7 @@ flac_encoder_open(struct encoder *_encoder, struct audio_format *audio_format,
return false; return false;
} }
if (!flac_encoder_setup(encoder, error)) { if (!flac_encoder_setup(encoder, bits_per_sample, error)) {
FLAC__stream_encoder_delete(encoder->fse); FLAC__stream_encoder_delete(encoder->fse);
return false; return false;
} }
...@@ -237,20 +254,23 @@ flac_encoder_write(struct encoder *_encoder, ...@@ -237,20 +254,23 @@ flac_encoder_write(struct encoder *_encoder,
num_frames = length / audio_format_frame_size(&encoder->audio_format); num_frames = length / audio_format_frame_size(&encoder->audio_format);
num_samples = num_frames * encoder->audio_format.channels; num_samples = num_frames * encoder->audio_format.channels;
switch (encoder->audio_format.bits) { switch (encoder->audio_format.format) {
case 8: case SAMPLE_FORMAT_S8:
exbuffer = pcm_buffer_get(&encoder->expand_buffer, length*4); exbuffer = pcm_buffer_get(&encoder->expand_buffer, length*4);
pcm8_to_flac(exbuffer, data, num_samples); pcm8_to_flac(exbuffer, data, num_samples);
buffer = exbuffer; buffer = exbuffer;
break; break;
case 16:
case SAMPLE_FORMAT_S16:
exbuffer = pcm_buffer_get(&encoder->expand_buffer, length*2); exbuffer = pcm_buffer_get(&encoder->expand_buffer, length*2);
pcm16_to_flac(exbuffer, data, num_samples); pcm16_to_flac(exbuffer, data, num_samples);
buffer = exbuffer; buffer = exbuffer;
break; break;
case 24:
case 32: /* nothing need to be done case SAMPLE_FORMAT_S24_P32:
* format is the same for both mpd and libFLAC */ case SAMPLE_FORMAT_S32:
/* nothing need to be done; format is the same for
both mpd and libFLAC */
buffer = data; buffer = data;
break; break;
} }
......
...@@ -185,7 +185,7 @@ lame_encoder_open(struct encoder *_encoder, struct audio_format *audio_format, ...@@ -185,7 +185,7 @@ lame_encoder_open(struct encoder *_encoder, struct audio_format *audio_format,
{ {
struct lame_encoder *encoder = (struct lame_encoder *)_encoder; struct lame_encoder *encoder = (struct lame_encoder *)_encoder;
audio_format->bits = 16; audio_format->format = SAMPLE_FORMAT_S16;
audio_format->channels = 2; audio_format->channels = 2;
encoder->audio_format = *audio_format; encoder->audio_format = *audio_format;
......
...@@ -192,7 +192,7 @@ twolame_encoder_open(struct encoder *_encoder, struct audio_format *audio_format ...@@ -192,7 +192,7 @@ twolame_encoder_open(struct encoder *_encoder, struct audio_format *audio_format
{ {
struct twolame_encoder *encoder = (struct twolame_encoder *)_encoder; struct twolame_encoder *encoder = (struct twolame_encoder *)_encoder;
audio_format->bits = 16; audio_format->format = SAMPLE_FORMAT_S16;
audio_format->channels = 2; audio_format->channels = 2;
encoder->audio_format = *audio_format; encoder->audio_format = *audio_format;
......
...@@ -212,7 +212,7 @@ vorbis_encoder_open(struct encoder *_encoder, ...@@ -212,7 +212,7 @@ vorbis_encoder_open(struct encoder *_encoder,
struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder;
bool ret; bool ret;
audio_format->bits = 16; audio_format->format = SAMPLE_FORMAT_S16;
encoder->audio_format = *audio_format; encoder->audio_format = *audio_format;
......
...@@ -114,16 +114,39 @@ wave_encoder_open(struct encoder *_encoder, ...@@ -114,16 +114,39 @@ wave_encoder_open(struct encoder *_encoder,
struct wave_encoder *encoder = (struct wave_encoder *)_encoder; struct wave_encoder *encoder = (struct wave_encoder *)_encoder;
void *buffer; void *buffer;
encoder->bits = audio_format->bits; assert(audio_format_valid(audio_format));
switch (audio_format->format) {
case SAMPLE_FORMAT_S8:
encoder->bits = 8;
break;
case SAMPLE_FORMAT_S16:
encoder->bits = 16;
break;
case SAMPLE_FORMAT_S24_P32:
encoder->bits = 24;
break;
case SAMPLE_FORMAT_S32:
encoder->bits = 32;
break;
default:
audio_format->format = SAMPLE_FORMAT_S16;
encoder->bits = 16;
break;
}
buffer = pcm_buffer_get(&encoder->buffer, sizeof(struct wave_header) ); buffer = pcm_buffer_get(&encoder->buffer, sizeof(struct wave_header) );
/* create PCM wave header in initial buffer */ /* create PCM wave header in initial buffer */
fill_wave_header((struct wave_header *) buffer, fill_wave_header((struct wave_header *) buffer,
audio_format->channels, audio_format->channels,
audio_format->bits, encoder->bits,
audio_format->sample_rate, audio_format->sample_rate,
(audio_format->bits / 8) * audio_format->channels ); (encoder->bits / 8) * audio_format->channels );
encoder->buffer_length = sizeof(struct wave_header); encoder->buffer_length = sizeof(struct wave_header);
return true; return true;
......
...@@ -75,8 +75,9 @@ volume_filter_open(struct filter *_filter, ...@@ -75,8 +75,9 @@ volume_filter_open(struct filter *_filter,
{ {
struct volume_filter *filter = (struct volume_filter *)_filter; struct volume_filter *filter = (struct volume_filter *)_filter;
if (audio_format->bits != 8 && audio_format->bits != 16 && if (audio_format->format != SAMPLE_FORMAT_S8 &&
audio_format->bits != 24) { audio_format->format != SAMPLE_FORMAT_S16 &&
audio_format->format != SAMPLE_FORMAT_S24_P32) {
g_set_error(error_r, volume_quark(), 0, g_set_error(error_r, volume_quark(), 0,
"Unsupported audio format"); "Unsupported audio format");
return false; return false;
......
...@@ -47,7 +47,8 @@ void finishNormalization(void) ...@@ -47,7 +47,8 @@ void finishNormalization(void)
void normalizeData(void *buffer, int bufferSize, void normalizeData(void *buffer, int bufferSize,
const struct audio_format *format) const struct audio_format *format)
{ {
if ((format->bits != 16) || (format->channels != 2)) return; if (format->format != SAMPLE_FORMAT_S16 || format->channels != 2)
return;
Compressor_Process_int16(compressor, buffer, bufferSize / 2); Compressor_Process_int16(compressor, buffer, bufferSize / 2);
} }
...@@ -185,13 +185,22 @@ alsa_test_default_device(void) ...@@ -185,13 +185,22 @@ alsa_test_default_device(void)
static snd_pcm_format_t static snd_pcm_format_t
get_bitformat(const struct audio_format *af) get_bitformat(const struct audio_format *af)
{ {
switch (af->bits) { switch (af->format) {
case 8: return SND_PCM_FORMAT_S8; case SAMPLE_FORMAT_S8:
case 16: return SND_PCM_FORMAT_S16; return SND_PCM_FORMAT_S8;
case 24: return SND_PCM_FORMAT_S24;
case 32: return SND_PCM_FORMAT_S32; case SAMPLE_FORMAT_S16:
} return SND_PCM_FORMAT_S16;
case SAMPLE_FORMAT_S24_P32:
return SND_PCM_FORMAT_S24;
case SAMPLE_FORMAT_S32:
return SND_PCM_FORMAT_S32;
default:
return SND_PCM_FORMAT_UNKNOWN; return SND_PCM_FORMAT_UNKNOWN;
}
} }
static snd_pcm_format_t static snd_pcm_format_t
...@@ -264,61 +273,67 @@ configure_hw: ...@@ -264,61 +273,67 @@ configure_hw:
err = snd_pcm_hw_params_set_format(ad->pcm, hwparams, err = snd_pcm_hw_params_set_format(ad->pcm, hwparams,
byteswap_bitformat(bitformat)); byteswap_bitformat(bitformat));
if (err == 0) { if (err == 0) {
g_debug("ALSA device \"%s\": converting %u bit to reverse-endian\n", g_debug("ALSA device \"%s\": converting format %s to reverse-endian",
alsa_device(ad), audio_format->bits); alsa_device(ad),
sample_format_to_string(audio_format->format));
audio_format->reverse_endian = 1; audio_format->reverse_endian = 1;
} }
} }
if (err == -EINVAL && (audio_format->bits == 24 || if (err == -EINVAL && (audio_format->format == SAMPLE_FORMAT_S24_P32 ||
audio_format->bits == 16)) { audio_format->format == SAMPLE_FORMAT_S16)) {
/* fall back to 32 bit, let pcm_convert.c do the conversion */ /* fall back to 32 bit, let pcm_convert.c do the conversion */
err = snd_pcm_hw_params_set_format(ad->pcm, hwparams, err = snd_pcm_hw_params_set_format(ad->pcm, hwparams,
SND_PCM_FORMAT_S32); SND_PCM_FORMAT_S32);
if (err == 0) { if (err == 0) {
g_debug("ALSA device \"%s\": converting %u bit to 32 bit\n", g_debug("ALSA device \"%s\": converting format %s to 32 bit\n",
alsa_device(ad), audio_format->bits); alsa_device(ad),
audio_format->bits = 32; sample_format_to_string(audio_format->format));
audio_format->format = SAMPLE_FORMAT_S32;
} }
} }
if (err == -EINVAL && (audio_format->bits == 24 || if (err == -EINVAL && (audio_format->format == SAMPLE_FORMAT_S24_P32 ||
audio_format->bits == 16)) { audio_format->format == SAMPLE_FORMAT_S16)) {
/* fall back to 32 bit, let pcm_convert.c do the conversion */ /* fall back to 32 bit, let pcm_convert.c do the conversion */
err = snd_pcm_hw_params_set_format(ad->pcm, hwparams, err = snd_pcm_hw_params_set_format(ad->pcm, hwparams,
byteswap_bitformat(SND_PCM_FORMAT_S32)); byteswap_bitformat(SND_PCM_FORMAT_S32));
if (err == 0) { if (err == 0) {
g_debug("ALSA device \"%s\": converting %u bit to 32 bit backward-endian\n", g_debug("ALSA device \"%s\": converting format %s to 32 bit backward-endian\n",
alsa_device(ad), audio_format->bits); alsa_device(ad),
audio_format->bits = 32; sample_format_to_string(audio_format->format));
audio_format->format = SAMPLE_FORMAT_S32;
audio_format->reverse_endian = 1; audio_format->reverse_endian = 1;
} }
} }
if (err == -EINVAL && audio_format->bits != 16) { if (err == -EINVAL && audio_format->format != SAMPLE_FORMAT_S16) {
/* fall back to 16 bit, let pcm_convert.c do the conversion */ /* fall back to 16 bit, let pcm_convert.c do the conversion */
err = snd_pcm_hw_params_set_format(ad->pcm, hwparams, err = snd_pcm_hw_params_set_format(ad->pcm, hwparams,
SND_PCM_FORMAT_S16); SND_PCM_FORMAT_S16);
if (err == 0) { if (err == 0) {
g_debug("ALSA device \"%s\": converting %u bit to 16 bit\n", g_debug("ALSA device \"%s\": converting format %s to 16 bit\n",
alsa_device(ad), audio_format->bits); alsa_device(ad),
audio_format->bits = 16; sample_format_to_string(audio_format->format));
audio_format->format = SAMPLE_FORMAT_S16;
} }
} }
if (err == -EINVAL && audio_format->bits != 16) { if (err == -EINVAL && audio_format->format != SAMPLE_FORMAT_S16) {
/* fall back to 16 bit, let pcm_convert.c do the conversion */ /* fall back to 16 bit, let pcm_convert.c do the conversion */
err = snd_pcm_hw_params_set_format(ad->pcm, hwparams, err = snd_pcm_hw_params_set_format(ad->pcm, hwparams,
byteswap_bitformat(SND_PCM_FORMAT_S16)); byteswap_bitformat(SND_PCM_FORMAT_S16));
if (err == 0) { if (err == 0) {
g_debug("ALSA device \"%s\": converting %u bit to 16 bit backward-endian\n", g_debug("ALSA device \"%s\": converting format %s to 16 bit backward-endian\n",
alsa_device(ad), audio_format->bits); alsa_device(ad),
audio_format->bits = 16; sample_format_to_string(audio_format->format));
audio_format->format = SAMPLE_FORMAT_S16;
audio_format->reverse_endian = 1; audio_format->reverse_endian = 1;
} }
} }
if (err < 0) { if (err < 0) {
g_set_error(error, alsa_output_quark(), err, g_set_error(error, alsa_output_quark(), err,
"ALSA device \"%s\" does not support %u bit audio: %s", "ALSA device \"%s\" does not support format %s: %s",
alsa_device(ad), audio_format->bits, alsa_device(ad),
sample_format_to_string(audio_format->format),
snd_strerror(-err)); snd_strerror(-err));
return false; return false;
} }
...@@ -449,7 +464,7 @@ alsa_open(void *data, struct audio_format *audio_format, GError **error) ...@@ -449,7 +464,7 @@ alsa_open(void *data, struct audio_format *audio_format, GError **error)
/* sample format is not supported by this plugin - /* sample format is not supported by this plugin -
fall back to 16 bit samples */ fall back to 16 bit samples */
audio_format->bits = 16; audio_format->format = SAMPLE_FORMAT_S16;
bitformat = SND_PCM_FORMAT_S16; bitformat = SND_PCM_FORMAT_S16;
} }
......
...@@ -170,13 +170,24 @@ ao_output_open(void *data, struct audio_format *audio_format, ...@@ -170,13 +170,24 @@ ao_output_open(void *data, struct audio_format *audio_format,
ao_sample_format format; ao_sample_format format;
struct ao_data *ad = (struct ao_data *)data; struct ao_data *ad = (struct ao_data *)data;
/* support for 24 bit samples in libao is currently dubious, switch (audio_format->format) {
and until we have sorted that out, resample everything to case SAMPLE_FORMAT_S8:
16 bit */ format.bits = 8;
if (audio_format->bits > 16) break;
audio_format->bits = 16;
case SAMPLE_FORMAT_S16:
format.bits = 16;
break;
default:
/* support for 24 bit samples in libao is currently
dubious, and until we have sorted that out,
convert everything to 16 bit */
audio_format->format = SAMPLE_FORMAT_S16;
format.bits = 16;
break;
}
format.bits = audio_format->bits;
format.rate = audio_format->sample_rate; format.rate = audio_format->sample_rate;
format.byte_format = AO_FMT_NATIVE; format.byte_format = AO_FMT_NATIVE;
format.channels = audio_format->channels; format.channels = audio_format->channels;
......
...@@ -157,8 +157,9 @@ set_audioformat(struct jack_data *jd, struct audio_format *audio_format) ...@@ -157,8 +157,9 @@ set_audioformat(struct jack_data *jd, struct audio_format *audio_format)
else if (audio_format->channels > jd->num_source_ports) else if (audio_format->channels > jd->num_source_ports)
audio_format->channels = 2; audio_format->channels = 2;
if (audio_format->bits != 16 && audio_format->bits != 24) if (audio_format->format != SAMPLE_FORMAT_S16 &&
audio_format->bits = 24; audio_format->format != SAMPLE_FORMAT_S24_P32)
audio_format->format = SAMPLE_FORMAT_S24_P32;
} }
static void static void
...@@ -606,13 +607,13 @@ static void ...@@ -606,13 +607,13 @@ static void
mpd_jack_write_samples(struct jack_data *jd, const void *src, mpd_jack_write_samples(struct jack_data *jd, const void *src,
unsigned num_samples) unsigned num_samples)
{ {
switch (jd->audio_format.bits) { switch (jd->audio_format.format) {
case 16: case SAMPLE_FORMAT_S16:
mpd_jack_write_samples_16(jd, (const int16_t*)src, mpd_jack_write_samples_16(jd, (const int16_t*)src,
num_samples); num_samples);
break; break;
case 24: case SAMPLE_FORMAT_S24_P32:
mpd_jack_write_samples_24(jd, (const int32_t*)src, mpd_jack_write_samples_24(jd, (const int32_t*)src,
num_samples); num_samples);
break; break;
......
...@@ -172,19 +172,19 @@ mvp_set_pcm_params(struct mvp_data *md, struct audio_format *audio_format, ...@@ -172,19 +172,19 @@ mvp_set_pcm_params(struct mvp_data *md, struct audio_format *audio_format,
} }
/* 0,1=24bit(24) , 2,3=16bit */ /* 0,1=24bit(24) , 2,3=16bit */
switch (audio_format->bits) { switch (audio_format->format) {
case 16: case SAMPLE_FORMAT_S16:
mix[1] = 2; mix[1] = 2;
break; break;
case 24: case SAMPLE_FORMAT_S24_P32:
mix[1] = 0; mix[1] = 0;
break; break;
default: default:
g_debug("unsupported sample format %u - falling back to stereo", g_debug("unsupported sample format %s - falling back to 16 bit",
audio_format->bits); sample_format_to_string(audio_format->format));
audio_format->bits = 16; audio_format->format = SAMPLE_FORMAT_S16;
mix[1] = 2; mix[1] = 2;
break; break;
} }
......
...@@ -58,25 +58,29 @@ openal_output_quark(void) ...@@ -58,25 +58,29 @@ openal_output_quark(void)
static ALenum static ALenum
openal_audio_format(struct audio_format *audio_format) openal_audio_format(struct audio_format *audio_format)
{ {
/* Only 8 and 16 bit samples are supported */ switch (audio_format->format) {
if (audio_format->bits != 16 && audio_format->bits != 8) case SAMPLE_FORMAT_S16:
audio_format->bits = 16;
switch (audio_format->bits)
{
case 16:
if (audio_format->channels == 2) if (audio_format->channels == 2)
return AL_FORMAT_STEREO16; return AL_FORMAT_STEREO16;
if (audio_format->channels == 1) if (audio_format->channels == 1)
return AL_FORMAT_MONO16; return AL_FORMAT_MONO16;
break; break;
case 8: case SAMPLE_FORMAT_S8:
if (audio_format->channels == 2) if (audio_format->channels == 2)
return AL_FORMAT_STEREO8; return AL_FORMAT_STEREO8;
if (audio_format->channels == 1) if (audio_format->channels == 1)
return AL_FORMAT_MONO8; return AL_FORMAT_MONO8;
break; break;
default:
/* fall back to 16 bit */
audio_format->format = SAMPLE_FORMAT_S16;
if (audio_format->channels == 2)
return AL_FORMAT_STEREO16;
if (audio_format->channels == 1)
return AL_FORMAT_MONO16;
break;
} }
return 0; return 0;
......
...@@ -490,17 +490,18 @@ oss_setup(struct oss_data *od, GError **error) ...@@ -490,17 +490,18 @@ oss_setup(struct oss_data *od, GError **error)
} }
od->audio_format.sample_rate = tmp; od->audio_format.sample_rate = tmp;
switch (od->audio_format.bits) { switch (od->audio_format.format) {
case 8: case SAMPLE_FORMAT_S8:
tmp = AFMT_S8; tmp = AFMT_S8;
break; break;
case 16:
case SAMPLE_FORMAT_S16:
tmp = AFMT_S16_MPD; tmp = AFMT_S16_MPD;
break; break;
default: default:
/* not supported by OSS - fall back to 16 bit */ /* not supported by OSS - fall back to 16 bit */
od->audio_format.bits = 16; od->audio_format.format = SAMPLE_FORMAT_S16;
tmp = AFMT_S16_MPD; tmp = AFMT_S16_MPD;
break; break;
} }
......
...@@ -166,9 +166,6 @@ osx_output_open(void *data, struct audio_format *audio_format, GError **error) ...@@ -166,9 +166,6 @@ osx_output_open(void *data, struct audio_format *audio_format, GError **error)
OSStatus status; OSStatus status;
ComponentResult result; ComponentResult result;
if (audio_format->bits > 16)
audio_format->bits = 16;
desc.componentType = kAudioUnitType_Output; desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_DefaultOutput; desc.componentSubType = kAudioUnitSubType_DefaultOutput;
desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentManufacturer = kAudioUnitManufacturer_Apple;
...@@ -226,7 +223,21 @@ osx_output_open(void *data, struct audio_format *audio_format, GError **error) ...@@ -226,7 +223,21 @@ osx_output_open(void *data, struct audio_format *audio_format, GError **error)
stream_description.mFramesPerPacket = 1; stream_description.mFramesPerPacket = 1;
stream_description.mBytesPerFrame = stream_description.mBytesPerPacket; stream_description.mBytesPerFrame = stream_description.mBytesPerPacket;
stream_description.mChannelsPerFrame = audio_format->channels; stream_description.mChannelsPerFrame = audio_format->channels;
stream_description.mBitsPerChannel = audio_format->bits;
switch (audio_format->format) {
case SAMPLE_FORMAT_S8:
stream_description.mBitsPerChannel = 8;
break;
case SAMPLE_FORMAT_S16:
stream_description.mBitsPerChannel = 16;
break;
default:
audio_format->format = SAMPLE_FORMAT_S16;
stream_description.mBitsPerChannel = 16;
break;
}
result = AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat, result = AudioUnitSetProperty(od->au, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, 0, kAudioUnitScope_Input, 0,
......
...@@ -467,7 +467,7 @@ pulse_output_open(void *data, struct audio_format *audio_format, ...@@ -467,7 +467,7 @@ pulse_output_open(void *data, struct audio_format *audio_format,
/* MPD doesn't support the other pulseaudio sample formats, so /* MPD doesn't support the other pulseaudio sample formats, so
we just force MPD to send us everything as 16 bit */ we just force MPD to send us everything as 16 bit */
audio_format->bits = 16; audio_format->format = SAMPLE_FORMAT_S16;
ss.format = PA_SAMPLE_S16NE; ss.format = PA_SAMPLE_S16NE;
ss.rate = audio_format->sample_rate; ss.rate = audio_format->sample_rate;
......
...@@ -89,7 +89,7 @@ solaris_output_open(void *data, struct audio_format *audio_format, ...@@ -89,7 +89,7 @@ solaris_output_open(void *data, struct audio_format *audio_format,
/* support only 16 bit mono/stereo for now; nothing else has /* support only 16 bit mono/stereo for now; nothing else has
been tested */ been tested */
audio_format->bits = 16; audio_format->format = SAMPLE_FORMAT_S16;
/* open the device in non-blocking mode */ /* open the device in non-blocking mode */
...@@ -119,7 +119,7 @@ solaris_output_open(void *data, struct audio_format *audio_format, ...@@ -119,7 +119,7 @@ solaris_output_open(void *data, struct audio_format *audio_format,
info.play.sample_rate = audio_format->sample_rate; info.play.sample_rate = audio_format->sample_rate;
info.play.channels = audio_format->channels; info.play.channels = audio_format->channels;
info.play.precision = audio_format->bits; info.play.precision = 16;
info.play.encoding = AUDIO_ENCODING_LINEAR; info.play.encoding = AUDIO_ENCODING_LINEAR;
ret = ioctl(so->fd, AUDIO_SETINFO, &info); ret = ioctl(so->fd, AUDIO_SETINFO, &info);
......
...@@ -63,15 +63,15 @@ pcm_convert_16(struct pcm_convert_state *state, ...@@ -63,15 +63,15 @@ pcm_convert_16(struct pcm_convert_state *state,
const int16_t *buf; const int16_t *buf;
size_t len; size_t len;
assert(dest_format->bits == 16); assert(dest_format->format == SAMPLE_FORMAT_S16);
buf = pcm_convert_to_16(&state->format_buffer, &state->dither, buf = pcm_convert_to_16(&state->format_buffer, &state->dither,
src_format->bits, src_buffer, src_size, src_format->format, src_buffer, src_size,
&len); &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, g_set_error(error_r, pcm_convert_quark(), 0,
"Conversion from %u to 16 bit is not implemented", "Conversion from %s to 16 bit is not implemented",
src_format->bits); sample_format_to_string(src_format->format));
return NULL; return NULL;
} }
...@@ -119,14 +119,14 @@ pcm_convert_24(struct pcm_convert_state *state, ...@@ -119,14 +119,14 @@ pcm_convert_24(struct pcm_convert_state *state,
const int32_t *buf; const int32_t *buf;
size_t len; size_t len;
assert(dest_format->bits == 24); assert(dest_format->format == SAMPLE_FORMAT_S24_P32);
buf = pcm_convert_to_24(&state->format_buffer, src_format->bits, buf = pcm_convert_to_24(&state->format_buffer, src_format->format,
src_buffer, src_size, &len); src_buffer, src_size, &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, g_set_error(error_r, pcm_convert_quark(), 0,
"Conversion from %u to 24 bit is not implemented", "Conversion from %s to 24 bit is not implemented",
src_format->bits); sample_format_to_string(src_format->format));
return NULL; return NULL;
} }
...@@ -174,14 +174,14 @@ pcm_convert_32(struct pcm_convert_state *state, ...@@ -174,14 +174,14 @@ pcm_convert_32(struct pcm_convert_state *state,
const int32_t *buf; const int32_t *buf;
size_t len; size_t len;
assert(dest_format->bits == 32); assert(dest_format->format == SAMPLE_FORMAT_S32);
buf = pcm_convert_to_32(&state->format_buffer, src_format->bits, buf = pcm_convert_to_32(&state->format_buffer, src_format->format,
src_buffer, src_size, &len); src_buffer, src_size, &len);
if (buf == NULL) { if (buf == NULL) {
g_set_error(error_r, pcm_convert_quark(), 0, g_set_error(error_r, pcm_convert_quark(), 0,
"Conversion from %u to 24 bit is not implemented", "Conversion from %s to 24 bit is not implemented",
src_format->bits); sample_format_to_string(src_format->format));
return NULL; return NULL;
} }
...@@ -227,20 +227,20 @@ pcm_convert(struct pcm_convert_state *state, ...@@ -227,20 +227,20 @@ pcm_convert(struct pcm_convert_state *state,
size_t *dest_size_r, size_t *dest_size_r,
GError **error_r) GError **error_r)
{ {
switch (dest_format->bits) { switch (dest_format->format) {
case 16: case SAMPLE_FORMAT_S16:
return pcm_convert_16(state, return pcm_convert_16(state,
src_format, src, src_size, src_format, src, src_size,
dest_format, dest_size_r, dest_format, dest_size_r,
error_r); error_r);
case 24: case SAMPLE_FORMAT_S24_P32:
return pcm_convert_24(state, return pcm_convert_24(state,
src_format, src, src_size, src_format, src, src_size,
dest_format, dest_size_r, dest_format, dest_size_r,
error_r); error_r);
case 32: case SAMPLE_FORMAT_S32:
return pcm_convert_32(state, return pcm_convert_32(state,
src_format, src, src_size, src_format, src, src_size,
dest_format, dest_size_r, dest_format, dest_size_r,
...@@ -248,8 +248,8 @@ pcm_convert(struct pcm_convert_state *state, ...@@ -248,8 +248,8 @@ pcm_convert(struct pcm_convert_state *state,
default: default:
g_set_error(error_r, pcm_convert_quark(), 0, g_set_error(error_r, pcm_convert_quark(), 0,
"PCM conversion to %u bit is not implemented", "PCM conversion to %s is not implemented",
dest_format->bits); sample_format_to_string(dest_format->format));
return NULL; return NULL;
} }
} }
...@@ -50,14 +50,17 @@ pcm_convert_32_to_16(struct pcm_dither *dither, ...@@ -50,14 +50,17 @@ pcm_convert_32_to_16(struct pcm_dither *dither,
const int16_t * const int16_t *
pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither, pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
uint8_t bits, const void *src, enum sample_format src_format, const void *src,
size_t src_size, size_t *dest_size_r) size_t src_size, size_t *dest_size_r)
{ {
unsigned num_samples; unsigned num_samples;
int16_t *dest; int16_t *dest;
switch (bits) { switch (src_format) {
case 8: case SAMPLE_FORMAT_UNDEFINED:
break;
case SAMPLE_FORMAT_S8:
num_samples = src_size; num_samples = src_size;
*dest_size_r = src_size * sizeof(*dest); *dest_size_r = src_size * sizeof(*dest);
dest = pcm_buffer_get(buffer, *dest_size_r); dest = pcm_buffer_get(buffer, *dest_size_r);
...@@ -67,11 +70,11 @@ pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither, ...@@ -67,11 +70,11 @@ pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
num_samples); num_samples);
return dest; return dest;
case 16: case SAMPLE_FORMAT_S16:
*dest_size_r = src_size; *dest_size_r = src_size;
return src; return src;
case 24: case SAMPLE_FORMAT_S24_P32:
num_samples = src_size / 4; num_samples = src_size / 4;
*dest_size_r = num_samples * sizeof(*dest); *dest_size_r = num_samples * sizeof(*dest);
dest = pcm_buffer_get(buffer, *dest_size_r); dest = pcm_buffer_get(buffer, *dest_size_r);
...@@ -81,7 +84,7 @@ pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither, ...@@ -81,7 +84,7 @@ pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
num_samples); num_samples);
return dest; return dest;
case 32: case SAMPLE_FORMAT_S32:
num_samples = src_size / 4; num_samples = src_size / 4;
*dest_size_r = num_samples * sizeof(*dest); *dest_size_r = num_samples * sizeof(*dest);
dest = pcm_buffer_get(buffer, *dest_size_r); dest = pcm_buffer_get(buffer, *dest_size_r);
...@@ -127,14 +130,17 @@ pcm_convert_32_to_24(int32_t *out, const int16_t *in, ...@@ -127,14 +130,17 @@ pcm_convert_32_to_24(int32_t *out, const int16_t *in,
const int32_t * const int32_t *
pcm_convert_to_24(struct pcm_buffer *buffer, pcm_convert_to_24(struct pcm_buffer *buffer,
uint8_t bits, const void *src, enum sample_format src_format, const void *src,
size_t src_size, size_t *dest_size_r) size_t src_size, size_t *dest_size_r)
{ {
unsigned num_samples; unsigned num_samples;
int32_t *dest; int32_t *dest;
switch (bits) { switch (src_format) {
case 8: case SAMPLE_FORMAT_UNDEFINED:
break;
case SAMPLE_FORMAT_S8:
num_samples = src_size; num_samples = src_size;
*dest_size_r = src_size * sizeof(*dest); *dest_size_r = src_size * sizeof(*dest);
dest = pcm_buffer_get(buffer, *dest_size_r); dest = pcm_buffer_get(buffer, *dest_size_r);
...@@ -143,7 +149,7 @@ pcm_convert_to_24(struct pcm_buffer *buffer, ...@@ -143,7 +149,7 @@ pcm_convert_to_24(struct pcm_buffer *buffer,
num_samples); num_samples);
return dest; return dest;
case 16: case SAMPLE_FORMAT_S16:
num_samples = src_size / 2; num_samples = src_size / 2;
*dest_size_r = num_samples * sizeof(*dest); *dest_size_r = num_samples * sizeof(*dest);
dest = pcm_buffer_get(buffer, *dest_size_r); dest = pcm_buffer_get(buffer, *dest_size_r);
...@@ -152,11 +158,11 @@ pcm_convert_to_24(struct pcm_buffer *buffer, ...@@ -152,11 +158,11 @@ pcm_convert_to_24(struct pcm_buffer *buffer,
num_samples); num_samples);
return dest; return dest;
case 24: case SAMPLE_FORMAT_S24_P32:
*dest_size_r = src_size; *dest_size_r = src_size;
return src; return src;
case 32: case SAMPLE_FORMAT_S32:
num_samples = src_size / 4; num_samples = src_size / 4;
*dest_size_r = num_samples * sizeof(*dest); *dest_size_r = num_samples * sizeof(*dest);
dest = pcm_buffer_get(buffer, *dest_size_r); dest = pcm_buffer_get(buffer, *dest_size_r);
...@@ -201,14 +207,17 @@ pcm_convert_24_to_32(int32_t *out, const int32_t *in, ...@@ -201,14 +207,17 @@ pcm_convert_24_to_32(int32_t *out, const int32_t *in,
const int32_t * const int32_t *
pcm_convert_to_32(struct pcm_buffer *buffer, pcm_convert_to_32(struct pcm_buffer *buffer,
uint8_t bits, const void *src, enum sample_format src_format, const void *src,
size_t src_size, size_t *dest_size_r) size_t src_size, size_t *dest_size_r)
{ {
unsigned num_samples; unsigned num_samples;
int32_t *dest; int32_t *dest;
switch (bits) { switch (src_format) {
case 8: case SAMPLE_FORMAT_UNDEFINED:
break;
case SAMPLE_FORMAT_S8:
num_samples = src_size; num_samples = src_size;
*dest_size_r = src_size * sizeof(*dest); *dest_size_r = src_size * sizeof(*dest);
dest = pcm_buffer_get(buffer, *dest_size_r); dest = pcm_buffer_get(buffer, *dest_size_r);
...@@ -217,7 +226,7 @@ pcm_convert_to_32(struct pcm_buffer *buffer, ...@@ -217,7 +226,7 @@ pcm_convert_to_32(struct pcm_buffer *buffer,
num_samples); num_samples);
return dest; return dest;
case 16: case SAMPLE_FORMAT_S16:
num_samples = src_size / 2; num_samples = src_size / 2;
*dest_size_r = num_samples * sizeof(*dest); *dest_size_r = num_samples * sizeof(*dest);
dest = pcm_buffer_get(buffer, *dest_size_r); dest = pcm_buffer_get(buffer, *dest_size_r);
...@@ -226,7 +235,7 @@ pcm_convert_to_32(struct pcm_buffer *buffer, ...@@ -226,7 +235,7 @@ pcm_convert_to_32(struct pcm_buffer *buffer,
num_samples); num_samples);
return dest; return dest;
case 24: case SAMPLE_FORMAT_S24_P32:
num_samples = src_size / 4; num_samples = src_size / 4;
*dest_size_r = num_samples * sizeof(*dest); *dest_size_r = num_samples * sizeof(*dest);
dest = pcm_buffer_get(buffer, *dest_size_r); dest = pcm_buffer_get(buffer, *dest_size_r);
...@@ -235,7 +244,7 @@ pcm_convert_to_32(struct pcm_buffer *buffer, ...@@ -235,7 +244,7 @@ pcm_convert_to_32(struct pcm_buffer *buffer,
num_samples); num_samples);
return dest; return dest;
case 32: case SAMPLE_FORMAT_S32:
*dest_size_r = src_size; *dest_size_r = src_size;
return src; return src;
} }
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#ifndef PCM_FORMAT_H #ifndef PCM_FORMAT_H
#define PCM_FORMAT_H #define PCM_FORMAT_H
#include "audio_format.h"
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
...@@ -40,7 +42,7 @@ struct pcm_dither; ...@@ -40,7 +42,7 @@ struct pcm_dither;
*/ */
const int16_t * const int16_t *
pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither, pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
uint8_t bits, const void *src, enum sample_format src_format, const void *src,
size_t src_size, size_t *dest_size_r); size_t src_size, size_t *dest_size_r);
/** /**
...@@ -55,7 +57,7 @@ pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither, ...@@ -55,7 +57,7 @@ pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
*/ */
const int32_t * const int32_t *
pcm_convert_to_24(struct pcm_buffer *buffer, pcm_convert_to_24(struct pcm_buffer *buffer,
uint8_t bits, const void *src, enum sample_format src_format, const void *src,
size_t src_size, size_t *dest_size_r); size_t src_size, size_t *dest_size_r);
/** /**
...@@ -70,7 +72,7 @@ pcm_convert_to_24(struct pcm_buffer *buffer, ...@@ -70,7 +72,7 @@ pcm_convert_to_24(struct pcm_buffer *buffer,
*/ */
const int32_t * const int32_t *
pcm_convert_to_32(struct pcm_buffer *buffer, pcm_convert_to_32(struct pcm_buffer *buffer,
uint8_t bits, const void *src, enum sample_format src_format, const void *src,
size_t src_size, size_t *dest_size_r); size_t src_size, size_t *dest_size_r);
#endif #endif
...@@ -103,18 +103,18 @@ pcm_add(void *buffer1, const void *buffer2, size_t size, ...@@ -103,18 +103,18 @@ pcm_add(void *buffer1, const void *buffer2, size_t size,
int vol1, int vol2, int vol1, int vol2,
const struct audio_format *format) const struct audio_format *format)
{ {
switch (format->bits) { switch (format->format) {
case 8: case SAMPLE_FORMAT_S8:
pcm_add_8((int8_t *)buffer1, (const int8_t *)buffer2, pcm_add_8((int8_t *)buffer1, (const int8_t *)buffer2,
size, vol1, vol2); size, vol1, vol2);
break; break;
case 16: case SAMPLE_FORMAT_S16:
pcm_add_16((int16_t *)buffer1, (const int16_t *)buffer2, pcm_add_16((int16_t *)buffer1, (const int16_t *)buffer2,
size / 2, vol1, vol2); size / 2, vol1, vol2);
break; break;
case 24: case SAMPLE_FORMAT_S24_P32:
pcm_add_24((int32_t*)buffer1, pcm_add_24((int32_t*)buffer1,
(const int32_t*)buffer2, (const int32_t*)buffer2,
size / 4, vol1, vol2); size / 4, vol1, vol2);
...@@ -127,7 +127,8 @@ pcm_add(void *buffer1, const void *buffer2, size_t size, ...@@ -127,7 +127,8 @@ pcm_add(void *buffer1, const void *buffer2, size_t size,
break; break;
default: default:
g_error("%u bits not supported by pcm_add!\n", format->bits); g_error("format %s not supported by pcm_add",
sample_format_to_string(format->format));
} }
} }
......
...@@ -150,17 +150,17 @@ pcm_volume(void *buffer, int length, ...@@ -150,17 +150,17 @@ pcm_volume(void *buffer, int length,
return true; return true;
} }
switch (format->bits) { switch (format->format) {
case 8: case SAMPLE_FORMAT_S8:
pcm_volume_change_8((int8_t *)buffer, length, volume); pcm_volume_change_8((int8_t *)buffer, length, volume);
return true; return true;
case 16: case SAMPLE_FORMAT_S16:
pcm_volume_change_16((int16_t *)buffer, length / 2, pcm_volume_change_16((int16_t *)buffer, length / 2,
volume); volume);
return true; return true;
case 24: case SAMPLE_FORMAT_S24_P32:
pcm_volume_change_24((int32_t*)buffer, length / 4, pcm_volume_change_24((int32_t*)buffer, length / 4,
volume); volume);
return true; return true;
......
...@@ -63,7 +63,7 @@ int main(int argc, char **argv) ...@@ -63,7 +63,7 @@ int main(int argc, char **argv)
else else
encoder_name = "vorbis"; encoder_name = "vorbis";
audio_format_init(&audio_format, 44100, 16, 2); audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2);
/* create the encoder */ /* create the encoder */
......
...@@ -85,7 +85,7 @@ int main(int argc, char **argv) ...@@ -85,7 +85,7 @@ int main(int argc, char **argv)
return 1; return 1;
} }
audio_format_init(&audio_format, 44100, 16, 2); audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2);
g_thread_init(NULL); g_thread_init(NULL);
......
...@@ -119,7 +119,7 @@ int main(int argc, char **argv) ...@@ -119,7 +119,7 @@ int main(int argc, char **argv)
return 1; return 1;
} }
audio_format_init(&audio_format, 44100, 16, 2); audio_format_init(&audio_format, 44100, SAMPLE_FORMAT_S16, 2);
g_thread_init(NULL); g_thread_init(NULL);
......
...@@ -55,7 +55,7 @@ int main(int argc, char **argv) ...@@ -55,7 +55,7 @@ int main(int argc, char **argv)
return 1; return 1;
} }
} else } else
audio_format_init(&audio_format, 48000, 16, 2); audio_format_init(&audio_format, 48000, SAMPLE_FORMAT_S16, 2);
while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) { while ((nbytes = read(0, buffer, sizeof(buffer))) > 0) {
if (!pcm_volume(buffer, nbytes, &audio_format, if (!pcm_volume(buffer, nbytes, &audio_format,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment