decoder/vorbis: skip 16 bit quantisation, provide float samples
Internally the vorbis (non-Tremor) decoder is working in floating point, and it's not really necessary to cut the output back to 16-bit if the soundcard or OS supports higher resolution. The decoder can be trivially modified to bypass its internal quantisation and produce floating-point output, and a separate quantisation can be used as appropriate to the platform.
This commit is contained in:
parent
071aca60be
commit
5e9ccdec63
1
NEWS
1
NEWS
@ -1,6 +1,7 @@
|
|||||||
ver 0.18 (2012/??/??)
|
ver 0.18 (2012/??/??)
|
||||||
* decoder:
|
* decoder:
|
||||||
- opus: new decoder plugin for the Opus codec
|
- opus: new decoder plugin for the Opus codec
|
||||||
|
- vorbis: skip 16 bit quantisation, provide float samples
|
||||||
* improved decoder/output error reporting
|
* improved decoder/output error reporting
|
||||||
|
|
||||||
ver 0.17.2 (2012/??/??)
|
ver 0.17.2 (2012/??/??)
|
||||||
|
@ -161,6 +161,21 @@ vorbis_send_comments(struct decoder *decoder, struct input_stream *is,
|
|||||||
tag_free(tag);
|
tag_free(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_TREMOR
|
||||||
|
static void
|
||||||
|
vorbis_interleave(float *dest, const float *const*src,
|
||||||
|
unsigned nframes, unsigned channels)
|
||||||
|
{
|
||||||
|
for (const float *const*src_end = src + channels;
|
||||||
|
src != src_end; ++src, ++dest) {
|
||||||
|
float *d = dest;
|
||||||
|
for (const float *s = *src, *s_end = s + nframes;
|
||||||
|
s != s_end; ++s, d += channels)
|
||||||
|
*d = *s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* public */
|
/* public */
|
||||||
static void
|
static void
|
||||||
vorbis_stream_decode(struct decoder *decoder,
|
vorbis_stream_decode(struct decoder *decoder,
|
||||||
@ -188,7 +203,11 @@ vorbis_stream_decode(struct decoder *decoder,
|
|||||||
|
|
||||||
struct audio_format audio_format;
|
struct audio_format audio_format;
|
||||||
if (!audio_format_init_checked(&audio_format, vi->rate,
|
if (!audio_format_init_checked(&audio_format, vi->rate,
|
||||||
|
#ifdef HAVE_TREMOR
|
||||||
SAMPLE_FORMAT_S16,
|
SAMPLE_FORMAT_S16,
|
||||||
|
#else
|
||||||
|
SAMPLE_FORMAT_FLOAT,
|
||||||
|
#endif
|
||||||
vi->channels, &error)) {
|
vi->channels, &error)) {
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
@ -202,7 +221,16 @@ vorbis_stream_decode(struct decoder *decoder,
|
|||||||
decoder_initialized(decoder, &audio_format, vis.seekable, total_time);
|
decoder_initialized(decoder, &audio_format, vis.seekable, total_time);
|
||||||
|
|
||||||
enum decoder_command cmd = decoder_get_command(decoder);
|
enum decoder_command cmd = decoder_get_command(decoder);
|
||||||
|
|
||||||
|
#ifdef HAVE_TREMOR
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
|
#else
|
||||||
|
float buffer[2048];
|
||||||
|
const int frames_per_buffer =
|
||||||
|
G_N_ELEMENTS(buffer) / audio_format.channels;
|
||||||
|
const unsigned frame_size = sizeof(buffer[0]) * audio_format.channels;
|
||||||
|
#endif
|
||||||
|
|
||||||
int prev_section = -1;
|
int prev_section = -1;
|
||||||
unsigned kbit_rate = 0;
|
unsigned kbit_rate = 0;
|
||||||
|
|
||||||
@ -216,9 +244,25 @@ vorbis_stream_decode(struct decoder *decoder,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int current_section;
|
int current_section;
|
||||||
|
|
||||||
|
#ifdef HAVE_TREMOR
|
||||||
long nbytes = ov_read(&vf, buffer, sizeof(buffer),
|
long nbytes = ov_read(&vf, buffer, sizeof(buffer),
|
||||||
VORBIS_BIG_ENDIAN, 2, 1,
|
VORBIS_BIG_ENDIAN, 2, 1,
|
||||||
¤t_section);
|
¤t_section);
|
||||||
|
#else
|
||||||
|
float **per_channel;
|
||||||
|
long nframes = ov_read_float(&vf, &per_channel,
|
||||||
|
frames_per_buffer,
|
||||||
|
¤t_section);
|
||||||
|
long nbytes = nframes;
|
||||||
|
if (nframes > 0) {
|
||||||
|
vorbis_interleave(buffer,
|
||||||
|
(const float*const*)per_channel,
|
||||||
|
nframes, audio_format.channels);
|
||||||
|
nbytes *= frame_size;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (nbytes == OV_HOLE) /* bad packet */
|
if (nbytes == OV_HOLE) /* bad packet */
|
||||||
nbytes = 0;
|
nbytes = 0;
|
||||||
else if (nbytes <= 0)
|
else if (nbytes <= 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user