72 template <
class SampleFormatType>
static inline float getAsFloat (SampleFormatType& s)
noexcept {
return s.getAsFloatBE(); }
73 template <
class SampleFormatType>
static inline void setAsFloat (SampleFormatType& s,
float newValue)
noexcept { s.setAsFloatBE (newValue); }
74 template <
class SampleFormatType>
static inline int32 getAsInt32 (SampleFormatType& s)
noexcept {
return s.getAsInt32BE(); }
75 template <
class SampleFormatType>
static inline void setAsInt32 (SampleFormatType& s, int32 newValue)
noexcept { s.setAsInt32BE (newValue); }
76 template <
class SourceType,
class DestType>
static inline void copyFrom (DestType& dest, SourceType& source)
noexcept { dest.copyFromBE (source); }
77 enum { isBigEndian = 1 };
83 template <
class SampleFormatType>
static inline float getAsFloat (SampleFormatType& s)
noexcept {
return s.getAsFloatLE(); }
84 template <
class SampleFormatType>
static inline void setAsFloat (SampleFormatType& s,
float newValue)
noexcept { s.setAsFloatLE (newValue); }
85 template <
class SampleFormatType>
static inline int32 getAsInt32 (SampleFormatType& s)
noexcept {
return s.getAsInt32LE(); }
86 template <
class SampleFormatType>
static inline void setAsInt32 (SampleFormatType& s, int32 newValue)
noexcept { s.setAsInt32LE (newValue); }
87 template <
class SourceType,
class DestType>
static inline void copyFrom (DestType& dest, SourceType& source)
noexcept { dest.copyFromLE (source); }
88 enum { isBigEndian = 0 };
92 class NativeEndian :
public BigEndian {};
94 class NativeEndian :
public LittleEndian {};
101 inline Int8 (
void* d) noexcept : data (
static_cast<int8*
> (d)) {}
103 inline void advance() noexcept { ++data; }
104 inline void skip (
int numSamples)
noexcept { data += numSamples; }
105 inline float getAsFloatLE() const noexcept {
return (
float) (*data * (1.0 / (1.0 + (double) maxValue))); }
106 inline float getAsFloatBE() const noexcept {
return getAsFloatLE(); }
107 inline void setAsFloatLE (
float newValue)
noexcept { *data = (int8) jlimit ((
int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + (
double) maxValue))); }
108 inline void setAsFloatBE (
float newValue)
noexcept { setAsFloatLE (newValue); }
109 inline int32 getAsInt32LE() const noexcept {
return (
int) (*((uint8*) data) << 24); }
110 inline int32 getAsInt32BE() const noexcept {
return getAsInt32LE(); }
111 inline void setAsInt32LE (
int newValue)
noexcept { *data = (int8) (newValue >> 24); }
112 inline void setAsInt32BE (
int newValue)
noexcept { setAsInt32LE (newValue); }
113 inline void clear() noexcept { *data = 0; }
114 inline void clearMultiple (
int num)
noexcept { zeromem (data, (
size_t) (num * bytesPerSample)) ;}
115 template <
class SourceType>
inline void copyFromLE (SourceType& source)
noexcept { setAsInt32LE (source.getAsInt32()); }
116 template <
class SourceType>
inline void copyFromBE (SourceType& source)
noexcept { setAsInt32BE (source.getAsInt32()); }
117 inline void copyFromSameType (Int8& source)
noexcept { *data = *source.data; }
120 enum { bytesPerSample = 1, maxValue = 0x7f, resolution = (1 << 24), isFloat = 0 };
126 inline UInt8 (
void* d) noexcept : data (
static_cast<uint8*
> (d)) {}
128 inline void advance() noexcept { ++data; }
129 inline void skip (
int numSamples)
noexcept { data += numSamples; }
130 inline float getAsFloatLE() const noexcept {
return (
float) ((*data - 128) * (1.0 / (1.0 + (
double) maxValue))); }
131 inline float getAsFloatBE() const noexcept {
return getAsFloatLE(); }
132 inline void setAsFloatLE (
float newValue)
noexcept { *data = (uint8) jlimit (0, 255, 128 + roundToInt (newValue * (1.0 + (
double) maxValue))); }
133 inline void setAsFloatBE (
float newValue)
noexcept { setAsFloatLE (newValue); }
134 inline int32 getAsInt32LE() const noexcept {
return (
int) (((uint8) (*data - 128)) << 24); }
135 inline int32 getAsInt32BE() const noexcept {
return getAsInt32LE(); }
136 inline void setAsInt32LE (
int newValue)
noexcept { *data = (uint8) (128 + (newValue >> 24)); }
137 inline void setAsInt32BE (
int newValue)
noexcept { setAsInt32LE (newValue); }
138 inline void clear() noexcept { *data = 128; }
139 inline void clearMultiple (
int num)
noexcept { memset (data, 128, (
size_t) num) ;}
140 template <
class SourceType>
inline void copyFromLE (SourceType& source)
noexcept { setAsInt32LE (source.getAsInt32()); }
141 template <
class SourceType>
inline void copyFromBE (SourceType& source)
noexcept { setAsInt32BE (source.getAsInt32()); }
142 inline void copyFromSameType (UInt8& source)
noexcept { *data = *source.data; }
145 enum { bytesPerSample = 1, maxValue = 0x7f, resolution = (1 << 24), isFloat = 0 };
151 inline Int16 (
void* d) noexcept : data (
static_cast<uint16*
> (d)) {}
153 inline void advance() noexcept { ++data; }
154 inline void skip (
int numSamples)
noexcept { data += numSamples; }
155 inline float getAsFloatLE() const noexcept {
return (
float) ((1.0 / (1.0 + (double) maxValue)) * (int16)
ByteOrder::swapIfBigEndian (*data)); }
156 inline float getAsFloatBE() const noexcept {
return (
float) ((1.0 / (1.0 + (double) maxValue)) * (int16)
ByteOrder::swapIfLittleEndian (*data)); }
157 inline void setAsFloatLE (
float newValue)
noexcept { *data =
ByteOrder::swapIfBigEndian ((uint16) jlimit ((
int) -maxValue, (
int) maxValue, roundToInt (newValue * (1.0 + (
double) maxValue)))); }
158 inline void setAsFloatBE (
float newValue)
noexcept { *data =
ByteOrder::swapIfLittleEndian ((uint16) jlimit ((
int) -maxValue, (
int) maxValue, roundToInt (newValue * (1.0 + (
double) maxValue)))); }
163 inline void clear() noexcept { *data = 0; }
164 inline void clearMultiple (
int num)
noexcept { zeromem (data, (
size_t) (num * bytesPerSample)) ;}
165 template <
class SourceType>
inline void copyFromLE (SourceType& source)
noexcept { setAsInt32LE (source.getAsInt32()); }
166 template <
class SourceType>
inline void copyFromBE (SourceType& source)
noexcept { setAsInt32BE (source.getAsInt32()); }
167 inline void copyFromSameType (Int16& source)
noexcept { *data = *source.data; }
170 enum { bytesPerSample = 2, maxValue = 0x7fff, resolution = (1 << 16), isFloat = 0 };
176 inline Int24 (
void* d) noexcept : data (
static_cast<char*
> (d)) {}
178 inline void advance() noexcept { data += 3; }
179 inline void skip (
int numSamples)
noexcept { data += 3 * numSamples; }
180 inline float getAsFloatLE() const noexcept {
return (
float) (
ByteOrder::littleEndian24Bit (data) * (1.0 / (1.0 + (double) maxValue))); }
181 inline float getAsFloatBE() const noexcept {
return (
float) (
ByteOrder::bigEndian24Bit (data) * (1.0 / (1.0 + (double) maxValue))); }
182 inline void setAsFloatLE (
float newValue)
noexcept {
ByteOrder::littleEndian24BitToChars (jlimit ((
int) -maxValue, (
int) maxValue, roundToInt (newValue * (1.0 + (
double) maxValue))), data); }
183 inline void setAsFloatBE (
float newValue)
noexcept {
ByteOrder::bigEndian24BitToChars (jlimit ((
int) -maxValue, (
int) maxValue, roundToInt (newValue * (1.0 + (
double) maxValue))), data); }
188 inline void clear() noexcept { data[0] = 0; data[1] = 0; data[2] = 0; }
189 inline void clearMultiple (
int num)
noexcept { zeromem (data, (
size_t) (num * bytesPerSample)) ;}
190 template <
class SourceType>
inline void copyFromLE (SourceType& source)
noexcept { setAsInt32LE (source.getAsInt32()); }
191 template <
class SourceType>
inline void copyFromBE (SourceType& source)
noexcept { setAsInt32BE (source.getAsInt32()); }
192 inline void copyFromSameType (Int24& source)
noexcept { data[0] = source.data[0]; data[1] = source.data[1]; data[2] = source.data[2]; }
195 enum { bytesPerSample = 3, maxValue = 0x7fffff, resolution = (1 << 8), isFloat = 0 };
201 inline Int32 (
void* d) noexcept : data (
static_cast<uint32*
> (d)) {}
203 inline void advance() noexcept { ++data; }
204 inline void skip (
int numSamples)
noexcept { data += numSamples; }
205 inline float getAsFloatLE() const noexcept {
return (
float) ((1.0 / (1.0 + (double) maxValue)) * (int32)
ByteOrder::swapIfBigEndian (*data)); }
206 inline float getAsFloatBE() const noexcept {
return (
float) ((1.0 / (1.0 + (double) maxValue)) * (int32)
ByteOrder::swapIfLittleEndian (*data)); }
207 inline void setAsFloatLE (
float newValue)
noexcept { *data =
ByteOrder::swapIfBigEndian ((uint32) (int32) ((
double) maxValue * jlimit (-1.0, 1.0, (
double) newValue))); }
208 inline void setAsFloatBE (
float newValue)
noexcept { *data =
ByteOrder::swapIfLittleEndian ((uint32) (int32) ((
double) maxValue * jlimit (-1.0, 1.0, (
double) newValue))); }
213 inline void clear() noexcept { *data = 0; }
214 inline void clearMultiple (
int num)
noexcept { zeromem (data, (
size_t) (num * bytesPerSample)) ;}
215 template <
class SourceType>
inline void copyFromLE (SourceType& source)
noexcept { setAsInt32LE (source.getAsInt32()); }
216 template <
class SourceType>
inline void copyFromBE (SourceType& source)
noexcept { setAsInt32BE (source.getAsInt32()); }
217 inline void copyFromSameType (Int32& source)
noexcept { *data = *source.data; }
220 enum { bytesPerSample = 4, maxValue = 0x7fffffff, resolution = 1, isFloat = 0 };
227 inline Int24in32 (
void* d) noexcept : Int32 (d) {}
229 inline float getAsFloatLE()
const noexcept {
return (
float) ((1.0 / (1.0 + (double) maxValue)) * (int32)
ByteOrder::swapIfBigEndian (*data)); }
230 inline float getAsFloatBE()
const noexcept {
return (
float) ((1.0 / (1.0 + (double) maxValue)) * (int32)
ByteOrder::swapIfLittleEndian (*data)); }
231 inline void setAsFloatLE (
float newValue)
noexcept { *data =
ByteOrder::swapIfBigEndian ((uint32) ((
double) maxValue * jlimit (-1.0, 1.0, (
double) newValue))); }
232 inline void setAsFloatBE (
float newValue)
noexcept { *data =
ByteOrder::swapIfLittleEndian ((uint32) ((
double) maxValue * jlimit (-1.0, 1.0, (
double) newValue))); }
237 template <
class SourceType>
inline void copyFromLE (SourceType& source)
noexcept { setAsInt32LE (source.getAsInt32()); }
238 template <
class SourceType>
inline void copyFromBE (SourceType& source)
noexcept { setAsInt32BE (source.getAsInt32()); }
239 inline void copyFromSameType (
Int24in32& source)
noexcept { *data = *source.data; }
241 enum { bytesPerSample = 4, maxValue = 0x7fffff, resolution = (1 << 8), isFloat = 0 };
247 inline Float32 (
void* d) noexcept : data (
static_cast<float*
> (d)) {}
249 inline void advance() noexcept { ++data; }
250 inline void skip (
int numSamples)
noexcept { data += numSamples; }
252 inline float getAsFloatBE() const noexcept {
return *data; }
253 inline void setAsFloatBE (
float newValue)
noexcept { *data = newValue; }
254 inline float getAsFloatLE() const noexcept {
union { uint32 asInt;
float asFloat; } n; n.asInt =
ByteOrder::swap (*(uint32*) data);
return n.asFloat; }
255 inline void setAsFloatLE (
float newValue)
noexcept {
union { uint32 asInt;
float asFloat; } n; n.asFloat = newValue; *(uint32*) data =
ByteOrder::swap (n.asInt); }
257 inline float getAsFloatLE() const noexcept {
return *data; }
258 inline void setAsFloatLE (
float newValue)
noexcept { *data = newValue; }
259 inline float getAsFloatBE() const noexcept {
union { uint32 asInt;
float asFloat; } n; n.asInt =
ByteOrder::swap (*(uint32*) data);
return n.asFloat; }
260 inline void setAsFloatBE (
float newValue)
noexcept {
union { uint32 asInt;
float asFloat; } n; n.asFloat = newValue; *(uint32*) data =
ByteOrder::swap (n.asInt); }
262 inline int32 getAsInt32LE() const noexcept {
return (int32) roundToInt (jlimit (-1.0, 1.0, (
double) getAsFloatLE()) * (
double) maxValue); }
263 inline int32 getAsInt32BE() const noexcept {
return (int32) roundToInt (jlimit (-1.0, 1.0, (
double) getAsFloatBE()) * (
double) maxValue); }
264 inline void setAsInt32LE (int32 newValue)
noexcept { setAsFloatLE ((
float) (newValue * (1.0 / (1.0 + (
double) maxValue)))); }
265 inline void setAsInt32BE (int32 newValue)
noexcept { setAsFloatBE ((
float) (newValue * (1.0 / (1.0 + (
double) maxValue)))); }
266 inline void clear() noexcept { *data = 0; }
267 inline void clearMultiple (
int num)
noexcept { zeromem (data, (
size_t) (num * bytesPerSample)) ;}
268 template <
class SourceType>
inline void copyFromLE (SourceType& source)
noexcept { setAsFloatLE (source.getAsFloat()); }
269 template <
class SourceType>
inline void copyFromBE (SourceType& source)
noexcept { setAsFloatBE (source.getAsFloat()); }
270 inline void copyFromSameType (Float32& source)
noexcept { *data = *source.data; }
273 enum { bytesPerSample = 4, maxValue = 0x7fffffff, resolution = (1 << 8), isFloat = 1 };
280 inline NonInterleaved() =
default;
281 inline NonInterleaved (
const NonInterleaved&) =
default;
282 inline NonInterleaved (
const int)
noexcept {}
283 inline void copyFrom (
const NonInterleaved&)
noexcept {}
284 template <
class SampleFormatType>
inline void advanceData (SampleFormatType& s)
noexcept { s.advance(); }
285 template <
class SampleFormatType>
inline void advanceDataBy (SampleFormatType& s,
int numSamples)
noexcept { s.skip (numSamples); }
286 template <
class SampleFormatType>
inline void clear (SampleFormatType& s,
int numSamples)
noexcept { s.clearMultiple (numSamples); }
287 template <
class SampleFormatType>
inline static int getNumBytesBetweenSamples (
const SampleFormatType&)
noexcept {
return SampleFormatType::bytesPerSample; }
289 enum { isInterleavedType = 0, numInterleavedChannels = 1 };
295 inline Interleaved() noexcept {}
296 inline Interleaved (
const Interleaved& other) =
default;
297 inline Interleaved (
const int numInterleavedChans) noexcept : numInterleavedChannels (numInterleavedChans) {}
298 inline void copyFrom (
const Interleaved& other)
noexcept { numInterleavedChannels = other.numInterleavedChannels; }
299 template <
class SampleFormatType>
inline void advanceData (SampleFormatType& s)
noexcept { s.skip (numInterleavedChannels); }
300 template <
class SampleFormatType>
inline void advanceDataBy (SampleFormatType& s,
int numSamples)
noexcept { s.skip (numInterleavedChannels * numSamples); }
301 template <
class SampleFormatType>
inline void clear (SampleFormatType& s,
int numSamples)
noexcept {
while (--numSamples >= 0) { s.clear(); s.skip (numInterleavedChannels); } }
302 template <
class SampleFormatType>
inline int getNumBytesBetweenSamples (
const SampleFormatType&)
const noexcept {
return numInterleavedChannels * SampleFormatType::bytesPerSample; }
303 int numInterleavedChannels = 1;
304 enum { isInterleavedType = 1 };
311 using VoidType = void;
312 static inline void* toVoidPtr (VoidType* v)
noexcept {
return v; }
313 enum { isConst = 0 };
319 using VoidType =
const void;
320 static inline void* toVoidPtr (VoidType* v)
noexcept {
return const_cast<void*
> (v); }
321 enum { isConst = 1 };
350 template <
typename SampleFormat,
352 typename InterleavingType,
362 Pointer (
typename Constness::VoidType* sourceData) noexcept
363 : data (Constness::toVoidPtr (sourceData))
367 static_assert (InterleavingType::isInterleavedType == 0,
"Incorrect constructor for interleaved data");
373 Pointer (
typename Constness::VoidType* sourceData,
int numInterleaved) noexcept
374 : InterleavingType (numInterleaved), data (Constness::toVoidPtr (sourceData))
380 : InterleavingType (other), data (other.data)
386 InterleavingType::operator= (other);
396 inline float getAsFloat() const noexcept {
return Endianness::getAsFloat (data); }
408 static_assert (Constness::isConst == 0,
"Attempt to write to a const pointer");
409 Endianness::setAsFloat (data, newValue);
418 inline int32
getAsInt32() const noexcept {
return Endianness::getAsInt32 (data); }
426 static_assert (Constness::isConst == 0,
"Attempt to write to a const pointer");
427 Endianness::setAsInt32 (data, newValue);
437 Pointer& operator+= (
int samplesToJump)
noexcept { this->advanceDataBy (data, samplesToJump);
return *
this; }
445 static_assert (Constness::isConst == 0,
"Attempt to write to a const pointer");
447 for (
Pointer dest (*
this); --numSamples >= 0;)
449 dest.data.copyFromSameType (source.data);
458 template <
class OtherPo
interType>
462 static_assert (Constness::isConst == 0,
"Attempt to write to a const pointer");
466 if (source.getRawData() != getRawData() || source.getNumBytesBetweenSamples() >= getNumBytesBetweenSamples())
468 while (--numSamples >= 0)
470 Endianness::copyFrom (dest.data, source);
478 source += numSamples;
480 while (--numSamples >= 0)
481 Endianness::copyFrom ((--dest).data, --source);
489 dest.clear (dest.data, numSamples);
500 if (isFloatingPoint())
506 while (--numSamples > 0)
522 while (--numSamples > 0)
531 return Range<float> (mn * (
float) (1.0 / (1.0 + (
double) Int32::maxValue)),
532 mx * (
float) (1.0 / (1.0 + (
double) Int32::maxValue)));
536 void findMinAndMax (
size_t numSamples,
float& minValue,
float& maxValue)
const noexcept
547 static bool isBigEndian() noexcept {
return (
bool) Endianness::isBigEndian; }
566 const void*
getRawData() const noexcept {
return data.data; }
572 inline void advance() noexcept { this->advanceData (data); }
574 Pointer operator++ (
int);
575 Pointer operator-- (
int);
593 virtual void convertSamples (
void* destSamples,
const void* sourceSamples,
int numSamples)
const = 0;
600 const void* sourceSamples,
int sourceSubChannel,
int numSamples)
const = 0;
612 template <
class SourceSampleType,
class DestSampleType>
617 : sourceChannels (numSourceChannels), destChannels (numDestChannels)
620 void convertSamples (
void* dest,
const void* source,
int numSamples)
const override
622 SourceSampleType s (source, sourceChannels);
623 DestSampleType d (dest, destChannels);
624 d.convertSamples (s, numSamples);
628 const void* source,
int sourceSubChannel,
int numSamples)
const override
630 jassert (destSubChannel < destChannels && sourceSubChannel < sourceChannels);
632 SourceSampleType s (addBytesToPointer (source, sourceSubChannel * SourceSampleType::getBytesPerSample()), sourceChannels);
633 DestSampleType d (addBytesToPointer (dest, destSubChannel * DestSampleType::getBytesPerSample()), destChannels);
634 d.convertSamples (s, numSamples);
640 const int sourceChannels, destChannels;
660 static void convertFloatToInt16LE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample = 2);
661 static void convertFloatToInt16BE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample = 2);
663 static void convertFloatToInt24LE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample = 3);
664 static void convertFloatToInt24BE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample = 3);
666 static void convertFloatToInt32LE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample = 4);
667 static void convertFloatToInt32BE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample = 4);
669 static void convertFloatToFloat32LE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample = 4);
670 static void convertFloatToFloat32BE (
const float* source,
void* dest,
int numSamples,
int destBytesPerSample = 4);
673 static void convertInt16LEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample = 2);
674 static void convertInt16BEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample = 2);
676 static void convertInt24LEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample = 3);
677 static void convertInt24BEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample = 3);
679 static void convertInt32LEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample = 4);
680 static void convertInt32BEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample = 4);
682 static void convertFloat32LEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample = 4);
683 static void convertFloat32BEToFloat (
const void* source,
float* dest,
int numSamples,
int srcBytesPerSample = 4);
698 static void convertFloatToFormat (DataFormat destFormat,
699 const float* source,
void* dest,
int numSamples);
701 static void convertFormatToFloat (DataFormat sourceFormat,
702 const void* source,
float* dest,
int numSamples);
705 static void interleaveSamples (
const float** source,
float* dest,
706 int numSamples,
int numChannels);
708 static void deinterleaveSamples (
const float* source,
float** dest,
709 int numSamples,
int numChannels);
void convertSamples(void *dest, const void *source, int numSamples) const override
void convertSamples(void *dest, int destSubChannel, const void *source, int sourceSubChannel, int numSamples) const override
virtual void convertSamples(void *destSamples, int destSubChannel, const void *sourceSamples, int sourceSubChannel, int numSamples) const =0
virtual void convertSamples(void *destSamples, const void *sourceSamples, int numSamples) const =0
int getNumBytesBetweenSamples() const noexcept
void setAsInt32(int32 newValue) noexcept
void clearSamples(int numSamples) const noexcept
static int getBytesPerSample() noexcept
const void * getRawData() const noexcept
void convertSamples(OtherPointerType source, int numSamples) const noexcept
int getNumInterleavedChannels() const noexcept
Pointer(const Pointer &other) noexcept
void convertSamples(Pointer source, int numSamples) const noexcept
int32 getAsInt32() const noexcept
void setAsFloat(float newValue) noexcept
Range< float > findMinAndMax(size_t numSamples) const noexcept
Pointer & operator--() noexcept
Pointer(typename Constness::VoidType *sourceData, int numInterleaved) noexcept
Pointer & operator++() noexcept
static bool isFloatingPoint() noexcept
float getAsFloat() const noexcept
Pointer(typename Constness::VoidType *sourceData) noexcept
void findMinAndMax(size_t numSamples, float &minValue, float &maxValue) const noexcept
static int get32BitResolution() noexcept
static bool isBigEndian() noexcept
static JUCE_CONSTEXPR uint16 swap(uint16 value) noexcept
static Type swapIfLittleEndian(Type value) noexcept
static void littleEndian24BitToChars(int32 value, void *destBytes) noexcept
static JUCE_CONSTEXPR int bigEndian24Bit(const void *bytes) noexcept
static void bigEndian24BitToChars(int32 value, void *destBytes) noexcept
static Type swapIfBigEndian(Type value) noexcept
static JUCE_CONSTEXPR int littleEndian24Bit(const void *bytes) noexcept
JUCE_CONSTEXPR ValueType getStart() const noexcept
JUCE_CONSTEXPR ValueType getEnd() const noexcept