decoder/dsf: fix multi-channel files
The plugin was horribly bugged for files that were not stereo.
This commit is contained in:
parent
d8782ce5fd
commit
02cc77cd82
1
NEWS
1
NEWS
|
@ -43,6 +43,7 @@ ver 0.19 (not yet released)
|
|||
- audiofile: log libaudiofile errors
|
||||
- dsdiff, dsf: report bit rate
|
||||
- dsf: support DSD512
|
||||
- dsf: support multi-channel files
|
||||
- dsf: fix noise at end of malformed file
|
||||
- sndfile: support scanning remote files
|
||||
- sndfile: support tags "comment", "album", "track", "genre"
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
#include "tag/TagHandler.hxx"
|
||||
#include "Log.hxx"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static constexpr unsigned DSF_BLOCK_SIZE = 4096;
|
||||
|
||||
struct DsfMetaData {
|
||||
|
@ -188,6 +190,13 @@ bit_reverse_buffer(uint8_t *p, uint8_t *end)
|
|||
*p = bit_reverse(*p);
|
||||
}
|
||||
|
||||
static void
|
||||
InterleaveDsfBlockMono(uint8_t *gcc_restrict dest,
|
||||
const uint8_t *gcc_restrict src)
|
||||
{
|
||||
memcpy(dest, src, DSF_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* DSF data is build up of alternating 4096 blocks of DSD samples for left and
|
||||
* right. Convert the buffer holding 1 block of 4096 DSD left samples and 1
|
||||
|
@ -195,7 +204,8 @@ bit_reverse_buffer(uint8_t *p, uint8_t *end)
|
|||
* order.
|
||||
*/
|
||||
static void
|
||||
dsf_to_pcm_order(uint8_t *gcc_restrict dest, const uint8_t *gcc_restrict src)
|
||||
InterleaveDsfBlockStereo(uint8_t *gcc_restrict dest,
|
||||
const uint8_t *gcc_restrict src)
|
||||
{
|
||||
for (size_t i = 0; i < DSF_BLOCK_SIZE; ++i) {
|
||||
dest[2 * i] = src[i];
|
||||
|
@ -203,6 +213,36 @@ dsf_to_pcm_order(uint8_t *gcc_restrict dest, const uint8_t *gcc_restrict src)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
InterleaveDsfBlockChannel(uint8_t *gcc_restrict dest,
|
||||
const uint8_t *gcc_restrict src,
|
||||
unsigned channels)
|
||||
{
|
||||
for (size_t i = 0; i < DSF_BLOCK_SIZE; ++i, dest += channels, ++src)
|
||||
*dest = *src;
|
||||
}
|
||||
|
||||
static void
|
||||
InterleaveDsfBlockGeneric(uint8_t *gcc_restrict dest,
|
||||
const uint8_t *gcc_restrict src,
|
||||
unsigned channels)
|
||||
{
|
||||
for (unsigned c = 0; c < channels; ++c, ++dest, src += DSF_BLOCK_SIZE)
|
||||
InterleaveDsfBlockChannel(dest, src, channels);
|
||||
}
|
||||
|
||||
static void
|
||||
InterleaveDsfBlock(uint8_t *gcc_restrict dest, const uint8_t *gcc_restrict src,
|
||||
unsigned channels)
|
||||
{
|
||||
if (channels == 1)
|
||||
InterleaveDsfBlockMono(dest, src);
|
||||
else if (channels == 2)
|
||||
InterleaveDsfBlockStereo(dest, src);
|
||||
else
|
||||
InterleaveDsfBlockGeneric(dest, src, channels);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode one complete DSF 'data' chunk i.e. a complete song
|
||||
*/
|
||||
|
@ -212,14 +252,10 @@ dsf_decode_chunk(Decoder &decoder, InputStream &is,
|
|||
offset_type chunk_size,
|
||||
bool bitreverse)
|
||||
{
|
||||
uint8_t buffer[DSF_BLOCK_SIZE * 2];
|
||||
/* worst-case buffer size */
|
||||
uint8_t buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
|
||||
|
||||
const size_t sample_size = sizeof(buffer[0]);
|
||||
const size_t frame_size = channels * sample_size;
|
||||
const unsigned buffer_frames = sizeof(buffer) / frame_size;
|
||||
const unsigned buffer_samples = buffer_frames * frame_size;
|
||||
const size_t buffer_size = buffer_samples * sample_size;
|
||||
const size_t block_size = buffer_size;
|
||||
const size_t block_size = channels * DSF_BLOCK_SIZE;
|
||||
|
||||
while (chunk_size >= block_size) {
|
||||
chunk_size -= block_size;
|
||||
|
@ -230,8 +266,8 @@ dsf_decode_chunk(Decoder &decoder, InputStream &is,
|
|||
if (bitreverse)
|
||||
bit_reverse_buffer(buffer, buffer + block_size);
|
||||
|
||||
uint8_t interleaved_buffer[DSF_BLOCK_SIZE * 2];
|
||||
dsf_to_pcm_order(interleaved_buffer, buffer);
|
||||
uint8_t interleaved_buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
|
||||
InterleaveDsfBlock(interleaved_buffer, buffer, channels);
|
||||
|
||||
const auto cmd = decoder_data(decoder, is,
|
||||
interleaved_buffer, block_size,
|
||||
|
|
Loading…
Reference in New Issue