50#define LIBTWOLAME_STATIC
60 struct id3_frame *id3_frame_new(
char const *);
61 id3_length_t id3_latin1_length(id3_latin1_t
const *);
62 void id3_latin1_decode(id3_latin1_t
const *, id3_ucs4_t *);
122 {
XO(
"MPEG2"),
XO(
"MPEG1") },
129 { 32, 48, 56, 64, 80, 96,112,128,160, 192, 224, 256, 320, 384 },
136 { 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 },
146 std::unordered_map<ExportOptionID, ExportValue>
mValues;
153 mValues[option.id] = option.defaultValue;
158 return static_cast<int>(
mOptions.size());
162 if(index >= 0 && index <
mOptions.size())
171 const auto it =
mValues.find(
id);
182 if(it ==
mValues.end() || it->second.index() != value.index())
206 if(*std::get_if<int>(&it->second) == TWOLAME_MPEG1)
207 return { 32000, 44100, 48000 };
208 return {16000, 22050, 24000 };
213 config.
Write(
wxT(
"/FileFormats/MP2Version"), *std::get_if<int>(&it->second));
215 config.
Write(
wxT(
"/FileFormats/MP2BitrateMPEG1"), *std::get_if<int>(&it->second));
217 config.
Write(
wxT(
"/FileFormats/MP2BitrateMPEG2"), *std::get_if<int>(&it->second));
269 double t0,
double t1,
bool selectedOnly,
272 const Tags* tags)
override;
279 static void AddFrame(
struct id3_tag *tp,
const wxString & n,
const wxString & v,
const char *
name);
295 std::unique_ptr<ExportOptionsEditor>
311 wxT(
"MP2"),
XO(
"MP2 Files"), {
wxT(
"mp2") }, 2,
true
315std::unique_ptr<ExportOptionsEditor>
318 return std::make_unique<MP2ExportOptionsEditor>(listener);
323 return std::make_unique<MP2ExportProcessor>();
329 twolame_close(&
context.encodeOptions);
336 double t0,
double t1,
bool selectionOnly,
339 const Tags* metadata)
345 bool stereo = (channels == 2);
346 const auto version =
static_cast<TWOLAME_MPEG_version
>(
350 const auto bitrate = version == TWOLAME_MPEG1
372 throw ExportException(
_(
"Cannot export MP2 with this sample rate and bit rate"));
376 if (metadata == NULL)
380 if (!
context.outFile->IsOpened()) {
386 if (
context.id3len && !endOfFile) {
396 ?
XO(
"Exporting selected audio at %ld kbps")
398 :
XO(
"Exporting the audio at %ld kbps")
421 auto pcmNumSamples =
context.mixer->Process();
422 if (pcmNumSamples == 0)
425 short *pcmBuffer = (
short *)
context.mixer->GetBuffer();
427 int mp2BufferNumBytes = twolame_encode_buffer_interleaved(
434 if (mp2BufferNumBytes < 0) {
439 if (
context.outFile->Write(mp2Buffer.get(), mp2BufferNumBytes).GetLastError() ) {
448 int mp2BufferNumBytes = twolame_encode_flush(
453 if (mp2BufferNumBytes > 0)
454 if (
context.outFile->Write(mp2Buffer.get(), mp2BufferNumBytes).GetLastError() ) {
467 if ( !
context.outFile->Close() ) {
476struct id3_tag_deleter {
477 void operator () (id3_tag *p)
const {
if (p) id3_tag_delete(p); }
479using id3_tag_holder = std::unique_ptr<id3_tag, id3_tag_deleter>;
484 bool *endOfFile,
const Tags *tags)
487 id3_tag_holder tp { id3_tag_new() };
489 for (
const auto &pair : tags->
GetRange()) {
490 const auto &n = pair.first;
491 const auto &v = pair.second;
492 const char *
name =
"TXXX";
495 name = ID3_FRAME_TITLE;
498 name = ID3_FRAME_ARTIST;
501 name = ID3_FRAME_ALBUM;
503 else if (n.CmpNoCase(
TAG_YEAR) == 0) {
506 AddFrame(tp.get(), n, v,
"TYER");
507 name = ID3_FRAME_YEAR;
510 name = ID3_FRAME_GENRE;
513 name = ID3_FRAME_COMMENT;
516 name = ID3_FRAME_TRACK;
519 AddFrame(tp.get(), n, v,
name);
522 tp->options &= (~ID3_TAG_OPTION_COMPRESSION);
527 #ifdef ID3_TAG_HAS_TAG_OPTION_ID3V2_3
528 tp->options |= ID3_TAG_OPTION_ID3V2_3;
535 len = id3_tag_render(tp.get(), 0);
537 len = id3_tag_render(tp.get(), (id3_byte_t *)buffer.get());
547void MP2ExportProcessor::AddFrame(
struct id3_tag *tp,
const wxString & n,
const wxString & v,
const char *
name)
549 struct id3_frame *frame = id3_frame_new(
name);
551 if (!n.IsAscii() || !v.IsAscii()) {
552 id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_UTF_16);
555 id3_field_settextencoding(id3_frame_field(frame, 0), ID3_FIELD_TEXTENCODING_ISO_8859_1);
559 id3_utf8_ucs4duplicate((id3_utf8_t *) (
const char *) v.mb_str(wxConvUTF8)) };
561 if (strcmp(
name, ID3_FRAME_COMMENT) == 0) {
567 id3_field *f = id3_frame_field(frame, 1);
568 memset(f->immediate.value, 0,
sizeof(f->immediate.value));
569 id3_field_setfullstring(id3_frame_field(frame, 3), ucs4.get());
571 else if (strcmp(
name,
"TXXX") == 0) {
572 id3_field_setstring(id3_frame_field(frame, 2), ucs4.get());
574 ucs4.reset(id3_utf8_ucs4duplicate((id3_utf8_t *) (
const char *) n.mb_str(wxConvUTF8)));
576 id3_field_setstring(id3_frame_field(frame, 1), ucs4.get());
579 auto addr = ucs4.get();
580 id3_field_setstrings(id3_frame_field(frame, 1), 1, &addr);
583 id3_tag_attachframe(tp, frame);
588 []{
return std::make_unique< ExportMP2 >(); }
const TranslatableString name
static ExportPluginRegistry::RegisteredPlugin sRegisteredPlugin
TranslatableString n_kbps(int n)
std::variant< bool, int, double, std::string > ExportValue
A type of option values (parameters) used by exporting plugins.
std::unique_ptr< Character[], freer > MallocString
declares abstract base class Track, TrackList, and iterators over TrackList
std::vector< TranslatableString > TranslatableStrings
void reinit(Integral count, bool initialize=false)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
int GetFormatCount() const override
std::unique_ptr< ExportProcessor > CreateProcessor(int) 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 ...
FormatInfo GetFormatInfo(int) const override
Returns FormatInfo structure for given index if it's valid, or a default one. FormatInfo::format isn'...
Listener object that is used to report on option changes.
virtual void OnExportOptionChangeEnd()=0
Called after OnExportOptionChange
virtual void OnExportOptionChangeBegin()=0
Called before OnExportOptionChange
virtual void OnExportOptionChange(const ExportOption &option)=0
Called when option change.
virtual void OnSampleRateListChange()=0
Editor objects are used to retrieve a set of export options, and configure exporting parameters accor...
std::vector< int > SampleRateList
static T GetParameterValue(const ExportProcessor::Parameters ¶meters, int id, T defaultValue=T())
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
std::vector< ExportOption > mOptions
bool GetOption(int index, ExportOption &option) const override
void Load(const audacity::BasicSettings &config) override
std::unordered_map< ExportOptionID, ExportValue > mValues
bool GetValue(ExportOptionID id, ExportValue &value) const override
int GetOptionsCount() const override
MP2ExportOptionsEditor(Listener *listener)
SampleRateList GetSampleRateList() const override
void Store(audacity::BasicSettings &config) const override
bool SetValue(ExportOptionID id, const ExportValue &value) override
ArrayOf< char > id3buffer
static constexpr size_t mp2BufferSize
ExportResult Process(ExportProcessorDelegate &delegate) override
std::unique_ptr< FileIO > outFile
twolame_options * encodeOptions
struct MP2ExportProcessor::@165 context
static int AddTags(ArrayOf< char > &buffer, bool *endOfFile, const Tags *tags)
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.
TranslatableString status
std::unique_ptr< Mixer > mixer
~MP2ExportProcessor() override
static constexpr size_t pcmBufferSize
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.
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 std::initializer_list< ExportOption > MP2Options
const TranslatableStrings BitRateMPEG2Names
@ MP2OptionIDBitRateMPEG2
@ MP2OptionIDBitRateMPEG1
const TranslatableStrings BitRateMPEG1Names
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.
@ Hidden
Option is not used and may be hidden from the user.