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();
169 mListener->OnExportOptionChangeEnd();
188 config.
Read(L
"/FileFormats/WavPackEncodeQuality", quality);
189 config.
Read(L
"/FileFormats/WavPackBitDepth", bitDepth);
190 config.
Read(L
"/FileFormats/WavPackHybridMode", hybridMode);
191 config.
Read(L
"/FileFormats/WavPackCreateCorrectionFile", createCorrection);
192 config.
Read(L
"/FileFormats/WavPackBitrate", bitRate);
194 OnHybridModeChange(*hybridMode);
200 if(it != mValues.end())
201 config.
Write(L
"/FileFormats/WavPackEncodeQuality", *std::get_if<int>(&it->second));
204 if(it != mValues.end())
205 config.
Write(L
"/FileFormats/WavPackBitDepth", *std::get_if<int>(&it->second));
208 if(it != mValues.end())
209 config.
Write(L
"/FileFormats/WavPackHybridMode", *std::get_if<bool>(&it->second));
212 if(it != mValues.end())
213 config.
Write(L
"/FileFormats/WavPackCreateCorrectionFile", *std::get_if<bool>(&it->second));
216 if(it != mValues.end())
217 config.
Write(L
"/FileFormats/WavPackBitrate", *std::get_if<int>(&it->second));
269 double t0,
double t1,
bool selectedOnly,
272 const Tags* tags)
override;
277 static int WriteBlock(
void *
id,
void *data, int32_t length);
289 std::vector<std::string>
GetMimeTypes(
int)
const override;
293 std::unique_ptr<ExportOptionsEditor>
309 wxT(
"WavPack"),
XO(
"WavPack Files"), {
wxT(
"wv") }, 255,
true
315 return {
"audio/x-wavpack" };
320 if(!config.IsObject() ||
321 !config.HasMember(
"quality") || !config[
"quality"].IsNumber() ||
322 !config.HasMember(
"bit_rate") || !config[
"bit_rate"].IsNumber() ||
323 !config.HasMember(
"bit_depth") || !config[
"bit_depth"].IsNumber() ||
324 !config.HasMember(
"hybrid_mode") || !config[
"hybrid_mode"].IsBool())
327 const auto quality =
ExportValue(config[
"quality"].GetInt());
328 const auto bitRate =
ExportValue(config[
"bit_rate"].GetInt());
329 const auto bitDepth =
ExportValue(config[
"bit_depth"].GetInt());
330 const auto hybridMode =
ExportValue(config[
"hybrid_mode"].GetBool());
335 std::find(option.values.begin(),
337 quality) == option.values.end())
340 std::find(option.values.begin(),
342 bitRate) == option.values.end())
345 std::find(option.values.begin(),
347 bitDepth) == option.values.end()))
361std::unique_ptr<ExportOptionsEditor>
364 return std::make_unique<ExportOptionsWavPackEditor>(listener);
369 return std::make_unique<WavPackExportProcessor>();
382 double t0,
double t1,
bool selectionOnly,
385 const Tags* metadata)
392 WavpackConfig config = {};
401 const auto quality = ExportPluginHelpers::GetParameterValue<int>(
405 const auto hybridMode = ExportPluginHelpers::GetParameterValue<bool>(
409 const auto createCorrectionFile = ExportPluginHelpers::GetParameterValue<bool>(
413 const auto bitRate = ExportPluginHelpers::GetParameterValue<int>(
417 const auto bitDepth = ExportPluginHelpers::GetParameterValue<int>(
424 if (bitDepth == 24) {
426 }
else if (bitDepth == 32) {
432 config.bits_per_sample = bitDepth;
433 config.bytes_per_sample = bitDepth/8;
436 if (config.num_channels <= 2)
437 config.channel_mask = 0x5 - config.num_channels;
438 else if (config.num_channels <= 18)
439 config.channel_mask = (1U << config.num_channels) - 1;
441 config.channel_mask = 0x3FFFF;
444 config.flags |= CONFIG_FAST_FLAG;
445 }
else if (quality == 2) {
446 config.flags |= CONFIG_HIGH_FLAG;
447 }
else if (quality == 3) {
448 config.flags |= CONFIG_HIGH_FLAG | CONFIG_VERY_HIGH_FLAG;
452 config.flags |= CONFIG_HYBRID_FLAG;
453 config.bitrate = bitRate / 10.0;
455 if (createCorrectionFile) {
456 config.flags |= CONFIG_CREATE_WVC;
468 if (!hybridMode || !createCorrectionFile)
469 wxRemoveFile(
fName.GetFullPath().Append(
"c"));
472 if (!WavpackSetConfiguration64(
context.wpc, &config, -1,
nullptr) || !WavpackPackInit(
context.wpc)) {
477 ?
XO(
"Exporting selected audio as WavPack")
478 :
XO(
"Exporting the audio as WavPack");
480 context.metadata = std::make_unique<Tags>(
505 auto samplesThisRun =
context.mixer->Process();
507 if (samplesThisRun == 0)
511 const int16_t *mixed =
reinterpret_cast<const int16_t*
>(
context.mixer->GetBuffer());
512 for (
decltype(samplesThisRun) j = 0; j < samplesThisRun; j++) {
513 for (
size_t i = 0; i <
context.numChannels; i++) {
514 wavpackBuffer[j*
context.numChannels + i] = (
static_cast<int32_t
>(*mixed++) * 65536) >> 16;
518 const int *mixed =
reinterpret_cast<const int*
>(
context.mixer->GetBuffer());
519 for (
decltype(samplesThisRun) j = 0; j < samplesThisRun; j++) {
520 for (
size_t i = 0; i <
context.numChannels; i++) {
521 wavpackBuffer[j*
context.numChannels + i] = *mixed++;
526 if (!WavpackPackSamples(
context.wpc, wavpackBuffer.get(), samplesThisRun)) {
534 if (!WavpackFlushSamples(
context.wpc)) {
540 for (
const auto &pair :
context.metadata->GetRange()) {
542 const auto &v = pair.second;
544 WavpackAppendTagItem(
context.wpc,
545 n.mb_str(wxConvUTF8),
546 v.mb_str(wxConvUTF8),
547 static_cast<int>( strlen(v.mb_str(wxConvUTF8)) ));
550 if (!WavpackWriteTag(
context.wpc)) {
555 if ( !
context.outWvFile.file.get()->Close()
556 || (
context.outWvcFile.file &&
context.outWvcFile.file.get() && !
context.outWvcFile.file.get()->Close())) {
562 if (!
context.outWvFile.file->Open(
context.fName.GetFullPath(), wxFile::read_write)) {
567 context.outWvFile.file->Read(firstBlockBuffer.get(),
context.outWvFile.firstBlockSize);
570 WavpackUpdateNumSamples(
context.wpc, firstBlockBuffer.get());
571 context.outWvFile.file->Seek(0);
572 context.outWvFile.file->Write(firstBlockBuffer.get(),
context.outWvFile.firstBlockSize);
574 if ( !
context.outWvFile.file.get()->Close() ) {
585 if (
id ==
nullptr || data ==
nullptr || length == 0)
596 if (outId->
file->Write(data, length) != length) {
610 []{
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 AudacityProject &project, 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.
Holds a msgid for the translation catalog; may also bind format arguments.
~WavPackExportProcessor()
std::unique_ptr< Mixer > mixer
TranslatableString status
struct WavPackExportProcessor::@186 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
const std::initializer_list< ExportOption > ExportWavPackOptions
TranslatableString n_bps(int n)
const TranslatableStrings ExportQualityNames
@ OptionIDCreateCorrection
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