Prepare for ogg/opus encoding

This commit is contained in:
Robin Gareus 2022-12-05 23:43:34 +01:00
parent 8a7684bd2f
commit 211ff64e7d
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
6 changed files with 72 additions and 1 deletions

View File

@ -80,6 +80,7 @@ class LIBARDOUR_API ExportFormatBase {
SF_Float = SF_FORMAT_FLOAT,
SF_Double = SF_FORMAT_DOUBLE,
SF_Vorbis = SF_FORMAT_VORBIS,
SF_Opus = 0x0064, /* SF_FORMAT_OPUS */
SF_MPEG_LAYER_III = 0x0082 /* SF_FORMAT_MPEG_LAYER_III */
};

View File

@ -355,6 +355,32 @@ public:
}
};
class LIBARDOUR_API ExportFormatOggOpus : public ExportFormat, public HasSampleFormat, public HasCodecQuality
{
public:
ExportFormatOggOpus ();
~ExportFormatOggOpus (){};
bool set_compatibility_state (ExportFormatCompatibility const& compatibility);
Type get_type () const
{
return T_Sndfile;
}
SampleFormat get_explicit_sample_format () const
{
return SF_Opus;
}
int default_codec_quality () const
{
return 40;
}
virtual bool supports_tagging () const
{
return true;
}
};
class LIBARDOUR_API ExportFormatMPEG : public ExportFormat, public HasSampleFormat, public HasCodecQuality
{
public:

View File

@ -652,6 +652,7 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (ExportFormatBase, SF_Float);
REGISTER_CLASS_ENUM (ExportFormatBase, SF_Double);
REGISTER_CLASS_ENUM (ExportFormatBase, SF_Vorbis);
REGISTER_CLASS_ENUM (ExportFormatBase, SF_Opus);
REGISTER_CLASS_ENUM (ExportFormatBase, SF_MPEG_LAYER_III);
REGISTER (_ExportFormatBase_SampleFormat);

View File

@ -204,6 +204,11 @@ ExportFormatManager::init_formats ()
fl_ptr->set_extension ("raw");
add_format (f_ptr);
try {
f_ptr.reset (new ExportFormatOggOpus ());
add_format (f_ptr);
} catch (ExportFormatIncompatible & e) {}
try {
f_ptr.reset (new ExportFormatOggVorbis ());
add_format (f_ptr);

View File

@ -179,6 +179,8 @@ HasSampleFormat::get_sample_format_name (ExportFormatBase::SampleFormat format)
return _("8-bit unsigned");
case ExportFormatBase::SF_Vorbis:
return _("Vorbis sample format");
case ExportFormatBase::SF_Opus:
return _("OPUS codec");
case ExportFormatBase::SF_MPEG_LAYER_III:
return _("MPEG-2 Audio Layer III");
case ExportFormatBase::SF_None:
@ -382,6 +384,41 @@ ExportFormatBWF::set_compatibility_state (ExportFormatCompatibility const & comp
}
/*** OPUS ***/
ExportFormatOggOpus::ExportFormatOggOpus ()
: HasSampleFormat (sample_formats)
{
SF_INFO sf_info;
sf_info.channels = 2;
sf_info.samplerate = SR_44_1;
sf_info.format = F_Ogg | SF_Opus;
if (sf_format_check (&sf_info) != SF_TRUE) {
throw ExportFormatIncompatible();
}
set_name ("Ogg OPUS");
set_format_id (F_Ogg);
sample_formats.insert (SF_Opus);
// libsndfile doesn't expose direct quality control - use these coarse approximations
add_codec_quality ("Low (0%)", 0);
add_codec_quality ("Default (40%)", 40);
add_codec_quality ("High (60%)", 60);
add_codec_quality ("Very High (100%)", 100);
set_extension ("opus");
set_quality (Q_LossyCompression);
}
bool
ExportFormatOggOpus::set_compatibility_state (ExportFormatCompatibility const& compatibility)
{
bool compatible = compatibility.has_format (F_Ogg);
set_compatible (compatible);
return compatible;
}
/*** MPEG / MP3 ***/
ExportFormatMPEG::ExportFormatMPEG (std::string const& name, std::string const& ext) :

View File

@ -345,7 +345,8 @@ ExportGraphBuilder::Encoder::init_writer (boost::shared_ptr<AudioGrapher::Sndfil
writer.reset (new AudioGrapher::SndfileWriter<T> (writer_filename, format, channels, config.format->sample_rate(), config.broadcast_info));
writer->FileWritten.connect_same_thread (copy_files_connection, boost::bind (&ExportGraphBuilder::Encoder::copy_files, this, _1));
if ((format & SF_FORMAT_SUBMASK) == ExportFormatBase::SF_Vorbis ||
(format & SF_FORMAT_TYPEMASK) == ExportFormatBase::F_MPEG) {
(format & SF_FORMAT_TYPEMASK) == ExportFormatBase::F_MPEG ||
(format & SF_FORMAT_SUBMASK) == ExportFormatBase::SF_Opus) {
/* libsndfile uses range 0..1 (worst.. best) for
* SFC_SET_VBR_ENCODING_QUALITY and maps
* SFC_SET_COMPRESSION_LEVEL = 1.0 - VBR_ENCODING_QUALITY