Browse Source

Moved the data format structure of AudioThumbnail to be a public class.

tags/2021-05-28
Julian Storer 15 years ago
parent
commit
322cd4dba2
5 changed files with 162 additions and 163 deletions
  1. +56
    -73
      juce_amalgamated.cpp
  2. +24
    -8
      juce_amalgamated.h
  3. +57
    -74
      src/audio/audio_file_formats/juce_AudioThumbnail.cpp
  4. +24
    -7
      src/audio/audio_file_formats/juce_AudioThumbnail.h
  5. +1
    -1
      src/core/juce_StandardHeader.h

+ 56
- 73
juce_amalgamated.cpp View File

@@ -21535,45 +21535,13 @@ END_JUCE_NAMESPACE
/*** Start of inlined file: juce_AudioThumbnail.cpp ***/
BEGIN_JUCE_NAMESPACE

const int timeBeforeDeletingReader = 2000;

struct AudioThumbnailDataFormat
{
char thumbnailMagic[4];
int samplesPerThumbSample;
int64 totalSamples; // source samples
int64 numFinishedSamples; // source samples
int numThumbnailSamples;
int numChannels;
int sampleRate;
char future[16];
char data[1];

void swapEndiannessIfNeeded() throw()
{
#if JUCE_BIG_ENDIAN
flip (samplesPerThumbSample);
flip (totalSamples);
flip (numFinishedSamples);
flip (numThumbnailSamples);
flip (numChannels);
flip (sampleRate);
#endif
}

private:
#if JUCE_BIG_ENDIAN
static void flip (int& n) { n = (int) ByteOrder::swap ((uint32) n); }
static void flip (int64& n) { n = (int64) ByteOrder::swap ((uint64) n); }
#endif
};

AudioThumbnail::AudioThumbnail (const int orginalSamplesPerThumbnailSample_,
AudioFormatManager& formatManagerToUse_,
AudioThumbnailCache& cacheToUse)
: formatManagerToUse (formatManagerToUse_),
cache (cacheToUse),
orginalSamplesPerThumbnailSample (orginalSamplesPerThumbnailSample_)
orginalSamplesPerThumbnailSample (orginalSamplesPerThumbnailSample_),
timeBeforeDeletingReader (2000)
{
clear();
}
@@ -21586,6 +21554,12 @@ AudioThumbnail::~AudioThumbnail()
reader = 0;
}

AudioThumbnail::DataFormat* AudioThumbnail::getData() const throw()
{
jassert (data.getData() != 0);
return static_cast <DataFormat*> (data.getData());
}

void AudioThumbnail::setSource (InputSource* const newSource)
{
cache.removeThumbnail (this);
@@ -21670,9 +21644,9 @@ void AudioThumbnail::timerCallback()

void AudioThumbnail::clear()
{
data.setSize (sizeof (AudioThumbnailDataFormat) + 3);
data.setSize (sizeof (DataFormat) + 3);

AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
DataFormat* const d = getData();

d->thumbnailMagic[0] = 'j';
d->thumbnailMagic[1] = 'a';
@@ -21697,8 +21671,8 @@ void AudioThumbnail::loadFrom (InputStream& input)
data.setSize (0);
input.readIntoMemoryBlock (data);

AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
d->swapEndiannessIfNeeded();
DataFormat* const d = getData();
d->flipEndiannessIfBigEndian();

if (! (d->thumbnailMagic[0] == 'j'
&& d->thumbnailMagic[1] == 'a'
@@ -21714,15 +21688,17 @@ void AudioThumbnail::loadFrom (InputStream& input)

void AudioThumbnail::saveTo (OutputStream& output) const
{
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
d->swapEndiannessIfNeeded();
output.write (data.getData(), (int) data.getSize());
d->swapEndiannessIfNeeded();
const ScopedLock sl (readerLock);

DataFormat* const d = getData();
d->flipEndiannessIfBigEndian();
output.write (d, (int) data.getSize());
d->flipEndiannessIfBigEndian();
}

bool AudioThumbnail::initialiseFromAudioFile (AudioFormatReader& fileReader)
{
AudioThumbnailDataFormat* d = (AudioThumbnailDataFormat*) data.getData();
DataFormat* d = getData();

d->totalSamples = fileReader.lengthInSamples;
d->numChannels = jmin ((uint32) 2, fileReader.numChannels);
@@ -21730,17 +21706,17 @@ bool AudioThumbnail::initialiseFromAudioFile (AudioFormatReader& fileReader)
d->sampleRate = roundToInt (fileReader.sampleRate);
d->numThumbnailSamples = (int) (d->totalSamples / d->samplesPerThumbSample) + 1;

data.setSize (sizeof (AudioThumbnailDataFormat) + 3 + d->numThumbnailSamples * d->numChannels * 2);
data.setSize (sizeof (DataFormat) + 3 + d->numThumbnailSamples * d->numChannels * 2);

d = (AudioThumbnailDataFormat*) data.getData();
zeromem (&(d->data[0]), d->numThumbnailSamples * d->numChannels * 2);
d = getData();
zeromem (d->data, d->numThumbnailSamples * d->numChannels * 2);

return d->totalSamples > 0;
}

bool AudioThumbnail::readNextBlockFromAudioFile (AudioFormatReader& fileReader)
{
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
DataFormat* const d = getData();

if (d->numFinishedSamples < d->totalSamples)
{
@@ -21754,24 +21730,20 @@ bool AudioThumbnail::readNextBlockFromAudioFile (AudioFormatReader& fileReader)
}

cacheNeedsRefilling = true;
return (d->numFinishedSamples < d->totalSamples);
return d->numFinishedSamples < d->totalSamples;
}

int AudioThumbnail::getNumChannels() const throw()
{
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);

return d->numChannels;
return getData()->numChannels;
}

double AudioThumbnail::getTotalLength() const throw()
{
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
const DataFormat* const d = getData();

if (d->sampleRate > 0)
return d->totalSamples / (double)d->sampleRate;
return d->totalSamples / (double) d->sampleRate;
else
return 0.0;
}
@@ -21780,14 +21752,13 @@ void AudioThumbnail::generateSection (AudioFormatReader& fileReader,
int64 startSample,
int numSamples)
{
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
DataFormat* const d = getData();

int firstDataPos = (int) (startSample / d->samplesPerThumbSample);
int lastDataPos = (int) ((startSample + numSamples) / d->samplesPerThumbSample);
const int firstDataPos = (int) (startSample / d->samplesPerThumbSample);
const int lastDataPos = (int) ((startSample + numSamples) / d->samplesPerThumbSample);

char* l = getChannelData (0);
char* r = getChannelData (1);
char* const l = getChannelData (0);
char* const r = getChannelData (1);

for (int i = firstDataPos; i < lastDataPos; ++i)
{
@@ -21822,8 +21793,7 @@ void AudioThumbnail::generateSection (AudioFormatReader& fileReader,

char* AudioThumbnail::getChannelData (int channel) const
{
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
DataFormat* const d = getData();

if (channel >= 0 && channel < d->numChannels)
return d->data + (channel * 2 * d->numThumbnailSamples);
@@ -21833,9 +21803,7 @@ char* AudioThumbnail::getChannelData (int channel) const

bool AudioThumbnail::isFullyLoaded() const throw()
{
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);

const DataFormat* const d = getData();
return d->numFinishedSamples >= d->totalSamples;
}

@@ -21843,8 +21811,7 @@ void AudioThumbnail::refillCache (const int numSamples,
double startTime,
const double timePerPixel)
{
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
const DataFormat* const d = getData();

if (numSamples <= 0
|| timePerPixel <= 0.0
@@ -22017,17 +21984,33 @@ void AudioThumbnail::drawChannel (Graphics& g,
cacheData += numChannelsCached << 1;

if (mn <= mx) // if the wrong way round, signifies that the sample's not yet known
g.drawLine ((float) x, jmax (midY - mx * vscale - 0.3f, topY),
(float) x, jmin (midY - mn * vscale + 0.3f, bottomY));

++x;
g.drawVerticalLine (x, jmax (midY - mx * vscale - 0.3f, topY),
jmin (midY - mn * vscale + 0.3f, bottomY));

if (x >= clip.getRight())
if (++x >= clip.getRight())
break;
}
}
}

void AudioThumbnail::DataFormat::flipEndiannessIfBigEndian() throw()
{
#if JUCE_BIG_ENDIAN
struct Flipper
{
static void flip (int32& n) { n = (int32) ByteOrder::swap ((uint32) n); }
static void flip (int64& n) { n = (int64) ByteOrder::swap ((uint64) n); }
};

Flipper::flip (samplesPerThumbSample);
Flipper::flip (totalSamples);
Flipper::flip (numFinishedSamples);
Flipper::flip (numThumbnailSamples);
Flipper::flip (numChannels);
Flipper::flip (sampleRate);
#endif
}

END_JUCE_NAMESPACE
/*** End of inlined file: juce_AudioThumbnail.cpp ***/



+ 24
- 8
juce_amalgamated.h View File

@@ -64,7 +64,7 @@
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 52
#define JUCE_BUILDNUMBER 56
#define JUCE_BUILDNUMBER 57

/** Current Juce version number.

@@ -31087,10 +31087,27 @@ public:
int channelNum,
float verticalZoomFactor);

/** Returns true if the low res preview is fully generated.
*/
/** Returns true if the low res preview is fully generated. */
bool isFullyLoaded() const throw();

/** The binary data format that is stored in the thumbnail file. */
struct DataFormat
{
char thumbnailMagic[4]; /**< Should be 'jatm'. */
int32 samplesPerThumbSample; /**< Number of source samples per thumbnail sample. */
int64 totalSamples; /**< Total number of source samples. */
int64 numFinishedSamples; /**< Number of valid source samples that have been read into the thumbnail. */
int32 numThumbnailSamples; /**< Number of samples in the thumbnail data. */
int32 numChannels; /**< Number of audio channels. */
int32 sampleRate; /**< Source sample rate. */
char future[16]; /**< Reserved for future use. */
char data[1]; /**< The raw thumbnail samples, two signed bytes per
sample (min and max values). Channels are interleaved. */

/** Flips the endianness of the values in this data structure if the CPU is big-endian. */
void flipEndiannessIfBigEndian() throw();
};

/** @internal */
bool useTimeSlice();
/** @internal */
@@ -31102,24 +31119,23 @@ private:
AudioFormatManager& formatManagerToUse;
AudioThumbnailCache& cache;
ScopedPointer <InputSource> source;

CriticalSection readerLock;
ScopedPointer <AudioFormatReader> reader;

MemoryBlock data, cachedLevels;
int orginalSamplesPerThumbnailSample;

int numChannelsCached, numSamplesCached;
double cachedStart, cachedTimePerPixel;
bool cacheNeedsRefilling;
const int timeBeforeDeletingReader;

friend class AudioThumbnailCache;

void clear();
AudioFormatReader* createReader() const;
void generateSection (AudioFormatReader& reader, int64 startSample, int numSamples);
char* getChannelData (int channel) const;
void refillCache (int numSamples, double startTime, double timePerPixel);

friend class AudioThumbnailCache;
DataFormat* getData() const throw();

// true if it needs more callbacks from the readNextBlockFromAudioFile() method
bool initialiseFromAudioFile (AudioFormatReader& reader);


+ 57
- 74
src/audio/audio_file_formats/juce_AudioThumbnail.cpp View File

@@ -30,40 +30,6 @@ BEGIN_JUCE_NAMESPACE
#include "juce_AudioThumbnail.h"
#include "juce_AudioThumbnailCache.h"
const int timeBeforeDeletingReader = 2000;
//==============================================================================
struct AudioThumbnailDataFormat
{
char thumbnailMagic[4];
int samplesPerThumbSample;
int64 totalSamples; // source samples
int64 numFinishedSamples; // source samples
int numThumbnailSamples;
int numChannels;
int sampleRate;
char future[16];
char data[1];
void swapEndiannessIfNeeded() throw()
{
#if JUCE_BIG_ENDIAN
flip (samplesPerThumbSample);
flip (totalSamples);
flip (numFinishedSamples);
flip (numThumbnailSamples);
flip (numChannels);
flip (sampleRate);
#endif
}
private:
#if JUCE_BIG_ENDIAN
static void flip (int& n) { n = (int) ByteOrder::swap ((uint32) n); }
static void flip (int64& n) { n = (int64) ByteOrder::swap ((uint64) n); }
#endif
};
//==============================================================================
AudioThumbnail::AudioThumbnail (const int orginalSamplesPerThumbnailSample_,
@@ -71,7 +37,8 @@ AudioThumbnail::AudioThumbnail (const int orginalSamplesPerThumbnailSample_,
AudioThumbnailCache& cacheToUse)
: formatManagerToUse (formatManagerToUse_),
cache (cacheToUse),
orginalSamplesPerThumbnailSample (orginalSamplesPerThumbnailSample_)
orginalSamplesPerThumbnailSample (orginalSamplesPerThumbnailSample_),
timeBeforeDeletingReader (2000)
{
clear();
}
@@ -84,6 +51,12 @@ AudioThumbnail::~AudioThumbnail()
reader = 0;
}
AudioThumbnail::DataFormat* AudioThumbnail::getData() const throw()
{
jassert (data.getData() != 0);
return static_cast <DataFormat*> (data.getData());
}
void AudioThumbnail::setSource (InputSource* const newSource)
{
cache.removeThumbnail (this);
@@ -168,9 +141,9 @@ void AudioThumbnail::timerCallback()
void AudioThumbnail::clear()
{
data.setSize (sizeof (AudioThumbnailDataFormat) + 3);
data.setSize (sizeof (DataFormat) + 3);
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
DataFormat* const d = getData();
d->thumbnailMagic[0] = 'j';
d->thumbnailMagic[1] = 'a';
@@ -195,8 +168,8 @@ void AudioThumbnail::loadFrom (InputStream& input)
data.setSize (0);
input.readIntoMemoryBlock (data);
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
d->swapEndiannessIfNeeded();
DataFormat* const d = getData();
d->flipEndiannessIfBigEndian();
if (! (d->thumbnailMagic[0] == 'j'
&& d->thumbnailMagic[1] == 'a'
@@ -212,15 +185,17 @@ void AudioThumbnail::loadFrom (InputStream& input)
void AudioThumbnail::saveTo (OutputStream& output) const
{
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
d->swapEndiannessIfNeeded();
output.write (data.getData(), (int) data.getSize());
d->swapEndiannessIfNeeded();
const ScopedLock sl (readerLock);
DataFormat* const d = getData();
d->flipEndiannessIfBigEndian();
output.write (d, (int) data.getSize());
d->flipEndiannessIfBigEndian();
}
bool AudioThumbnail::initialiseFromAudioFile (AudioFormatReader& fileReader)
{
AudioThumbnailDataFormat* d = (AudioThumbnailDataFormat*) data.getData();
DataFormat* d = getData();
d->totalSamples = fileReader.lengthInSamples;
d->numChannels = jmin ((uint32) 2, fileReader.numChannels);
@@ -228,17 +203,17 @@ bool AudioThumbnail::initialiseFromAudioFile (AudioFormatReader& fileReader)
d->sampleRate = roundToInt (fileReader.sampleRate);
d->numThumbnailSamples = (int) (d->totalSamples / d->samplesPerThumbSample) + 1;
data.setSize (sizeof (AudioThumbnailDataFormat) + 3 + d->numThumbnailSamples * d->numChannels * 2);
data.setSize (sizeof (DataFormat) + 3 + d->numThumbnailSamples * d->numChannels * 2);
d = (AudioThumbnailDataFormat*) data.getData();
zeromem (&(d->data[0]), d->numThumbnailSamples * d->numChannels * 2);
d = getData();
zeromem (d->data, d->numThumbnailSamples * d->numChannels * 2);
return d->totalSamples > 0;
}
bool AudioThumbnail::readNextBlockFromAudioFile (AudioFormatReader& fileReader)
{
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
DataFormat* const d = getData();
if (d->numFinishedSamples < d->totalSamples)
{
@@ -252,24 +227,20 @@ bool AudioThumbnail::readNextBlockFromAudioFile (AudioFormatReader& fileReader)
}
cacheNeedsRefilling = true;
return (d->numFinishedSamples < d->totalSamples);
return d->numFinishedSamples < d->totalSamples;
}
int AudioThumbnail::getNumChannels() const throw()
{
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
return d->numChannels;
return getData()->numChannels;
}
double AudioThumbnail::getTotalLength() const throw()
{
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
const DataFormat* const d = getData();
if (d->sampleRate > 0)
return d->totalSamples / (double)d->sampleRate;
return d->totalSamples / (double) d->sampleRate;
else
return 0.0;
}
@@ -278,14 +249,13 @@ void AudioThumbnail::generateSection (AudioFormatReader& fileReader,
int64 startSample,
int numSamples)
{
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
DataFormat* const d = getData();
int firstDataPos = (int) (startSample / d->samplesPerThumbSample);
int lastDataPos = (int) ((startSample + numSamples) / d->samplesPerThumbSample);
const int firstDataPos = (int) (startSample / d->samplesPerThumbSample);
const int lastDataPos = (int) ((startSample + numSamples) / d->samplesPerThumbSample);
char* l = getChannelData (0);
char* r = getChannelData (1);
char* const l = getChannelData (0);
char* const r = getChannelData (1);
for (int i = firstDataPos; i < lastDataPos; ++i)
{
@@ -320,8 +290,7 @@ void AudioThumbnail::generateSection (AudioFormatReader& fileReader,
char* AudioThumbnail::getChannelData (int channel) const
{
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
DataFormat* const d = getData();
if (channel >= 0 && channel < d->numChannels)
return d->data + (channel * 2 * d->numThumbnailSamples);
@@ -331,9 +300,7 @@ char* AudioThumbnail::getChannelData (int channel) const
bool AudioThumbnail::isFullyLoaded() const throw()
{
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
const DataFormat* const d = getData();
return d->numFinishedSamples >= d->totalSamples;
}
@@ -341,8 +308,7 @@ void AudioThumbnail::refillCache (const int numSamples,
double startTime,
const double timePerPixel)
{
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
jassert (d != 0);
const DataFormat* const d = getData();
if (numSamples <= 0
|| timePerPixel <= 0.0
@@ -515,16 +481,33 @@ void AudioThumbnail::drawChannel (Graphics& g,
cacheData += numChannelsCached << 1;
if (mn <= mx) // if the wrong way round, signifies that the sample's not yet known
g.drawLine ((float) x, jmax (midY - mx * vscale - 0.3f, topY),
(float) x, jmin (midY - mn * vscale + 0.3f, bottomY));
++x;
g.drawVerticalLine (x, jmax (midY - mx * vscale - 0.3f, topY),
jmin (midY - mn * vscale + 0.3f, bottomY));
if (x >= clip.getRight())
if (++x >= clip.getRight())
break;
}
}
}
//==============================================================================
void AudioThumbnail::DataFormat::flipEndiannessIfBigEndian() throw()
{
#if JUCE_BIG_ENDIAN
struct Flipper
{
static void flip (int32& n) { n = (int32) ByteOrder::swap ((uint32) n); }
static void flip (int64& n) { n = (int64) ByteOrder::swap ((uint64) n); }
};
Flipper::flip (samplesPerThumbSample);
Flipper::flip (totalSamples);
Flipper::flip (numFinishedSamples);
Flipper::flip (numThumbnailSamples);
Flipper::flip (numChannels);
Flipper::flip (sampleRate);
#endif
}
END_JUCE_NAMESPACE

+ 24
- 7
src/audio/audio_file_formats/juce_AudioThumbnail.h View File

@@ -136,10 +136,28 @@ public:
int channelNum,
float verticalZoomFactor);
/** Returns true if the low res preview is fully generated.
*/
/** Returns true if the low res preview is fully generated. */
bool isFullyLoaded() const throw();
//==============================================================================
/** The binary data format that is stored in the thumbnail file. */
struct DataFormat
{
char thumbnailMagic[4]; /**< Should be 'jatm'. */
int32 samplesPerThumbSample; /**< Number of source samples per thumbnail sample. */
int64 totalSamples; /**< Total number of source samples. */
int64 numFinishedSamples; /**< Number of valid source samples that have been read into the thumbnail. */
int32 numThumbnailSamples; /**< Number of samples in the thumbnail data. */
int32 numChannels; /**< Number of audio channels. */
int32 sampleRate; /**< Source sample rate. */
char future[16]; /**< Reserved for future use. */
char data[1]; /**< The raw thumbnail samples, two signed bytes per
sample (min and max values). Channels are interleaved. */
/** Flips the endianness of the values in this data structure if the CPU is big-endian. */
void flipEndiannessIfBigEndian() throw();
};
//==============================================================================
/** @internal */
bool useTimeSlice();
@@ -153,24 +171,23 @@ private:
AudioFormatManager& formatManagerToUse;
AudioThumbnailCache& cache;
ScopedPointer <InputSource> source;
CriticalSection readerLock;
ScopedPointer <AudioFormatReader> reader;
MemoryBlock data, cachedLevels;
int orginalSamplesPerThumbnailSample;
int numChannelsCached, numSamplesCached;
double cachedStart, cachedTimePerPixel;
bool cacheNeedsRefilling;
const int timeBeforeDeletingReader;
friend class AudioThumbnailCache;
void clear();
AudioFormatReader* createReader() const;
void generateSection (AudioFormatReader& reader, int64 startSample, int numSamples);
char* getChannelData (int channel) const;
void refillCache (int numSamples, double startTime, double timePerPixel);
friend class AudioThumbnailCache;
DataFormat* getData() const throw();
// true if it needs more callbacks from the readNextBlockFromAudioFile() method
bool initialiseFromAudioFile (AudioFormatReader& reader);


+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -33,7 +33,7 @@
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 52
#define JUCE_BUILDNUMBER 56
#define JUCE_BUILDNUMBER 57
/** Current Juce version number.


Loading…
Cancel
Save