mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
AudioThumbnail: Add new member to set an AudioBuffer as source
This commit is contained in:
parent
fcb7e0fc20
commit
fa37d47ebb
3 changed files with 85 additions and 0 deletions
|
|
@ -436,6 +436,9 @@ public:
|
|||
/** Adds a number of samples to the pointer's position. */
|
||||
Pointer& operator+= (int samplesToJump) noexcept { this->advanceDataBy (data, samplesToJump); return *this; }
|
||||
|
||||
/** Returns a new pointer with the specified offset from this pointer's position. */
|
||||
Pointer operator+ (int samplesToJump) const { return Pointer { *this } += samplesToJump; }
|
||||
|
||||
/** Writes a stream of samples into this pointer from another pointer.
|
||||
This will copy the specified number of samples, converting between formats appropriately.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -99,6 +99,18 @@ public:
|
|||
*/
|
||||
void setReader (AudioFormatReader* newReader, int64 hashCode) override;
|
||||
|
||||
/** Sets an AudioBuffer as the source for the thumbnail.
|
||||
|
||||
The buffer contents aren't copied and you must ensure that the lifetime of the buffer is
|
||||
valid for as long as the AudioThumbnail uses it as its source. Calling this function will
|
||||
start reading the audio in a background thread (unless the hash code can be looked-up
|
||||
successfully in the thumbnail cache).
|
||||
*/
|
||||
void setSource (const AudioBuffer<float>* newSource, double sampleRate, int64 hashCode);
|
||||
|
||||
/** Same as the other setSource() overload except for int data. */
|
||||
void setSource (const AudioBuffer<int>* newSource, double sampleRate, int64 hashCode);
|
||||
|
||||
/** Resets the thumbnail, ready for adding data with the specified format.
|
||||
If you're going to generate a thumbnail yourself, call this before using addBlock()
|
||||
to add the data.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue