diff --git a/au3/modules/import-export/mod-ogg/ExportOGG.cpp b/au3/modules/import-export/mod-ogg/ExportOGG.cpp index 65ae9694ed..44fdf4993f 100644 --- a/au3/modules/import-export/mod-ogg/ExportOGG.cpp +++ b/au3/modules/import-export/mod-ogg/ExportOGG.cpp @@ -16,9 +16,57 @@ #include #include +namespace { +/* i18n-hint: kbit/s abbreviates "thousands of bits per second" */ +TranslatableString n_kbps(int n) +{ + return XO("%d kbit/s").Format(n); +} + +enum : int { + OptionIDOGGBitRate = 1, +}; + +// NOTE: there's a nominal Quality -> bitrate conversion in Ogg Vorbis +// but effective bitrate may vary depending on sample rate +const PlainExportOptionsEditor::OptionDesc OGGOptionBitrate { + { + OptionIDOGGBitRate, XO("Quality"), + 6, + ExportOption::TypeEnum, + { + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + }, + { + n_kbps(64), + n_kbps(80), + n_kbps(96), + n_kbps(112), + n_kbps(128), + n_kbps(160), + n_kbps(192), + n_kbps(224), + n_kbps(256), + n_kbps(320), + n_kbps(500), + } + }, wxT("/FileFormats/OGG/Bitrate") +}; +} + ExportOptionOGGEditor::ExportOptionOGGEditor() { - mQualityUnscaled = *std::get_if(&OGGQualityOption.defaultValue); + mQualityUnscaled = *std::get_if(&OGGOptionBitrate.option.defaultValue); } std::string ExportOptionOGGEditor::GetName() const @@ -33,7 +81,7 @@ int ExportOptionOGGEditor::GetOptionsCount() const bool ExportOptionOGGEditor::GetOption(int, ExportOption& option) const { - option = OGGQualityOption; + option = OGGOptionBitrate.option; return true; } @@ -59,12 +107,12 @@ ExportOptionOGGEditor::SampleRateList ExportOptionOGGEditor::GetSampleRateList() void ExportOptionOGGEditor::Load(const audacity::BasicSettings& config) { - mQualityUnscaled = config.Read(wxT("/FileFormats/OggExportQuality"), 50) / 10; + mQualityUnscaled = config.Read(wxT("/FileFormats/OGG/Bitrate"), 50) / 10; } void ExportOptionOGGEditor::Store(audacity::BasicSettings& config) const { - config.Write(wxT("/FileFormats/OggExportQuality"), mQualityUnscaled * 10); + config.Write(wxT("/FileFormats/OGG/Bitrate"), mQualityUnscaled * 10); } ExportOGG::ExportOGG() = default; @@ -108,7 +156,8 @@ bool OGGExportProcessor::Initialize(AudacityProject& project, context.t1 = t1; context.numChannels = numChannels; - double quality = ExportPluginHelpers::GetParameterValue(parameters, 0, 5) / 10.0; + double quality = ExportPluginHelpers::GetParameterValue( + parameters, OptionIDOGGBitRate, 6) / 10.0; wxLogNull logNo; // temporarily disable wxWidgets error messages diff --git a/au3/modules/import-export/mod-ogg/ExportOGG.h b/au3/modules/import-export/mod-ogg/ExportOGG.h index 4532645cb9..685a6e3c9f 100644 --- a/au3/modules/import-export/mod-ogg/ExportOGG.h +++ b/au3/modules/import-export/mod-ogg/ExportOGG.h @@ -21,17 +21,6 @@ #define SAMPLES_PER_RUN 8192u -enum : int { - OptionIDOGGQuality = 0 -}; - -const ExportOption OGGQualityOption { - OptionIDOGGQuality, XO("Quality"), - 5, - ExportOption::TypeRange, - { 0, 10 } -}; - class ExportOptionOGGEditor final : public ExportOptionsEditor { public: diff --git a/src/importexport/export/iexporter.h b/src/importexport/export/iexporter.h index 8455f2c47e..d6a1640b3b 100644 --- a/src/importexport/export/iexporter.h +++ b/src/importexport/export/iexporter.h @@ -23,6 +23,7 @@ public: virtual int formatIndex(const std::string& format) const = 0; virtual std::vector formatExtensions(const std::string& format) const = 0; virtual bool isCustomFFmpegExportFormat() const = 0; + virtual bool isOggExportFormat() const = 0; virtual bool hasMetadata() const = 0; virtual int maxChannels() const = 0; diff --git a/src/importexport/export/internal/au3/au3exporter.cpp b/src/importexport/export/internal/au3/au3exporter.cpp index c0937c8754..216d8f4a37 100644 --- a/src/importexport/export/internal/au3/au3exporter.cpp +++ b/src/importexport/export/internal/au3/au3exporter.cpp @@ -275,6 +275,16 @@ bool Au3Exporter::isCustomFFmpegExportFormat() const return editor->GetName() == "custom_ffmpeg"; } +bool Au3Exporter::isOggExportFormat() const +{ + OptionsEditorUPtr editor = optionsEditor(); + if (!editor) { + return false; + } + + return editor->GetName() == "ogg"; +} + bool Au3Exporter::hasMetadata() const { std::string format = exportConfiguration()->currentFormat(); diff --git a/src/importexport/export/internal/au3/au3exporter.h b/src/importexport/export/internal/au3/au3exporter.h index 018f74db59..24f8f560a0 100644 --- a/src/importexport/export/internal/au3/au3exporter.h +++ b/src/importexport/export/internal/au3/au3exporter.h @@ -33,6 +33,7 @@ public: int formatIndex(const std::string& format) const override; std::vector formatExtensions(const std::string& format) const override; bool isCustomFFmpegExportFormat() const override; + bool isOggExportFormat() const override; bool hasMetadata() const override; int maxChannels() const override; diff --git a/src/importexport/export/qml/Export/ExportDialog.qml b/src/importexport/export/qml/Export/ExportDialog.qml index d3950ba332..a4eb9742a4 100644 --- a/src/importexport/export/qml/Export/ExportDialog.qml +++ b/src/importexport/export/qml/Export/ExportDialog.qml @@ -509,6 +509,21 @@ StyledDialogView { } } } + + RowLayout { + + visible: exportPreferencesModel.oggFormatOptionsVisible + + Item { + width: root.labelColumnWidth + } + + StyledTextLabel { + id: oggWarning + + text: qsTrc("export", "Effective bitrate may vary") + } + } } } diff --git a/src/importexport/export/view/exportpreferencesmodel.cpp b/src/importexport/export/view/exportpreferencesmodel.cpp index ae4ecc7617..48e9c06255 100644 --- a/src/importexport/export/view/exportpreferencesmodel.cpp +++ b/src/importexport/export/view/exportpreferencesmodel.cpp @@ -265,6 +265,7 @@ void ExportPreferencesModel::setCurrentFormat(const QString& format) exportConfiguration()->setCurrentFormat(format.toStdString()); emit customFFmpegOptionsVisibleChanged(); + emit oggFormatOptionsVisibleChanged(); emit hasMetadataChanged(); } @@ -466,6 +467,11 @@ bool ExportPreferencesModel::customFFmpegOptionsVisible() return exporter()->isCustomFFmpegExportFormat(); } +bool ExportPreferencesModel::oggFormatOptionsVisible() +{ + return exporter()->isOggExportFormat(); +} + bool ExportPreferencesModel::hasMetadata() { return exporter()->hasMetadata(); diff --git a/src/importexport/export/view/exportpreferencesmodel.h b/src/importexport/export/view/exportpreferencesmodel.h index c0488f15ed..8baa0e4e05 100644 --- a/src/importexport/export/view/exportpreferencesmodel.h +++ b/src/importexport/export/view/exportpreferencesmodel.h @@ -52,6 +52,7 @@ class ExportPreferencesModel : public QObject, public muse::async::Asyncable // dynamic inputs section Q_PROPERTY(bool customFFmpegOptionsVisible READ customFFmpegOptionsVisible NOTIFY customFFmpegOptionsVisibleChanged) + Q_PROPERTY(bool oggFormatOptionsVisible READ oggFormatOptionsVisible NOTIFY oggFormatOptionsVisibleChanged) Q_PROPERTY(bool hasMetadata READ hasMetadata NOTIFY hasMetadataChanged) Q_PROPERTY(int optionsCount READ optionsCount NOTIFY optionsCountChanged) @@ -96,6 +97,7 @@ public: // dynamic inputs bool customFFmpegOptionsVisible(); + bool oggFormatOptionsVisible(); bool hasMetadata(); int optionsCount(); @@ -113,6 +115,7 @@ signals: void exportSampleRateListChanged(); void customFFmpegOptionsVisibleChanged(); + void oggFormatOptionsVisibleChanged(); void hasMetadataChanged(); void optionsCountChanged(); void optionTitleListChanged();