diff --git a/include/AudioFileDevice.h b/include/AudioFileDevice.h index 70ea48843..7b6b81eab 100644 --- a/include/AudioFileDevice.h +++ b/include/AudioFileDevice.h @@ -29,19 +29,15 @@ #include #include "AudioDevice.h" +#include "OutputSettings.h" class AudioFileDevice : public AudioDevice { public: - AudioFileDevice( const sample_rate_t _sample_rate, - const ch_cnt_t _channels, const QString & _file, - const bool _use_vbr, - const bitrate_t _nom_bitrate, - const bitrate_t _min_bitrate, - const bitrate_t _max_bitrate, - const int _depth, - Mixer* mixer ); + AudioFileDevice(OutputSettings const & outputSettings, + const ch_cnt_t _channels, const QString & _file, + Mixer* mixer ); virtual ~AudioFileDevice(); QString outputFile() const @@ -49,35 +45,12 @@ public: return m_outputFile.fileName(); } + OutputSettings const & getOutputSettings() const { return m_outputSettings; } + protected: int writeData( const void* data, int len ); - inline bool useVBR() const - { - return m_useVbr; - } - - inline bitrate_t nominalBitrate() const - { - return m_nomBitrate; - } - - inline bitrate_t minBitrate() const - { - return m_minBitrate; - } - - inline bitrate_t maxBitrate() const - { - return m_maxBitrate; - } - - inline int depth() const - { - return m_depth; - } - inline bool outputFileOpened() const { return m_outputFile.isOpen(); @@ -86,29 +59,16 @@ protected: private: QFile m_outputFile; - - bool m_useVbr; - - bitrate_t m_nomBitrate; - bitrate_t m_minBitrate; - bitrate_t m_maxBitrate; - - int m_depth; - + OutputSettings m_outputSettings; } ; typedef AudioFileDevice * ( * AudioFileDeviceInstantiaton ) - ( const sample_rate_t _sample_rate, - const ch_cnt_t _channels, - bool & _success_ful, - const QString & _file, - const bool _use_vbr, - const bitrate_t _nom_bitrate, - const bitrate_t _min_bitrate, - const bitrate_t _max_bitrate, - const int _depth, - Mixer* mixer ); + ( const QString & outputFilename, + OutputSettings const & outputSettings, + const ch_cnt_t channels, + Mixer* mixer, + bool & successful ); #endif diff --git a/include/AudioFileOgg.h b/include/AudioFileOgg.h index 50728fd96..656a7174e 100644 --- a/include/AudioFileOgg.h +++ b/include/AudioFileOgg.h @@ -38,33 +38,21 @@ class AudioFileOgg : public AudioFileDevice { public: - AudioFileOgg( const sample_rate_t _sample_rate, + AudioFileOgg( OutputSettings const & outputSettings, const ch_cnt_t _channels, bool & _success_ful, const QString & _file, - const bool _use_vbr, - const bitrate_t _nom_bitrate, - const bitrate_t _min_bitrate, - const bitrate_t _max_bitrate, - const int _depth, Mixer* mixer ); virtual ~AudioFileOgg(); - static AudioFileDevice * getInst( const sample_rate_t _sample_rate, - const ch_cnt_t _channels, - bool & _success_ful, - const QString & _file, - const bool _use_vbr, - const bitrate_t _nom_bitrate, - const bitrate_t _min_bitrate, - const bitrate_t _max_bitrate, - const int _depth, - Mixer* mixer ) + static AudioFileDevice * getInst( const QString & outputFilename, + OutputSettings const & outputSettings, + const ch_cnt_t channels, + Mixer* mixer, + bool & successful ) { - return new AudioFileOgg( _sample_rate, _channels, _success_ful, - _file, _use_vbr, _nom_bitrate, - _min_bitrate, _max_bitrate, - _depth, mixer ); + return new AudioFileOgg( outputSettings, channels, successful, + outputFilename, mixer ); } @@ -77,15 +65,33 @@ private: void finishEncoding(); inline int writePage(); + inline bitrate_t nominalBitrate() const + { + return getOutputSettings().getBitRateSettings().getBitRate(); + } + inline bitrate_t minBitrate() const + { + if (nominalBitrate() > 64) + { + return nominalBitrate() - 64; + } + else + { + return 64; + } + } + + inline bitrate_t maxBitrate() const + { + return nominalBitrate() + 64; + } + +private: bool m_ok; ch_cnt_t m_channels; sample_rate_t m_rate; - // Various bitrate/quality options - bitrate_t m_minBitrate; - bitrate_t m_maxBitrate; - uint32_t m_serialNo; vorbis_comment * m_comments; diff --git a/include/AudioFileWave.h b/include/AudioFileWave.h index 88dfa89b0..4d2778bad 100644 --- a/include/AudioFileWave.h +++ b/include/AudioFileWave.h @@ -35,34 +35,21 @@ class AudioFileWave : public AudioFileDevice { public: - AudioFileWave( const sample_rate_t _sample_rate, - const ch_cnt_t _channels, - bool & _success_ful, - const QString & _file, - const bool _use_vbr, - const bitrate_t _nom_bitrate, - const bitrate_t _min_bitrate, - const bitrate_t _max_bitrate, - const int _depth, + AudioFileWave( OutputSettings const & outputSettings, + const ch_cnt_t channels, + bool & successful, + const QString & file, Mixer* mixer ); virtual ~AudioFileWave(); - static AudioFileDevice * getInst( const sample_rate_t _sample_rate, - const ch_cnt_t _channels, - bool & _success_ful, - const QString & _file, - const bool _use_vbr, - const bitrate_t _nom_bitrate, - const bitrate_t _min_bitrate, - const bitrate_t _max_bitrate, - const int _depth, - Mixer* mixer ) + static AudioFileDevice * getInst( const QString & outputFilename, + OutputSettings const & outputSettings, + const ch_cnt_t channels, + Mixer* mixer, + bool & successful ) { - return new AudioFileWave( _sample_rate, _channels, - _success_ful, _file, _use_vbr, - _nom_bitrate, _min_bitrate, - _max_bitrate, _depth, - mixer ); + return new AudioFileWave( outputSettings, channels, successful, + outputFilename, mixer ); } @@ -74,11 +61,9 @@ private: bool startEncoding(); void finishEncoding(); - +private: SF_INFO m_si; SNDFILE * m_sf; - } ; - #endif diff --git a/include/OutputSettings.h b/include/OutputSettings.h new file mode 100644 index 000000000..1aecb7df0 --- /dev/null +++ b/include/OutputSettings.h @@ -0,0 +1,84 @@ +/* + * OutputSettings.h - Stores the settings for file rendering + * + * Copyright (c) 2008-2009 Tobias Doerffel + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef OUTPUT_SETTINGS_H +#define OUTPUT_SETTINGS_H + + +class OutputSettings +{ +public: + enum BitDepth + { + Depth_16Bit, + Depth_24Bit, + Depth_32Bit, + NumDepths + }; + + class BitRateSettings + { + public: + BitRateSettings(bitrate_t bitRate, bool isVariableBitRate) : + m_bitRate(bitRate), + m_isVariableBitRate(isVariableBitRate) + {} + + bool isVariableBitRate() const { return m_isVariableBitRate; } + void setVariableBitrate(bool variableBitRate = true) { m_isVariableBitRate = variableBitRate; } + + bitrate_t getBitRate() const { return m_bitRate; } + void setBitRate(bitrate_t bitRate) { m_bitRate = bitRate; } + + private: + bitrate_t m_bitRate; + bool m_isVariableBitRate; + }; + +public: + OutputSettings( sample_rate_t sampleRate, + BitRateSettings const & bitRateSettings, + BitDepth bitDepth ) : + m_sampleRate(sampleRate), + m_bitRateSettings(bitRateSettings), + m_bitDepth(bitDepth) + { + } + + sample_rate_t getSampleRate() const { return m_sampleRate; } + void setSampleRate(sample_rate_t sampleRate) { m_sampleRate = sampleRate; } + + BitRateSettings const & getBitRateSettings() const { return m_bitRateSettings; } + void setBitRateSettings(BitRateSettings const & bitRateSettings) { m_bitRateSettings = bitRateSettings; } + + BitDepth getBitDepth() const { return m_bitDepth; } + void setBitDepth(BitDepth bitDepth) { m_bitDepth = bitDepth; } + +private: + sample_rate_t m_sampleRate; + BitRateSettings m_bitRateSettings; + BitDepth m_bitDepth; +}; + +#endif diff --git a/include/ProjectRenderer.h b/include/ProjectRenderer.h index 06f08a20b..20ccbc0de 100644 --- a/include/ProjectRenderer.h +++ b/include/ProjectRenderer.h @@ -28,6 +28,7 @@ #include "AudioFileDevice.h" #include "lmmsconfig.h" #include "Mixer.h" +#include "OutputSettings.h" class ProjectRenderer : public QThread @@ -41,31 +42,6 @@ public: NumFileFormats } ; - enum Depths - { - Depth_16Bit, - Depth_24Bit, - Depth_32Bit, - NumDepths - } ; - - struct OutputSettings - { - sample_rate_t samplerate; - bool vbr; - int bitrate; - Depths depth; - - OutputSettings( sample_rate_t _sr, bool _vbr, int _bitrate, - Depths _d ) : - samplerate( _sr ), - vbr( _vbr ), - bitrate( _bitrate ), - depth( _d ) - { - } - } ; - struct FileEncodeDevice { ExportFileFormats m_fileFormat; diff --git a/include/RenderManager.h b/include/RenderManager.h index a22a047f5..e7e119b87 100644 --- a/include/RenderManager.h +++ b/include/RenderManager.h @@ -29,6 +29,8 @@ #include #include "ProjectRenderer.h" +#include "OutputSettings.h" + class RenderManager : public QObject { @@ -36,7 +38,7 @@ class RenderManager : public QObject public: RenderManager( const Mixer::qualitySettings & qualitySettings, - const ProjectRenderer::OutputSettings & outputSettings, + const OutputSettings & outputSettings, ProjectRenderer::ExportFileFormats fmt, QString outputPath); @@ -63,7 +65,7 @@ private: void restoreMutedState(); const Mixer::qualitySettings m_qualitySettings; - const ProjectRenderer::OutputSettings m_outputSettings; + const OutputSettings m_outputSettings; ProjectRenderer::ExportFileFormats m_format; QString m_outputPath; diff --git a/src/core/ProjectRenderer.cpp b/src/core/ProjectRenderer.cpp index b14634332..5dee4ed16 100644 --- a/src/core/ProjectRenderer.cpp +++ b/src/core/ProjectRenderer.cpp @@ -60,51 +60,32 @@ const ProjectRenderer::FileEncodeDevice ProjectRenderer::fileEncodeDevices[] = -ProjectRenderer::ProjectRenderer( const Mixer::qualitySettings & _qs, - const OutputSettings & _os, - ExportFileFormats _file_format, - const QString & _out_file ) : +ProjectRenderer::ProjectRenderer( const Mixer::qualitySettings & qualitySettings, + const OutputSettings & outputSettings, + ExportFileFormats exportFileFormat, + const QString & outputFilename ) : QThread( Engine::mixer() ), m_fileDev( NULL ), - m_qualitySettings( _qs ), + m_qualitySettings( qualitySettings ), m_oldQualitySettings( Engine::mixer()->currentQualitySettings() ), m_progress( 0 ), m_abort( false ) { - if( fileEncodeDevices[_file_format].m_getDevInst == NULL ) - { - return; - } + AudioFileDeviceInstantiaton audioEncoderFactory = fileEncodeDevices[exportFileFormat].m_getDevInst; - int depth; - switch (_os.depth) + if (audioEncoderFactory) { - case Depth_16Bit: - depth = 16; - break; - case Depth_24Bit: - depth = 24; - break; - case Depth_32Bit: - depth = 32; - break; - default: - // If this line is reached the enum has been extended without taking care here - Q_ASSERT(false); - } + bool successful = false; - bool successful = false; - m_fileDev = fileEncodeDevices[_file_format].m_getDevInst( - _os.samplerate, DEFAULT_CHANNELS, successful, - _out_file, _os.vbr, - _os.bitrate, _os.bitrate - 64, _os.bitrate + 64, - depth, Engine::mixer() ); - if( !successful ) - { - delete m_fileDev; - m_fileDev = NULL; + m_fileDev = audioEncoderFactory( + outputFilename, outputSettings, DEFAULT_CHANNELS, + Engine::mixer(), successful ); + if( !successful ) + { + delete m_fileDev; + m_fileDev = NULL; + } } - } diff --git a/src/core/RenderManager.cpp b/src/core/RenderManager.cpp index f404b6e3d..5fcc6a583 100644 --- a/src/core/RenderManager.cpp +++ b/src/core/RenderManager.cpp @@ -30,9 +30,10 @@ #include "BBTrackContainer.h" #include "BBTrack.h" + RenderManager::RenderManager( const Mixer::qualitySettings & qualitySettings, - const ProjectRenderer::OutputSettings & outputSettings, + const OutputSettings & outputSettings, ProjectRenderer::ExportFileFormats fmt, QString outputPath) : m_qualitySettings(qualitySettings), diff --git a/src/core/audio/AudioFileDevice.cpp b/src/core/audio/AudioFileDevice.cpp index ac3d94c33..2c340861c 100644 --- a/src/core/audio/AudioFileDevice.cpp +++ b/src/core/audio/AudioFileDevice.cpp @@ -30,24 +30,15 @@ #include "GuiApplication.h" -AudioFileDevice::AudioFileDevice( const sample_rate_t _sample_rate, +AudioFileDevice::AudioFileDevice( OutputSettings const & outputSettings, const ch_cnt_t _channels, const QString & _file, - const bool _use_vbr, - const bitrate_t _nom_bitrate, - const bitrate_t _min_bitrate, - const bitrate_t _max_bitrate, - const int _depth, Mixer* _mixer ) : AudioDevice( _channels, _mixer ), m_outputFile( _file ), - m_useVbr( _use_vbr ), - m_nomBitrate( _nom_bitrate ), - m_minBitrate( _min_bitrate ), - m_maxBitrate( _max_bitrate ), - m_depth( _depth ) + m_outputSettings(outputSettings) { - setSampleRate( _sample_rate ); + setSampleRate( outputSettings.getSampleRate() ); if( m_outputFile.open( QFile::WriteOnly | QFile::Truncate ) == false ) { diff --git a/src/core/audio/AudioFileOgg.cpp b/src/core/audio/AudioFileOgg.cpp index 39771f3d3..526776a73 100644 --- a/src/core/audio/AudioFileOgg.cpp +++ b/src/core/audio/AudioFileOgg.cpp @@ -36,21 +36,14 @@ #include "Mixer.h" -AudioFileOgg::AudioFileOgg( const sample_rate_t _sample_rate, - const ch_cnt_t _channels, - bool & _success_ful, - const QString & _file, - const bool _use_vbr, - const bitrate_t _nom_bitrate, - const bitrate_t _min_bitrate, - const bitrate_t _max_bitrate, - const int _depth, - Mixer* _mixer ) : - AudioFileDevice( _sample_rate, _channels, _file, _use_vbr, - _nom_bitrate, _min_bitrate, _max_bitrate, - _depth, _mixer ) +AudioFileOgg::AudioFileOgg( OutputSettings const & outputSettings, + const ch_cnt_t channels, + bool & successful, + const QString & file, + Mixer* mixer ) : + AudioFileDevice( outputSettings, channels, file, mixer ) { - m_ok = _success_ful = outputFileOpened() && startEncoding(); + m_ok = successful = outputFileOpened() && startEncoding(); } @@ -89,18 +82,18 @@ bool AudioFileOgg::startEncoding() vc.vendor = NULL; m_channels = channels(); - // vbr enabled? - if( useVBR() == 0 ) + + bool useVariableBitRate = getOutputSettings().getBitRateSettings().isVariableBitRate(); + bitrate_t minimalBitrate = nominalBitrate(); + bitrate_t maximumBitrate = nominalBitrate(); + + if( useVariableBitRate ) { - m_minBitrate = nominalBitrate(); // min for vbr - m_maxBitrate = nominalBitrate(); // max for vbr - } - else - { - m_minBitrate = minBitrate(); // min for vbr - m_maxBitrate = maxBitrate(); // max for vbr + minimalBitrate = minBitrate(); // min for vbr + maximumBitrate = maxBitrate(); // max for vbr } + m_rate = sampleRate(); // default-samplerate if( m_rate > 48000 ) { @@ -114,9 +107,9 @@ bool AudioFileOgg::startEncoding() vorbis_info_init( &m_vi ); if( vorbis_encode_setup_managed( &m_vi, m_channels, m_rate, - ( m_maxBitrate > 0 )? m_maxBitrate * 1000 : -1, + ( maximumBitrate > 0 )? maximumBitrate * 1000 : -1, nominalBitrate() * 1000, - ( m_minBitrate > 0 )? m_minBitrate * 1000 : -1 ) ) + ( minimalBitrate > 0 )? minimalBitrate * 1000 : -1 ) ) { printf( "Mode initialization failed: invalid parameters for " "bitrate\n" ); @@ -125,15 +118,15 @@ bool AudioFileOgg::startEncoding() return false; } - if( useVBR() == false ) - { - vorbis_encode_ctl( &m_vi, OV_ECTL_RATEMANAGE_AVG, NULL ); - } - else if( useVBR() == true ) + if( useVariableBitRate ) { // Turn off management entirely (if it was turned on). vorbis_encode_ctl( &m_vi, OV_ECTL_RATEMANAGE_SET, NULL ); } + else + { + vorbis_encode_ctl( &m_vi, OV_ECTL_RATEMANAGE_AVG, NULL ); + } vorbis_encode_setup_init( &m_vi ); diff --git a/src/core/audio/AudioFileWave.cpp b/src/core/audio/AudioFileWave.cpp index a52ea5a96..fb6e2901f 100644 --- a/src/core/audio/AudioFileWave.cpp +++ b/src/core/audio/AudioFileWave.cpp @@ -28,21 +28,14 @@ #include "Mixer.h" -AudioFileWave::AudioFileWave( const sample_rate_t _sample_rate, - const ch_cnt_t _channels, bool & _success_ful, - const QString & _file, - const bool _use_vbr, - const bitrate_t _nom_bitrate, - const bitrate_t _min_bitrate, - const bitrate_t _max_bitrate, - const int _depth, - Mixer* _mixer ) : - AudioFileDevice( _sample_rate, _channels, _file, _use_vbr, - _nom_bitrate, _min_bitrate, _max_bitrate, - _depth, _mixer ), +AudioFileWave::AudioFileWave( OutputSettings const & outputSettings, + const ch_cnt_t channels, bool & successful, + const QString & file, + Mixer* mixer ) : + AudioFileDevice( outputSettings, channels, file, mixer ), m_sf( NULL ) { - _success_ful = outputFileOpened() && startEncoding(); + successful = outputFileOpened() && startEncoding(); } @@ -66,15 +59,15 @@ bool AudioFileWave::startEncoding() m_si.format = SF_FORMAT_WAV; - switch( depth() ) + switch( getOutputSettings().getBitDepth() ) { - case 32: + case OutputSettings::Depth_32Bit: m_si.format |= SF_FORMAT_FLOAT; break; - case 24: + case OutputSettings::Depth_24Bit: m_si.format |= SF_FORMAT_PCM_24; break; - case 16: + case OutputSettings::Depth_16Bit: default: m_si.format |= SF_FORMAT_PCM_16; break; @@ -97,7 +90,9 @@ void AudioFileWave::writeBuffer( const surroundSampleFrame * _ab, const fpp_t _frames, const float _master_gain ) { - if( depth() == 32 || depth() == 24 ) + OutputSettings::BitDepth bitDepth = getOutputSettings().getBitDepth(); + + if( bitDepth == OutputSettings::Depth_32Bit || bitDepth == OutputSettings::Depth_24Bit ) { float * buf = new float[_frames*channels()]; for( fpp_t frame = 0; frame < _frames; ++frame ) diff --git a/src/core/main.cpp b/src/core/main.cpp index b2f962534..d288a0f2e 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -65,6 +65,7 @@ #include "GuiApplication.h" #include "ImportFilter.h" #include "MainWindow.h" +#include "OutputSettings.h" #include "ProjectRenderer.h" #include "RenderManager.h" #include "Song.h" @@ -259,8 +260,7 @@ int main( int argc, char * * argv ) new MainApplication( argc, argv ); Mixer::qualitySettings qs( Mixer::qualitySettings::Mode_HighQuality ); - ProjectRenderer::OutputSettings os( 44100, false, 160, - ProjectRenderer::Depth_16Bit ); + OutputSettings os( 44100, OutputSettings::BitRateSettings(160, false), OutputSettings::Depth_16Bit ); ProjectRenderer::ExportFileFormats eff = ProjectRenderer::WaveFile; // second of two command-line parsing stages @@ -414,7 +414,7 @@ int main( int argc, char * * argv ) sample_rate_t sr = QString( argv[i] ).toUInt(); if( sr >= 44100 && sr <= 192000 ) { - os.samplerate = sr; + os.setSampleRate(sr); } else { @@ -439,7 +439,9 @@ int main( int argc, char * * argv ) if( br >= 64 && br <= 384 ) { - os.bitrate = br; + OutputSettings::BitRateSettings bitRateSettings = os.getBitRateSettings(); + bitRateSettings.setBitRate(br); + os.setBitRateSettings(bitRateSettings); } else { @@ -450,7 +452,7 @@ int main( int argc, char * * argv ) } else if( arg =="--float" || arg == "-a" ) { - os.depth = ProjectRenderer::Depth_32Bit; + os.setBitDepth(OutputSettings::Depth_32Bit); } else if( arg == "--interpolation" || arg == "-i" ) { diff --git a/src/gui/ExportProjectDialog.cpp b/src/gui/ExportProjectDialog.cpp index d993841fc..3f8c36abb 100644 --- a/src/gui/ExportProjectDialog.cpp +++ b/src/gui/ExportProjectDialog.cpp @@ -31,6 +31,7 @@ #include "Song.h" #include "GuiApplication.h" #include "MainWindow.h" +#include "OutputSettings.h" ExportProjectDialog::ExportProjectDialog( const QString & _file_name, @@ -137,13 +138,13 @@ void ExportProjectDialog::startExport() static_cast(oversamplingCB->currentIndex()) ); const int samplerates[5] = { 44100, 48000, 88200, 96000, 192000 }; - const int bitrates[6] = { 64, 128, 160, 192, 256, 320 }; + const bitrate_t bitrates[6] = { 64, 128, 160, 192, 256, 320 }; - ProjectRenderer::OutputSettings os = ProjectRenderer::OutputSettings( + OutputSettings::BitRateSettings bitRateSettings(bitrates[ bitrateCB->currentIndex() ], false); + OutputSettings os = OutputSettings( samplerates[ samplerateCB->currentIndex() ], - false, - bitrates[ bitrateCB->currentIndex() ], - static_cast( depthCB->currentIndex() ) ); + bitRateSettings, + static_cast( depthCB->currentIndex() ) ); m_renderManager = new RenderManager( qs, os, m_ft, m_fileName );