18#include <wavpack/wavpack.h>
33 WavpackContext* Context {
nullptr };
38 : Block {
std::move(block) }
40 WavpackConfig config = {};
42 config.num_channels = 1;
43 config.channel_mask = 0x4;
45 config.sample_rate = 48000;
48 config.bits_per_sample = config.bytes_per_sample * 8;
51 config.flags = CONFIG_FAST_FLAG;
53 Context = WavpackOpenFileOutput(WriteBlock,
this,
nullptr);
56 !WavpackSetConfiguration(
57 Context, &config, Block.
Block->GetSampleCount()) ||
58 !WavpackPackInit(Context))
60 WavpackCloseFile(Context);
67 if (Context !=
nullptr)
68 WavpackCloseFile(Context);
77 std::vector<std::remove_pointer_t<samplePtr>> sampleData;
78 sampleData.resize(dataSize);
80 const size_t samplesRead = Block.
Block->GetSamples(
86 CompressedData.reserve(sampleData.size() * 3 / 2);
90 constexpr size_t conversionSamplesCount = 4096;
92 const int16_t* int16Data =
reinterpret_cast<const int16_t*
>(sampleData.data());
93 std::vector<int32_t> buffer;
94 buffer.resize(conversionSamplesCount);
96 for (
size_t firstSample = 0; firstSample < samplesRead;
97 firstSample += conversionSamplesCount)
99 const auto samplesThisRun =
100 std::min(conversionSamplesCount, samplesRead - firstSample);
102 for (
size_t i = 0; i < samplesThisRun; ++i)
104 (
static_cast<int32_t
>(int16Data[firstSample + i]) * 65536) >>
107 WavpackPackSamples(Context, buffer.data(), samplesThisRun);
112 const void* data = sampleData.data();
114 Context,
static_cast<int32_t*
>(
const_cast<void*
>(data)),
120 return std::move(CompressedData);
123 void Feed(int32_t* data, int32_t count)
125 if (Context ==
nullptr)
128 WavpackPackSamples(Context, data, count);
133 if (Context ==
nullptr)
136 WavpackFlushSamples(Context);
138 const std::string formatString = std::to_string(
unsigned(Block.
Format));
139 WavpackAppendTagItem(
140 Context,
"FORMAT", formatString.data(), formatString.size());
142 const std::string blockIdString = std::to_string(Block.
Id);
143 WavpackAppendTagItem(
144 Context,
"BLOCK_ID", blockIdString.data(), blockIdString.size());
146 WavpackAppendTagItem(
147 Context,
"HASH", Block.
Hash.data(), Block.
Hash.size());
149 WavpackWriteTag(Context);
150 WavpackCloseFile(Context);
157 if (
id ==
nullptr || data ==
nullptr || length == 0)
162 auto start =
reinterpret_cast<uint8_t*
>(data);
163 auto end = start + length;
174 WavpackContext* Context {
nullptr };
177 const void* Data {
nullptr };
180 int64_t Offset { 0 };
183 uint32_t SamplesCount {};
185 uint8_t UngetcChar { 0 };
186 bool UngetcFlag {
false };
191 int64_t BlockId { -1 };
200 return Context !=
nullptr && SamplesCount > 0 &&
208 if (Data ==
nullptr ||
Size == 0)
213 Context = WavpackOpenFileInputEx64(
214 &raw_reader,
this,
nullptr, error, OPEN_DSD_AS_PCM | OPEN_TAGS, 0);
216 if (Context ==
nullptr)
219 Mode = WavpackGetMode(Context);
220 SamplesCount = WavpackGetNumSamples(Context);
222 const auto formatString = ReadTag(
"FORMAT");
225 formatString.c_str(), formatString.c_str() + formatString.size(),
227 if (result.ec == std::errc {})
230 auto blockIdString = ReadTag(
"BLOCK_ID");
232 blockIdString.c_str(), blockIdString.c_str() + blockIdString.size(),
238 if (Context ==
nullptr)
241 const auto tagLength = WavpackGetTagItem(Context, tagName,
nullptr, 0);
247 tag.resize(tagLength + 1);
248 WavpackGetTagItem(Context, tagName, tag.data(), tagLength + 1);
249 tag.resize(tagLength);
257 if (Context !=
nullptr)
258 WavpackCloseFile(Context);
266 Int32Buffer.resize(SamplesCount);
269 Int16Buffer.resize(SamplesCount);
271 FloatBuffer.resize(SamplesCount);
273 const auto samplesRead =
274 WavpackUnpackSamples(Context, Int32Buffer.data(), SamplesCount);
276 if (samplesRead != SamplesCount)
279 const bool floatSamples = (Mode & MODE_FLOAT) == MODE_FLOAT;
283 FloatBuffer.resize(SamplesCount);
285 FloatBuffer.data(), Int32Buffer.data(),
286 SamplesCount *
sizeof(
float));
290 const auto bytesPerSample = WavpackGetBytesPerSample(Context);
292 if (bytesPerSample == 1)
294 for (
size_t i = 0; i < SamplesCount; ++i)
295 Int16Buffer[i] =
static_cast<int16_t
>(Int32Buffer[i]) << 8;
297 else if (bytesPerSample == 2)
299 for (
size_t i = 0; i < SamplesCount; ++i)
300 Int16Buffer[i] =
static_cast<int16_t
>(Int32Buffer[i]);
316 uint8_t* outptr =
static_cast<uint8_t*
>(data);
325 const auto bytesToCopy =
326 std::min<int32_t>(bcount, importer->
Size - importer->
Offset);
329 outptr,
static_cast<const uint8_t*
>(importer->
Data) + importer->
Offset,
332 outptr += bytesToCopy;
333 bcount -= bytesToCopy;
335 importer->
Offset += bytesToCopy;
337 return static_cast<int32_t
>(outptr -
static_cast<uint8_t*
>(data));
352 return raw_set_pos_rel(
id, pos, SEEK_SET);
363 if (delta < 0 || delta > importer->
Size)
370 const auto newOffset = delta + importer->
Offset;
371 if (newOffset < 0 || newOffset > importer->
Size)
373 importer->
Offset += delta;
378 if (delta > 0 || -delta > importer->
Size)
413 WavpackStreamReader64 raw_reader { raw_read_bytes, raw_write_bytes,
414 raw_get_pos, raw_set_pos_abs,
415 raw_set_pos_rel, raw_push_back_byte,
416 raw_get_length, raw_can_seek,
417 nullptr, raw_close_stream };
423 return static_cast<float>(value) / std::numeric_limits<int16_t>::max();
428 return static_cast<float>(value) / ((1 << 23) - 1);
439 const auto samplesCount = data.size();
440 const auto sum256Count = (samplesCount + 255) / 256;
441 const auto sum64kCount = (samplesCount + 65535) / 65536;
448 for (
size_t i = 0; i < samplesCount; ++i)
452 blockStats.Min =
std::min(blockStats.Min, value);
453 blockStats.Max = std::max(blockStats.Max, value);
454 blockStats.RMS += value * value;
458 summary256.Min =
std::min(summary256.Min, value);
459 summary256.Max = std::max(summary256.Max, value);
460 summary256.RMS += value * value;
462 auto& summary64k = block.
Summary64k[i / 65536];
463 summary64k.Min =
std::min(summary64k.Min, value);
464 summary64k.Max = std::max(summary64k.Max, value);
465 summary64k.RMS += value * value;
470 auto samplesProcessed = 0;
473 const auto samplesToProcess = std::min<int>(256, samplesCount - samplesProcessed);
474 summary.RMS =
std::sqrt(summary.RMS / samplesToProcess);
475 samplesProcessed += samplesToProcess;
478 samplesProcessed = 0;
481 const auto samplesToProcess = std::min<int>(65536, samplesCount - samplesProcessed);
482 summary.RMS =
std::sqrt(summary.RMS / samplesToProcess);
483 samplesProcessed += samplesToProcess;
490 Exporter exporter { block };
491 return exporter.Compress();
494std::optional<DecompressedBlock>
497 if (data ==
nullptr ||
size == 0)
502 if (!importer.Unpack())
507 result.
BlockId = importer.BlockId;
508 result.Format = importer.Format;
510 const auto sampleSize =
SAMPLE_SIZE(importer.Format);
512 result.Data.resize(importer.SamplesCount * sampleSize);
517 result.Data.data(), importer.Int16Buffer.data(), result.Data.size());
523 result.Data.data(), importer.Int32Buffer.data(), result.Data.size());
529 result.Data.data(), importer.FloatBuffer.data(), result.Data.size());
FromCharsResult FromChars(const char *buffer, const char *last, float &value) noexcept
Parse a string into a single precision floating point value, always uses the dot as decimal.
Declare functions to convert numeric types to string representation.
Singleton class which actually imports the audio, using ImportPlugin objects that are registered by m...
Positions or offsets within audio files need a wide type.
void UpdateRMS(DecompressedBlock &block, const std::vector< T > &data)
float GetFloatValue(float value) noexcept
std::optional< DecompressedBlock > DecompressBlock(const void *data, const std::size_t size)
std::vector< uint8_t > CompressBlock(const LockedBlock &block)
const char * end(const char *str) noexcept
SizeType< float > Size
Alias for SizeType<float>
__finl float_x4 __vecc sqrt(const float_x4 &a)
std::vector< MinMaxRMS > Summary256
std::vector< MinMaxRMS > Summary64k
static int WriteBlock(void *id, void *data, int32_t length)
Exporter(LockedBlock block)
void Feed(int32_t *data, int32_t count)
std::vector< uint8_t > CompressedData
std::vector< uint8_t > Compress()
static int raw_set_pos_rel(void *id, int64_t delta, int mode)
static int32_t raw_write_bytes(void *id, void *data, int32_t bcount)
Importer(const void *data, const int64_t size)
static int raw_push_back_byte(void *id, int c)
static int64_t raw_get_pos(void *id)
static int32_t raw_read_bytes(void *id, void *data, int32_t bcount)
static int64_t raw_get_length(void *id)
static int raw_close_stream(void *)
static int raw_set_pos_abs(void *id, int64_t pos)
std::vector< int16_t > Int16Buffer
std::string ReadTag(const char *tagName)
std::vector< int32_t > Int32Buffer
static int raw_can_seek(void *)
std::vector< float > FloatBuffer