mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
WavAudioFormat: Add support for writing 32 bit integral (PCM) format
This commit is contained in:
parent
34675235e5
commit
386daafe23
43 changed files with 677 additions and 125 deletions
|
|
@ -525,6 +525,7 @@ add_library( ${BINARY_NAME}
|
|||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatReaderSource.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriterOptions.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp"
|
||||
|
|
@ -3184,6 +3185,7 @@ set_source_files_properties(
|
|||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatReaderSource.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriterOptions.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp"
|
||||
|
|
|
|||
|
|
@ -3558,6 +3558,7 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReaderSource.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_BufferingAudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_MemoryMappedAudioFormatReader.h"/>
|
||||
|
|
|
|||
|
|
@ -4974,6 +4974,9 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -3558,6 +3558,7 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReaderSource.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_BufferingAudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_MemoryMappedAudioFormatReader.h"/>
|
||||
|
|
|
|||
|
|
@ -4974,6 +4974,9 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -480,6 +480,7 @@ add_library( ${BINARY_NAME}
|
|||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatReaderSource.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriterOptions.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp"
|
||||
|
|
@ -2753,6 +2754,7 @@ set_source_files_properties(
|
|||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatReaderSource.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriterOptions.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp"
|
||||
|
|
|
|||
|
|
@ -3072,6 +3072,7 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReaderSource.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_BufferingAudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_MemoryMappedAudioFormatReader.h"/>
|
||||
|
|
|
|||
|
|
@ -4236,6 +4236,9 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -513,6 +513,7 @@ add_library( ${BINARY_NAME}
|
|||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatReaderSource.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriterOptions.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp"
|
||||
|
|
@ -2939,6 +2940,7 @@ set_source_files_properties(
|
|||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatReaderSource.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriterOptions.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp"
|
||||
|
|
|
|||
|
|
@ -3252,6 +3252,7 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReaderSource.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_BufferingAudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_MemoryMappedAudioFormatReader.h"/>
|
||||
|
|
|
|||
|
|
@ -4512,6 +4512,9 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -3252,6 +3252,7 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReaderSource.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_BufferingAudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_MemoryMappedAudioFormatReader.h"/>
|
||||
|
|
|
|||
|
|
@ -4512,6 +4512,9 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -484,6 +484,7 @@ add_library( ${BINARY_NAME}
|
|||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatReaderSource.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriterOptions.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp"
|
||||
|
|
@ -2837,6 +2838,7 @@ set_source_files_properties(
|
|||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatReaderSource.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriter.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioFormatWriterOptions.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_AudioSubsectionReader.h"
|
||||
"../../../../../modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp"
|
||||
|
|
|
|||
|
|
@ -3163,6 +3163,7 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReaderSource.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_BufferingAudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_MemoryMappedAudioFormatReader.h"/>
|
||||
|
|
|
|||
|
|
@ -4377,6 +4377,9 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -3364,6 +3364,7 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReaderSource.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_BufferingAudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_MemoryMappedAudioFormatReader.h"/>
|
||||
|
|
|
|||
|
|
@ -4671,6 +4671,9 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -3364,6 +3364,7 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReaderSource.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_BufferingAudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_MemoryMappedAudioFormatReader.h"/>
|
||||
|
|
|
|||
|
|
@ -4671,6 +4671,9 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -3139,6 +3139,7 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatReaderSource.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_BufferingAudioFormatReader.h"/>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_MemoryMappedAudioFormatReader.h"/>
|
||||
|
|
|
|||
|
|
@ -4344,6 +4344,9 @@
|
|||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriter.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioFormatWriterOptions.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\..\modules\juce_audio_formats\format\juce_AudioSubsectionReader.h">
|
||||
<Filter>JUCE Modules\juce_audio_formats\format</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -1031,4 +1031,20 @@ AudioFormatWriter* AiffAudioFormat::createWriterFor (OutputStream* out,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> AiffAudioFormat::createWriterFor (std::unique_ptr<OutputStream>& streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options)
|
||||
{
|
||||
if (streamToWriteTo == nullptr || ! getPossibleBitDepths().contains (options.getBitsPerSample()))
|
||||
return nullptr;
|
||||
|
||||
StringPairArray metadata;
|
||||
metadata.addUnorderedMap (options.getMetadataValues());
|
||||
|
||||
return std::make_unique<AiffAudioFormatWriter> (std::exchange (streamToWriteTo, {}).release(),
|
||||
options.getSampleRate(),
|
||||
(unsigned int) options.getNumChannels(),
|
||||
(unsigned int) options.getBitsPerSample(),
|
||||
metadata);
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
|
|
@ -94,6 +94,10 @@ public:
|
|||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) override;
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> createWriterFor (std::unique_ptr<OutputStream>& streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options) override;
|
||||
|
||||
using AudioFormat::createWriterFor;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -665,6 +665,13 @@ AudioFormatWriter* CoreAudioFormat::createWriterFor (OutputStream*,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> CoreAudioFormat::createWriterFor (std::unique_ptr<OutputStream>&,
|
||||
const AudioFormatWriterOptions&)
|
||||
{
|
||||
jassertfalse; // not yet implemented!
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -112,6 +112,10 @@ public:
|
|||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) override;
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> createWriterFor (std::unique_ptr<OutputStream>& streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options) override;
|
||||
|
||||
using AudioFormat::createWriterFor;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -610,7 +610,7 @@ AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out,
|
|||
if (out != nullptr && getPossibleBitDepths().contains (bitsPerSample))
|
||||
{
|
||||
std::unique_ptr<FlacWriter> w (new FlacWriter (out, sampleRate, numberOfChannels,
|
||||
(uint32) bitsPerSample, qualityOptionIndex));
|
||||
(uint32) bitsPerSample, qualityOptionIndex));
|
||||
if (w->ok)
|
||||
return w.release();
|
||||
}
|
||||
|
|
@ -618,6 +618,24 @@ AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> FlacAudioFormat::createWriterFor (std::unique_ptr<OutputStream>& streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options)
|
||||
{
|
||||
if (streamToWriteTo == nullptr || ! getPossibleBitDepths().contains (options.getBitsPerSample()))
|
||||
return nullptr;
|
||||
|
||||
auto writer = std::make_unique<FlacWriter> (std::exchange (streamToWriteTo, {}).release(),
|
||||
options.getSampleRate(),
|
||||
(uint32) options.getNumChannels(),
|
||||
(uint32) options.getBitsPerSample(),
|
||||
options.getQualityOptionIndex());
|
||||
|
||||
if (! writer->ok)
|
||||
return nullptr;
|
||||
|
||||
return writer;
|
||||
}
|
||||
|
||||
StringArray FlacAudioFormat::getQualityOptions()
|
||||
{
|
||||
return { "0 (Fastest)", "1", "2", "3", "4", "5 (Default)","6", "7", "8 (Highest quality)" };
|
||||
|
|
|
|||
|
|
@ -63,6 +63,9 @@ public:
|
|||
StringArray getQualityOptions() override;
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<AudioFormatWriter> createWriterFor (std::unique_ptr<OutputStream>& streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options) override;
|
||||
|
||||
AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
bool deleteStreamIfOpeningFails) override;
|
||||
|
||||
|
|
@ -72,6 +75,7 @@ public:
|
|||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) override;
|
||||
|
||||
using AudioFormat::createWriterFor;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -50,36 +50,39 @@ public:
|
|||
{
|
||||
WavAudioFormat wavFormat;
|
||||
|
||||
if (auto out = tempWav.getFile().createOutputStream())
|
||||
writer = wavFormat.createWriterFor (tempWav.getFile().createOutputStream(),
|
||||
AudioFormatWriter::Options{}.withSampleRate (sampleRateIn)
|
||||
.withNumChannels ((int) numberOfChannels)
|
||||
.withBitsPerSample (bitsPerSampleIn)
|
||||
.withMetadataValues (metadata));
|
||||
|
||||
if (writer == nullptr)
|
||||
return;
|
||||
|
||||
args.add (appFile.getFullPathName());
|
||||
|
||||
args.add ("--quiet");
|
||||
|
||||
if (cbrBitrate == 0)
|
||||
{
|
||||
writer.reset (wavFormat.createWriterFor (out.release(), sampleRateIn, numChannels,
|
||||
bitsPerSampleIn, metadata, 0));
|
||||
|
||||
args.add (appFile.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");
|
||||
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)
|
||||
|
|
@ -165,10 +168,6 @@ LAMEEncoderAudioFormat::LAMEEncoderAudioFormat (const File& lameApplication)
|
|||
{
|
||||
}
|
||||
|
||||
LAMEEncoderAudioFormat::~LAMEEncoderAudioFormat()
|
||||
{
|
||||
}
|
||||
|
||||
bool LAMEEncoderAudioFormat::canHandleFile (const File&)
|
||||
{
|
||||
return false;
|
||||
|
|
@ -208,6 +207,33 @@ AudioFormatReader* LAMEEncoderAudioFormat::createReaderFor (InputStream*, const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> LAMEEncoderAudioFormat::createWriterFor (std::unique_ptr<OutputStream> streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options)
|
||||
{
|
||||
if (streamToWriteTo == nullptr)
|
||||
return nullptr;
|
||||
|
||||
int vbr = 4;
|
||||
int cbr = 0;
|
||||
|
||||
const String qual (getQualityOptions() [options.getQualityOptionIndex()]);
|
||||
|
||||
if (qual.contains ("VBR"))
|
||||
vbr = qual.retainCharacters ("0123456789").getIntValue();
|
||||
else
|
||||
cbr = qual.getIntValue();
|
||||
|
||||
return std::make_unique<Writer> (streamToWriteTo.release(),
|
||||
getFormatName(),
|
||||
lameApp,
|
||||
vbr,
|
||||
cbr,
|
||||
options.getSampleRate(),
|
||||
(unsigned int) options.getNumChannels(),
|
||||
options.getBitsPerSample(),
|
||||
options.getMetadataValues());
|
||||
}
|
||||
|
||||
AudioFormatWriter* LAMEEncoderAudioFormat::createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
|
|
|
|||
|
|
@ -60,21 +60,24 @@ public:
|
|||
executable at the location given.
|
||||
*/
|
||||
LAMEEncoderAudioFormat (const File& lameExecutableToUse);
|
||||
~LAMEEncoderAudioFormat();
|
||||
|
||||
bool canHandleFile (const File&);
|
||||
Array<int> getPossibleSampleRates();
|
||||
Array<int> getPossibleBitDepths();
|
||||
bool canDoStereo();
|
||||
bool canDoMono();
|
||||
bool isCompressed();
|
||||
StringArray getQualityOptions();
|
||||
bool canHandleFile (const File&) override;
|
||||
Array<int> getPossibleSampleRates() override;
|
||||
Array<int> getPossibleBitDepths() override;
|
||||
bool canDoStereo() override;
|
||||
bool canDoMono() override;
|
||||
bool isCompressed() override;
|
||||
StringArray getQualityOptions() override;
|
||||
|
||||
AudioFormatReader* createReaderFor (InputStream*, bool deleteStreamIfOpeningFails);
|
||||
std::unique_ptr<AudioFormatWriter> createWriterFor (std::unique_ptr<OutputStream> streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options) override;
|
||||
|
||||
AudioFormatReader* createReaderFor (InputStream*, bool deleteStreamIfOpeningFails) override;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream*, double sampleRateToUse,
|
||||
unsigned int numberOfChannels, int bitsPerSample,
|
||||
const StringPairArray& metadataValues, int qualityOptionIndex);
|
||||
|
||||
using AudioFormat::createWriterFor;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -3173,6 +3173,13 @@ AudioFormatReader* MP3AudioFormat::createReaderFor (InputStream* sourceStream, c
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> MP3AudioFormat::createWriterFor (std::unique_ptr<OutputStream>&,
|
||||
const AudioFormatWriterOptions&)
|
||||
{
|
||||
jassertfalse; // not yet implemented!
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioFormatWriter* MP3AudioFormat::createWriterFor (OutputStream*, double /*sampleRateToUse*/,
|
||||
unsigned int /*numberOfChannels*/, int /*bitsPerSample*/,
|
||||
const StringPairArray& /*metadataValues*/, int /*qualityOptionIndex*/)
|
||||
|
|
|
|||
|
|
@ -74,6 +74,10 @@ public:
|
|||
AudioFormatWriter* createWriterFor (OutputStream*, double sampleRateToUse,
|
||||
unsigned int numberOfChannels, int bitsPerSample,
|
||||
const StringPairArray& metadataValues, int qualityOptionIndex) override;
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> createWriterFor (std::unique_ptr<OutputStream>& streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options) override;
|
||||
|
||||
using AudioFormat::createWriterFor;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -463,6 +463,28 @@ AudioFormatReader* OggVorbisAudioFormat::createReaderFor (InputStream* in, bool
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> OggVorbisAudioFormat::createWriterFor (std::unique_ptr<OutputStream>& streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options)
|
||||
{
|
||||
if (streamToWriteTo == nullptr)
|
||||
return nullptr;
|
||||
|
||||
StringPairArray metadata;
|
||||
metadata.addUnorderedMap (options.getMetadataValues());
|
||||
|
||||
auto w = std::make_unique<OggWriter> (std::exchange (streamToWriteTo, {}).release(),
|
||||
options.getSampleRate(),
|
||||
(unsigned int) options.getNumChannels(),
|
||||
(unsigned int) options.getBitsPerSample(),
|
||||
options.getQualityOptionIndex(),
|
||||
metadata);
|
||||
|
||||
if (! w->ok)
|
||||
return nullptr;
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
AudioFormatWriter* OggVorbisAudioFormat::createWriterFor (OutputStream* out,
|
||||
double sampleRate,
|
||||
unsigned int numChannels,
|
||||
|
|
|
|||
|
|
@ -93,12 +93,16 @@ public:
|
|||
AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
bool deleteStreamIfOpeningFails) override;
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> createWriterFor (std::unique_ptr<OutputStream>& streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options) override;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) override;
|
||||
|
||||
using AudioFormat::createWriterFor;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -35,18 +35,6 @@
|
|||
namespace juce
|
||||
{
|
||||
|
||||
using StringMap = std::unordered_map<String, String>;
|
||||
|
||||
static auto toMap (const StringPairArray& array)
|
||||
{
|
||||
StringMap result;
|
||||
|
||||
for (auto i = 0; i < array.size(); ++i)
|
||||
result[array.getAllKeys()[i]] = array.getAllValues()[i];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static auto getValueWithDefault (const StringMap& m, const String& key, const String& fallback = {})
|
||||
{
|
||||
const auto iter = m.find (key);
|
||||
|
|
@ -1599,30 +1587,36 @@ class WavAudioFormatWriter final : public AudioFormatWriter
|
|||
public:
|
||||
WavAudioFormatWriter (OutputStream* const out, const double rate,
|
||||
const AudioChannelSet& channelLayoutToUse, const unsigned int bits,
|
||||
const StringPairArray& metadataValues)
|
||||
const StringMap& metadataValues,
|
||||
AudioFormatWriterOptions::SampleFormat sampleFormat)
|
||||
: AudioFormatWriter (out, wavFormatName, rate, channelLayoutToUse, bits)
|
||||
{
|
||||
using namespace WavFileHelpers;
|
||||
using SampleFormat = AudioFormatWriterOptions::SampleFormat;
|
||||
|
||||
if (metadataValues.size() > 0)
|
||||
// The floating point format is only supported with a bit depth of 32
|
||||
jassert (sampleFormat != SampleFormat::floatingPoint || bits == 32);
|
||||
|
||||
usesFloatingPointData = bits == 32 && sampleFormat != SampleFormat::integral;
|
||||
|
||||
if (! metadataValues.empty())
|
||||
{
|
||||
// The meta data should have been sanitised for the WAV format.
|
||||
// If it was originally sourced from an AIFF file the MetaDataSource
|
||||
// key should be removed (or set to "WAV") once this has been done
|
||||
jassert (metadataValues.getValue ("MetaDataSource", "None") != "AIFF");
|
||||
jassert (metadataValues.count ("MetaDataSource") == 0
|
||||
|| metadataValues.at ("MetaDataSource") != "AIFF");
|
||||
|
||||
const auto map = toMap (metadataValues);
|
||||
|
||||
bwavChunk = BWAVChunk::createFrom (map);
|
||||
ixmlChunk = IXMLChunk::createFrom (map);
|
||||
axmlChunk = AXMLChunk::createFrom (map);
|
||||
smplChunk = SMPLChunk::createFrom (map);
|
||||
instChunk = InstChunk::createFrom (map);
|
||||
cueChunk = CueChunk ::createFrom (map);
|
||||
listChunk = ListChunk::createFrom (map);
|
||||
listInfoChunk = ListInfoChunk::createFrom (map);
|
||||
acidChunk = AcidChunk::createFrom (map);
|
||||
trckChunk = TracktionChunk::createFrom (map);
|
||||
bwavChunk = BWAVChunk::createFrom (metadataValues);
|
||||
ixmlChunk = IXMLChunk::createFrom (metadataValues);
|
||||
axmlChunk = AXMLChunk::createFrom (metadataValues);
|
||||
smplChunk = SMPLChunk::createFrom (metadataValues);
|
||||
instChunk = InstChunk::createFrom (metadataValues);
|
||||
cueChunk = CueChunk ::createFrom (metadataValues);
|
||||
listChunk = ListChunk::createFrom (metadataValues);
|
||||
listInfoChunk = ListInfoChunk::createFrom (metadataValues);
|
||||
acidChunk = AcidChunk::createFrom (metadataValues);
|
||||
trckChunk = TracktionChunk::createFrom (metadataValues);
|
||||
}
|
||||
|
||||
headerPosition = out->getPosition();
|
||||
|
|
@ -1773,8 +1767,12 @@ private:
|
|||
else
|
||||
{
|
||||
writeChunkHeader (chunkName ("fmt "), 16);
|
||||
output->writeShort (bitsPerSample < 32 ? (short) 1 /*WAVE_FORMAT_PCM*/
|
||||
: (short) 3 /*WAVE_FORMAT_IEEE_FLOAT*/);
|
||||
|
||||
constexpr short waveFormatIeeeFloat = 3;
|
||||
constexpr short waveFormatPcm = 1;
|
||||
|
||||
output->writeShort (usesFloatingPointData ? waveFormatIeeeFloat
|
||||
: waveFormatPcm);
|
||||
}
|
||||
|
||||
output->writeShort ((short) numChannels);
|
||||
|
|
@ -1789,7 +1787,7 @@ private:
|
|||
output->writeShort ((short) bitsPerSample); // wValidBitsPerSample
|
||||
output->writeInt (channelMask);
|
||||
|
||||
const ExtensibleWavSubFormat& subFormat = bitsPerSample < 32 ? pcmFormat : IEEEFloatFormat;
|
||||
const ExtensibleWavSubFormat& subFormat = usesFloatingPointData ? IEEEFloatFormat : pcmFormat;
|
||||
|
||||
output->writeInt ((int) subFormat.data1);
|
||||
output->writeShort ((short) subFormat.data2);
|
||||
|
|
@ -1809,8 +1807,6 @@ private:
|
|||
writeChunk (trckChunk, chunkName ("Trkn"));
|
||||
|
||||
writeChunkHeader (chunkName ("data"), isRF64 ? -1 : (int) (lengthInSamples * bytesPerFrame));
|
||||
|
||||
usesFloatingPointData = (bitsPerSample == 32);
|
||||
}
|
||||
|
||||
static size_t chunkSize (const MemoryBlock& data) noexcept { return data.isEmpty() ? 0 : (8 + data.getSize()); }
|
||||
|
|
@ -2027,6 +2023,25 @@ MemoryMappedAudioFormatReader* WavAudioFormat::createMemoryMappedReader (FileInp
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> WavAudioFormat::createWriterFor (std::unique_ptr<OutputStream>& streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options)
|
||||
{
|
||||
if (streamToWriteTo == nullptr || ! getPossibleBitDepths().contains (options.getBitsPerSample()))
|
||||
return nullptr;
|
||||
|
||||
const auto layout = options.getChannelLayout().value_or (WavFileHelpers::canonicalWavChannelSet (options.getNumChannels()));
|
||||
|
||||
if (! isChannelLayoutSupported (layout))
|
||||
return nullptr;
|
||||
|
||||
return std::make_unique<WavAudioFormatWriter> (std::exchange (streamToWriteTo, {}).release(),
|
||||
options.getSampleRate(),
|
||||
layout,
|
||||
(unsigned int) options.getBitsPerSample(),
|
||||
options.getMetadataValues(),
|
||||
options.getSampleFormat());
|
||||
}
|
||||
|
||||
AudioFormatWriter* WavAudioFormat::createWriterFor (OutputStream* out, double sampleRate,
|
||||
unsigned int numChannels, int bitsPerSample,
|
||||
const StringPairArray& metadataValues, int qualityOptionIndex)
|
||||
|
|
@ -2044,44 +2059,39 @@ AudioFormatWriter* WavAudioFormat::createWriterFor (OutputStream* out,
|
|||
{
|
||||
if (out != nullptr && getPossibleBitDepths().contains (bitsPerSample) && isChannelLayoutSupported (channelLayout))
|
||||
return new WavAudioFormatWriter (out, sampleRate, channelLayout,
|
||||
(unsigned int) bitsPerSample, metadataValues);
|
||||
(unsigned int) bitsPerSample, toMap (metadataValues),
|
||||
AudioFormatWriterOptions::SampleFormat::automatic);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
namespace WavFileHelpers
|
||||
{
|
||||
static bool slowCopyWavFileWithNewMetadata (const File& file, const StringPairArray& metadata)
|
||||
static bool slowCopyWavFileWithNewMetadata (const File& file, const StringMap& metadata)
|
||||
{
|
||||
TemporaryFile tempFile (file);
|
||||
WavAudioFormat wav;
|
||||
|
||||
std::unique_ptr<AudioFormatReader> reader (wav.createReaderFor (file.createInputStream().release(), true));
|
||||
|
||||
if (reader != nullptr)
|
||||
{
|
||||
std::unique_ptr<OutputStream> outStream (tempFile.getFile().createOutputStream());
|
||||
if (reader == nullptr)
|
||||
return false;
|
||||
|
||||
if (outStream != nullptr)
|
||||
{
|
||||
std::unique_ptr<AudioFormatWriter> writer (wav.createWriterFor (outStream.get(), reader->sampleRate,
|
||||
reader->numChannels, (int) reader->bitsPerSample,
|
||||
metadata, 0));
|
||||
std::unique_ptr<OutputStream> stream = tempFile.getFile().createOutputStream();
|
||||
auto writer = wav.createWriterFor (stream,
|
||||
AudioFormatWriter::Options{}.withSampleRate (reader->sampleRate)
|
||||
.withNumChannels ((int) reader->numChannels)
|
||||
.withBitsPerSample ((int) reader->bitsPerSample)
|
||||
.withMetadataValues (metadata));
|
||||
|
||||
if (writer != nullptr)
|
||||
{
|
||||
outStream.release();
|
||||
if (writer == nullptr)
|
||||
return false;
|
||||
|
||||
bool ok = writer->writeFromAudioReader (*reader, 0, -1);
|
||||
writer.reset();
|
||||
reader.reset();
|
||||
bool ok = writer->writeFromAudioReader (*reader, 0, -1);
|
||||
writer.reset();
|
||||
reader.reset();
|
||||
|
||||
return ok && tempFile.overwriteTargetFileWithTemporary();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return ok && tempFile.overwriteTargetFileWithTemporary();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2123,7 +2133,7 @@ bool WavAudioFormat::replaceMetadataInFile (const File& wavFile, const StringPai
|
|||
}
|
||||
}
|
||||
|
||||
return slowCopyWavFileWithNewMetadata (wavFile, newMetadata);
|
||||
return slowCopyWavFileWithNewMetadata (wavFile, toMap (newMetadata));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2172,15 +2182,14 @@ struct WaveAudioFormatTests final : public UnitTest
|
|||
{
|
||||
beginTest ("Metadata can be written and read");
|
||||
|
||||
const auto newMetadata = getMetadataAfterReading (format, writeToBlock (format, metadataArray));
|
||||
const auto newMetadata = getMetadataAfterReading (format, writeToBlock (format, metadataValues));
|
||||
expect (newMetadata == metadataArray, "Somehow, the metadata is different!");
|
||||
}
|
||||
|
||||
{
|
||||
beginTest ("Files containing a riff info source and an empty ISRC associate the source with the riffInfoSource key");
|
||||
StringPairArray meta;
|
||||
meta.addMap ({ { WavAudioFormat::riffInfoSource, "customsource" },
|
||||
{ WavAudioFormat::internationalStandardRecordingCode, "" } });
|
||||
StringMap meta { { WavAudioFormat::riffInfoSource, "customsource" },
|
||||
{ WavAudioFormat::internationalStandardRecordingCode, "" } };
|
||||
const auto mb = writeToBlock (format, meta);
|
||||
checkPatternsPresent (mb, { "INFOISRC" });
|
||||
checkPatternsNotPresent (mb, { "ISRC:", "<ebucore" });
|
||||
|
|
@ -2192,8 +2201,7 @@ struct WaveAudioFormatTests final : public UnitTest
|
|||
{
|
||||
beginTest ("Files containing a riff info source and no ISRC associate the source with both keys "
|
||||
"for backwards compatibility");
|
||||
StringPairArray meta;
|
||||
meta.addMap ({ { WavAudioFormat::riffInfoSource, "customsource" } });
|
||||
StringMap meta { { WavAudioFormat::riffInfoSource, "customsource" } };
|
||||
const auto mb = writeToBlock (format, meta);
|
||||
checkPatternsPresent (mb, { "INFOISRC", "ISRC:customsource", "<ebucore" });
|
||||
const auto a = getMetadataAfterReading (format, mb);
|
||||
|
|
@ -2204,8 +2212,7 @@ struct WaveAudioFormatTests final : public UnitTest
|
|||
{
|
||||
beginTest ("Files containing an ISRC associate the value with the internationalStandardRecordingCode key "
|
||||
"and the riffInfoSource key for backwards compatibility");
|
||||
StringPairArray meta;
|
||||
meta.addMap ({ { WavAudioFormat::internationalStandardRecordingCode, "AABBBCCDDDDD" } });
|
||||
StringMap meta { { WavAudioFormat::internationalStandardRecordingCode, "AABBBCCDDDDD" } };
|
||||
const auto mb = writeToBlock (format, meta);
|
||||
checkPatternsPresent (mb, { "ISRC:AABBBCCDDDDD", "<ebucore" });
|
||||
checkPatternsNotPresent (mb, { "INFOISRC" });
|
||||
|
|
@ -2216,9 +2223,8 @@ struct WaveAudioFormatTests final : public UnitTest
|
|||
|
||||
{
|
||||
beginTest ("Files containing an ISRC and a riff info source associate the values with the appropriate keys");
|
||||
StringPairArray meta;
|
||||
meta.addMap ({ { WavAudioFormat::riffInfoSource, "source" } });
|
||||
meta.addMap ({ { WavAudioFormat::internationalStandardRecordingCode, "UUVVVXXYYYYY" } });
|
||||
StringMap meta { { WavAudioFormat::riffInfoSource, "source" },
|
||||
{ WavAudioFormat::internationalStandardRecordingCode, "UUVVVXXYYYYY" } };
|
||||
const auto mb = writeToBlock (format, meta);
|
||||
checkPatternsPresent (mb, { "INFOISRC", "ISRC:UUVVVXXYYYYY", "<ebucore" });
|
||||
const auto a = getMetadataAfterReading (format, mb);
|
||||
|
|
@ -2229,13 +2235,19 @@ struct WaveAudioFormatTests final : public UnitTest
|
|||
{
|
||||
beginTest ("Files containing ASWG metadata read and write correctly");
|
||||
MemoryBlock block;
|
||||
StringPairArray meta;
|
||||
StringMap meta;
|
||||
|
||||
for (const auto& key : WavFileHelpers::IXMLChunk::aswgMetadataKeys)
|
||||
meta.set (key, "Test123&<>");
|
||||
meta[key] = "Test123&<>";
|
||||
|
||||
{
|
||||
auto writer = rawToUniquePtr (WavAudioFormat().createWriterFor (new MemoryOutputStream (block, false), 48000, 1, 32, meta, 0));
|
||||
const auto writerOptions = AudioFormatWriterOptions{}.withSampleRate (48000.0)
|
||||
.withNumChannels (1)
|
||||
.withBitsPerSample (32)
|
||||
.withMetadataValues (meta);
|
||||
|
||||
std::unique_ptr<OutputStream> stream = std::make_unique<MemoryOutputStream> (block, false);
|
||||
auto writer = format.createWriterFor (stream, writerOptions);
|
||||
expect (writer != nullptr);
|
||||
}
|
||||
|
||||
|
|
@ -2270,9 +2282,8 @@ struct WaveAudioFormatTests final : public UnitTest
|
|||
auto reader = rawToUniquePtr (WavAudioFormat().createReaderFor (new MemoryInputStream (block, false), true));
|
||||
expect (reader != nullptr);
|
||||
|
||||
for (const auto& key : meta.getAllKeys())
|
||||
for (const auto& [key, oldValue] : meta)
|
||||
{
|
||||
const auto oldValue = meta.getValue (key, "!");
|
||||
const auto newValue = reader->metadataValues.getValue (key, "");
|
||||
expectEquals (oldValue, newValue);
|
||||
}
|
||||
|
|
@ -2280,22 +2291,128 @@ struct WaveAudioFormatTests final : public UnitTest
|
|||
expect (reader->metadataValues.getValue (WavAudioFormat::aswgVersion, "") == "3.01");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
beginTest ("Writing 32-bit integer samples should work");
|
||||
|
||||
const auto minimum = std::numeric_limits<int>::min();
|
||||
const auto maximum = std::numeric_limits<int>::max();
|
||||
|
||||
std::vector<int> dataIn { minimum,
|
||||
minimum + 1,
|
||||
minimum + 999,
|
||||
0,
|
||||
1,
|
||||
maximum - 1001,
|
||||
maximum - 1,
|
||||
maximum };
|
||||
|
||||
const int* ptr = dataIn.data();
|
||||
|
||||
WavFormatWriterTestData integralTestData { &ptr,
|
||||
dataIn.size(),
|
||||
AudioFormatWriterOptions::SampleFormat::integral };
|
||||
|
||||
auto* reader = integralTestData.getReader();
|
||||
|
||||
if (reader == nullptr)
|
||||
{
|
||||
expect (false, "WavFormatReader should be non-null");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<int> dataOut ((size_t) reader->lengthInSamples);
|
||||
int* const outPtr = dataOut.data();
|
||||
reader->read (&outPtr, 1, 0, (int) dataOut.size(), false);
|
||||
|
||||
expect (reader->usesFloatingPointData == false);
|
||||
expect (dataIn == dataOut);
|
||||
}
|
||||
|
||||
{
|
||||
beginTest ("Writing 32-bit float samples should work");
|
||||
|
||||
std::vector<float> dataIn { -1.0f,
|
||||
-0.8f,
|
||||
0.0f,
|
||||
0.8f,
|
||||
1.0f };
|
||||
|
||||
const int* ptr = (int*) dataIn.data();
|
||||
|
||||
WavFormatWriterTestData floatingPointTestData { &ptr,
|
||||
dataIn.size(),
|
||||
AudioFormatWriterOptions::SampleFormat::floatingPoint };
|
||||
|
||||
auto* reader = floatingPointTestData.getReader();
|
||||
|
||||
if (reader == nullptr)
|
||||
{
|
||||
expect (false, "WavFormatReader should be non-null");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<float> dataOut ((size_t) reader->lengthInSamples);
|
||||
float* const outPtr = dataOut.data();
|
||||
reader->read (&outPtr, 1, 0, (int) dataOut.size());
|
||||
|
||||
expect (reader->usesFloatingPointData == true);
|
||||
expect (dataIn.size() == dataOut.size());
|
||||
|
||||
for (auto [index, value] : enumerate (dataOut, size_t{}))
|
||||
expect (approximatelyEqual (value, dataIn[index]));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryBlock writeToBlock (WavAudioFormat& format, StringPairArray meta)
|
||||
struct WavFormatWriterTestData
|
||||
{
|
||||
WavFormatWriterTestData (const int** ptr,
|
||||
size_t numSamples,
|
||||
AudioFormatWriterOptions::SampleFormat sampleFormat)
|
||||
{
|
||||
const auto writerOptions = AudioFormatWriterOptions{}.withSampleRate (48000.0)
|
||||
.withNumChannels (1)
|
||||
.withBitsPerSample (32)
|
||||
.withSampleFormat (sampleFormat);
|
||||
|
||||
WavAudioFormat format;
|
||||
|
||||
{
|
||||
std::unique_ptr<OutputStream> stream = std::make_unique<MemoryOutputStream> (block, false);
|
||||
auto writer = format.createWriterFor (stream, writerOptions);
|
||||
|
||||
writer->write (ptr, (int) numSamples);
|
||||
}
|
||||
|
||||
reader = rawToUniquePtr (format.createReaderFor (new MemoryInputStream (block, false), true));
|
||||
}
|
||||
|
||||
AudioFormatReader* getReader()
|
||||
{
|
||||
return reader.get();
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryBlock block;
|
||||
std::unique_ptr<AudioFormatReader> reader;
|
||||
};
|
||||
|
||||
MemoryBlock writeToBlock (WavAudioFormat& format, const StringMap& meta)
|
||||
{
|
||||
MemoryBlock mb;
|
||||
|
||||
{
|
||||
const auto writerOptions = AudioFormatWriterOptions{}.withSampleRate (44100.0)
|
||||
.withNumChannels ((int) numTestAudioBufferChannels)
|
||||
.withBitsPerSample (16)
|
||||
.withMetadataValues (meta);
|
||||
|
||||
// The destructor of the writer will modify the block, so make sure that we've
|
||||
// destroyed the writer before returning the block!
|
||||
auto writer = rawToUniquePtr (format.createWriterFor (new MemoryOutputStream (mb, false),
|
||||
44100.0,
|
||||
numTestAudioBufferChannels,
|
||||
16,
|
||||
meta,
|
||||
0));
|
||||
std::unique_ptr<OutputStream> stream = std::make_unique<MemoryOutputStream> (mb, false);
|
||||
auto writer = format.createWriterFor (stream, writerOptions);
|
||||
|
||||
expect (writer != nullptr);
|
||||
AudioBuffer<float> buffer (numTestAudioBufferChannels, numTestAudioBufferSamples);
|
||||
expect (writer->writeFromAudioSampleBuffer (buffer, 0, numTestAudioBufferSamples));
|
||||
|
|
|
|||
|
|
@ -297,6 +297,9 @@ public:
|
|||
MemoryMappedAudioFormatReader* createMemoryMappedReader (const File&) override;
|
||||
MemoryMappedAudioFormatReader* createMemoryMappedReader (FileInputStream*) override;
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> createWriterFor (std::unique_ptr<OutputStream>& streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options) override;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
|
|
@ -310,6 +313,7 @@ public:
|
|||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) override;
|
||||
|
||||
using AudioFormat::createWriterFor;
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -365,6 +365,13 @@ AudioFormatWriter* WindowsMediaAudioFormat::createWriterFor (OutputStream* /*str
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> WindowsMediaAudioFormat::createWriterFor (std::unique_ptr<OutputStream>&,
|
||||
const AudioFormatWriterOptions&)
|
||||
{
|
||||
jassertfalse; // not yet implemented!
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
|
|
|||
|
|
@ -60,9 +60,13 @@ public:
|
|||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream*, bool deleteStreamIfOpeningFails) override;
|
||||
|
||||
std::unique_ptr<AudioFormatWriter> createWriterFor (std::unique_ptr<OutputStream>& streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options) override;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream*, double sampleRateToUse,
|
||||
unsigned int numberOfChannels, int bitsPerSample,
|
||||
const StringPairArray& metadataValues, int qualityOptionIndex) override;
|
||||
|
||||
using AudioFormat::createWriterFor;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,53 @@ bool AudioFormat::isChannelLayoutSupported (const AudioChannelSet& channelSet)
|
|||
return false;
|
||||
}
|
||||
|
||||
using StringMap = std::unordered_map<String, String>;
|
||||
|
||||
static StringMap toMap (const StringPairArray& array)
|
||||
{
|
||||
StringMap result;
|
||||
|
||||
for (auto i = 0; i < array.size(); ++i)
|
||||
result[array.getAllKeys()[i]] = array.getAllValues()[i];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
AudioFormatWriter* AudioFormat::createWriterForRawPtr (OutputStream* streamToWriteTo,
|
||||
const AudioFormatWriterOptions& opt)
|
||||
{
|
||||
auto owned = rawToUniquePtr (streamToWriteTo);
|
||||
|
||||
if (auto writer = createWriterFor (owned, opt))
|
||||
{
|
||||
// Creating the writer succeeded, so it's the writer's responsibility to eventually free
|
||||
// the stream
|
||||
jassert (owned == nullptr);
|
||||
return writer.release();
|
||||
}
|
||||
|
||||
// Creating the writer failed, so the stream should remain alive for re-use
|
||||
jassert (owned != nullptr);
|
||||
owned.release();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
AudioFormatWriter* AudioFormat::createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex)
|
||||
{
|
||||
auto opt = AudioFormatWriter::Options{}.withSampleRate (sampleRateToUse)
|
||||
.withNumChannels ((int) numberOfChannels)
|
||||
.withBitsPerSample (bitsPerSample)
|
||||
.withMetadataValues (toMap (metadataValues))
|
||||
.withQualityOptionIndex (qualityOptionIndex);
|
||||
return createWriterForRawPtr (streamToWriteTo, opt);
|
||||
}
|
||||
|
||||
AudioFormatWriter* AudioFormat::createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
const AudioChannelSet& channelLayout,
|
||||
|
|
@ -89,12 +136,15 @@ AudioFormatWriter* AudioFormat::createWriterFor (OutputStream* streamToWriteTo,
|
|||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex)
|
||||
{
|
||||
if (isChannelLayoutSupported (channelLayout))
|
||||
return createWriterFor (streamToWriteTo, sampleRateToUse,
|
||||
static_cast<unsigned int> (channelLayout.size()),
|
||||
bitsPerSample, metadataValues, qualityOptionIndex);
|
||||
if (! isChannelLayoutSupported (channelLayout))
|
||||
return nullptr;
|
||||
|
||||
return nullptr;
|
||||
auto opt = AudioFormatWriter::Options{}.withSampleRate (sampleRateToUse)
|
||||
.withChannelLayout (channelLayout)
|
||||
.withBitsPerSample (bitsPerSample)
|
||||
.withMetadataValues (toMap (metadataValues))
|
||||
.withQualityOptionIndex (qualityOptionIndex);
|
||||
return createWriterForRawPtr (streamToWriteTo, opt);
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
|
|
@ -125,6 +125,26 @@ public:
|
|||
virtual MemoryMappedAudioFormatReader* createMemoryMappedReader (const File& file);
|
||||
virtual MemoryMappedAudioFormatReader* createMemoryMappedReader (FileInputStream* fin);
|
||||
|
||||
/** Tries to create an object that can write to a stream with this audio format.
|
||||
|
||||
If the writer can't be created for some reason (e.g. the parameters passed in
|
||||
here aren't suitable), this will return nullptr.
|
||||
|
||||
@param streamToWriteTo a reference to a unique_ptr that owns the output stream. If creating
|
||||
the writer succeeds, then ownership of the stream will be
|
||||
transferred to the writer, and this argument will be set to nullptr.
|
||||
If creating the writer fails, then streamToWriteTo will remain
|
||||
unchanged, allowing it to be reused to create a writer of a
|
||||
different format.
|
||||
@param options options that specify details of the output file. If the audio format
|
||||
does not support these settings, then this function may return
|
||||
nullptr.
|
||||
|
||||
@see AudioFormatWriterOptions
|
||||
*/
|
||||
virtual std::unique_ptr<AudioFormatWriter> createWriterFor (std::unique_ptr<OutputStream>& streamToWriteTo,
|
||||
const AudioFormatWriterOptions& options) = 0;
|
||||
|
||||
/** Tries to create an object that can write to a stream with this audio format.
|
||||
|
||||
The writer object that is returned can be used to write to the stream, and
|
||||
|
|
@ -217,6 +237,8 @@ protected:
|
|||
AudioFormat (StringRef formatName, StringRef fileExtensions);
|
||||
|
||||
private:
|
||||
AudioFormatWriter* createWriterForRawPtr (OutputStream*, const AudioFormatWriterOptions&);
|
||||
|
||||
//==============================================================================
|
||||
String formatName;
|
||||
StringArray fileExtensions;
|
||||
|
|
|
|||
|
|
@ -93,6 +93,8 @@ protected:
|
|||
unsigned int bitsPerSample);
|
||||
|
||||
public:
|
||||
using Options = AudioFormatWriterOptions;
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~AudioFormatWriter();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
Options that affect the output data format produced by an AudioFormatWriter. Format
|
||||
specific writers may ignore some of these options.
|
||||
|
||||
@see AudioFormat::createWriterFor(), AudioFormatWriter
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API AudioFormatWriterOptions final
|
||||
{
|
||||
public:
|
||||
/** Used to provide a hint to the AudioFormatWriter for the output sample format.
|
||||
|
||||
Use automatic for the old behaviour. The values integral and floatingPoint can be used with
|
||||
the WavAudioFormat when using a bit depth of 32. Other formats are not affected by this
|
||||
setting.
|
||||
*/
|
||||
enum class SampleFormat
|
||||
{
|
||||
automatic, ///< Lets the writer decide the format based on the other parameter values.
|
||||
integral, ///< Integral format, e.g. PCM in case of the WavAudioFormat
|
||||
floatingPoint ///< IEEE floating point format
|
||||
};
|
||||
|
||||
/** Returns a copy of these options with the specified sample format.
|
||||
|
||||
@see SampleFormat
|
||||
*/
|
||||
[[nodiscard]] AudioFormatWriterOptions withSampleFormat (SampleFormat x) const
|
||||
{
|
||||
return withMember (*this, &AudioFormatWriterOptions::sampleFormat, x);
|
||||
}
|
||||
|
||||
/** Returns a copy of these options with the specified sample rate.
|
||||
|
||||
This specifies the sample rate for the file, which must be one of the ones
|
||||
returned by AudioFormat::getPossibleSampleRates().
|
||||
*/
|
||||
[[nodiscard]] AudioFormatWriterOptions withSampleRate (double x) const
|
||||
{
|
||||
return withMember (*this, &AudioFormatWriterOptions::sampleRate, x);
|
||||
}
|
||||
|
||||
/** Returns a copy of these options with the specified channel set.
|
||||
|
||||
Setting this option will supersede the value passed into withNumChannels().
|
||||
|
||||
You should prefer to use withChannelLayout(), if specifying an AudioChannelSet is
|
||||
applicable, and withNumChannels() otherwise.
|
||||
*/
|
||||
[[nodiscard]] AudioFormatWriterOptions withChannelLayout (const AudioChannelSet& x) const
|
||||
{
|
||||
return withMember (*this, &AudioFormatWriterOptions::channelLayout, x);
|
||||
}
|
||||
|
||||
/** Returns a copy of these options with the specified number of channels.
|
||||
|
||||
This is meant as a fallback for specifying the channel layout. Setting this option will
|
||||
have no effect if the channel layout is specified.
|
||||
|
||||
@see withChannelLayout()
|
||||
*/
|
||||
[[nodiscard]] AudioFormatWriterOptions withNumChannels (int x) const
|
||||
{
|
||||
return withMember (*this, &AudioFormatWriterOptions::numChannels, x);
|
||||
}
|
||||
|
||||
/** Returns a copy of these options with the specified bit size per sample.
|
||||
|
||||
This must be one of the values returned by AudioFormat::getPossibleBitDepths().
|
||||
*/
|
||||
[[nodiscard]] AudioFormatWriterOptions withBitsPerSample (int x) const
|
||||
{
|
||||
return withMember (*this, &AudioFormatWriterOptions::bitsPerSample, x);
|
||||
}
|
||||
|
||||
/** Returns a copy of these options with the specified metadata container.
|
||||
|
||||
As an alternative to this function, you can specify the key-value pairs one-by-one using
|
||||
the withMetadata function.
|
||||
|
||||
Subsequent calls of this function overwrites all previously added metadata.
|
||||
|
||||
This parameter is a set of metadata values that the writer should try to write to the stream.
|
||||
Exactly what these are depends on the format, and the subclass doesn't actually have to do
|
||||
anything with them if it doesn't want to. Have a look at the specific format implementation
|
||||
classes to see possible values that can be used.
|
||||
*/
|
||||
[[nodiscard]] AudioFormatWriterOptions withMetadataValues (const std::unordered_map<String, String>& x) const
|
||||
{
|
||||
return withMember (*this, &AudioFormatWriterOptions::metadataValues, x);
|
||||
}
|
||||
|
||||
/** Returns a copy of these options with the specified metadata added.
|
||||
|
||||
Subsequent calls of this function adds new metadata values, while also preserving the
|
||||
previously added ones.
|
||||
|
||||
Here you can specify metadata values that the writer should try to write to the stream.
|
||||
Exactly what these are depends on the format, and the subclass doesn't actually have to do
|
||||
anything with them if it doesn't want to. Have a look at the specific format implementation
|
||||
classes to see possible values that can be used.
|
||||
*/
|
||||
[[nodiscard]] AudioFormatWriterOptions withMetadata (const String& key, const String& value) const
|
||||
{
|
||||
auto copy = *this;
|
||||
copy.metadataValues[key] = value;
|
||||
return copy;
|
||||
}
|
||||
|
||||
/** Returns a copy of these options with the specified quality option index.
|
||||
|
||||
The index of one of the items returned by the AudioFormat::getQualityOptions() method.
|
||||
*/
|
||||
[[nodiscard]] AudioFormatWriterOptions withQualityOptionIndex (int x) const
|
||||
{
|
||||
return withMember (*this, &AudioFormatWriterOptions::qualityOptionIndex, x);
|
||||
}
|
||||
|
||||
/** @see withSampleRate() */
|
||||
[[nodiscard]] auto getSampleRate() const { return sampleRate; }
|
||||
/** @see withChannelLayout() */
|
||||
[[nodiscard]] auto getChannelLayout() const { return channelLayout; }
|
||||
/** @see withNumChannels() */
|
||||
[[nodiscard]] auto getNumChannels() const { return channelLayout.has_value() ? channelLayout->size() : numChannels; }
|
||||
/** @see withBitsPerSample() */
|
||||
[[nodiscard]] auto getBitsPerSample() const { return bitsPerSample; }
|
||||
/** @see withMetadataValues() */
|
||||
[[nodiscard]] auto getMetadataValues() const { return metadataValues; }
|
||||
/** @see withQualityOptionIndex() */
|
||||
[[nodiscard]] auto getQualityOptionIndex() const { return qualityOptionIndex; }
|
||||
/** @see withSampleFormat() */
|
||||
[[nodiscard]] auto getSampleFormat() const { return sampleFormat; }
|
||||
|
||||
private:
|
||||
double sampleRate = 48000.0;
|
||||
int numChannels = 1;
|
||||
std::optional<AudioChannelSet> channelLayout = std::nullopt;
|
||||
int bitsPerSample = 16;
|
||||
std::unordered_map<String, String> metadataValues;
|
||||
int qualityOptionIndex = 0;
|
||||
SampleFormat sampleFormat = SampleFormat::automatic;
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
|
|
@ -121,6 +121,7 @@
|
|||
|
||||
//==============================================================================
|
||||
#include "format/juce_AudioFormatReader.h"
|
||||
#include "format/juce_AudioFormatWriterOptions.h"
|
||||
#include "format/juce_AudioFormatWriter.h"
|
||||
#include "format/juce_MemoryMappedAudioFormatReader.h"
|
||||
#include "format/juce_AudioFormat.h"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue