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

Public Member Functions

 ~WavPackExportProcessor ()
 
bool Initialize (AudacityProject &project, const Parameters &parameters, const wxFileNameWrapper &filename, double t0, double t1, bool selectedOnly, double sampleRate, unsigned channels, MixerOptions::Downmix *mixerSpec, const Tags *tags) override
 Called before start processing. More...
 
ExportResult Process (ExportProcessorDelegate &delegate) override
 
- Public Member Functions inherited from ExportProcessor
 ExportProcessor (const ExportProcessor &)=delete
 
ExportProcessoroperator= (const ExportProcessor &)=delete
 
 ExportProcessor ()=default
 
virtual ~ExportProcessor ()
 
virtual bool Initialize (AudacityProject &project, const Parameters &parameters, const wxFileNameWrapper &filename, double t0, double t1, bool selectedOnly, double rate, unsigned channels, MixerOptions::Downmix *mixerSpec=nullptr, const Tags *tags=nullptr)=0
 Called before start processing. More...
 
virtual ExportResult Process (ExportProcessorDelegate &delegate)=0
 

Static Private Member Functions

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

Private Attributes

struct {
   TranslatableString   status
 
   double   t0
 
   double   t1
 
   unsigned   numChannels
 
   wxFileNameWrapper   fName
 
   sampleFormat   format
 
   WriteId   outWvFile
 
   WriteId   outWvcFile
 
   WavpackContext *   wpc {}
 
   std::unique_ptr< Mixer >   mixer
 
   std::unique_ptr< Tags >   metadata
 
context
 

Static Private Attributes

static constexpr size_t SAMPLES_PER_RUN = 8192u
 

Additional Inherited Members

- Public Types inherited from ExportProcessor
using Parameters = std::vector< std::tuple< ExportOptionID, ExportValue > >
 

Detailed Description

Definition at line 244 of file ExportWavPack.cpp.

Constructor & Destructor Documentation

◆ ~WavPackExportProcessor()

WavPackExportProcessor::~WavPackExportProcessor ( )

Definition at line 373 of file ExportWavPack.cpp.

374{
375 if(context.wpc)
376 WavpackCloseFile(context.wpc);
377}
struct WavPackExportProcessor::@186 context

References context.

Member Function Documentation

◆ Initialize()

bool WavPackExportProcessor::Initialize ( AudacityProject project,
const Parameters parameters,
const wxFileNameWrapper filename,
double  t0,
double  t1,
bool  selectedOnly,
double  rate,
unsigned  channels,
MixerOptions::Downmix mixerSpec,
const Tags tags 
)
overridevirtual

Called before start processing.

Parameters
projectProcessor may access project data, take care to exclude any data race
parametersA format-dependent set of parameters used in exporting
selectedOnlySet to true if all tracks should be mixed, to false if only the selected tracks should be mixed and exported.
tagsA Tags object that will over-ride the one in *project and be used to tag the file that is exported. @retern Implementations may simply return false without any error reporting. This is to temporarily preserve old behavior, which is to be removed in the nearest future.

Implements ExportProcessor.

Definition at line 379 of file ExportWavPack.cpp.

386{
387 context.t0 = t0;
388 context.t1 = t1;
389 context.numChannels = numChannels;
390 context.fName = fName;
391
392 WavpackConfig config = {};
393 auto& outWvFile = context.outWvFile;
394 auto& outWvcFile = context.outWvcFile;
395 outWvFile.file = std::make_unique< wxFile >();
396
397 if (!outWvFile.file->Create(fName.GetFullPath(), true) || !outWvFile.file->IsOpened()) {
398 throw ExportException(_("Unable to open target file for writing"));
399 }
400
401 const auto quality = ExportPluginHelpers::GetParameterValue<int>(
402 parameters,
404 1);
405 const auto hybridMode = ExportPluginHelpers::GetParameterValue<bool>(
406 parameters,
408 false);
409 const auto createCorrectionFile = ExportPluginHelpers::GetParameterValue<bool>(
410 parameters,
412 false);
413 const auto bitRate = ExportPluginHelpers::GetParameterValue<int>(
414 parameters,
416 40);
417 const auto bitDepth = ExportPluginHelpers::GetParameterValue<int>(
418 parameters,
420 16);
421
422
423 context.format = int16Sample;
424 if (bitDepth == 24) {
425 context.format = int24Sample;
426 } else if (bitDepth == 32) {
427 context.format = floatSample;
428 }
429
430 config.num_channels = numChannels;
431 config.sample_rate = sampleRate;
432 config.bits_per_sample = bitDepth;
433 config.bytes_per_sample = bitDepth/8;
434 config.float_norm_exp = context.format == floatSample ? 127 : 0;
435
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;
440 else
441 config.channel_mask = 0x3FFFF;
442
443 if (quality == 0) {
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;
449 }
450
451 if (hybridMode) {
452 config.flags |= CONFIG_HYBRID_FLAG;
453 config.bitrate = bitRate / 10.0;
454
455 if (createCorrectionFile) {
456 config.flags |= CONFIG_CREATE_WVC;
457
458 outWvcFile.file = std::make_unique< wxFile >();
459 if (!outWvcFile.file->Create(fName.GetFullPath().Append("c"), true)) {
460 throw ExportException(_("Unable to create target file for writing"));
461 }
462 }
463 }
464
465 // If we're not creating a correction file now, any one that currently exists with this name
466 // will become obsolete now, so delete it if it happens to exist (although it usually won't)
467
468 if (!hybridMode || !createCorrectionFile)
469 wxRemoveFile(fName.GetFullPath().Append("c"));
470
471 context.wpc = WavpackOpenFileOutput(WriteBlock, &outWvFile, createCorrectionFile ? &outWvcFile : nullptr);
472 if (!WavpackSetConfiguration64(context.wpc, &config, -1, nullptr) || !WavpackPackInit(context.wpc)) {
473 throw ExportErrorException( WavpackGetErrorMessage(context.wpc) );
474 }
475
476 context.status = selectionOnly
477 ? XO("Exporting selected audio as WavPack")
478 : XO("Exporting the audio as WavPack");
479
480 context.metadata = std::make_unique<Tags>(
481 metadata == nullptr
482 ? Tags::Get( project )
483 : *metadata
484 );
485
487 project, selectionOnly, t0, t1, numChannels, SAMPLES_PER_RUN, true,
488 sampleRate, context.format, mixerSpec);
489
490 return true;
491}
XO("Cut/Copy/Paste")
#define _(s)
Definition: Internat.h:73
const auto project
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)
static Tags & Get(AudacityProject &project)
Definition: Tags.cpp:214
static constexpr size_t SAMPLES_PER_RUN
static int WriteBlock(void *id, void *data, int32_t length)
wxFileNameWrapper fName
std::unique_ptr< Tags > metadata
std::unique_ptr< wxFile > file

References _, context, ExportPluginHelpers::CreateMixer(), WriteId::file, floatSample, fName, Tags::Get(), int16Sample, int24Sample, metadata, numChannels, anonymous_namespace{ExportWavPack.cpp}::OptionIDBitDepth, anonymous_namespace{ExportWavPack.cpp}::OptionIDBitRate, anonymous_namespace{ExportWavPack.cpp}::OptionIDCreateCorrection, anonymous_namespace{ExportWavPack.cpp}::OptionIDHybridMode, anonymous_namespace{ExportWavPack.cpp}::OptionIDQuality, outWvcFile, outWvFile, project, anonymous_namespace{ClipSegmentTest.cpp}::sampleRate, SAMPLES_PER_RUN, t0, t1, WriteBlock(), and XO().

Here is the call graph for this function:

◆ Process()

ExportResult WavPackExportProcessor::Process ( ExportProcessorDelegate delegate)
overridevirtual

Implements ExportProcessor.

Definition at line 493 of file ExportWavPack.cpp.

494{
495 delegate.SetStatusString(context.status);
496
497 const size_t bufferSize = SAMPLES_PER_RUN * context.numChannels;
498
499 ArrayOf<int32_t> wavpackBuffer{ bufferSize };
500
501 auto exportResult = ExportResult::Success;
502 {
503
504 while (exportResult == ExportResult::Success) {
505 auto samplesThisRun = context.mixer->Process();
506
507 if (samplesThisRun == 0)
508 break;
509
510 if (context.format == int16Sample) {
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;
515 }
516 }
517 } else {
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++;
522 }
523 }
524 }
525
526 if (!WavpackPackSamples(context.wpc, wavpackBuffer.get(), samplesThisRun)) {
527 throw ExportErrorException(WavpackGetErrorMessage(context.wpc));
528 }
530 delegate, *context.mixer, context.t0, context.t1);
531 }
532 }
533
534 if (!WavpackFlushSamples(context.wpc)) {
535 throw ExportErrorException( WavpackGetErrorMessage(context.wpc) );
536 } else {
537
538
539 wxString n;
540 for (const auto &pair : context.metadata->GetRange()) {
541 n = pair.first;
542 const auto &v = pair.second;
543
544 WavpackAppendTagItem(context.wpc,
545 n.mb_str(wxConvUTF8),
546 v.mb_str(wxConvUTF8),
547 static_cast<int>( strlen(v.mb_str(wxConvUTF8)) ));
548 }
549
550 if (!WavpackWriteTag(context.wpc)) {
551 throw ExportErrorException( WavpackGetErrorMessage(context.wpc) );
552 }
553 }
554
555 if ( !context.outWvFile.file.get()->Close()
556 || ( context.outWvcFile.file && context.outWvcFile.file.get() && !context.outWvcFile.file.get()->Close())) {
557 return ExportResult::Error;
558 }
559
560 // wxFile::Create opens the file with only write access
561 // So, need to open the file again with both read and write access
562 if (!context.outWvFile.file->Open(context.fName.GetFullPath(), wxFile::read_write)) {
563 throw ExportErrorException("Unable to update the actual length of the file");
564 }
565
566 ArrayOf<int32_t> firstBlockBuffer { context.outWvFile.firstBlockSize };
567 context.outWvFile.file->Read(firstBlockBuffer.get(), context.outWvFile.firstBlockSize);
568
569 // Update the first block written with the actual number of samples written
570 WavpackUpdateNumSamples(context.wpc, firstBlockBuffer.get());
571 context.outWvFile.file->Seek(0);
572 context.outWvFile.file->Write(firstBlockBuffer.get(), context.outWvFile.firstBlockSize);
573
574 if ( !context.outWvFile.file.get()->Close() ) {
575 return ExportResult::Error;
576 }
577 return exportResult;
578}
This simplifies arrays of arrays, each array separately allocated with NEW[] But it might be better t...
Definition: MemoryX.h:29
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...
virtual void SetStatusString(const TranslatableString &str)=0

References context, Error, int16Sample, SAMPLES_PER_RUN, ExportProcessorDelegate::SetStatusString(), Success, and ExportPluginHelpers::UpdateProgress().

Here is the call graph for this function:

◆ WriteBlock()

int WavPackExportProcessor::WriteBlock ( void *  id,
void *  data,
int32_t  length 
)
staticprivate

Definition at line 583 of file ExportWavPack.cpp.

584{
585 if (id == nullptr || data == nullptr || length == 0)
586 return true; // This is considered to be success in wavpack.c reference code
587
588 WriteId *outId = static_cast<WriteId*>(id);
589
590 if (!outId->file)
591 // This does not match the wavpack.c but in our case if file is nullptr -
592 // the stream error has occured
593 return false;
594
595 // if (!outId->file->Write(data, length).IsOk()) {
596 if (outId->file->Write(data, length) != length) {
597 outId->file.reset();
598 return false;
599 }
600
601 outId->bytesWritten += length;
602
603 if (outId->firstBlockSize == 0)
604 outId->firstBlockSize = length;
605
606 return true;
607}
int id
uint32_t bytesWritten
uint32_t firstBlockSize

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

Referenced by Initialize().

Here is the caller graph for this function:

Member Data Documentation

◆ 

struct { ... } WavPackExportProcessor::context

◆ fName

wxFileNameWrapper WavPackExportProcessor::fName

Definition at line 255 of file ExportWavPack.cpp.

Referenced by Initialize().

◆ format

sampleFormat WavPackExportProcessor::format

Definition at line 256 of file ExportWavPack.cpp.

◆ metadata

std::unique_ptr<Tags> WavPackExportProcessor::metadata

Definition at line 260 of file ExportWavPack.cpp.

Referenced by Initialize().

◆ mixer

std::unique_ptr<Mixer> WavPackExportProcessor::mixer

Definition at line 259 of file ExportWavPack.cpp.

◆ numChannels

unsigned WavPackExportProcessor::numChannels

Definition at line 254 of file ExportWavPack.cpp.

Referenced by Initialize().

◆ outWvcFile

WriteId WavPackExportProcessor::outWvcFile

Definition at line 257 of file ExportWavPack.cpp.

Referenced by Initialize().

◆ outWvFile

WriteId WavPackExportProcessor::outWvFile

Definition at line 257 of file ExportWavPack.cpp.

Referenced by Initialize().

◆ SAMPLES_PER_RUN

constexpr size_t WavPackExportProcessor::SAMPLES_PER_RUN = 8192u
staticconstexprprivate

Definition at line 247 of file ExportWavPack.cpp.

Referenced by Initialize(), and Process().

◆ status

TranslatableString WavPackExportProcessor::status

Definition at line 251 of file ExportWavPack.cpp.

◆ t0

double WavPackExportProcessor::t0

Definition at line 252 of file ExportWavPack.cpp.

Referenced by Initialize().

◆ t1

double WavPackExportProcessor::t1

Definition at line 253 of file ExportWavPack.cpp.

Referenced by Initialize().

◆ wpc

WavpackContext* WavPackExportProcessor::wpc {}

Definition at line 258 of file ExportWavPack.cpp.


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