29#if JUCE_USE_LAME_AUDIO_FORMAT
34 Writer (OutputStream* destStream,
const String& formatName,
35 const File& appFile,
int vbr,
int cbr,
36 double sampleRateIn,
unsigned int numberOfChannels,
37 int bitsPerSampleIn,
const StringPairArray& metadata)
38 : AudioFormatWriter (destStream, formatName, sampleRateIn,
39 numberOfChannels, (unsigned int) bitsPerSampleIn),
40 vbrLevel (vbr), cbrBitrate (cbr)
42 WavAudioFormat wavFormat;
44 if (
auto out = tempWav.getFile().createOutputStream())
46 writer.reset (wavFormat.createWriterFor (out.release(), sampleRateIn, numChannels,
47 bitsPerSampleIn, metadata, 0));
49 args.add (appFile.getFullPathName());
55 args.add (
"--vbr-new");
57 args.add (String (vbrLevel));
63 args.add (String (cbrBitrate));
66 addMetadataArg (metadata,
"id3title",
"--tt");
67 addMetadataArg (metadata,
"id3artist",
"--ta");
68 addMetadataArg (metadata,
"id3album",
"--tl");
69 addMetadataArg (metadata,
"id3comment",
"--tc");
70 addMetadataArg (metadata,
"id3date",
"--ty");
71 addMetadataArg (metadata,
"id3genre",
"--tg");
72 addMetadataArg (metadata,
"id3trackNumber",
"--tn");
76 void addMetadataArg (
const StringPairArray& metadata,
const char* key,
const char* lameFlag)
78 auto value = metadata.getValue (key, {});
80 if (value.isNotEmpty())
89 if (writer !=
nullptr)
98 bool write (
const int** samplesToWrite,
int numSamples)
100 return writer !=
nullptr && writer->write (samplesToWrite, numSamples);
104 int vbrLevel, cbrBitrate;
106 std::unique_ptr<AudioFormatWriter> writer;
113 if (cp.start (processArgs))
115 [[maybe_unused]]
auto childOutput = cp.readAllProcessOutput();
118 cp.waitForProcessToFinish (10000);
119 return tempMP3.getFile().getSize() > 0;
125 bool convertToMP3()
const
130 args2.add (tempWav.getFile().getFullPathName());
131 args2.add (tempMP3.getFile().getFullPathName());
133 DBG (args2.joinIntoString (
" "));
135 if (runLameChildProcess (tempMP3, args2))
139 if (fis.openedOk() && output->writeFromInputStream (fis, -1) > 0)
149 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Writer)
153LAMEEncoderAudioFormat::LAMEEncoderAudioFormat (
const File& lameApplication)
154 : AudioFormat (
"MP3 file",
".mp3"),
155 lameApp (lameApplication)
159LAMEEncoderAudioFormat::~LAMEEncoderAudioFormat()
163bool LAMEEncoderAudioFormat::canHandleFile (
const File&)
168Array<int> LAMEEncoderAudioFormat::getPossibleSampleRates()
170 return { 32000, 44100, 48000 };
173Array<int> LAMEEncoderAudioFormat::getPossibleBitDepths()
178bool LAMEEncoderAudioFormat::canDoStereo() {
return true; }
179bool LAMEEncoderAudioFormat::canDoMono() {
return true; }
180bool LAMEEncoderAudioFormat::isCompressed() {
return true; }
182StringArray LAMEEncoderAudioFormat::getQualityOptions()
184 static const char* vbrOptions[] = {
"VBR quality 0 (best)",
"VBR quality 1",
"VBR quality 2",
"VBR quality 3",
185 "VBR quality 4 (normal)",
"VBR quality 5",
"VBR quality 6",
"VBR quality 7",
186 "VBR quality 8",
"VBR quality 9 (smallest)",
nullptr };
187 StringArray opts (vbrOptions);
189 const int cbrRates[] = { 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 };
191 for (
int i = 0; i < numElementsInArray (cbrRates); ++i)
192 opts.add (String (cbrRates[i]) +
" Kb/s CBR");
197AudioFormatReader* LAMEEncoderAudioFormat::createReaderFor (InputStream*,
const bool)
202AudioFormatWriter* LAMEEncoderAudioFormat::createWriterFor (OutputStream* streamToWriteTo,
203 double sampleRateToUse,
204 unsigned int numberOfChannels,
206 const StringPairArray& metadataValues,
207 int qualityOptionIndex)
209 if (streamToWriteTo ==
nullptr)
215 const String qual (getQualityOptions() [qualityOptionIndex]);
217 if (qual.contains (
"VBR"))
218 vbr = qual.retainCharacters (
"0123456789").getIntValue();
220 cbr = qual.getIntValue();
222 return new Writer (streamToWriteTo, getFormatName(), lameApp, vbr, cbr,
223 sampleRateToUse, numberOfChannels, bitsPerSample, metadataValues);