Audacity 3.2.0
Public Member Functions | Static Public Member Functions | List of all members
ExportWavPack Class Referencefinal
Inheritance diagram for ExportWavPack:
[legend]
Collaboration diagram for ExportWavPack:
[legend]

Public Member Functions

 ExportWavPack ()
 
void OptionsCreate (ShuttleGui &S, int format) override
 
ProgressResult Export (AudacityProject *project, std::unique_ptr< BasicUI::ProgressDialog > &pDialog, unsigned channels, const wxFileNameWrapper &fName, bool selectedOnly, double t0, double t1, MixerSpec *mixerSpec=NULL, const Tags *metadata=NULL, int subformat=0) override
 called to export audio into a file. More...
 
- Public Member Functions inherited from ExportPlugin
 ExportPlugin ()
 
virtual ~ExportPlugin ()
 
int AddFormat ()
 Add a NEW entry to the list of formats this plug-in can export. More...
 
void SetFormat (const wxString &format, int index)
 
void SetDescription (const TranslatableString &description, int index)
 
void AddExtension (const FileExtension &extension, int index)
 
void SetExtensions (FileExtensions extensions, int index)
 
void SetMask (FileNames::FileTypes mask, int index)
 
void SetMaxChannels (unsigned maxchannels, unsigned index)
 
void SetCanMetaData (bool canmetadata, int index)
 
virtual int GetFormatCount ()
 
virtual wxString GetFormat (int index)
 
TranslatableString GetDescription (int index)
 
virtual FileExtension GetExtension (int index=0)
 Return the (first) file name extension for the sub-format. More...
 
virtual FileExtensions GetExtensions (int index=0)
 Return all the file name extensions used for the sub-format. More...
 
FileNames::FileTypes GetMask (int index)
 
virtual unsigned GetMaxChannels (int index)
 
virtual bool GetCanMetaData (int index)
 
virtual bool IsExtension (const FileExtension &ext, int index)
 
virtual bool DisplayOptions (wxWindow *parent, int format=0)
 
virtual void OptionsCreate (ShuttleGui &S, int format)=0
 
virtual bool CheckFileName (wxFileName &filename, int format=0)
 
virtual int SetNumExportChannels ()
 Exporter plug-ins may override this to specify the number of channels in exported file. -1 for unspecified. More...
 
virtual ProgressResult Export (AudacityProject *project, std::unique_ptr< BasicUI::ProgressDialog > &pDialog, unsigned channels, const wxFileNameWrapper &fName, bool selectedOnly, double t0, double t1, MixerSpec *mixerSpec=NULL, const Tags *metadata=NULL, int subformat=0)=0
 called to export audio into a file. More...
 

Static Public Member Functions

static int WriteBlock (void *id, void *data, int32_t length)
 

Additional Inherited Members

- Public Types inherited from ExportPlugin
using ProgressResult = BasicUI::ProgressResult
 
- Protected Member Functions inherited from ExportPlugin
std::unique_ptr< MixerCreateMixer (const TrackList &tracks, bool selectionOnly, double startTime, double stopTime, unsigned numOutChannels, size_t outBufferSize, bool outInterleaved, double outRate, sampleFormat outFormat, MixerSpec *mixerSpec)
 
- Static Protected Member Functions inherited from ExportPlugin
static void InitProgress (std::unique_ptr< BasicUI::ProgressDialog > &pDialog, const TranslatableString &title, const TranslatableString &message)
 
static void InitProgress (std::unique_ptr< BasicUI::ProgressDialog > &pDialog, const wxFileNameWrapper &title, const TranslatableString &message)
 

Detailed Description

Definition at line 240 of file ExportWavPack.cpp.

Constructor & Destructor Documentation

◆ ExportWavPack()

ExportWavPack::ExportWavPack ( )

Definition at line 262 of file ExportWavPack.cpp.

263: ExportPlugin()
264{
265 AddFormat();
266 SetFormat(wxT("WavPack"),0);
267 AddExtension(wxT("wv"),0);
268 SetMaxChannels(255,0);
269 SetCanMetaData(true,0);
270 SetDescription(XO("WavPack Files"),0);
271}
wxT("CloseDown"))
XO("Cut/Copy/Paste")
ExportPlugin()
Definition: Export.cpp:80
void AddExtension(const FileExtension &extension, int index)
Definition: Export.cpp:126
int AddFormat()
Add a NEW entry to the list of formats this plug-in can export.
Definition: Export.cpp:100
void SetFormat(const wxString &format, int index)
Definition: Export.cpp:116
void SetDescription(const TranslatableString &description, int index)
Definition: Export.cpp:121
void SetCanMetaData(bool canmetadata, int index)
Definition: Export.cpp:146
void SetMaxChannels(unsigned maxchannels, unsigned index)
Definition: Export.cpp:141

References ExportPlugin::AddExtension(), ExportPlugin::AddFormat(), ExportPlugin::SetCanMetaData(), ExportPlugin::SetDescription(), ExportPlugin::SetFormat(), ExportPlugin::SetMaxChannels(), wxT(), and XO().

Here is the call graph for this function:

Member Function Documentation

◆ Export()

ProgressResult ExportWavPack::Export ( AudacityProject project,
std::unique_ptr< BasicUI::ProgressDialog > &  pDialog,
unsigned  channels,
const wxFileNameWrapper fName,
bool  selectedOnly,
double  t0,
double  t1,
MixerSpec mixerSpec = NULL,
const Tags metadata = NULL,
int  subformat = 0 
)
overridevirtual

called to export audio into a file.

Parameters
pDialogTo be initialized with pointer to a NEW ProgressDialog if it was null, otherwise gives an existing dialog to be reused (working around a problem in wxWidgets for Mac; see bug 1600)
selectedOnlySet to true if all tracks should be mixed, to false if only the selected tracks should be mixed and exported.
metadataA Tags object that will over-ride the one in *project and be used to tag the file that is exported.
subformatControl which of the multiple formats this exporter is capable of exporting should be used. Used where a single export plug-in handles a number of related formats, but they have separate entries in the Format drop-down list box. For example, the options to export to "Other PCM", "AIFF 16 Bit" and "WAV 16 Bit" are all the same libsndfile export plug-in, but with subformat set to 0, 1, and 2 respectively.
Returns
ProgressResult::Failed or ProgressResult::Cancelled if export fails to complete for any reason, in which case this function is responsible for alerting the user. Otherwise ProgressResult::Success or ProgressResult::Stopped

Implements ExportPlugin.

Definition at line 273 of file ExportWavPack.cpp.

283{
284 WavpackConfig config = {};
285 WriteId outWvFile, outWvcFile;
286 outWvFile.file = std::make_unique< wxFile >();
287
288 if (!outWvFile.file->Create(fName.GetFullPath(), true) || !outWvFile.file.get()->IsOpened()) {
289 AudacityMessageBox( XO("Unable to open target file for writing") );
290 return ProgressResult::Failed;
291 }
292
293 double rate = ProjectRate::Get( *project ).GetRate();
294 const auto &tracks = TrackList::Get( *project );
295
296 int quality = QualitySetting.Read();
297 bool hybridMode = HybridModeSetting.Read();
298 bool createCorrectionFile = CreateCorrectionFileSetting.Read();
299 int bitRate = BitrateSetting.Read();
300 int bitDepth = BitDepthSetting.Read();
301
303 if (bitDepth == 24) {
305 } else if (bitDepth == 32) {
307 }
308
309 config.num_channels = numChannels;
310 config.sample_rate = rate;
311 config.bits_per_sample = bitDepth;
312 config.bytes_per_sample = bitDepth/8;
313 config.float_norm_exp = format == floatSample ? 127 : 0;
314
315 if (config.num_channels <= 2)
316 config.channel_mask = 0x5 - config.num_channels;
317 else if (config.num_channels <= 18)
318 config.channel_mask = (1U << config.num_channels) - 1;
319 else
320 config.channel_mask = 0x3FFFF;
321
322 if (quality == 0) {
323 config.flags |= CONFIG_FAST_FLAG;
324 } else if (quality == 2) {
325 config.flags |= CONFIG_HIGH_FLAG;
326 } else if (quality == 3) {
327 config.flags |= CONFIG_HIGH_FLAG | CONFIG_VERY_HIGH_FLAG;
328 }
329
330 if (hybridMode) {
331 config.flags |= CONFIG_HYBRID_FLAG;
332 config.bitrate = bitRate / 10.0;
333
334 if (createCorrectionFile) {
335 config.flags |= CONFIG_CREATE_WVC;
336
337 outWvcFile.file = std::make_unique< wxFile >();
338 if (!outWvcFile.file->Create(fName.GetFullPath().Append("c"), true)) {
339 AudacityMessageBox( XO("Unable to create target file for writing") );
340 return ProgressResult::Failed;
341 }
342 }
343 }
344
345 // If we're not creating a correction file now, any one that currently exists with this name
346 // will become obsolete now, so delete it if it happens to exist (although it usually won't)
347
348 if (!hybridMode || !createCorrectionFile)
349 wxRemoveFile(fName.GetFullPath().Append("c"));
350
351 WavpackContext *wpc = WavpackOpenFileOutput(WriteBlock, &outWvFile, createCorrectionFile ? &outWvcFile : nullptr);
352 auto closeWavPackContext = finally([wpc]() { WavpackCloseFile(wpc); });
353
354 if (!WavpackSetConfiguration64(wpc, &config, -1, nullptr) || !WavpackPackInit(wpc)) {
355 ShowExportErrorDialog( WavpackGetErrorMessage(wpc) );
356 return ProgressResult::Failed;
357 }
358
359 // Samples to write per run
360 constexpr size_t SAMPLES_PER_RUN = 8192u;
361
362 const size_t bufferSize = SAMPLES_PER_RUN * numChannels;
363 ArrayOf<int32_t> wavpackBuffer{ bufferSize };
364 auto updateResult = ProgressResult::Success;
365 {
366 auto mixer = CreateMixer(tracks, selectionOnly,
367 t0, t1,
368 numChannels, SAMPLES_PER_RUN, true,
369 rate, format, mixerSpec);
370
371 InitProgress( pDialog, fName,
372 selectionOnly
373 ? XO("Exporting selected audio as WavPack")
374 : XO("Exporting the audio as WavPack") );
375 auto &progress = *pDialog;
376
377 while (updateResult == ProgressResult::Success) {
378 auto samplesThisRun = mixer->Process();
379
380 if (samplesThisRun == 0)
381 break;
382
383 if (format == int16Sample) {
384 const int16_t *mixed = reinterpret_cast<const int16_t*>(mixer->GetBuffer());
385 for (decltype(samplesThisRun) j = 0; j < samplesThisRun; j++) {
386 for (size_t i = 0; i < numChannels; i++) {
387 wavpackBuffer[j*numChannels + i] = (static_cast<int32_t>(*mixed++) * 65536) >> 16;
388 }
389 }
390 } else {
391 const int *mixed = reinterpret_cast<const int*>(mixer->GetBuffer());
392 for (decltype(samplesThisRun) j = 0; j < samplesThisRun; j++) {
393 for (size_t i = 0; i < numChannels; i++) {
394 wavpackBuffer[j*numChannels + i] = *mixed++;
395 }
396 }
397 }
398
399 if (!WavpackPackSamples(wpc, wavpackBuffer.get(), samplesThisRun)) {
400 ShowExportErrorDialog( WavpackGetErrorMessage(wpc) );
401 return ProgressResult::Failed;
402 }
403
404 if (updateResult == ProgressResult::Success)
405 updateResult =
406 progress.Poll(mixer->MixGetCurrentTime() - t0, t1 - t0);
407 }
408 }
409
410 if (!WavpackFlushSamples(wpc)) {
411 ShowExportErrorDialog( WavpackGetErrorMessage(wpc) );
412 return ProgressResult::Failed;
413 } else {
414 if (metadata == NULL)
415 metadata = &Tags::Get( *project );
416
417 wxString n;
418 for (const auto &pair : metadata->GetRange()) {
419 n = pair.first;
420 const auto &v = pair.second;
421
422 WavpackAppendTagItem(wpc,
423 n.mb_str(wxConvUTF8),
424 v.mb_str(wxConvUTF8),
425 static_cast<int>( strlen(v.mb_str(wxConvUTF8)) ));
426 }
427
428 if (!WavpackWriteTag(wpc)) {
429 ShowExportErrorDialog( WavpackGetErrorMessage(wpc) );
430 return ProgressResult::Failed;
431 }
432 }
433
434 if ( !outWvFile.file.get()->Close()
435 || ( outWvcFile.file && outWvcFile.file.get() && !outWvcFile.file.get()->Close())) {
436 return ProgressResult::Failed;
437 }
438
439 // wxFile::Create opens the file with only write access
440 // So, need to open the file again with both read and write access
441 if (!outWvFile.file->Open(fName.GetFullPath(), wxFile::read_write)) {
442 ShowExportErrorDialog( "Unable to update the actual length of the file" );
443 return ProgressResult::Failed;
444 }
445
446 ArrayOf<int32_t> firstBlockBuffer { outWvFile.firstBlockSize };
447 size_t bytesRead = outWvFile.file->Read(firstBlockBuffer.get(), outWvFile.firstBlockSize);
448
449 // Update the first block written with the actual number of samples written
450 WavpackUpdateNumSamples(wpc, firstBlockBuffer.get());
451 outWvFile.file->Seek(0);
452 size_t bytesWritten = outWvFile.file->Write(firstBlockBuffer.get(), outWvFile.firstBlockSize);
453
454 if ( !outWvFile.file.get()->Close() ) {
455 return ProgressResult::Failed;
456 }
457
458 return updateResult;
459}
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
void ShowExportErrorDialog(wxString ErrorCode, TranslatableString message, const TranslatableString &caption, bool allowReporting)
Definition: Export.cpp:1479
#define SAMPLES_PER_RUN
Definition: ExportFLAC.cpp:160
int format
Definition: ExportPCM.cpp:53
sampleFormat
The ordering of these values with operator < agrees with the order of increasing bit width.
Definition: SampleFormat.h:30
This simplifies arrays of arrays, each array separately allocated with NEW[] But it might be better t...
Definition: MemoryX.h:27
static void InitProgress(std::unique_ptr< BasicUI::ProgressDialog > &pDialog, const TranslatableString &title, const TranslatableString &message)
Definition: Export.cpp:250
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, MixerSpec *mixerSpec)
Definition: Export.cpp:222
static int WriteBlock(void *id, void *data, int32_t length)
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28
double GetRate() const
Definition: ProjectRate.cpp:53
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:200
Iterators GetRange() const
Definition: Tags.cpp:436
static Tags & Get(AudacityProject &project)
Definition: Tags.cpp:214
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:360
uint32_t firstBlockSize
std::unique_ptr< wxFile > file

References AudacityMessageBox(), anonymous_namespace{ExportWavPack.cpp}::BitDepthSetting, anonymous_namespace{ExportWavPack.cpp}::BitrateSetting, anonymous_namespace{ExportWavPack.cpp}::CreateCorrectionFileSetting, ExportPlugin::CreateMixer(), WriteId::file, WriteId::firstBlockSize, floatSample, format, ProjectRate::Get(), Tags::Get(), TrackList::Get(), Tags::GetRange(), ProjectRate::GetRate(), anonymous_namespace{ExportWavPack.cpp}::HybridModeSetting, ExportPlugin::InitProgress(), int16Sample, int24Sample, anonymous_namespace{ExportWavPack.cpp}::QualitySetting, Setting< T >::Read(), SAMPLES_PER_RUN, ShowExportErrorDialog(), BasicUI::Success, WriteBlock(), and XO().

Here is the call graph for this function:

◆ OptionsCreate()

void ExportWavPack::OptionsCreate ( ShuttleGui S,
int  format 
)
overridevirtual

Implements ExportPlugin.

Definition at line 489 of file ExportWavPack.cpp.

490{
491 S.AddWindow( safenew ExportWavPackOptions{ S.GetParent(), format } );
492}
#define safenew
Definition: MemoryX.h:10
#define S(N)
Definition: ToChars.cpp:64

References format, S, and safenew.

◆ WriteBlock()

int ExportWavPack::WriteBlock ( void *  id,
void *  data,
int32_t  length 
)
static

Definition at line 463 of file ExportWavPack.cpp.

464{
465 if (id == nullptr || data == nullptr || length == 0)
466 return true; // This is considered to be success in wavpack.c reference code
467
468 WriteId *outId = static_cast<WriteId*>(id);
469
470 if (!outId->file)
471 // This does not match the wavpack.c but in our case if file is nullptr -
472 // the stream error has occured
473 return false;
474
475 // if (!outId->file->Write(data, length).IsOk()) {
476 if (outId->file->Write(data, length) != length) {
477 outId->file.reset();
478 return false;
479 }
480
481 outId->bytesWritten += length;
482
483 if (outId->firstBlockSize == 0)
484 outId->firstBlockSize = length;
485
486 return true;
487}
int id
uint32_t bytesWritten

References WriteId::bytesWritten, WriteId::file, WriteId::firstBlockSize, and id.

Referenced by Export().

Here is the caller graph for this function:

The documentation for this class was generated from the following file: