|
- /*
- ==============================================================================
-
- This file is part of the Water library.
- Copyright (c) 2015 ROLI Ltd.
- Copyright (C) 2018 Filipe Coelho <falktx@falktx.com>
-
- Permission is granted to use this software under the terms of either:
- a) the GPL v2 (or any later version)
- b) the Affero GPL v3
-
- Details of these licenses can be found at: www.gnu.org/licenses
-
- Water 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.
-
- ==============================================================================
- */
-
- #ifndef WATER_AUDIOFORMATREADER_H_INCLUDED
- #define WATER_AUDIOFORMATREADER_H_INCLUDED
-
- #include "../buffers/AudioDataConverters.h"
- #include "../text/StringPairArray.h"
-
- #include "CarlaJuceUtils.hpp"
-
- namespace water {
-
- //==============================================================================
- /**
- Reads samples from an audio file stream.
-
- A subclass that reads a specific type of audio format will be created by
- an AudioFormat object.
-
- @see AudioFormat, AudioFormatWriter
- */
- class AudioFormatReader
- {
- protected:
- //==============================================================================
- /** Creates an AudioFormatReader object.
-
- @param sourceStream the stream to read from - this will be deleted
- by this object when it is no longer needed. (Some
- specialised readers might not use this parameter and
- can leave it as nullptr).
- @param formatName the description that will be returned by the getFormatName()
- method
- */
- AudioFormatReader (InputStream* sourceStream,
- const String& formatName);
-
- public:
- /** Destructor. */
- virtual ~AudioFormatReader();
-
- //==============================================================================
- /** Returns a description of what type of format this is.
-
- E.g. "AIFF"
- */
- const String& getFormatName() const noexcept { return formatName; }
-
- //==============================================================================
- /** Reads samples from the stream.
-
- @param destSamples an array of buffers into which the sample data for each
- channel will be written.
- If the format is fixed-point, each channel will be written
- as an array of 32-bit signed integers using the full
- range -0x80000000 to 0x7fffffff, regardless of the source's
- bit-depth. If it is a floating-point format, you should cast
- the resulting array to a (float**) to get the values (in the
- range -1.0 to 1.0 or beyond)
- If the format is stereo, then destSamples[0] is the left channel
- data, and destSamples[1] is the right channel.
- The numDestChannels parameter indicates how many pointers this array
- contains, but some of these pointers can be null if you don't want to
- read data for some of the channels
- @param numDestChannels the number of array elements in the destChannels array
- @param startSampleInSource the position in the audio file or stream at which the samples
- should be read, as a number of samples from the start of the
- stream. It's ok for this to be beyond the start or end of the
- available data - any samples that are out-of-range will be returned
- as zeros.
- @param numSamplesToRead the number of samples to read. If this is greater than the number
- of samples that the file or stream contains. the result will be padded
- with zeros
- @param fillLeftoverChannelsWithCopies if true, this indicates that if there's no source data available
- for some of the channels that you pass in, then they should be filled with
- copies of valid source channels.
- E.g. if you're reading a mono file and you pass 2 channels to this method, then
- if fillLeftoverChannelsWithCopies is true, both destination channels will be filled
- with the same data from the file's single channel. If fillLeftoverChannelsWithCopies
- was false, then only the first channel would be filled with the file's contents, and
- the second would be cleared. If there are many channels, e.g. you try to read 4 channels
- from a stereo file, then the last 3 would all end up with copies of the same data.
- @returns true if the operation succeeded, false if there was an error. Note
- that reading sections of data beyond the extent of the stream isn't an
- error - the reader should just return zeros for these regions
- @see readMaxLevels
- */
- bool read (int* const* destSamples,
- int numDestChannels,
- int64 startSampleInSource,
- int numSamplesToRead,
- bool fillLeftoverChannelsWithCopies);
-
- /** Fills a section of an AudioSampleBuffer from this reader.
-
- This will convert the reader's fixed- or floating-point data to
- the buffer's floating-point format, and will try to intelligently
- cope with mismatches between the number of channels in the reader
- and the buffer.
- */
- void read (AudioSampleBuffer* buffer,
- int startSampleInDestBuffer,
- int numSamples,
- int64 readerStartSample,
- bool useReaderLeftChan,
- bool useReaderRightChan);
-
- //==============================================================================
- /** The sample-rate of the stream. */
- double sampleRate;
-
- /** The number of bits per sample, e.g. 16, 24, 32. */
- unsigned int bitsPerSample;
-
- /** The total number of samples in the audio stream. */
- int64 lengthInSamples;
-
- /** The total number of channels in the audio stream. */
- unsigned int numChannels;
-
- /** Indicates whether the data is floating-point or fixed. */
- bool usesFloatingPointData;
-
- /** A set of metadata values that the reader has pulled out of the stream.
-
- Exactly what these values are depends on the format, so you can
- check out the format implementation code to see what kind of stuff
- they understand.
- */
- StringPairArray metadataValues;
-
- /** The input stream, for use by subclasses. */
- InputStream* input;
-
-
- //==============================================================================
- /** Subclasses must implement this method to perform the low-level read operation.
-
- Callers should use read() instead of calling this directly.
-
- @param destSamples the array of destination buffers to fill. Some of these
- pointers may be null
- @param numDestChannels the number of items in the destSamples array. This
- value is guaranteed not to be greater than the number of
- channels that this reader object contains
- @param startOffsetInDestBuffer the number of samples from the start of the
- dest data at which to begin writing
- @param startSampleInFile the number of samples into the source data at which
- to begin reading. This value is guaranteed to be >= 0.
- @param numSamples the number of samples to read
- */
- virtual bool readSamples (int** destSamples,
- int numDestChannels,
- int startOffsetInDestBuffer,
- int64 startSampleInFile,
- int numSamples) = 0;
-
-
- protected:
- //==============================================================================
- /** Used by AudioFormatReader subclasses to copy data to different formats. */
- template <class DestSampleType, class SourceSampleType, class SourceEndianness>
- struct ReadHelper
- {
- typedef AudioData::Pointer<DestSampleType, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst> DestType;
- typedef AudioData::Pointer<SourceSampleType, SourceEndianness, AudioData::Interleaved, AudioData::Const> SourceType;
-
- template <typename TargetType>
- static void read (TargetType* const* destData, int destOffset, int numDestChannels,
- const void* sourceData, int numSourceChannels, int numSamples) noexcept
- {
- for (int i = 0; i < numDestChannels; ++i)
- {
- if (void* targetChan = destData[i])
- {
- DestType dest (targetChan);
- dest += destOffset;
-
- if (i < numSourceChannels)
- dest.convertSamples (SourceType (addBytesToPointer (sourceData, i * SourceType::getBytesPerSample()), numSourceChannels), numSamples);
- else
- dest.clearSamples (numSamples);
- }
- }
- }
- };
-
- /** Used by AudioFormatReader subclasses to clear any parts of the data blocks that lie
- beyond the end of their available length.
- */
- static void clearSamplesBeyondAvailableLength (int** destSamples, int numDestChannels,
- int startOffsetInDestBuffer, int64 startSampleInFile,
- int& numSamples, int64 fileLengthInSamples)
- {
- jassert (destSamples != nullptr);
- const int64 samplesAvailable = fileLengthInSamples - startSampleInFile;
-
- if (samplesAvailable < numSamples)
- {
- for (int i = numDestChannels; --i >= 0;)
- if (destSamples[i] != nullptr)
- zeromem (destSamples[i] + startOffsetInDestBuffer, sizeof (int) * (size_t) numSamples);
-
- numSamples = (int) samplesAvailable;
- }
- }
-
- private:
- String formatName;
-
- CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioFormatReader)
- };
-
- }
-
- #endif // WATER_AUDIOFORMATREADER_H_INCLUDED
|