Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FLAC export and related options #3731

Merged
merged 20 commits into from
Aug 3, 2017
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,14 @@ ELSE()
ENDIF()

# check for libsndfile
PKG_CHECK_MODULES(SNDFILE REQUIRED sndfile>=1.0.11)
PKG_CHECK_MODULES(SNDFILE REQUIRED sndfile>=1.0.18)
IF(NOT SNDFILE_FOUND)
MESSAGE(FATAL_ERROR "LMMS requires libsndfile1 and libsndfile1-dev >= 1.0.11 - please install, remove CMakeCache.txt and try again!")
ENDIF(NOT SNDFILE_FOUND)
MESSAGE(FATAL_ERROR "LMMS requires libsndfile1 and libsndfile1-dev >= 1.0.18 - please install, remove CMakeCache.txt and try again!")
ENDIF()
# check if we can use SF_SET_COMPRESSION_LEVEL
IF(NOT SNDFILE_VERSION VERSION_LESS 1.0.26)
SET(LMMS_HAVE_SF_COMPLEVEL TRUE)
ENDIF()

IF(WANT_CALF)
SET(LMMS_HAVE_CALF TRUE)
Expand Down
48 changes: 48 additions & 0 deletions include/AudioFileFlac.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* AudioFileFlac.h - Audio device which encodes a wave stream into a FLAC file.
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should put the copyright information here.


#ifndef AUDIO_FILE_FLAC_H
#define AUDIO_FILE_FLAC_H

#include "lmmsconfig.h"

#include "AudioFileDevice.h"
#include <sndfile.h>

class AudioFileFlac: public AudioFileDevice
{
public:
AudioFileFlac(OutputSettings const& outputSettings,
ch_cnt_t const channels,
bool& successful,
QString const& file,
Mixer* mixer
);

virtual ~AudioFileFlac();

static AudioFileDevice* getInst(QString const& outputFilename,
OutputSettings const& outputSettings,
ch_cnt_t const channels,
Mixer* mixer,
bool& successful)
{
return new AudioFileFlac(outputSettings,channels,successful,outputFilename,mixer);
}

private:

SF_INFO m_sfinfo;
SNDFILE* m_sf;

virtual void writeBuffer(surroundSampleFrame const* _ab,
fpp_t const frames,
float master_gain) override;

bool startEncoding();
void finishEncoding();

};

#endif //AUDIO_FILE_FLAC_H
6 changes: 2 additions & 4 deletions include/ExportProjectDialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#define EXPORT_PROJECT_DIALOG_H

#include <QDialog>
#include <vector>
#include <memory>
#include "ui_export_project.h"

#include "ProjectRenderer.h"
Expand All @@ -39,8 +39,6 @@ class ExportProjectDialog : public QDialog, public Ui::ExportProjectDialog
Q_OBJECT
public:
ExportProjectDialog( const QString & _file_name, QWidget * _parent, bool multi_export );
virtual ~ExportProjectDialog();


protected:
virtual void reject( void );
Expand All @@ -62,7 +60,7 @@ private slots:
bool m_multiExport;

ProjectRenderer::ExportFileFormats m_ft;
RenderManager* m_renderManager;
std::unique_ptr<RenderManager> m_renderManager;
} ;

#endif
11 changes: 10 additions & 1 deletion include/OutputSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ class OutputSettings
m_sampleRate(sampleRate),
m_bitRateSettings(bitRateSettings),
m_bitDepth(bitDepth),
m_stereoMode(stereoMode)
m_stereoMode(stereoMode),
m_compressionLevel(0.5)
{
}

Expand All @@ -95,11 +96,19 @@ class OutputSettings
StereoMode getStereoMode() const { return m_stereoMode; }
void setStereoMode(StereoMode stereoMode) { m_stereoMode = stereoMode; }


double getCompressionLevel() const{ return m_compressionLevel; }
void setCompressionLevel(double level){
// legal range is 0.0 to 1.0.
m_compressionLevel = level;
}

private:
sample_rate_t m_sampleRate;
BitRateSettings m_bitRateSettings;
BitDepth m_bitDepth;
StereoMode m_stereoMode;
double m_compressionLevel;
};

#endif
1 change: 1 addition & 0 deletions include/ProjectRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class ProjectRenderer : public QThread
enum ExportFileFormats: int
{
WaveFile,
FlacFile,
OggFile,
MP3File,
NumFileFormats
Expand Down
1 change: 1 addition & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ set(LMMS_SRCS
core/audio/AudioFileDevice.cpp
core/audio/AudioFileMP3.cpp
core/audio/AudioFileOgg.cpp
core/audio/AudioFileFlac.cpp
core/audio/AudioFileWave.cpp
core/audio/AudioJack.cpp
core/audio/AudioOss.cpp
Expand Down
6 changes: 6 additions & 0 deletions src/core/ProjectRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "AudioFileWave.h"
#include "AudioFileOgg.h"
#include "AudioFileMP3.h"
#include "AudioFileFlac.h"

#ifdef LMMS_HAVE_SCHED_H
#include "sched.h"
Expand All @@ -42,6 +43,11 @@ const ProjectRenderer::FileEncodeDevice ProjectRenderer::fileEncodeDevices[] =
{ ProjectRenderer::WaveFile,
QT_TRANSLATE_NOOP( "ProjectRenderer", "WAV-File (*.wav)" ),
".wav", &AudioFileWave::getInst },
{ ProjectRenderer::FlacFile,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@irrenhaus3 this needs formatting, spaces versus tabs. :)

QT_TRANSLATE_NOOP("ProjectRenderer", "FLAC-File (*.flac)"),
".flac",
&AudioFileFlac::getInst
},
{ ProjectRenderer::OggFile,
QT_TRANSLATE_NOOP( "ProjectRenderer", "Compressed OGG-File (*.ogg)" ),
".ogg",
Expand Down
95 changes: 95 additions & 0 deletions src/core/audio/AudioFileFlac.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include <memory>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, too.


#include "AudioFileFlac.h"
#include "endian_handling.h"
#include "Mixer.h"

AudioFileFlac::AudioFileFlac(OutputSettings const& outputSettings, ch_cnt_t const channels, bool& successful, QString const& file, Mixer* mixer):
AudioFileDevice(outputSettings,channels,file,mixer),
m_sf(nullptr)
{
successful = outputFileOpened() && startEncoding();
}

AudioFileFlac::~AudioFileFlac()
{
finishEncoding();
}

bool AudioFileFlac::startEncoding()
{
m_sfinfo.samplerate=sampleRate();
m_sfinfo.channels=channels();
m_sfinfo.frames = mixer()->framesPerPeriod();
m_sfinfo.sections=1;
m_sfinfo.seekable=0;

m_sfinfo.format = SF_FORMAT_FLAC;

switch (getOutputSettings().getBitDepth())
{
case OutputSettings::Depth_24Bit:
case OutputSettings::Depth_32Bit:
// FLAC does not support 32bit sampling, so take it as 24.
m_sfinfo.format |= SF_FORMAT_PCM_24;
break;
default:
m_sfinfo.format |= SF_FORMAT_PCM_16;
}

#ifdef LMMS_HAVE_SF_COMPLEVEL
double compression = getOutputSettings().getCompressionLevel();
sf_command(m_sf,SFC_SET_COMPRESSION_LEVEL,&compression,sizeof(double));
#endif

m_sf = sf_open(
#ifdef LMMS_BUILD_WIN32
outputFile().toLocal8bit().constData(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toLocal8bit() -> toLocal8Bit()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lol, and here I was wondering why travis exploded. Thanks!

#else
outputFile().toUtf8().constData(),
#endif
SFM_WRITE,
&m_sfinfo
);

sf_command(m_sf,SFC_SET_CLIPPING,nullptr,SF_TRUE);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is conventional to put spaces between parameters.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like foo(b, a, r);.


sf_set_string(m_sf,SF_STR_SOFTWARE,"LMMS");

return true;
}

void AudioFileFlac::writeBuffer(surroundSampleFrame const* _ab, fpp_t const frames, float master_gain)
{
OutputSettings::BitDepth depth = getOutputSettings().getBitDepth();

if (depth == OutputSettings::Depth_24Bit || depth == OutputSettings::Depth_32Bit) // Float encoding
{
std::unique_ptr<sample_t[]> buf{ new sample_t[frames*channels()] };
for(fpp_t frame = 0; frame < frames; ++frame)
{
for(ch_cnt_t channel=0; channel<channels(); ++channel)
{
buf[frame*channels()+channel] = _ab[frame][channel] * master_gain;
}
}
sf_writef_float(m_sf,static_cast<float*>(buf.get()),frames);
}
else // integer PCM encoding
{
std::unique_ptr<int_sample_t[]> buf{ new int_sample_t[frames*channels()] };
convertToS16(_ab,frames,master_gain,buf.get(),!isLittleEndian());
sf_writef_short(m_sf,static_cast<short*>(buf.get()),frames);
}

}


void AudioFileFlac::finishEncoding()
{
if (m_sf)
{
sf_write_sync(m_sf);
sf_close(m_sf);
}
}
4 changes: 4 additions & 0 deletions src/core/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,10 @@ int main( int argc, char * * argv )
eff = ProjectRenderer::MP3File;
}
#endif
else if (ext == "flac")
{
eff = ProjectRenderer::FlacFile;
}
else
{
printf( "\nInvalid output format %s.\n\n"
Expand Down
Loading