From fe3a2e4495db0fa70080af805f2687b9fff1dee8 Mon Sep 17 00:00:00 2001 From: jules Date: Wed, 27 Feb 2013 17:55:24 +0000 Subject: [PATCH] Added method AudioFormatWriter::writeFromFloatArrays() --- .../format/juce_AudioFormatWriter.cpp | 111 ++++++++++-------- .../format/juce_AudioFormatWriter.h | 3 + 2 files changed, 68 insertions(+), 46 deletions(-) diff --git a/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp b/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp index e2e085a84d..b2f41dc156 100644 --- a/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp +++ b/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp @@ -42,6 +42,23 @@ AudioFormatWriter::~AudioFormatWriter() delete output; } +static void convertFloatsToInts (int* dest, const float* src, int numSamples) noexcept +{ + while (--numSamples >= 0) + { + const double samp = *src++; + + if (samp <= -1.0) + *dest = std::numeric_limits::min(); + else if (samp >= 1.0) + *dest = std::numeric_limits::max(); + else + *dest = roundToInt (std::numeric_limits::max() * samp); + + ++dest; + } +} + bool AudioFormatWriter::writeFromAudioReader (AudioFormatReader& reader, int64 startSample, int64 numSamplesToRead) @@ -70,31 +87,12 @@ bool AudioFormatWriter::writeFromAudioReader (AudioFormatReader& reader, while (*bufferChan != nullptr) { - int* b = *bufferChan++; + void* const b = *bufferChan++; if (isFloatingPoint()) - { - // int -> float - const double factor = 1.0 / std::numeric_limits::max(); - - for (int i = 0; i < numToDo; ++i) - reinterpret_cast (b)[i] = (float) (factor * b[i]); - } + FloatVectorOperations::convertFixedToFloat ((float*) b, (int*) b, 1.0f / 0x7fffffff, numToDo); else - { - // float -> int - for (int i = 0; i < numToDo; ++i) - { - const double samp = *(const float*) b; - - if (samp <= -1.0) - *b++ = std::numeric_limits::min(); - else if (samp >= 1.0) - *b++ = std::numeric_limits::max(); - else - *b++ = roundToInt (std::numeric_limits::max() * samp); - } - } + convertFloatsToInts ((int*) b, (float*) b, numToDo); } } @@ -130,39 +128,60 @@ bool AudioFormatWriter::writeFromAudioSource (AudioSource& source, int numSample return true; } -bool AudioFormatWriter::writeFromAudioSampleBuffer (const AudioSampleBuffer& source, int startSample, int numSamples) +bool AudioFormatWriter::writeFromFloatArrays (const float** channels, int numSourceChannels, int numSamples) { - jassert (startSample >= 0 && startSample + numSamples <= source.getNumSamples() && source.getNumChannels() > 0); - if (numSamples <= 0) return true; - HeapBlock tempBuffer; - HeapBlock chans (numChannels + 1); - chans [numChannels] = 0; - if (isFloatingPoint()) - { - for (int i = (int) numChannels; --i >= 0;) - chans[i] = reinterpret_cast (source.getSampleData (i, startSample)); - } - else - { - tempBuffer.malloc (((size_t) numSamples) * (size_t) numChannels); + return write ((const int**) channels, numSamples); - for (unsigned int i = 0; i < numChannels; ++i) - { - typedef AudioData::Pointer DestSampleType; - typedef AudioData::Pointer SourceSampleType; + int* chans [256]; + int scratch [4096]; - chans[i] = tempBuffer + (int) i * numSamples; - DestSampleType destData (chans[i]); - SourceSampleType sourceData (source.getSampleData ((int) i, startSample)); - destData.convertSamples (sourceData, numSamples); - } + jassert (numSourceChannels < numElementsInArray (chans)); + const int maxSamples = (int) (numElementsInArray (scratch) / numSourceChannels); + + for (int i = 0; i < numSourceChannels; ++i) + chans[i] = scratch + (i * maxSamples); + + chans[numSourceChannels] = nullptr; + int startSample = 0; + + while (numSamples > 0) + { + const int numToDo = jmin (numSamples, maxSamples); + + for (int i = 0; i < numSourceChannels; ++i) + convertFloatsToInts (chans[i], channels[i] + startSample, numToDo); + + if (! write ((const int**) chans, numToDo)) + return false; + + startSample += numToDo; + numSamples -= numToDo; } - return write ((const int**) chans.getData(), numSamples); + return true; +} + +bool AudioFormatWriter::writeFromAudioSampleBuffer (const AudioSampleBuffer& source, int startSample, int numSamples) +{ + const int numSourceChannels = source.getNumChannels(); + jassert (startSample >= 0 && startSample + numSamples <= source.getNumSamples() && numSourceChannels > 0); + + if (startSample == 0) + return writeFromFloatArrays ((const float**) source.getArrayOfChannels(), numSourceChannels, numSamples); + + const float* chans [256]; + jassert (numChannels < numElementsInArray (chans)); + + for (int i = 0; i < numSourceChannels; ++i) + chans[i] = source.getSampleData (i, startSample); + + chans[numSourceChannels] = nullptr; + + return writeFromFloatArrays (chans, numSourceChannels, numSamples); } //============================================================================== diff --git a/modules/juce_audio_formats/format/juce_AudioFormatWriter.h b/modules/juce_audio_formats/format/juce_AudioFormatWriter.h index 48041099ee..c062d883f7 100644 --- a/modules/juce_audio_formats/format/juce_AudioFormatWriter.h +++ b/modules/juce_audio_formats/format/juce_AudioFormatWriter.h @@ -130,6 +130,9 @@ public: bool writeFromAudioSampleBuffer (const AudioSampleBuffer& source, int startSample, int numSamples); + /** Writes some samples from a set of float data channels. */ + bool writeFromFloatArrays (const float** channels, int numChannels, int numSamples); + //============================================================================== /** Returns the sample rate being used. */ double getSampleRate() const noexcept { return sampleRate; }