Export.hxx 5.2 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright 2003-2019 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 * 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.
 */

20 21
#ifndef PCM_EXPORT_HXX
#define PCM_EXPORT_HXX
22

23
#include "SampleFormat.hxx"
24
#include "Buffer.hxx"
25
#include "config.h"
26

27
#ifdef ENABLE_DSD
28 29
#include "Dsd16.hxx"
#include "Dsd32.hxx"
30 31 32
#include "Dop.hxx"
#endif

33 34
#include <stdint.h>

35
template<typename T> struct ConstBuffer;
36
struct AudioFormat;
37 38 39 40

/**
 * An object that handles export of PCM samples to some instance
 * outside of MPD.  It has a few more options to tweak the binary
41
 * representation which are not supported by the #PcmConvert library.
42
 */
43
class PcmExport {
44 45 46 47 48 49 50
	/**
	 * This buffer is used to reorder channels.
	 *
	 * @see #alsa_channel_order
	 */
	PcmBuffer order_buffer;

51
#ifdef ENABLE_DSD
52
	/**
53 54 55 56 57 58
	 * @see DsdMode::U16
	 */
	Dsd16Converter dsd16_converter;

	/**
	 * @see DsdMode::U32
59
	 */
60
	Dsd32Converter dsd32_converter;
61

62
	/**
63
	 * @see DsdMode::DOP
64
	 */
65
	DsdToDopConverter dop_converter;
66
#endif
67

68
	/**
69
	 * The buffer is used to pack samples, removing padding.
70
	 *
71
	 * @see #pack24
72
	 */
73
	PcmBuffer pack_buffer;
74

75
	/**
76
	 * The buffer is used to reverse the byte order.
77 78 79
	 *
	 * @see #reverse_endian
	 */
80
	PcmBuffer reverse_buffer;
81

82 83 84 85
	size_t silence_size;

	uint8_t silence_buffer[64]; /* worst-case size */

86 87 88 89 90
	/**
	 * The sample format of input data.
	 */
	SampleFormat src_sample_format;

91 92 93 94 95
	/**
	 * The number of channels.
	 */
	uint8_t channels;

96 97 98 99
	/**
	 * Convert the given buffer from FLAC channel order to ALSA
	 * channel order using ToAlsaChannelOrder()?
	 */
100
	bool alsa_channel_order;
101

102
#ifdef ENABLE_DSD
103 104 105
public:
	enum class DsdMode : uint8_t {
		NONE,
106

107 108 109 110
		/**
		 * Convert DSD (U8) to DSD_U16?
		 */
		U16,
111

112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
		/**
		 * Convert DSD (U8) to DSD_U32?
		 */
		U32,

		/**
		 * Convert DSD to DSD-over-PCM (DoP)?  Input format
		 * must be SampleFormat::DSD and output format must be
		 * SampleFormat::S24_P32.
		 */
		DOP,
	};

private:
	DsdMode dsd_mode;
127
#endif
128

129 130 131 132 133 134
	/**
	 * Convert (padded) 24 bit samples to 32 bit by shifting 8
	 * bits to the left?
	 */
	bool shift8;

135 136 137 138 139
	/**
	 * Pack 24 bit samples?
	 */
	bool pack24;

140
	/**
141 142 143
	 * Export the samples in reverse byte order?  A non-zero value
	 * means the option is enabled and represents the size of each
	 * sample (2 or bigger).
144
	 */
145
	uint8_t reverse_endian;
146

147 148 149 150
public:
	struct Params {
		bool alsa_channel_order = false;
#ifdef ENABLE_DSD
151
		DsdMode dsd_mode = DsdMode::NONE;
152 153 154 155 156 157 158 159 160 161 162 163
#endif
		bool shift8 = false;
		bool pack24 = false;
		bool reverse_endian = false;

		/**
		 * Calculate the output sample rate, given a specific input
		 * sample rate.  Usually, both are the same; however, with
		 * DSD_U32, four input bytes (= 4 * 8 bits) are combined to
		 * one output word (32 bits), dividing the sample rate by 4.
		 */
		gcc_pure
164
		unsigned CalcOutputSampleRate(unsigned input_sample_rate) const noexcept;
165 166 167 168 169

		/**
		 * The inverse of CalcOutputSampleRate().
		 */
		gcc_pure
170
		unsigned CalcInputSampleRate(unsigned output_sample_rate) const noexcept;
171 172
	};

173
	/**
Max Kellermann's avatar
Max Kellermann committed
174
	 * Open the object.
175 176
	 *
	 * There is no "close" method.  This function may be called multiple
177
	 * times to reuse the object.
178 179 180
	 *
	 * This function cannot fail.
	 *
181
	 * @param channels the number of channels; ignored unless dop is set
182
	 */
183
	void Open(SampleFormat sample_format, unsigned channels,
184
		  Params params) noexcept;
185

186 187 188
	/**
	 * Reset the filter's state, e.g. drop/flush buffers.
	 */
189
	void Reset() noexcept;
190

191 192 193 194 195 196 197 198
	/**
	 * Calculate the size of one input frame.
	 */
	gcc_pure
	size_t GetInputFrameSize() const noexcept {
		return channels * sample_format_size(src_sample_format);
	}

199 200 201 202
	/**
	 * Calculate the size of one output frame.
	 */
	gcc_pure
203
	size_t GetOutputFrameSize() const noexcept;
204

205 206 207 208 209 210 211 212 213 214 215 216
	/**
	 * @return the size of one input block in bytes
	 */
	gcc_pure
	size_t GetInputBlockSize() const noexcept;

	/**
	 * @return the size of one output block in bytes
	 */
	gcc_pure
	size_t GetOutputBlockSize() const noexcept;

217 218 219 220 221 222 223 224
	/**
	 * @return one block of silence output; its size is the same
	 * as GetOutputBlockSize(); the pointer is valid as long as
	 * this #PcmExport object exists and until the next Open()
	 * call
	 */
	ConstBuffer<void> GetSilence() const noexcept;

225 226 227 228
	/**
	 * Export a PCM buffer.
	 *
	 * @param src the source PCM buffer
229 230
	 * @return the destination buffer; may be empty (and may be a
	 * pointer to the source buffer)
231
	 */
232
	ConstBuffer<void> Export(ConstBuffer<void> src) noexcept;
233

234
	/**
235
	 * Converts the number of consumed bytes from the Export()
236 237 238 239
	 * destination buffer to the according number of bytes from the
	 * pcm_export() source buffer.
	 */
	gcc_pure
240
	size_t CalcInputSize(size_t dest_size) const noexcept;
241
};
242

243
#endif