decoder/dsdiff: don't convert to PCM
Move the responsibility for the conversion to the PCM library. This will allow passing the verbatim DSD samples to an output plugin.
This commit is contained in:
parent
c9c57af5f7
commit
9c36e71081
@ -481,7 +481,6 @@ libdecoder_plugins_a_SOURCES = \
|
|||||||
src/decoder/pcm_decoder_plugin.c \
|
src/decoder/pcm_decoder_plugin.c \
|
||||||
src/decoder/dsdiff_decoder_plugin.c \
|
src/decoder/dsdiff_decoder_plugin.c \
|
||||||
src/decoder/dsdiff_decoder_plugin.h \
|
src/decoder/dsdiff_decoder_plugin.h \
|
||||||
src/dsd2pcm/dsd2pcm.c src/dsd2pcm/dsd2pcm.h \
|
|
||||||
src/decoder_buffer.c \
|
src/decoder_buffer.c \
|
||||||
src/decoder_plugin.c \
|
src/decoder_plugin.c \
|
||||||
src/decoder_list.c
|
src/decoder_list.c
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
#include "dsdiff_decoder_plugin.h"
|
#include "dsdiff_decoder_plugin.h"
|
||||||
#include "decoder_api.h"
|
#include "decoder_api.h"
|
||||||
#include "audio_check.h"
|
#include "audio_check.h"
|
||||||
#include "dsd2pcm/dsd2pcm.h"
|
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h> /* for SEEK_SET, SEEK_CUR */
|
#include <stdio.h> /* for SEEK_SET, SEEK_CUR */
|
||||||
@ -55,12 +54,14 @@ struct dsdiff_metadata {
|
|||||||
unsigned sample_rate, channels;
|
unsigned sample_rate, channels;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool lsbitfirst;
|
static enum sample_format dsd_sample_format;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
dsdiff_init(const struct config_param *param)
|
dsdiff_init(const struct config_param *param)
|
||||||
{
|
{
|
||||||
lsbitfirst = config_get_block_bool(param, "lsbitfirst", false);
|
dsd_sample_format = config_get_block_bool(param, "lsbitfirst", false)
|
||||||
|
? SAMPLE_FORMAT_DSD_LSBFIRST
|
||||||
|
: SAMPLE_FORMAT_DSD;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +307,7 @@ dsdiff_read_metadata(struct decoder *decoder, struct input_stream *is,
|
|||||||
static bool
|
static bool
|
||||||
dsdiff_decode_chunk(struct decoder *decoder, struct input_stream *is,
|
dsdiff_decode_chunk(struct decoder *decoder, struct input_stream *is,
|
||||||
unsigned channels,
|
unsigned channels,
|
||||||
dsd2pcm_ctx **dsd2pcm, uint64_t chunk_size)
|
uint64_t chunk_size)
|
||||||
{
|
{
|
||||||
uint8_t buffer[8192];
|
uint8_t buffer[8192];
|
||||||
const size_t sample_size = sizeof(buffer[0]);
|
const size_t sample_size = sizeof(buffer[0]);
|
||||||
@ -314,18 +315,15 @@ dsdiff_decode_chunk(struct decoder *decoder, struct input_stream *is,
|
|||||||
const unsigned buffer_frames = sizeof(buffer) / frame_size;
|
const unsigned buffer_frames = sizeof(buffer) / frame_size;
|
||||||
const unsigned buffer_samples = buffer_frames * frame_size;
|
const unsigned buffer_samples = buffer_frames * frame_size;
|
||||||
const size_t buffer_size = buffer_samples * sample_size;
|
const size_t buffer_size = buffer_samples * sample_size;
|
||||||
float f_buffer[G_N_ELEMENTS(buffer)];
|
|
||||||
|
|
||||||
while (chunk_size > 0) {
|
while (chunk_size > 0) {
|
||||||
/* see how much aligned data from the remaining chunk
|
/* see how much aligned data from the remaining chunk
|
||||||
fits into the local buffer */
|
fits into the local buffer */
|
||||||
unsigned now_frames = buffer_frames;
|
unsigned now_frames = buffer_frames;
|
||||||
size_t now_size = buffer_size;
|
size_t now_size = buffer_size;
|
||||||
unsigned now_samples = buffer_samples;
|
|
||||||
if (chunk_size < (uint64_t)now_size) {
|
if (chunk_size < (uint64_t)now_size) {
|
||||||
now_frames = (unsigned)chunk_size / frame_size;
|
now_frames = (unsigned)chunk_size / frame_size;
|
||||||
now_size = now_frames * frame_size;
|
now_size = now_frames * frame_size;
|
||||||
now_samples = now_frames * channels;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nbytes = decoder_read(decoder, is, buffer, now_size);
|
size_t nbytes = decoder_read(decoder, is, buffer, now_size);
|
||||||
@ -334,20 +332,8 @@ dsdiff_decode_chunk(struct decoder *decoder, struct input_stream *is,
|
|||||||
|
|
||||||
chunk_size -= nbytes;
|
chunk_size -= nbytes;
|
||||||
|
|
||||||
/* invoke the dsp2pcm library, once for each
|
|
||||||
channel */
|
|
||||||
|
|
||||||
for (unsigned c = 0; c < channels; ++c)
|
|
||||||
dsd2pcm_translate(dsd2pcm[c], now_frames,
|
|
||||||
buffer + c, channels,
|
|
||||||
lsbitfirst, f_buffer + c, channels);
|
|
||||||
|
|
||||||
/* convert to integer and submit to the decoder API */
|
|
||||||
|
|
||||||
enum decoder_command cmd =
|
enum decoder_command cmd =
|
||||||
decoder_data(decoder, is, f_buffer,
|
decoder_data(decoder, is, buffer, nbytes, 0);
|
||||||
now_samples * sizeof(f_buffer[0]),
|
|
||||||
0);
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case DECODE_COMMAND_NONE:
|
case DECODE_COMMAND_NONE:
|
||||||
break;
|
break;
|
||||||
@ -381,25 +367,13 @@ dsdiff_stream_decode(struct decoder *decoder, struct input_stream *is)
|
|||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
struct audio_format audio_format;
|
struct audio_format audio_format;
|
||||||
if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8,
|
if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8,
|
||||||
SAMPLE_FORMAT_FLOAT,
|
dsd_sample_format,
|
||||||
metadata.channels, &error)) {
|
metadata.channels, &error)) {
|
||||||
g_warning("%s", error->message);
|
g_warning("%s", error->message);
|
||||||
g_error_free(error);
|
g_error_free(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize the dsd2pcm library */
|
|
||||||
|
|
||||||
dsd2pcm_ctx *dsd2pcm[MAX_CHANNELS];
|
|
||||||
for (unsigned i = 0; i < metadata.channels; ++i) {
|
|
||||||
dsd2pcm[i] = dsd2pcm_init();
|
|
||||||
if (dsd2pcm[i] == NULL) {
|
|
||||||
for (unsigned j = 0; j < i; ++j)
|
|
||||||
dsd2pcm_destroy(dsd2pcm[j]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* success: file was recognized */
|
/* success: file was recognized */
|
||||||
|
|
||||||
decoder_initialized(decoder, &audio_format, false, -1);
|
decoder_initialized(decoder, &audio_format, false, -1);
|
||||||
@ -413,7 +387,7 @@ dsdiff_stream_decode(struct decoder *decoder, struct input_stream *is)
|
|||||||
if (dsdiff_id_equals(&chunk_header.id, "DSD ")) {
|
if (dsdiff_id_equals(&chunk_header.id, "DSD ")) {
|
||||||
if (!dsdiff_decode_chunk(decoder, is,
|
if (!dsdiff_decode_chunk(decoder, is,
|
||||||
metadata.channels,
|
metadata.channels,
|
||||||
dsd2pcm, chunk_size))
|
chunk_size))
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
/* ignore other chunks */
|
/* ignore other chunks */
|
||||||
@ -428,9 +402,6 @@ dsdiff_stream_decode(struct decoder *decoder, struct input_stream *is)
|
|||||||
if (!dsdiff_read_chunk_header(decoder, is, &chunk_header))
|
if (!dsdiff_read_chunk_header(decoder, is, &chunk_header))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < metadata.channels; ++i)
|
|
||||||
dsd2pcm_destroy(dsd2pcm[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -449,7 +420,7 @@ dsdiff_scan_stream(struct input_stream *is,
|
|||||||
|
|
||||||
struct audio_format audio_format;
|
struct audio_format audio_format;
|
||||||
if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8,
|
if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8,
|
||||||
SAMPLE_FORMAT_S24_P32,
|
dsd_sample_format,
|
||||||
metadata.channels, NULL))
|
metadata.channels, NULL))
|
||||||
/* refuse to parse files which we cannot play anyway */
|
/* refuse to parse files which we cannot play anyway */
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
Reference in New Issue
Block a user