DsfDecoderPlugin.cxx 9.84 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright 2003-2021 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
 * 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.
 */

/* \file
 *
 * This plugin decodes DSDIFF data (SACD) embedded in DSF files.
 *
 * The DSF code was created using the specification found here:
 * http://dsd-guide.com/sonys-dsf-file-format-spec
 *
 * All functions common to both DSD decoders have been moved to dsdlib
 */

#include "config.h"
31
#include "DsfDecoderPlugin.hxx"
32
#include "../DecoderAPI.hxx"
Max Kellermann's avatar
Max Kellermann committed
33
#include "input/InputStream.hxx"
34
#include "pcm/CheckAudioFormat.hxx"
35
#include "util/BitReverse.hxx"
36
#include "util/ByteOrder.hxx"
37
#include "DsdLib.hxx"
38
#include "tag/Handler.hxx"
39

40 41
#include <string.h>

42 43
static constexpr unsigned DSF_BLOCK_SIZE = 4096;

44
struct DsfMetaData {
45 46
	unsigned sample_rate, channels;
	bool bitreverse;
47
	offset_type n_blocks;
48
#ifdef ENABLE_ID3TAG
49
	offset_type id3_offset;
50
#endif
51 52
};

53
struct DsfHeader {
54
	/** DSF header id: "DSD " */
55
	DsdId id;
56
	/** DSD chunk size, including id = 28 */
57
	DsdUint64 size;
58
	/** total file size */
59
	DsdUint64 fsize;
60
	/** pointer to id3v2 metadata, should be at the end of the file */
61
	DsdUint64 pmeta;
62
};
63

64
/** DSF file fmt chunk */
65
struct DsfFmtChunk {
66
	/** id: "fmt " */
67
	DsdId id;
68
	/** fmt chunk size, including id, normally 52 */
69
	DsdUint64 size;
70 71 72 73 74 75 76 77 78 79 80 81 82
	/** version of this format = 1 */
	uint32_t version;
	/** 0: DSD raw */
	uint32_t formatid;
	/** channel type, 1 = mono, 2 = stereo, 3 = 3 channels, etc */
	uint32_t channeltype;
	/** Channel number, 1 = mono, 2 = stereo, ... 6 = 6 channels */
	uint32_t channelnum;
	/** sample frequency: 2822400, 5644800 */
	uint32_t sample_freq;
	/** bits per sample 1 or 8 */
	uint32_t bitssample;
	/** Sample count per channel in bytes */
83
	DsdUint64 scnt;
84 85 86 87 88 89
	/** block size per channel = 4096 */
	uint32_t block_size;
	/** reserved, should be all zero */
	uint32_t reserved;
};

90
struct DsfDataChunk {
91
	DsdId id;
92
	/** "data" chunk size, includes header (id+size) */
93
	DsdUint64 size;
94 95 96 97 98 99
};

/**
 * Read and parse all needed metadata chunks for DSF files.
 */
static bool
100
dsf_read_metadata(DecoderClient *client, InputStream &is,
101
		  DsfMetaData *metadata)
102
{
103
	DsfHeader dsf_header;
104
	if (!decoder_read_full(client, is, &dsf_header, sizeof(dsf_header)) ||
105
	    !dsf_header.id.Equals("DSD "))
106 107
		return false;

108
	const offset_type chunk_size = dsf_header.size.Read();
109 110 111
	if (sizeof(dsf_header) != chunk_size)
		return false;

112
#ifdef ENABLE_ID3TAG
113
	const offset_type metadata_offset = dsf_header.pmeta.Read();
114 115
#endif

116
	/* read the 'fmt ' chunk of the DSF file */
117
	DsfFmtChunk dsf_fmt_chunk;
118
	if (!decoder_read_full(client, is,
119
			       &dsf_fmt_chunk, sizeof(dsf_fmt_chunk)) ||
120
	    !dsf_fmt_chunk.id.Equals("fmt "))
121 122
		return false;

123
	const uint64_t fmt_chunk_size = dsf_fmt_chunk.size.Read();
124 125 126
	if (fmt_chunk_size != sizeof(dsf_fmt_chunk))
		return false;

127
	uint32_t samplefreq = FromLE32(dsf_fmt_chunk.sample_freq);
128
	const unsigned channels = FromLE32(dsf_fmt_chunk.channelnum);
129 130

	/* for now, only support version 1 of the standard, DSD raw stereo
131
	   files with a sample freq of 2822400 or 5644800 Hz */
132

133 134
	if (FromLE32(dsf_fmt_chunk.version) != 1 ||
	    FromLE32(dsf_fmt_chunk.formatid) != 0 ||
135
	    !audio_valid_channel_count(channels) ||
136
	    !dsdlib_valid_freq(samplefreq))
137 138
		return false;

139
	uint32_t chblksize = FromLE32(dsf_fmt_chunk.block_size);
140
	/* according to the spec block size should always be 4096 */
141
	if (chblksize != DSF_BLOCK_SIZE)
142 143 144
		return false;

	/* read the 'data' chunk of the DSF file */
145
	DsfDataChunk data_chunk;
146
	if (!decoder_read_full(client, is, &data_chunk, sizeof(data_chunk)) ||
147
	    !data_chunk.id.Equals("data"))
148 149 150 151 152
		return false;

	/* data size of DSF files are padded to multiple of 4096,
	   we use the actual data size as chunk size */

153
	offset_type data_size = data_chunk.size.Read();
154 155 156
	if (data_size < sizeof(data_chunk))
		return false;

157 158
	data_size -= sizeof(data_chunk);

159
	/* data_size cannot be bigger or equal to total file size */
160 161
	if (is.KnownSize() && data_size > is.GetRest())
		return false;
162

163 164 165 166
	/* use the sample count from the DSF header as the upper
	   bound, because some DSF files contain junk at the end of
	   the "data" chunk */
	const uint64_t samplecnt = dsf_fmt_chunk.scnt.Read();
167
	const offset_type playable_size = samplecnt * channels / 8;
168 169 170
	if (data_size > playable_size)
		data_size = playable_size;

171 172
	const size_t block_size = channels * DSF_BLOCK_SIZE;
	metadata->n_blocks = data_size / block_size;
173
	metadata->channels = channels;
174
	metadata->sample_rate = samplefreq;
175
#ifdef ENABLE_ID3TAG
176
	metadata->id3_offset = metadata_offset;
177
#endif
178
	/* check bits per sample format, determine if bitreverse is needed */
179
	metadata->bitreverse = FromLE32(dsf_fmt_chunk.bitssample) == 1;
180 181 182 183 184 185 186 187 188 189
	return true;
}

static void
bit_reverse_buffer(uint8_t *p, uint8_t *end)
{
	for (; p < end; ++p)
		*p = bit_reverse(*p);
}

190 191 192 193 194 195 196
static void
InterleaveDsfBlockMono(uint8_t *gcc_restrict dest,
		       const uint8_t *gcc_restrict src)
{
	memcpy(dest, src, DSF_BLOCK_SIZE);
}

197 198 199 200 201 202 203
/**
 * 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
 * block of 4096 DSD right samples to 8k of samples in normal PCM left/right
 * order.
 */
static void
204 205
InterleaveDsfBlockStereo(uint8_t *gcc_restrict dest,
			 const uint8_t *gcc_restrict src)
206
{
207 208 209
	for (size_t i = 0; i < DSF_BLOCK_SIZE; ++i) {
		dest[2 * i] = src[i];
		dest[2 * i + 1] = src[DSF_BLOCK_SIZE + i];
210 211 212
	}
}

213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
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);
}

243
static offset_type
244
FrameToBlock(uint64_t frame)
245
{
246
	return frame / DSF_BLOCK_SIZE;
247 248
}

249 250 251 252
/**
 * Decode one complete DSF 'data' chunk i.e. a complete song
 */
static bool
253
dsf_decode_chunk(DecoderClient &client, InputStream &is,
254
		 unsigned channels, unsigned sample_rate,
255
		 offset_type n_blocks,
Max Kellermann's avatar
Max Kellermann committed
256
		 bool bitreverse)
257
{
258
	const unsigned kbit_rate = channels * sample_rate / 1000;
259
	const size_t block_size = channels * DSF_BLOCK_SIZE;
260
	const offset_type start_offset = is.GetOffset();
261

262
	auto cmd = client.GetCommand();
263
	for (offset_type i = 0; i < n_blocks && cmd != DecoderCommand::STOP;) {
264
		if (cmd == DecoderCommand::SEEK) {
265
			uint64_t frame = client.GetSeekFrame();
266
			offset_type block = FrameToBlock(frame);
267
			if (block >= n_blocks) {
268
				client.CommandFinished();
269 270 271 272 273
				break;
			}

			offset_type offset =
				start_offset + block * block_size;
274
			if (dsdlib_skip_to(&client, is, offset)) {
275
				client.CommandFinished();
276 277
				i = block;
			} else
278
				client.SeekError();
279 280
		}

281 282
		/* worst-case buffer size */
		uint8_t buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
283
		if (!decoder_read_full(&client, is, buffer, block_size))
284 285 286
			return false;

		if (bitreverse)
287
			bit_reverse_buffer(buffer, buffer + block_size);
288

289 290
		uint8_t interleaved_buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
		InterleaveDsfBlock(interleaved_buffer, buffer, channels);
291

292 293
		cmd = client.SubmitData(is,
					interleaved_buffer, block_size,
294
					kbit_rate);
295
		++i;
296
	}
297

298
	return true;
299 300 301
}

static void
302
dsf_stream_decode(DecoderClient &client, InputStream &is)
303 304
{
	/* check if it is a proper DSF file */
305
	DsfMetaData metadata;
306
	if (!dsf_read_metadata(&client, is, &metadata))
307 308
		return;

309 310 311 312
	auto audio_format = CheckAudioFormat(metadata.sample_rate / 8,
					     SampleFormat::DSD,
					     metadata.channels);

313
	/* Calculate song time from DSD chunk size and sample frequency */
314
	const auto n_blocks = metadata.n_blocks;
315 316
	auto songtime = SongTime::FromScale<uint64_t>(n_blocks * DSF_BLOCK_SIZE,
						      audio_format.sample_rate);
317 318

	/* success: file was recognized */
319
	client.Ready(audio_format, is.IsSeekable(), songtime);
320

321
	dsf_decode_chunk(client, is, metadata.channels,
322 323 324
			 metadata.sample_rate,
			 n_blocks,
			 metadata.bitreverse);
325 326 327
}

static bool
328
dsf_scan_stream(InputStream &is, TagHandler &handler)
329 330
{
	/* check DSF metadata */
331
	DsfMetaData metadata;
332
	if (!dsf_read_metadata(nullptr, is, &metadata))
333 334
		return false;

335 336 337
	const auto sample_rate = metadata.sample_rate / 8;
	if (!audio_valid_sample_rate(sample_rate))
		return false;
338

339
	/* calculate song time and add as tag */
340 341
	const auto n_blocks = metadata.n_blocks;
	auto songtime = SongTime::FromScale<uint64_t>(n_blocks * DSF_BLOCK_SIZE,
342
						      sample_rate);
343
	handler.OnDuration(songtime);
344

345
#ifdef ENABLE_ID3TAG
346
	/* Add available tags from the ID3 tag */
347
	dsdlib_tag_id3(is, handler, metadata.id3_offset);
348
#endif
349 350 351 352 353
	return true;
}

static const char *const dsf_suffixes[] = {
	"dsf",
354
	nullptr
355 356 357 358
};

static const char *const dsf_mime_types[] = {
	"application/x-dsf",
359 360
	"audio/x-dsf",
	"audio/x-dsd",
361
	nullptr
362 363
};

364 365 366 367
constexpr DecoderPlugin dsf_decoder_plugin =
	DecoderPlugin("dsf", dsf_stream_decode, dsf_scan_stream)
	.WithSuffixes(dsf_suffixes)
	.WithMimeTypes(dsf_mime_types);