21#include <wavpack/wavpack.h>
23#include <rapidjson/document.h>
44 XO(
"Low Quality (Fast)") ,
45 XO(
"Normal Quality") ,
46 XO(
"High Quality (Slow)") ,
47 XO(
"Very High Quality (Slowest)") ,
108 { 22, 25, 30, 35, 40, 45, 50, 60, 70, 80 },
117 std::unordered_map<ExportOptionID, ExportValue>
mValues;
121 : mListener(listener)
123 for(
const auto& option : mOptions)
124 mValues[option.id] = option.defaultValue;
129 return static_cast<int>(mOptions.size());
134 if(index >= 0 && index < mOptions.size())
136 option = mOptions[index];
144 const auto it = mValues.find(
id);
145 if(it != mValues.end())
155 auto it = mValues.find(
id);
156 if(it == mValues.end() || value.index() != it->second.index())
162 OnHybridModeChange(*std::get_if<bool>(&value));
166 mListener->OnExportOptionChangeBegin();
168 mListener->OnExportOptionChangeEnd();
187 config.
Read(L
"/FileFormats/WavPackEncodeQuality", quality);
188 config.
Read(L
"/FileFormats/WavPackBitDepth", bitDepth);
189 config.
Read(L
"/FileFormats/WavPackHybridMode", hybridMode);
190 config.
Read(L
"/FileFormats/WavPackCreateCorrectionFile", createCorrection);
191 config.
Read(L
"/FileFormats/WavPackBitrate", bitRate);
193 OnHybridModeChange(*hybridMode);
199 if(it != mValues.end())
200 config.
Write(L
"/FileFormats/WavPackEncodeQuality", *std::get_if<int>(&it->second));
203 if(it != mValues.end())
204 config.
Write(L
"/FileFormats/WavPackBitDepth", *std::get_if<int>(&it->second));
207 if(it != mValues.end())
208 config.
Write(L
"/FileFormats/WavPackHybridMode", *std::get_if<bool>(&it->second));
211 if(it != mValues.end())
212 config.
Write(L
"/FileFormats/WavPackCreateCorrectionFile", *std::get_if<bool>(&it->second));
215 if(it != mValues.end())
216 config.
Write(L
"/FileFormats/WavPackBitrate", *std::get_if<int>(&it->second));
263 double t0,
double t1,
bool selectedOnly,
266 const Tags* tags)
override;
271 static int WriteBlock(
void *
id,
void *data, int32_t length);
283 std::vector<std::string>
GetMimeTypes(
int)
const override;
287 std::unique_ptr<ExportOptionsEditor>
303 wxT(
"WavPack"),
XO(
"WavPack Files"), {
wxT(
"wv") }, 255,
true
309 return {
"audio/x-wavpack" };
314 if(!config.IsObject() ||
315 !config.HasMember(
"quality") || !config[
"quality"].IsNumber() ||
316 !config.HasMember(
"bit_rate") || !config[
"bit_rate"].IsNumber() ||
317 !config.HasMember(
"bit_depth") || !config[
"bit_depth"].IsNumber() ||
318 !config.HasMember(
"hybrid_mode") || !config[
"hybrid_mode"].IsBool())
321 const auto quality =
ExportValue(config[
"quality"].GetInt());
322 const auto bitRate =
ExportValue(config[
"bit_rate"].GetInt());
323 const auto bitDepth =
ExportValue(config[
"bit_depth"].GetInt());
324 const auto hybridMode =
ExportValue(config[
"hybrid_mode"].GetBool());
329 std::find(option.values.begin(),
331 quality) == option.values.end())
334 std::find(option.values.begin(),
336 bitRate) == option.values.end())
339 std::find(option.values.begin(),
341 bitDepth) == option.values.end()))
355std::unique_ptr<ExportOptionsEditor>
358 return std::make_unique<ExportOptionsWavPackEditor>(listener);
363 return std::make_unique<WavPackExportProcessor>();
376 double t0,
double t1,
bool selectionOnly,
379 const Tags* metadata)
386 WavpackConfig config = {};
397 const auto quality = ExportPluginHelpers::GetParameterValue<int>(
401 const auto hybridMode = ExportPluginHelpers::GetParameterValue<bool>(
405 const auto createCorrectionFile = ExportPluginHelpers::GetParameterValue<bool>(
409 const auto bitRate = ExportPluginHelpers::GetParameterValue<int>(
413 const auto bitDepth = ExportPluginHelpers::GetParameterValue<int>(
420 if (bitDepth == 24) {
422 }
else if (bitDepth == 32) {
428 config.bits_per_sample = bitDepth;
429 config.bytes_per_sample = bitDepth/8;
432 if (config.num_channels <= 2)
433 config.channel_mask = 0x5 - config.num_channels;
434 else if (config.num_channels <= 18)
435 config.channel_mask = (1U << config.num_channels) - 1;
437 config.channel_mask = 0x3FFFF;
440 config.flags |= CONFIG_FAST_FLAG;
441 }
else if (quality == 2) {
442 config.flags |= CONFIG_HIGH_FLAG;
443 }
else if (quality == 3) {
444 config.flags |= CONFIG_HIGH_FLAG | CONFIG_VERY_HIGH_FLAG;
448 config.flags |= CONFIG_HYBRID_FLAG;
449 config.bitrate = bitRate / 10.0;
451 if (createCorrectionFile) {
452 config.flags |= CONFIG_CREATE_WVC;
464 if (!hybridMode || !createCorrectionFile)
465 wxRemoveFile(
fName.GetFullPath().Append(
"c"));
468 if (!WavpackSetConfiguration64(
context.wpc, &config, -1,
nullptr) || !WavpackPackInit(
context.wpc)) {
473 ?
XO(
"Exporting selected audio as WavPack")
474 :
XO(
"Exporting the audio as WavPack");
476 context.metadata = std::make_unique<Tags>(
502 auto samplesThisRun =
context.mixer->Process();
504 if (samplesThisRun == 0)
508 const int16_t *mixed =
reinterpret_cast<const int16_t*
>(
context.mixer->GetBuffer());
509 for (
decltype(samplesThisRun) j = 0; j < samplesThisRun; j++) {
510 for (
size_t i = 0; i <
context.numChannels; i++) {
511 wavpackBuffer[j*
context.numChannels + i] = (
static_cast<int32_t
>(*mixed++) * 65536) >> 16;
515 const int *mixed =
reinterpret_cast<const int*
>(
context.mixer->GetBuffer());
516 for (
decltype(samplesThisRun) j = 0; j < samplesThisRun; j++) {
517 for (
size_t i = 0; i <
context.numChannels; i++) {
518 wavpackBuffer[j*
context.numChannels + i] = *mixed++;
523 if (!WavpackPackSamples(
context.wpc, wavpackBuffer.get(), samplesThisRun)) {
531 if (!WavpackFlushSamples(
context.wpc)) {
537 for (
const auto &pair :
context.metadata->GetRange()) {
539 const auto &v = pair.second;
541 WavpackAppendTagItem(
context.wpc,
542 n.mb_str(wxConvUTF8),
543 v.mb_str(wxConvUTF8),
544 static_cast<int>( strlen(v.mb_str(wxConvUTF8)) ));
547 if (!WavpackWriteTag(
context.wpc)) {
552 if ( !
context.outWvFile.file.get()->Close()
553 || (
context.outWvcFile.file &&
context.outWvcFile.file.get() && !
context.outWvcFile.file.get()->Close())) {
559 if (!
context.outWvFile.file->Open(
context.fName.GetFullPath(), wxFile::read_write)) {
564 context.outWvFile.file->Read(firstBlockBuffer.get(),
context.outWvFile.firstBlockSize);
567 WavpackUpdateNumSamples(
context.wpc, firstBlockBuffer.get());
568 context.outWvFile.file->Seek(0);
569 context.outWvFile.file->Write(firstBlockBuffer.get(),
context.outWvFile.firstBlockSize);
571 if ( !
context.outWvFile.file.get()->Close() ) {
582 if (
id ==
nullptr || data ==
nullptr || length == 0)
593 if (outId->
file->Write(data, length) != length) {
607 []{
return std::make_unique< ExportWavPack >(); }
std::variant< bool, int, double, std::string > ExportValue
A type of option values (parameters) used by exporting plugins.
static ExportPluginRegistry::RegisteredPlugin sRegisteredPlugin
declares abstract base class Track, TrackList, and iterators over TrackList
std::vector< TranslatableString > TranslatableStrings
This simplifies arrays of arrays, each array separately allocated with NEW[] But it might be better t...
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Listener object that is used to report on option changes.
Editor objects are used to retrieve a set of export options, and configure exporting parameters accor...
std::vector< int > SampleRateList
static ExportResult UpdateProgress(ExportProcessorDelegate &delegate, Mixer &mixer, double t0, double t1)
Sends progress update to delegate and retrieves state update from it. Typically used inside each expo...
static std::unique_ptr< Mixer > CreateMixer(const TrackList &tracks, bool selectionOnly, double startTime, double stopTime, unsigned numOutChannels, size_t outBufferSize, bool outInterleaved, double outRate, sampleFormat outFormat, MixerOptions::Downmix *mixerSpec)
virtual void SetStatusString(const TranslatableString &str)=0
std::vector< std::tuple< ExportOptionID, ExportValue > > Parameters
FormatInfo GetFormatInfo(int) const override
Returns FormatInfo structure for given index if it's valid, or a default one. FormatInfo::format isn'...
int GetFormatCount() const override
std::unique_ptr< ExportOptionsEditor > CreateOptionsEditor(int, ExportOptionsEditor::Listener *) const override
Creates format-dependent options editor, that is used to create a valid set of parameters to be used ...
std::unique_ptr< ExportProcessor > CreateProcessor(int format) const override
bool ParseConfig(int formatIndex, const rapidjson::Value &document, ExportProcessor::Parameters ¶meters) const override
Attempt to parse configuration JSON object and produce a suitable set of parameters....
std::vector< std::string > GetMimeTypes(int) const override
A matrix of booleans, one row per input channel, column per output.
static TrackList & Get(AudacityProject &project)
Holds a msgid for the translation catalog; may also bind format arguments.
~WavPackExportProcessor()
std::unique_ptr< Mixer > mixer
TranslatableString status
struct WavPackExportProcessor::@179 context
static constexpr size_t SAMPLES_PER_RUN
ExportResult Process(ExportProcessorDelegate &delegate) override
static int WriteBlock(void *id, void *data, int32_t length)
bool Initialize(AudacityProject &project, const Parameters ¶meters, const wxFileNameWrapper &filename, double t0, double t1, bool selectedOnly, double sampleRate, unsigned channels, MixerOptions::Downmix *mixerSpec, const Tags *tags) override
Called before start processing.
std::unique_ptr< Tags > metadata
SampleRateList GetSampleRateList() const override
bool SetValue(ExportOptionID id, const ExportValue &value) override
bool GetValue(ExportOptionID id, ExportValue &value) const override
int GetOptionsCount() const override
ExportOptionsWavPackEditor(Listener *listener)
std::unordered_map< ExportOptionID, ExportValue > mValues
void Store(audacity::BasicSettings &config) const override
void OnHybridModeChange(bool hybridMode)
bool GetOption(int index, ExportOption &option) const override
void Load(const audacity::BasicSettings &config) override
Base class for objects that provide facility to store data persistently, and access it with string ke...
virtual bool Write(const wxString &key, bool value)=0
virtual bool Read(const wxString &key, bool *value) const =0
constexpr auto sampleRate
const TranslatableStrings ExportBitDepthNames
@ OptionIDCreateCorrection
const std::initializer_list< ExportOption > ExportWavPackOptions
TranslatableString n_bps(int n)
const TranslatableStrings ExportQualityNames
const TranslatableStrings BitRateNames
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
A type that provides a description of an exporting option. Isn't allowed to change except non-type re...
@ TypeEnum
List/enum option. values holds items, and names text to be displayed.
@ ReadOnly
Parameter is read-only, client should not attempt to change it's value.
int flags
A set of flag that desc.
std::unique_ptr< wxFile > file