mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
New class: LAMEEncoderAudioFormat
This commit is contained in:
parent
e6d817d20d
commit
773fc269f8
5 changed files with 303 additions and 2 deletions
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-11 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE 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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_USE_LAME_AUDIO_FORMAT
|
||||
|
||||
class LAMEEncoderAudioFormat::Writer : public AudioFormatWriter
|
||||
{
|
||||
public:
|
||||
Writer (OutputStream* destStream, const String& formatName,
|
||||
const File& lameApp, int vbr, int cbr,
|
||||
double sampleRate, unsigned int numberOfChannels,
|
||||
unsigned int bitsPerSample, const StringPairArray& metadata)
|
||||
: AudioFormatWriter (destStream, formatName, sampleRate,
|
||||
numberOfChannels, bitsPerSample),
|
||||
vbrLevel (vbr), cbrBitrate (cbr),
|
||||
tempWav (".wav")
|
||||
{
|
||||
WavAudioFormat wavFormat;
|
||||
|
||||
if (FileOutputStream* out = tempWav.getFile().createOutputStream())
|
||||
{
|
||||
writer = wavFormat.createWriterFor (out, sampleRate, numChannels,
|
||||
bitsPerSample, metadata, 0);
|
||||
|
||||
args.add (lameApp.getFullPathName());
|
||||
|
||||
args.add ("--quiet");
|
||||
|
||||
if (cbrBitrate == 0)
|
||||
{
|
||||
args.add ("-vbr-new");
|
||||
args.add ("-V");
|
||||
args.add (String (vbrLevel));
|
||||
}
|
||||
else
|
||||
{
|
||||
args.add ("--cbr");
|
||||
args.add ("-b");
|
||||
args.add (String (cbrBitrate));
|
||||
}
|
||||
|
||||
addMetadataArg (metadata, "id3title", "--tt");
|
||||
addMetadataArg (metadata, "id3artist", "--ta");
|
||||
addMetadataArg (metadata, "id3album", "--tl");
|
||||
addMetadataArg (metadata, "id3comment", "--tc");
|
||||
addMetadataArg (metadata, "id3date", "--ty");
|
||||
addMetadataArg (metadata, "id3genre", "--tg");
|
||||
addMetadataArg (metadata, "id3trackNumber", "--tn");
|
||||
}
|
||||
}
|
||||
|
||||
void addMetadataArg (const StringPairArray& metadata, const char* key, const char* lameFlag)
|
||||
{
|
||||
const String value (metadata.getValue (key, String::empty));
|
||||
|
||||
if (value.isNotEmpty())
|
||||
{
|
||||
args.add (lameFlag);
|
||||
args.add (value);
|
||||
}
|
||||
}
|
||||
|
||||
~Writer()
|
||||
{
|
||||
if (writer != nullptr)
|
||||
{
|
||||
writer = nullptr;
|
||||
|
||||
if (! convertToMP3())
|
||||
convertToMP3(); // try again
|
||||
}
|
||||
}
|
||||
|
||||
bool write (const int** samplesToWrite, int numSamples)
|
||||
{
|
||||
return writer != nullptr && writer->write (samplesToWrite, numSamples);
|
||||
}
|
||||
|
||||
private:
|
||||
int vbrLevel, cbrBitrate;
|
||||
TemporaryFile tempWav;
|
||||
ScopedPointer<AudioFormatWriter> writer;
|
||||
StringArray args;
|
||||
|
||||
bool convertToMP3() const
|
||||
{
|
||||
TemporaryFile tempMP3 (".mp3");
|
||||
|
||||
StringArray args2 (args);
|
||||
args2.add (tempWav.getFile().getFullPathName());
|
||||
args2.add (tempMP3.getFile().getFullPathName());
|
||||
|
||||
ChildProcess cp;
|
||||
|
||||
DBG (args2.joinIntoString(" "));
|
||||
|
||||
if (cp.start (args2))
|
||||
{
|
||||
String childOutput (cp.readAllProcessOutput());
|
||||
DBG (childOutput);
|
||||
|
||||
if (tempMP3.getFile().getSize() > 0)
|
||||
{
|
||||
FileInputStream fis (tempMP3.getFile());
|
||||
|
||||
if (fis.openedOk() && output->writeFromInputStream (fis, -1) > 0)
|
||||
{
|
||||
output->flush();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Writer)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
static const char* const lameFormatName = "MP3 file";
|
||||
static const char* const lameExtensions[] = { ".mp3", nullptr };
|
||||
|
||||
LAMEEncoderAudioFormat::LAMEEncoderAudioFormat (const File& lameApplication)
|
||||
: AudioFormat (TRANS (lameFormatName), StringArray (lameExtensions)),
|
||||
lameApp (lameApplication)
|
||||
{
|
||||
}
|
||||
|
||||
LAMEEncoderAudioFormat::~LAMEEncoderAudioFormat()
|
||||
{
|
||||
}
|
||||
|
||||
bool LAMEEncoderAudioFormat::canHandleFile (const File&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Array<int> LAMEEncoderAudioFormat::getPossibleSampleRates()
|
||||
{
|
||||
const int rates[] = { 32000, 44100, 48000, 0 };
|
||||
return Array <int> (rates);
|
||||
}
|
||||
|
||||
Array<int> LAMEEncoderAudioFormat::getPossibleBitDepths()
|
||||
{
|
||||
const int depths[] = { 16, 0 };
|
||||
return Array <int> (depths);
|
||||
}
|
||||
|
||||
bool LAMEEncoderAudioFormat::canDoStereo() { return true; }
|
||||
bool LAMEEncoderAudioFormat::canDoMono() { return true; }
|
||||
bool LAMEEncoderAudioFormat::isCompressed() { return true; }
|
||||
|
||||
StringArray LAMEEncoderAudioFormat::getQualityOptions()
|
||||
{
|
||||
const char* vbrOptions[] = { "VBR quality 0 (best)", "VBR quality 1", "VBR quality 2", "VBR quality 3",
|
||||
"VBR quality 4 (normal)", "VBR quality 5", "VBR quality 6", "VBR quality 7", "VBR quality 8",
|
||||
"VBR quality 9 (smallest)",
|
||||
nullptr };
|
||||
|
||||
StringArray opts (vbrOptions);
|
||||
|
||||
const int cbrRates[] = { 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 };
|
||||
|
||||
for (int i = 0; i < numElementsInArray (cbrRates); ++i)
|
||||
opts.add (String (cbrRates[i]) + " Kb/s CBR");
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
AudioFormatReader* LAMEEncoderAudioFormat::createReaderFor (InputStream*, const bool)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioFormatWriter* LAMEEncoderAudioFormat::createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex)
|
||||
{
|
||||
int vbr = 4;
|
||||
int cbr = 0;
|
||||
|
||||
const String qual (getQualityOptions() [qualityOptionIndex]);
|
||||
|
||||
if (qual.contains ("VBR"))
|
||||
vbr = qual.retainCharacters ("0123456789").getIntValue();
|
||||
else
|
||||
cbr = qual.getIntValue();
|
||||
|
||||
return new Writer (streamToWriteTo, getFormatName(), lameApp, vbr, cbr,
|
||||
sampleRateToUse, numberOfChannels, bitsPerSample, metadataValues);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-11 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE 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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_USE_LAME_AUDIO_FORMAT || defined (DOXYGEN)
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An AudioFormat class which can use an installed version of the LAME mp3
|
||||
encoder to encode a file.
|
||||
|
||||
This format can't read mp3s, it just writes them. Internally, the
|
||||
AudioFormatWriter object that is returned writes the incoming audio data
|
||||
to a temporary WAV file, and then when the writer is deleted, it invokes
|
||||
the LAME executable to convert the data to an MP3, whose data is then
|
||||
piped into the original OutputStream that was used when first creating
|
||||
the writer.
|
||||
|
||||
@see AudioFormat
|
||||
*/
|
||||
class JUCE_API LAMEEncoderAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
/** Creates a LAMEEncoderAudioFormat that expects to find a working LAME
|
||||
executable at the location given.
|
||||
*/
|
||||
LAMEEncoderAudioFormat (const File& lameApplicationToUse);
|
||||
~LAMEEncoderAudioFormat();
|
||||
|
||||
bool canHandleFile (const File&);
|
||||
Array<int> getPossibleSampleRates();
|
||||
Array<int> getPossibleBitDepths();
|
||||
bool canDoStereo();
|
||||
bool canDoMono();
|
||||
bool isCompressed();
|
||||
StringArray getQualityOptions();
|
||||
|
||||
AudioFormatReader* createReaderFor (InputStream*, bool deleteStreamIfOpeningFails);
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream*, double sampleRateToUse,
|
||||
unsigned int numberOfChannels, int bitsPerSample,
|
||||
const StringPairArray& metadataValues, int qualityOptionIndex);
|
||||
|
||||
private:
|
||||
File lameApp;
|
||||
class Writer;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LAMEEncoderAudioFormat)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -3003,7 +3003,7 @@ public:
|
|||
{
|
||||
if (decodedEnd <= decodedStart && ! readNextBlock())
|
||||
{
|
||||
for (int i = 2; --i >= 0;)
|
||||
for (int i = numDestChannels; --i >= 0;)
|
||||
if (destSamples[i] != nullptr)
|
||||
zeromem (destSamples[i] + startOffsetInDestBuffer, sizeof (float) * numSamples);
|
||||
|
||||
|
|
@ -3014,7 +3014,7 @@ public:
|
|||
float* const* const dst = reinterpret_cast <float**> (destSamples);
|
||||
memcpy (dst[0] + startOffsetInDestBuffer, decoded0 + decodedStart, sizeof (float) * numToCopy);
|
||||
|
||||
if (dst[1] != nullptr)
|
||||
if (numDestChannels > 1 && dst[1] != nullptr)
|
||||
memcpy (dst[1] + startOffsetInDestBuffer, (numChannels < 2 ? decoded0 : decoded1) + decodedStart, sizeof (float) * numToCopy);
|
||||
|
||||
startOffsetInDestBuffer += numToCopy;
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ namespace juce
|
|||
#include "codecs/juce_OggVorbisAudioFormat.cpp"
|
||||
#include "codecs/juce_QuickTimeAudioFormat.cpp"
|
||||
#include "codecs/juce_WavAudioFormat.cpp"
|
||||
#include "codecs/juce_LAMEEncoderAudioFormat.cpp"
|
||||
|
||||
#if JUCE_WINDOWS && JUCE_USE_WINDOWS_MEDIA_FORMAT
|
||||
#include "codecs/juce_WindowsMediaAudioFormat.cpp"
|
||||
|
|
|
|||
|
|
@ -63,6 +63,13 @@
|
|||
#define JUCE_USE_MP3AUDIOFORMAT 0
|
||||
#endif
|
||||
|
||||
/** Config: JUCE_USE_LAME_AUDIO_FORMAT
|
||||
Enables the LameEncoderAudioFormat class.
|
||||
*/
|
||||
#ifndef JUCE_USE_LAME_AUDIO_FORMAT
|
||||
#define JUCE_USE_LAME_AUDIO_FORMAT 0
|
||||
#endif
|
||||
|
||||
/** Config: JUCE_USE_WINDOWS_MEDIA_FORMAT
|
||||
Enables the Windows Media SDK codecs.
|
||||
*/
|
||||
|
|
@ -101,6 +108,7 @@ namespace juce
|
|||
#include "codecs/juce_AiffAudioFormat.h"
|
||||
#include "codecs/juce_CoreAudioFormat.h"
|
||||
#include "codecs/juce_FlacAudioFormat.h"
|
||||
#include "codecs/juce_LAMEEncoderAudioFormat.h"
|
||||
#include "codecs/juce_MP3AudioFormat.h"
|
||||
#include "codecs/juce_OggVorbisAudioFormat.h"
|
||||
#include "codecs/juce_QuickTimeAudioFormat.h"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue