|
|
@@ -83,6 +83,66 @@ private: |
|
|
|
int8 values[2];
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
template <typename T>
|
|
|
|
class AudioBufferReader : public AudioFormatReader
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
AudioBufferReader (const AudioBuffer<T>* bufferIn, double rate)
|
|
|
|
: AudioFormatReader (nullptr, "AudioBuffer"), buffer (bufferIn)
|
|
|
|
{
|
|
|
|
sampleRate = rate;
|
|
|
|
bitsPerSample = 32;
|
|
|
|
lengthInSamples = buffer->getNumSamples();
|
|
|
|
numChannels = (unsigned int) buffer->getNumChannels();
|
|
|
|
usesFloatingPointData = std::is_floating_point_v<T>;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool readSamples (int* const* destChannels,
|
|
|
|
int numDestChannels,
|
|
|
|
int startOffsetInDestBuffer,
|
|
|
|
int64 startSampleInFile,
|
|
|
|
int numSamples) override
|
|
|
|
{
|
|
|
|
clearSamplesBeyondAvailableLength (destChannels, numDestChannels, startOffsetInDestBuffer,
|
|
|
|
startSampleInFile, numSamples, lengthInSamples);
|
|
|
|
|
|
|
|
const auto numAvailableSamples = (int) ((int64) buffer->getNumSamples() - startSampleInFile);
|
|
|
|
const auto numSamplesToCopy = std::clamp (numAvailableSamples, 0, numSamples);
|
|
|
|
|
|
|
|
if (numSamplesToCopy == 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
for (int i = 0; i < numDestChannels; ++i)
|
|
|
|
{
|
|
|
|
if (void* targetChannel = destChannels[i])
|
|
|
|
{
|
|
|
|
const auto dest = DestType (targetChannel) + startOffsetInDestBuffer;
|
|
|
|
|
|
|
|
if (i < buffer->getNumChannels())
|
|
|
|
dest.convertSamples (SourceType (buffer->getReadPointer (i) + startSampleInFile), numSamplesToCopy);
|
|
|
|
else
|
|
|
|
dest.clearSamples (numSamples);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
using SourceNumericalType =
|
|
|
|
std::conditional_t<std::is_same_v<T, int>, AudioData::Int32,
|
|
|
|
std::conditional_t<std::is_same_v<T, float>, AudioData::Float32, void>>;
|
|
|
|
|
|
|
|
using DestinationNumericalType = std::conditional_t<std::is_floating_point_v<T>, AudioData::Float32, AudioData::Int32>;
|
|
|
|
|
|
|
|
using DestType = AudioData::Pointer<DestinationNumericalType, AudioData::LittleEndian, AudioData::NonInterleaved, AudioData::NonConst>;
|
|
|
|
using SourceType = AudioData::Pointer<SourceNumericalType, AudioData::LittleEndian, AudioData::NonInterleaved, AudioData::Const>;
|
|
|
|
|
|
|
|
const AudioBuffer<T>* buffer;
|
|
|
|
};
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
class AudioThumbnail::LevelDataSource : public TimeSliceClient
|
|
|
|
{
|
|
|
@@ -687,6 +747,16 @@ void AudioThumbnail::setReader (AudioFormatReader* newReader, int64 hash) |
|
|
|
setDataSource (new LevelDataSource (*this, newReader, hash));
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioThumbnail::setSource (const AudioBuffer<float>* newSource, double rate, int64 hash)
|
|
|
|
{
|
|
|
|
setReader (new AudioBufferReader<float> (newSource, rate), hash);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioThumbnail::setSource (const AudioBuffer<int>* newSource, double rate, int64 hash)
|
|
|
|
{
|
|
|
|
setReader (new AudioBufferReader<int> (newSource, rate), hash);
|
|
|
|
}
|
|
|
|
|
|
|
|
int64 AudioThumbnail::getHashCode() const
|
|
|
|
{
|
|
|
|
return source == nullptr ? 0 : source->hashCode;
|
|
|
|