arduino-audio-tools
Loading...
Searching...
No Matches
CodecDSF.h
Go to the documentation of this file.
19#pragma once
20#pragma GCC optimize("O3")
21
25
26namespace audio_tools {
27
32struct DSFMetadata : public AudioInfo {
33 DSFMetadata() = default;
34 DSFMetadata(int rate) { sample_rate = rate; }
36 uint32_t dsd_sample_rate = 0;
38 uint64_t dsd_data_bytes = 0;
40 uint64_t pcm_frames = 0;
42 float duration_sec = 0;
44 uint32_t block_size_per_channel = 4096;
46 float filter_cutoff = 0.45f;
50 int output_buffer_size = 2 * 1024;
52 bool is_raw = false;
53};
54
56struct __attribute__((packed)) DSDPrefix {
57 char id[4]; // "DSD "
58 uint64_t chunkSize; // 28
59 uint64_t fileSize; // total file size
60 uint64_t metadataOffset; // offset to "ID3 " chunk (0 if none)
61};
62
64struct __attribute__((packed)) DSFFormat {
65 char id[4]; // "fmt "
66 uint64_t chunkSize; // 52
67 uint32_t formatVersion; // 1
68 uint32_t formatID; // 0
69 uint32_t channelType; // e.g., 2 for stereo
70 uint32_t channelNum; // number of channels
71 uint32_t samplingFrequency; // e.g., 2822400
72 uint32_t bitsPerSample; // 1
73 uint64_t sampleCount; // total samples per channel
74 uint32_t blockSizePerChannel; // e.g., 4096
75 uint32_t reserved; // 0
76};
77
79struct __attribute__((packed)) DSFDataHeader {
80 char id[4]; // "data"
81 uint64_t chunkSize; // size of DSD data
82};
83
93class DSFDecoder : public AudioDecoder {
94 public:
95 DSFDecoder() = default;
96 DSFDecoder(DSFMetadata metaData) { setMetaData(metaData); };
97
98 const char* mime() override { return "audio/dsf"; }
99
100 AudioInfo audioInfo() override { return meta; }
101
102 void setAudioInfo(AudioInfo from) override {
103 TRACED();
105 meta.copyFrom(from);
106 if (isHeaderAvailable()) {
107 int buffer_size = getOutputBufferSize();
108 pcmBuffer.resize(buffer_size);
109
110 int perChBufSize = meta.block_size_per_channel * 2;
112 for (int ch = 0; ch < meta.channels; ch++) {
113 channelDsdBuffers[ch].resize(perChBufSize);
114 }
115
116 setupFilters();
118 }
119 }
120
121 bool begin() {
122 TRACED();
123 headerParsed = false;
124 blockPos = 0;
125 decimationStep = 64;
126 isActive = true;
127 return true;
128 }
129
130 void end() override { isActive = false; }
131
132 const DSFMetadata getMetadata() { return meta; }
133
134 void setMetaData(DSFMetadata metaData) {
135 meta = metaData;
137 }
138
140 void setInfoCallback(void (*callback)(const DSFFormat& fmt)) {
141 infoCallback = callback;
142 }
143
145
146 operator bool() { return isActive; }
147
148 size_t write(const uint8_t* data, size_t len) {
149 LOGD("write: %u", (unsigned)len);
150 size_t i = 0;
151
152 i += processHeader(data, len);
153
154 if (headerParsed && i < len) {
155 i += processDSDData(data, len, i);
156 }
157
158 return len;
159 }
160
161 protected:
162 bool headerParsed = false;
163 bool isActive = false;
164 uint32_t blockPos = 0;
165 void (*infoCallback)(const DSFFormat& fmt) = nullptr;
166
171
173
175 int frame_size = meta.bits_per_sample / 8 * meta.channels;
176 if (meta.bits_per_sample == 24) frame_size = 4 * meta.channels;
177 int buffer_size = frame_size;
178 if (meta.output_buffer_size > buffer_size)
179 buffer_size = meta.output_buffer_size;
180 return buffer_size;
181 }
182
183 size_t processHeader(const uint8_t* data, size_t len) {
184 if (headerParsed) return 0;
185 LOGI("processHeader: %u", (unsigned)len);
186
187 if (memcmp(data, "DSD ", 4) != 0) {
188 LOGE("Invalid DSF header magic");
189 return 0;
190 }
191
192 int dataPos = findTag("data", data, len);
193 int fmtPos = findTag("fmt ", data, len);
194 if (dataPos < 0 || fmtPos < 0) {
195 LOGE("DSF header not found in data (fmt: %d, data: %d)", fmtPos, dataPos);
196 return 0;
197 }
198
199 parseFMT(data + fmtPos, len - fmtPos);
200 parseData(data + dataPos, len - dataPos);
201 headerParsed = true;
202
203 if (infoCallback) {
204 infoCallback(*reinterpret_cast<const DSFFormat*>(data + fmtPos));
205 }
206
207 if (!meta.is_raw) {
209 }
210
211 return dataPos + sizeof(DSFDataHeader);
212 }
213
214 size_t processDSDData(const uint8_t* data, size_t len, size_t startPos) {
215 LOGD("processDSDData: %u (%u)", (unsigned)len, (unsigned)startPos);
216
217 if (meta.is_raw) {
218 size_t rawLen = len - startPos;
219 writeBlocking(getOutput(),(uint8_t*) data + startPos, rawLen);
220 return rawLen;
221 }
222
223 size_t totalProcessed = 0;
224 size_t pos = startPos;
225
226 while (pos < len) {
227 size_t buffered = bufferDSDData(data, len, pos);
228 if (buffered == 0) break;
229 pos += buffered;
230 totalProcessed += buffered;
232 }
233
234 return totalProcessed;
235 }
236
237 size_t bufferDSDData(const uint8_t* data, size_t len, size_t startPos) {
238 size_t consumed = 0;
239 uint32_t blockSetSize = meta.block_size_per_channel * meta.channels;
240
241 for (size_t i = startPos; i < len; i++) {
243 if (ch >= meta.channels) {
244 blockPos = 0;
245 ch = 0;
246 }
247 if (channelDsdBuffers[ch].availableForWrite() <= 0) break;
248 channelDsdBuffers[ch].write(data[i]);
249 consumed++;
250 blockPos++;
251 if (blockPos >= blockSetSize) blockPos = 0;
252 }
253 return consumed;
254 }
255
257 int bytesPerDecimation = decimationStep / 8;
258 int stages = getFilterStages();
259
260 while (allChannelsHaveData(bytesPerDecimation)) {
261 for (int ch = 0; ch < meta.channels; ch++) {
262 int ones = 0;
263 for (int b = 0; b < bytesPerDecimation; b++) {
264 uint8_t dsdByte;
265 channelDsdBuffers[ch].read(dsdByte);
266 ones += popcount8(dsdByte);
267 }
268
269 float pcm = 2.0f * ones / decimationStep - 1.0f;
270
271 for (int s = 0; s < stages; s++) {
272 pcm = channelFilters[ch * stages + s].process(pcm);
273 }
274
275 writePCMSample(clip(pcm));
276 }
277
278 if (pcmBuffer.isFull()) {
279 size_t frameSize = pcmBuffer.available();
280 writeBlocking(getOutput(), (uint8_t*)pcmBuffer.data(), frameSize);
282 }
283 }
284
285 // Flush remaining PCM samples
286 if (pcmBuffer.available() > 0) {
287 writeBlocking(getOutput(), (uint8_t*)pcmBuffer.data(),
290 }
291
292 // Compact linear buffers so write space is reclaimed
293 for (int ch = 0; ch < meta.channels; ch++) {
294 channelDsdBuffers[ch].trim();
295 }
296 }
297
298 bool allChannelsHaveData(int bytesNeeded) {
299 for (int ch = 0; ch < meta.channels; ch++) {
300 if (channelDsdBuffers[ch].available() < bytesNeeded) return false;
301 }
302 return true;
303 }
304
305 int popcount8(uint8_t v) {
306 v = (v & 0x55) + ((v >> 1) & 0x55);
307 v = (v & 0x33) + ((v >> 2) & 0x33);
308 return (v & 0x0F) + ((v >> 4) & 0x0F);
309 }
310
311 float clip(float value) {
312 if (value > 1.0f) return 1.0f;
313 if (value < -1.0f) return -1.0f;
314 return value;
315 }
316
318 int stages = meta.filter_stages;
319 if (stages < 0) stages = 0;
320 if (stages > 3) stages = 3;
321 return stages;
322 }
323
325 TRACEI();
326 int stages = getFilterStages();
327 if (stages == 0 || meta.sample_rate <= 0 || meta.channels <= 0) return;
328
329 float cutoffFreq = meta.sample_rate * meta.filter_cutoff;
330 channelFilters.resize(meta.channels * stages);
331
332 // Butterworth Q values for maximally-flat passband
333 static const float butterworthQ[][3] = {
334 {0.7071f, 0, 0},
335 {0.5412f, 1.3066f, 0},
336 {0.5176f, 0.7071f, 1.9319f},
337 };
338
339 for (int ch = 0; ch < meta.channels; ch++) {
340 for (int s = 0; s < stages; s++) {
341 float q = butterworthQ[stages - 1][s];
342 channelFilters[ch * stages + s].begin(cutoffFreq, meta.sample_rate, q);
343 }
344 }
345 }
346
348 TRACEI();
349 if (meta.sample_rate == 0 || meta.dsd_sample_rate == 0) {
350 LOGE("Invalid sample rates: DSD=%u, PCM=%u",
351 (unsigned)meta.dsd_sample_rate, (unsigned)meta.sample_rate);
352 return;
353 }
354
356 if (decimationStep < 64) {
357 LOGW("Decimation step %u too low, setting to 64",
358 (unsigned)decimationStep);
359 decimationStep = 64;
360 }
361 if (decimationStep > 512) {
362 LOGW("Decimation step %u too high, setting to 512",
363 (unsigned)decimationStep);
364 decimationStep = 512;
365 }
366
367 decimationStep = (decimationStep / 8) * 8;
368 if (decimationStep < 64) decimationStep = 64;
369
370 LOGI("Decimation step set to %u for DSD rate %u and target PCM rate %u",
371 (unsigned)decimationStep, (unsigned)meta.dsd_sample_rate,
372 (unsigned)meta.sample_rate);
373 }
374
375 void writePCMSample(float filteredValue) {
376 switch (meta.bits_per_sample) {
377 case 8: {
378 int8_t buffer8 = static_cast<int8_t>(filteredValue * 127.0f);
379 pcmBuffer.write(buffer8);
380 break;
381 }
382 case 16: {
383 int16_t buffer16 = static_cast<int16_t>(filteredValue * 32767.0f);
384 pcmBuffer.writeArray((uint8_t*)&buffer16, sizeof(int16_t));
385 break;
386 }
387 case 24: {
388 int24_t buffer24 = static_cast<int24_t>(filteredValue * 8388607.0f);
389 pcmBuffer.writeArray((uint8_t*)&buffer24, sizeof(int24_t));
390 break;
391 }
392 case 32: {
393 int32_t buffer32 = static_cast<int32_t>(filteredValue * 2147483647.0f);
394 pcmBuffer.writeArray((uint8_t*)&buffer32, sizeof(int32_t));
395 break;
396 }
397 default:
398 LOGE("Unsupported bits per sample: %d", meta.bits_per_sample);
399 break;
400 }
401 }
402
403 int findTag(const char* tag, const uint8_t* data, size_t len) {
404 int taglen = strlen(tag);
405 for (size_t j = 0; j + taglen <= len; j++) {
406 if (memcmp(tag, data + j, taglen) == 0) {
407 return j;
408 }
409 }
410 return -1;
411 }
412
413 bool parseFMT(const uint8_t* data, size_t len) {
414 TRACEI();
415 if (len < sizeof(DSFFormat)) {
416 LOGE("FMT section too short to parse DSF format header");
417 return false;
418 }
419 DSFFormat* fmt = (DSFFormat*)data;
420 meta.channels = fmt->channelNum;
421 if (meta.channels == 0) meta.channels = fmt->channelType;
422 meta.dsd_sample_rate = fmt->samplingFrequency;
423 meta.block_size_per_channel = fmt->blockSizePerChannel;
425
426 if (meta.channels == 0 || meta.channels > 8) {
427 LOGE("Invalid channel count: %u (must be 1-8)", (unsigned)meta.channels);
428 return false;
429 }
430
431 LOGI("channels: %u, DSD sample rate: %u, block size: %u",
432 (unsigned)meta.channels, (unsigned)meta.dsd_sample_rate,
433 (unsigned)meta.block_size_per_channel);
434 return true;
435 }
436
437 bool parseData(const uint8_t* data, size_t len) {
438 TRACEI();
439 if (len < sizeof(DSFDataHeader)) {
440 LOGE("Data section too short to parse DSF data header");
441 return false;
442 }
443 DSFDataHeader* header = (DSFDataHeader*)data;
444 meta.dsd_data_bytes = header->chunkSize;
445
446 uint64_t totalBits = meta.dsd_data_bytes * 8;
447 uint64_t totalDSDSamples = totalBits / meta.channels;
448 uint64_t totalPCMFrames =
449 totalDSDSamples / (meta.dsd_sample_rate / meta.sample_rate);
450 meta.pcm_frames = totalPCMFrames;
451 meta.duration_sec = (float)totalPCMFrames / meta.sample_rate;
452 return true;
453 }
454};
455
465class DSFEncoder : public AudioEncoder {
466 public:
467 DSFEncoder() = default;
468 DSFEncoder(DSFMetadata metaData) { setMetaData(metaData); }
469
470 const char* mime() override { return "audio/dsf"; }
471
472 void setOutput(Print& out) override { p_print = &out; }
473
474 void setAudioInfo(AudioInfo from) override {
476 meta.copyFrom(from);
477 }
478
479 void setMetaData(DSFMetadata metaData) {
480 meta = metaData;
482 }
483
484 const DSFMetadata getMetadata() { return meta; }
485
486 bool begin() override {
487 TRACED();
489
492
494 for (int ch = 0; ch < meta.channels; ch++) {
496 }
497
498 chState.resize(meta.channels);
499 for (int ch = 0; ch < meta.channels; ch++) {
500 chState[ch] = ChannelModState();
501 }
502
503 totalDsdBytes = 0;
504 headerWritten = false;
505 isOpen = true;
506 return true;
507 }
508
509 void end() override {
510 if (!isOpen) return;
512 isOpen = false;
513 }
514
515 size_t write(const uint8_t* data, size_t len) override {
516 if (!isOpen || p_print == nullptr) return 0;
517
518 if (!headerWritten) {
520 headerWritten = true;
521 }
522
523 int bytesPerSample = meta.bits_per_sample / 8;
524 if (meta.bits_per_sample == 24) bytesPerSample = 4;
525 int frameSize = bytesPerSample * meta.channels;
526 if (frameSize == 0) return 0;
527
528 size_t pos = 0;
529 while (pos + frameSize <= len) {
530 for (int ch = 0; ch < meta.channels; ch++) {
531 float sample = readPCMSample(data + pos + ch * bytesPerSample);
532 convertSampleToDSD(ch, sample);
533 }
534 pos += frameSize;
535
536 if (allBlocksFull()) {
538 }
539 }
540
541 return pos;
542 }
543
544 operator bool() override { return isOpen; }
545
546 protected:
548 float dsError1 = 0;
549 float dsError2 = 0;
550 float prevSample = 0;
551 uint8_t currentByte = 0;
552 int bitPos = 0;
553 };
554
556 Print* p_print = nullptr;
559 uint32_t oversamplingRatio = 64;
560 uint64_t totalDsdBytes = 0;
561 bool headerWritten = false;
562 bool isOpen = false;
563
564 float readPCMSample(const uint8_t* ptr) {
565 switch (meta.bits_per_sample) {
566 case 8:
567 return *reinterpret_cast<const int8_t*>(ptr) / 127.0f;
568 case 16: {
569 int16_t v;
570 memcpy(&v, ptr, sizeof(int16_t));
571 return v / 32767.0f;
572 }
573 case 24: {
574 int24_t v;
575 memcpy(&v, ptr, sizeof(int24_t));
576 return static_cast<float>(static_cast<int32_t>(v)) / 8388607.0f;
577 }
578 case 32: {
579 int32_t v;
580 memcpy(&v, ptr, sizeof(int32_t));
581 return v / 2147483647.0f;
582 }
583 default:
584 return 0.0f;
585 }
586 }
587
588 void convertSampleToDSD(int ch, float currentSample) {
589 float prevSample = chState[ch].prevSample;
590
591 for (uint32_t i = 0; i < oversamplingRatio; i++) {
592 // Linear interpolation between previous and current PCM sample
593 float t = (float)i / oversamplingRatio;
594 float input = prevSample + t * (currentSample - prevSample);
595 input *= 0.5f;
596
597 // 2nd order error-feedback delta-sigma: NTF = (1 - z^-1)^2
598 float shaped = input + 2.0f * chState[ch].dsError1 - chState[ch].dsError2;
599 int bit = (shaped >= 0.0f) ? 1 : 0;
600 float feedback = bit ? 1.0f : -1.0f;
601 float quantError = shaped - feedback;
602
603 if (quantError > 4.0f) quantError = 4.0f;
604 if (quantError < -4.0f) quantError = -4.0f;
605
606 chState[ch].dsError2 = chState[ch].dsError1;
607 chState[ch].dsError1 = quantError;
608
609 // LSB first for DSF format
610 if (bit) {
611 chState[ch].currentByte |= (1 << chState[ch].bitPos);
612 }
613 chState[ch].bitPos++;
614
615 if (chState[ch].bitPos >= 8) {
616 channelBlocks[ch].write(chState[ch].currentByte);
617 chState[ch].currentByte = 0;
618 chState[ch].bitPos = 0;
619 }
620 }
621
622 chState[ch].prevSample = currentSample;
623 }
624
626 for (int ch = 0; ch < meta.channels; ch++) {
627 if (!channelBlocks[ch].isFull()) return false;
628 }
629 return true;
630 }
631
633 for (int ch = 0; ch < meta.channels; ch++) {
634 writeBlocking(p_print, (uint8_t*)channelBlocks[ch].data(),
635 channelBlocks[ch].available());
636 totalDsdBytes += channelBlocks[ch].available();
637 channelBlocks[ch].reset();
638 }
639 }
640
642 bool hasData = false;
643 for (int ch = 0; ch < meta.channels; ch++) {
644 if (channelBlocks[ch].available() > 0 || chState[ch].bitPos > 0) {
645 hasData = true;
646 break;
647 }
648 }
649 if (!hasData) return;
650
651 for (int ch = 0; ch < meta.channels; ch++) {
652 if (chState[ch].bitPos > 0) {
653 channelBlocks[ch].write(chState[ch].currentByte);
654 chState[ch].currentByte = 0;
655 chState[ch].bitPos = 0;
656 }
657 }
658
659 // Pad to full block size with DSD silence (alternating bit pattern)
660 for (int ch = 0; ch < meta.channels; ch++) {
661 while (!channelBlocks[ch].isFull()) {
662 channelBlocks[ch].write(0x69);
663 }
664 }
666 }
667
669 uint64_t dsdDataBytes = meta.dsd_data_bytes;
670 bool streaming = (dsdDataBytes == 0);
671 uint64_t headerTotal =
672 sizeof(DSDPrefix) + sizeof(DSFFormat) + sizeof(DSFDataHeader);
673
674 DSDPrefix prefix;
675 memcpy(prefix.id, "DSD ", 4);
676 prefix.chunkSize = sizeof(DSDPrefix);
677 prefix.fileSize = streaming ? 0 : (headerTotal + dsdDataBytes);
678 prefix.metadataOffset = 0;
679
680 DSFFormat fmt;
681 memcpy(fmt.id, "fmt ", 4);
682 fmt.chunkSize = sizeof(DSFFormat);
683 fmt.formatVersion = 1;
684 fmt.formatID = 0;
685 fmt.channelType = meta.channels;
686 fmt.channelNum = meta.channels;
687 fmt.samplingFrequency = meta.dsd_sample_rate;
688 fmt.bitsPerSample = 1;
689 fmt.sampleCount = streaming ? 0 : (dsdDataBytes * 8 / meta.channels);
690 fmt.blockSizePerChannel = meta.block_size_per_channel;
691 fmt.reserved = 0;
692
693 DSFDataHeader dataHdr;
694 memcpy(dataHdr.id, "data", 4);
695 dataHdr.chunkSize = streaming ? 0 : (sizeof(DSFDataHeader) + dsdDataBytes);
696
697 p_print->write((uint8_t*)&prefix, sizeof(prefix));
698 p_print->write((uint8_t*)&fmt, sizeof(fmt));
699 p_print->write((uint8_t*)&dataHdr, sizeof(dataHdr));
700 }
701};
702
703} // namespace audio_tools
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
Definition Arduino.h:56
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:19
Print * getOutput()
Definition AudioCodecsBase.h:68
void setAudioInfo(AudioInfo from) override
for most decoders this is not needed
Definition AudioCodecsBase.h:32
Encoding of PCM data.
Definition AudioCodecsBase.h:101
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition AudioCodecsBase.h:110
void writeBlocking(Print *out, uint8_t *data, size_t len)
Definition AudioTypes.h:220
Decodes DSF files containing DSD audio and converts to PCM.
Definition CodecDSF.h:93
uint32_t blockPos
Definition CodecDSF.h:164
bool isHeaderAvailable()
Definition CodecDSF.h:144
void setMetaData(DSFMetadata metaData)
Definition CodecDSF.h:134
bool headerParsed
Definition CodecDSF.h:162
void(* infoCallback)(const DSFFormat &fmt)
Definition CodecDSF.h:165
int getFilterStages()
Definition CodecDSF.h:317
DSFMetadata meta
Definition CodecDSF.h:172
void convertDSDToPCM()
Definition CodecDSF.h:256
int getOutputBufferSize()
Definition CodecDSF.h:174
void setAudioInfo(AudioInfo from) override
for most decoders this is not needed
Definition CodecDSF.h:102
Vector< SingleBuffer< uint8_t > > channelDsdBuffers
Definition CodecDSF.h:168
bool begin()
Definition CodecDSF.h:121
size_t processDSDData(const uint8_t *data, size_t len, size_t startPos)
Definition CodecDSF.h:214
void end() override
Definition CodecDSF.h:130
const DSFMetadata getMetadata()
Definition CodecDSF.h:132
float clip(float value)
Definition CodecDSF.h:311
int popcount8(uint8_t v)
Definition CodecDSF.h:305
DSFDecoder(DSFMetadata metaData)
Definition CodecDSF.h:96
void setupDecimationStep()
Definition CodecDSF.h:347
bool allChannelsHaveData(int bytesNeeded)
Definition CodecDSF.h:298
SingleBuffer< uint8_t > pcmBuffer
Definition CodecDSF.h:167
bool isActive
Definition CodecDSF.h:163
bool parseData(const uint8_t *data, size_t len)
Definition CodecDSF.h:437
const char * mime() override
Provides the mime type of the data that is expected by this decoder.
Definition CodecDSF.h:98
int findTag(const char *tag, const uint8_t *data, size_t len)
Definition CodecDSF.h:403
uint32_t decimationStep
Definition CodecDSF.h:170
Vector< LowPassFilter< float > > channelFilters
Definition CodecDSF.h:169
size_t bufferDSDData(const uint8_t *data, size_t len, size_t startPos)
Definition CodecDSF.h:237
void writePCMSample(float filteredValue)
Definition CodecDSF.h:375
bool parseFMT(const uint8_t *data, size_t len)
Definition CodecDSF.h:413
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition CodecDSF.h:100
size_t processHeader(const uint8_t *data, size_t len)
Definition CodecDSF.h:183
void setInfoCallback(void(*callback)(const DSFFormat &fmt))
Register a callback that receives the raw DSFFormat header after parsing.
Definition CodecDSF.h:140
void setupFilters()
Definition CodecDSF.h:324
size_t write(const uint8_t *data, size_t len)
Definition CodecDSF.h:148
DSF (DSD Stream File) format encoder.
Definition CodecDSF.h:465
void setOutput(Print &out) override
Default output assignment (encoders may override to store Print reference)
Definition CodecDSF.h:472
Vector< ChannelModState > chState
Definition CodecDSF.h:558
uint32_t oversamplingRatio
Definition CodecDSF.h:559
void setMetaData(DSFMetadata metaData)
Definition CodecDSF.h:479
DSFMetadata meta
Definition CodecDSF.h:555
void flushPartialBlocks()
Definition CodecDSF.h:641
void convertSampleToDSD(int ch, float currentSample)
Definition CodecDSF.h:588
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition CodecDSF.h:474
bool headerWritten
Definition CodecDSF.h:561
void end() override
Definition CodecDSF.h:509
const DSFMetadata getMetadata()
Definition CodecDSF.h:484
size_t write(const uint8_t *data, size_t len) override
Definition CodecDSF.h:515
bool isOpen
Definition CodecDSF.h:562
float readPCMSample(const uint8_t *ptr)
Definition CodecDSF.h:564
bool allBlocksFull()
Definition CodecDSF.h:625
uint64_t totalDsdBytes
Definition CodecDSF.h:560
const char * mime() override
Provides the mime type of the encoded result.
Definition CodecDSF.h:470
void writeBlockSet()
Definition CodecDSF.h:632
DSFEncoder(DSFMetadata metaData)
Definition CodecDSF.h:468
bool begin() override
Definition CodecDSF.h:486
Print * p_print
Definition CodecDSF.h:556
Vector< SingleBuffer< uint8_t > > channelBlocks
Definition CodecDSF.h:557
void writeDSFHeader()
Definition CodecDSF.h:668
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:189
bool write(T sample) override
write add an entry to the buffer
Definition Buffers.h:223
int available() override
provides the number of entries that are available to read
Definition Buffers.h:250
bool isFull() override
checks if the buffer is full
Definition Buffers.h:257
int writeArray(const T data[], int len) override
Fills the buffer data.
Definition Buffers.h:218
T * data()
Provides address of actual data.
Definition Buffers.h:301
bool resize(size_t size)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:322
void reset() override
clears the buffer
Definition Buffers.h:303
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
24bit integer which is used for I2S sound processing. The values are represented as int32_t,...
Definition int24_4bytes_t.h:22
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
int24_4bytes_t int24_t
Definition int24_t.h:12
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:101
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57
float prevSample
Definition CodecDSF.h:550
uint8_t currentByte
Definition CodecDSF.h:551
float dsError2
Definition CodecDSF.h:549
float dsError1
Definition CodecDSF.h:548
int bitPos
Definition CodecDSF.h:552
Metadata structure for DSF (DSD Stream File) format.
Definition CodecDSF.h:32
uint64_t dsd_data_bytes
Total size of DSD data in bytes (0 for streaming mode)
Definition CodecDSF.h:38
bool is_raw
When true, output de-interleaved DSD bitstream instead of converting to PCM.
Definition CodecDSF.h:52
int output_buffer_size
PCM output buffer size in bytes (must be >= one frame)
Definition CodecDSF.h:50
uint32_t dsd_sample_rate
DSD sample rate in Hz (e.g. 2822400 for DSD64, 5644800 for DSD128)
Definition CodecDSF.h:36
uint32_t block_size_per_channel
DSF block size per channel in bytes (from file header, typically 4096)
Definition CodecDSF.h:44
int filter_stages
Number of cascaded Butterworth biquad filter stages (1-3), 0 to disable filtering.
Definition CodecDSF.h:48
uint64_t pcm_frames
Estimated number of PCM frames after DSD-to-PCM conversion.
Definition CodecDSF.h:40
float filter_cutoff
Anti-aliasing filter cutoff as fraction of sample_rate (~0.45 = 90% of Nyquist at 44....
Definition CodecDSF.h:46
DSFMetadata(int rate)
Definition CodecDSF.h:34
float duration_sec
Approximate audio duration in seconds.
Definition CodecDSF.h:42
enum VBanDataTypeList __attribute__