diff --git a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj index 3dff2a000d41..ee5e9b7dbebf 100644 --- a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj @@ -413,6 +413,7 @@ EBA6B46F7B3C11CA3744A4D0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_AudioDataConverters.h; path = ../../src/audio/dsp/juce_AudioDataConverters.h; sourceTree = SOURCE_ROOT; }; A1D687AE613A8B61EB63923D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_AudioSampleBuffer.cpp; path = ../../src/audio/dsp/juce_AudioSampleBuffer.cpp; sourceTree = SOURCE_ROOT; }; 812620B53BE820D26A63B65D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_AudioSampleBuffer.h; path = ../../src/audio/dsp/juce_AudioSampleBuffer.h; sourceTree = SOURCE_ROOT; }; + 11C1A96A35A2F03F8C34BD43 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Decibels.h; path = ../../src/audio/dsp/juce_Decibels.h; sourceTree = SOURCE_ROOT; }; E68EB4BC75216B5B56E3F937 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_IIRFilter.cpp; path = ../../src/audio/dsp/juce_IIRFilter.cpp; sourceTree = SOURCE_ROOT; }; EE2259D9768027C2C001EEAD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_IIRFilter.h; path = ../../src/audio/dsp/juce_IIRFilter.h; sourceTree = SOURCE_ROOT; }; B457515938E7141D5E79B671 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_MidiBuffer.cpp; path = ../../src/audio/midi/juce_MidiBuffer.cpp; sourceTree = SOURCE_ROOT; }; @@ -1111,6 +1112,7 @@ EBA6B46F7B3C11CA3744A4D0, A1D687AE613A8B61EB63923D, 812620B53BE820D26A63B65D, + 11C1A96A35A2F03F8C34BD43, E68EB4BC75216B5B56E3F937, EE2259D9768027C2C001EEAD ); name = dsp; sourceTree = ""; }; 99B60B012D5CCF0BD861011D = { isa = PBXGroup; children = ( diff --git a/Builds/VisualStudio2005/Juce.vcproj b/Builds/VisualStudio2005/Juce.vcproj index c65091856aff..4e8c3542bbbc 100644 --- a/Builds/VisualStudio2005/Juce.vcproj +++ b/Builds/VisualStudio2005/Juce.vcproj @@ -181,6 +181,7 @@ + diff --git a/Builds/VisualStudio2008/Juce.vcproj b/Builds/VisualStudio2008/Juce.vcproj index 4958349e4554..3cfa9c6ff99a 100644 --- a/Builds/VisualStudio2008/Juce.vcproj +++ b/Builds/VisualStudio2008/Juce.vcproj @@ -181,6 +181,7 @@ + diff --git a/Builds/VisualStudio2008_DLL/Juce.vcproj b/Builds/VisualStudio2008_DLL/Juce.vcproj index 2e5b90d27715..465db68f8ed6 100644 --- a/Builds/VisualStudio2008_DLL/Juce.vcproj +++ b/Builds/VisualStudio2008_DLL/Juce.vcproj @@ -183,6 +183,7 @@ + diff --git a/Builds/VisualStudio2010/Juce.vcxproj b/Builds/VisualStudio2010/Juce.vcxproj index 4437963a8962..e54ecca3ba40 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj +++ b/Builds/VisualStudio2010/Juce.vcxproj @@ -469,6 +469,7 @@ + diff --git a/Builds/VisualStudio2010/Juce.vcxproj.filters b/Builds/VisualStudio2010/Juce.vcxproj.filters index b199e275179b..9088669d9861 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj.filters +++ b/Builds/VisualStudio2010/Juce.vcxproj.filters @@ -1329,6 +1329,9 @@ Juce\Source\audio\dsp + + Juce\Source\audio\dsp + Juce\Source\audio\dsp diff --git a/Builds/iPhone/Juce.xcodeproj/project.pbxproj b/Builds/iPhone/Juce.xcodeproj/project.pbxproj index 91aecd946fcb..907e9ebff72a 100644 --- a/Builds/iPhone/Juce.xcodeproj/project.pbxproj +++ b/Builds/iPhone/Juce.xcodeproj/project.pbxproj @@ -413,6 +413,7 @@ EBA6B46F7B3C11CA3744A4D0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_AudioDataConverters.h; path = ../../src/audio/dsp/juce_AudioDataConverters.h; sourceTree = SOURCE_ROOT; }; A1D687AE613A8B61EB63923D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_AudioSampleBuffer.cpp; path = ../../src/audio/dsp/juce_AudioSampleBuffer.cpp; sourceTree = SOURCE_ROOT; }; 812620B53BE820D26A63B65D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_AudioSampleBuffer.h; path = ../../src/audio/dsp/juce_AudioSampleBuffer.h; sourceTree = SOURCE_ROOT; }; + 11C1A96A35A2F03F8C34BD43 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Decibels.h; path = ../../src/audio/dsp/juce_Decibels.h; sourceTree = SOURCE_ROOT; }; E68EB4BC75216B5B56E3F937 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_IIRFilter.cpp; path = ../../src/audio/dsp/juce_IIRFilter.cpp; sourceTree = SOURCE_ROOT; }; EE2259D9768027C2C001EEAD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_IIRFilter.h; path = ../../src/audio/dsp/juce_IIRFilter.h; sourceTree = SOURCE_ROOT; }; B457515938E7141D5E79B671 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_MidiBuffer.cpp; path = ../../src/audio/midi/juce_MidiBuffer.cpp; sourceTree = SOURCE_ROOT; }; @@ -1111,6 +1112,7 @@ EBA6B46F7B3C11CA3744A4D0, A1D687AE613A8B61EB63923D, 812620B53BE820D26A63B65D, + 11C1A96A35A2F03F8C34BD43, E68EB4BC75216B5B56E3F937, EE2259D9768027C2C001EEAD ); name = dsp; sourceTree = ""; }; 99B60B012D5CCF0BD861011D = { isa = PBXGroup; children = ( diff --git a/Juce.jucer b/Juce.jucer index 51f3e6304a4a..a4303b177c09 100644 --- a/Juce.jucer +++ b/Juce.jucer @@ -189,6 +189,8 @@ resource="0" file="src/audio/dsp/juce_AudioSampleBuffer.cpp"/> + *> (&text)->exchange (newText)); + StringHolder::release (reinterpret_cast &> (text).exchange (newText)); return *this; } -String::String (const size_t numChars, const int /*dummyVariable*/) - : text (StringHolder::createUninitialised (numChars)) +inline String::Preallocation::Preallocation (const size_t numChars_) : numChars (numChars_) {} + +String::String (const Preallocation& preallocationSize) + : text (StringHolder::createUninitialised (preallocationSize.numChars)) { } @@ -11992,7 +11999,7 @@ String::String (const juce_wchar* const t, const size_t maxChars) const String String::charToString (const juce_wchar character) { - String result ((size_t) 1, (int) 0); + String result (Preallocation (1)); result.text[0] = character; result.text[1] = 0; return result; @@ -12815,7 +12822,7 @@ bool String::matchesWildcard (const String& wildcard, const bool ignoreCase) con const String String::repeatedString (const String& stringToRepeat, int numberOfTimesToRepeat) { const int len = stringToRepeat.length(); - String result ((size_t) (len * numberOfTimesToRepeat + 1), (int) 0); + String result (Preallocation (len * numberOfTimesToRepeat + 1)); juce_wchar* n = result.text; *n = 0; @@ -12836,7 +12843,7 @@ const String String::paddedLeft (const juce_wchar padCharacter, int minimumLengt if (len >= minimumLength || padCharacter == 0) return *this; - String result ((size_t) minimumLength + 1, (int) 0); + String result (Preallocation (minimumLength + 1)); juce_wchar* n = result.text; minimumLength -= len; @@ -12902,7 +12909,7 @@ const String String::replaceSection (int index, int numCharsToReplace, const Str if (newTotalLen <= 0) return String::empty; - String result ((size_t) newTotalLen, (int) 0); + String result (Preallocation ((size_t) newTotalLen)); StringHolder::copyChars (result.text, text, index); @@ -13271,7 +13278,7 @@ const String String::retainCharacters (const String& charactersToRetain) const if (isEmpty()) return empty; - String result (StringHolder::getAllocatedNumChars (text), (int) 0); + String result (Preallocation (StringHolder::getAllocatedNumChars (text))); juce_wchar* dst = result.text; const juce_wchar* src = text; @@ -13292,7 +13299,7 @@ const String String::removeCharacters (const String& charactersToRemove) const if (isEmpty()) return empty; - String result (StringHolder::getAllocatedNumChars (text), (int) 0); + String result (Preallocation (StringHolder::getAllocatedNumChars (text))); juce_wchar* dst = result.text; const juce_wchar* src = text; @@ -13380,7 +13387,7 @@ const String String::formatted (const juce_wchar* const pf, ... ) va_start (args, pf); size_t bufferSize = 256; - String result (bufferSize, (int) 0); + String result (Preallocation ((size_t) bufferSize)); result.text[0] = 0; for (;;) @@ -13505,9 +13512,7 @@ const String String::toHexString (const short number) return toHexString ((int) (unsigned short) number); } -const String String::toHexString (const unsigned char* data, - const int size, - const int groupSize) +const String String::toHexString (const unsigned char* data, const int size, const int groupSize) { if (size <= 0) return empty; @@ -13516,7 +13521,7 @@ const String String::toHexString (const unsigned char* data, if (groupSize > 0) numChars += size / groupSize; - String s ((size_t) numChars, (int) 0); + String s (Preallocation ((size_t) numChars)); juce_wchar* d = s.text; @@ -13769,7 +13774,7 @@ const String String::fromUTF8 (const char* const buffer, int bufferSizeBytes) if (buffer [numBytes] == 0) break; - String result ((size_t) numBytes + 1, (int) 0); + String result (Preallocation (numBytes + 1)); juce_wchar* dest = result.text; size_t i = 0; @@ -22625,8 +22630,10 @@ void AudioThumbnail::saveTo (OutputStream& output) const channels.getUnchecked(chan)->getData(i)->write (output); } -void AudioThumbnail::setDataSource (LevelDataSource* newSource) +bool AudioThumbnail::setDataSource (LevelDataSource* newSource) { + jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); + numSamplesFinished = 0; if (cache.loadThumb (*this, newSource->hashCode) && isFullyLoaded()) @@ -22651,14 +22658,15 @@ void AudioThumbnail::setDataSource (LevelDataSource* newSource) createChannels (1 + (int) (totalSamples / samplesPerThumbSample)); } + + return sampleRate > 0 && totalSamples > 0; } -void AudioThumbnail::setSource (InputSource* const newSource) +bool AudioThumbnail::setSource (InputSource* const newSource) { clear(); - if (newSource != 0) - setDataSource (new LevelDataSource (*this, newSource)); + return newSource != 0 && setDataSource (new LevelDataSource (*this, newSource)); } void AudioThumbnail::setReader (AudioFormatReader* newReader, int64 hash) @@ -22669,6 +22677,11 @@ void AudioThumbnail::setReader (AudioFormatReader* newReader, int64 hash) setDataSource (new LevelDataSource (*this, newReader, hash)); } +int64 AudioThumbnail::getHashCode() const +{ + return source == 0 ? 0 : source->hashCode; +} + void AudioThumbnail::addBlock (const int64 startSample, const AudioSampleBuffer& incoming, int startOffsetInBuffer, int numSamples) { @@ -237848,7 +237861,7 @@ int64 Time::getHighResolutionTicks() throw() LARGE_INTEGER ticks; QueryPerformanceCounter (&ticks); - const int64 mainCounterAsHiResTicks = (GetTickCount() * hiResTicksPerSecond) / 1000; + const int64 mainCounterAsHiResTicks = (juce_millisecondsSinceStartup() * hiResTicksPerSecond) / 1000; const int64 newOffset = mainCounterAsHiResTicks - ticks.QuadPart; // fix for a very obscure PCI hardware bug that can make the counter @@ -255339,27 +255352,6 @@ namespace LinuxStatsHelpers return String::empty; } - - bool getTimeSinceStartup (timeval* const t) throw() - { - if (gettimeofday (t, 0) != 0) - return false; - - static unsigned int calibrate = 0; - static bool calibrated = false; - - if (! calibrated) - { - calibrated = true; - - struct sysinfo sysi; - if (sysinfo (&sysi) == 0) - calibrate = t->tv_sec - sysi.uptime; // Safe to assume system was not brought up earlier than 1970! - } - - t->tv_sec -= calibrate; - return true; - } } const String SystemStats::getCpuVendor() @@ -255423,20 +255415,18 @@ void PlatformUtilities::fpuReset() uint32 juce_millisecondsSinceStartup() throw() { - timeval t; - if (LinuxStatsHelpers::getTimeSinceStartup (&t)) - return (uint32) (t.tv_sec * 1000 + (t.tv_usec / 1000)); + timespec t; + clock_gettime (CLOCK_MONOTONIC, &t); - return 0; + return t.tv_sec * 1000 + t.tv_nsec / 1000000; } int64 Time::getHighResolutionTicks() throw() { - timeval t; - if (LinuxStatsHelpers::getTimeSinceStartup (&t)) - return ((int64) t.tv_sec * (int64) 1000000) + (int64) t.tv_usec; + timespec t; + clock_gettime (CLOCK_MONOTONIC, &t); - return 0; + return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / (int64) 1000); } int64 Time::getHighResolutionTicksPerSecond() throw() diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 5bbe9f07466b..a66237ef1e81 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -2712,8 +2712,14 @@ class JUCE_API String juce_wchar* text; - // internal constructor that preallocates a certain amount of memory - String (size_t numChars, int dummyVariable); + struct Preallocation + { + explicit Preallocation (size_t); + size_t numChars; + }; + + // This constructor preallocates a certain amount of memory + explicit String (const Preallocation&); String (const String& stringToCopy, size_t charsToAllocate); void createInternal (const juce_wchar* text, size_t numChars); @@ -8937,19 +8943,20 @@ class JUCE_API Time */ static int64 currentTimeMillis() throw(); - /** Returns the number of millisecs since system startup. + /** Returns the number of millisecs since a fixed event (usually system startup). - Should be accurate to within a few millisecs, depending on platform, + This returns a monotonically increasing value which it unaffected by changes to the + system clock. It should be accurate to within a few millisecs, depending on platform, hardware, etc. @see getApproximateMillisecondCounter */ static uint32 getMillisecondCounter() throw(); - /** Returns the number of millisecs since system startup. + /** Returns the number of millisecs since a fixed event (usually system startup). - Same as getMillisecondCounter(), but returns a more accurate value, using - the high-res timer. + This has the same function as getMillisecondCounter(), but returns a more accurate + value, using a higher-resolution timer if one is available. @see getMillisecondCounter */ @@ -17113,7 +17120,7 @@ class JUCE_API FileInputSource : public InputSource { public: - FileInputSource (const File& file); + FileInputSource (const File& file, bool useFileTimeInHashGeneration = false); ~FileInputSource(); InputStream* createInputStream(); @@ -17123,6 +17130,7 @@ class JUCE_API FileInputSource : public InputSource private: const File file; + bool useFileTimeInHashGeneration; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileInputSource); }; @@ -21641,8 +21649,8 @@ class Rectangle { const int x1 = (int) std::floor (static_cast (x)); const int y1 = (int) std::floor (static_cast (y)); - const int x2 = (int) std::floor (static_cast (x + w + 0.9999f)); - const int y2 = (int) std::floor (static_cast (y + h + 0.9999f)); + const int x2 = (int) std::ceil (static_cast (x + w)); + const int y2 = (int) std::ceil (static_cast (y + h)); return Rectangle (x1, y1, x2 - x1, y2 - y1); } @@ -22166,19 +22174,13 @@ class JUCE_API Path const Point getCurrentPosition() const; /** Adds a rectangle to the path. - - The rectangle is added as a new sub-path. (Any currently open paths will be - left open). - + The rectangle is added as a new sub-path. (Any currently open paths will be left open). @see addRoundedRectangle, addTriangle */ void addRectangle (float x, float y, float width, float height); /** Adds a rectangle to the path. - - The rectangle is added as a new sub-path. (Any currently open paths will be - left open). - + The rectangle is added as a new sub-path. (Any currently open paths will be left open). @see addRoundedRectangle, addTriangle */ template @@ -22189,30 +22191,45 @@ class JUCE_API Path } /** Adds a rectangle with rounded corners to the path. - - The rectangle is added as a new sub-path. (Any currently open paths will be - left open). - + The rectangle is added as a new sub-path. (Any currently open paths will be left open). @see addRectangle, addTriangle */ void addRoundedRectangle (float x, float y, float width, float height, float cornerSize); /** Adds a rectangle with rounded corners to the path. - - The rectangle is added as a new sub-path. (Any currently open paths will be - left open). - + The rectangle is added as a new sub-path. (Any currently open paths will be left open). @see addRectangle, addTriangle */ void addRoundedRectangle (float x, float y, float width, float height, float cornerSizeX, float cornerSizeY); + /** Adds a rectangle with rounded corners to the path. + The rectangle is added as a new sub-path. (Any currently open paths will be left open). + @see addRectangle, addTriangle + */ + template + void addRoundedRectangle (const Rectangle& rectangle, float cornerSizeX, float cornerSizeY) + { + addRoundedRectangle (static_cast (rectangle.getX()), static_cast (rectangle.getY()), + static_cast (rectangle.getWidth()), static_cast (rectangle.getHeight()), + cornerSizeX, cornerSizeY); + } + + /** Adds a rectangle with rounded corners to the path. + The rectangle is added as a new sub-path. (Any currently open paths will be left open). + @see addRectangle, addTriangle + */ + template + void addRoundedRectangle (const Rectangle& rectangle, float cornerSize) + { + addRoundedRectangle (rectangle, cornerSize, cornerSize); + } + /** Adds a triangle to the path. - The triangle is added as a new closed sub-path. (Any currently open paths will be - left open). + The triangle is added as a new closed sub-path. (Any currently open paths will be left open). Note that whether the vertices are specified in clockwise or anticlockwise order will affect how the triangle is filled when it overlaps other @@ -22224,8 +22241,7 @@ class JUCE_API Path /** Adds a quadrilateral to the path. - The quad is added as a new closed sub-path. (Any currently open paths will be - left open). + The quad is added as a new closed sub-path. (Any currently open paths will be left open). Note that whether the vertices are specified in clockwise or anticlockwise order will affect how the quad is filled when it overlaps other @@ -22238,8 +22254,7 @@ class JUCE_API Path /** Adds an ellipse to the path. - The shape is added as a new sub-path. (Any currently open paths will be - left open). + The shape is added as a new sub-path. (Any currently open paths will be left open). @see addArc */ @@ -32601,11 +32616,11 @@ class JUCE_API AudioThumbnail : public ChangeBroadcaster @endcode You can pass a zero in here to clear the thumbnail. - - The source that is passed in will be deleted by this object when it is no - longer needed + The source that is passed in will be deleted by this object when it is no longer needed. + @returns true if the source could be opened as a valid audio file, false if this failed for + some reason. */ - void setSource (InputSource* newSource); + bool setSource (InputSource* newSource); /** Gives the thumbnail an AudioFormatReader to use directly. This will start parsing the audio in a background thread (unless the hash code @@ -32685,6 +32700,9 @@ class JUCE_API AudioThumbnail : public ChangeBroadcaster /** Returns true if the low res preview is fully generated. */ bool isFullyLoaded() const throw(); + /** Returns the hash code that was set by setSource() or setReader(). */ + int64 getHashCode() const; + // (this is only public to avoid a VC6 bug) class LevelDataSource; @@ -32714,7 +32732,7 @@ class JUCE_API AudioThumbnail : public ChangeBroadcaster double sampleRate; CriticalSection lock; - void setDataSource (LevelDataSource* newSource); + bool setDataSource (LevelDataSource* newSource); void setLevels (const MinMaxValue* const* values, int thumbIndex, int numChans, int numValues); void createChannels (int length); @@ -39221,6 +39239,88 @@ class JUCE_API AudioDeviceManager : public ChangeBroadcaster #endif #ifndef __JUCE_AUDIOSAMPLEBUFFER_JUCEHEADER__ +#endif +#ifndef __JUCE_DECIBELS_JUCEHEADER__ + +/*** Start of inlined file: juce_Decibels.h ***/ +#ifndef __JUCE_DECIBELS_JUCEHEADER__ +#define __JUCE_DECIBELS_JUCEHEADER__ + +/** + This class contains some helpful static methods for dealing with decibel values. +*/ +class Decibels +{ +public: + + /** Converts a dBFS value to its equivalent gain level. + + A gain of 1.0 = 0 dB, and lower gains map onto negative decibel values. Any + decibel value lower than minusInfinityDb will return a gain of 0. + */ + template + static Type decibelsToGain (const Type decibels, + const Type minusInfinityDb = (Type) defaultMinusInfinitydB) + { + return decibels > minusInfinityDb ? powf ((Type) 10.0, decibels * (Type) 0.05) + : Type(); + } + + /** Converts a gain level into a dBFS value. + + A gain of 1.0 = 0 dB, and lower gains map onto negative decibel values. + If the gain is 0 (or negative), then the method will return the value + provided as minusInfinityDb. + */ + template + static Type gainToDecibels (const Type gain, + const Type minusInfinityDb = (Type) defaultMinusInfinitydB) + { + return gain > Type() ? jmax (minusInfinityDb, (Type) std::log (gain) * (Type) 20.0) + : minusInfinityDb; + } + + /** Converts a decibel reading to a string, with the 'dB' suffix. + If the decibel value is lower than minusInfinityDb, the return value will + be "-INF dB". + */ + template + static const String toString (const Type decibels, + const int decimalPlaces = 2, + const Type minusInfinityDb = (Type) defaultMinusInfinitydB) + { + String s; + + if (decibels <= minusInfinityDb) + { + s = "-INF dB"; + } + else + { + if (decibels >= Type()) + s << '+'; + + s << String (decibels, decimalPlaces) << " dB"; + } + + return s; + } + +private: + + enum + { + defaultMinusInfinitydB = -100 + }; + + Decibels(); // This class can't be instantiated, it's just a holder for static methods.. + JUCE_DECLARE_NON_COPYABLE (Decibels); +}; + +#endif // __JUCE_DECIBELS_JUCEHEADER__ +/*** End of inlined file: juce_Decibels.h ***/ + + #endif #ifndef __JUCE_IIRFILTER_JUCEHEADER__ diff --git a/src/audio/audio_file_formats/juce_AudioThumbnail.cpp b/src/audio/audio_file_formats/juce_AudioThumbnail.cpp index 5d3bf6f4f0fe..c16f1f7a078d 100644 --- a/src/audio/audio_file_formats/juce_AudioThumbnail.cpp +++ b/src/audio/audio_file_formats/juce_AudioThumbnail.cpp @@ -29,6 +29,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_AudioThumbnail.h" #include "juce_AudioThumbnailCache.h" +#include "../../events/juce_MessageManager.h" //============================================================================== @@ -582,8 +583,10 @@ void AudioThumbnail::saveTo (OutputStream& output) const } //============================================================================== -void AudioThumbnail::setDataSource (LevelDataSource* newSource) +bool AudioThumbnail::setDataSource (LevelDataSource* newSource) { + jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); + numSamplesFinished = 0; if (cache.loadThumb (*this, newSource->hashCode) && isFullyLoaded()) @@ -608,14 +611,15 @@ void AudioThumbnail::setDataSource (LevelDataSource* newSource) createChannels (1 + (int) (totalSamples / samplesPerThumbSample)); } + + return sampleRate > 0 && totalSamples > 0; } -void AudioThumbnail::setSource (InputSource* const newSource) +bool AudioThumbnail::setSource (InputSource* const newSource) { clear(); - if (newSource != 0) - setDataSource (new LevelDataSource (*this, newSource)); + return newSource != 0 && setDataSource (new LevelDataSource (*this, newSource)); } void AudioThumbnail::setReader (AudioFormatReader* newReader, int64 hash) @@ -626,6 +630,11 @@ void AudioThumbnail::setReader (AudioFormatReader* newReader, int64 hash) setDataSource (new LevelDataSource (*this, newReader, hash)); } +int64 AudioThumbnail::getHashCode() const +{ + return source == 0 ? 0 : source->hashCode; +} + void AudioThumbnail::addBlock (const int64 startSample, const AudioSampleBuffer& incoming, int startOffsetInBuffer, int numSamples) { diff --git a/src/audio/audio_file_formats/juce_AudioThumbnail.h b/src/audio/audio_file_formats/juce_AudioThumbnail.h index 8b680bc2e974..4a18a4b690b6 100644 --- a/src/audio/audio_file_formats/juce_AudioThumbnail.h +++ b/src/audio/audio_file_formats/juce_AudioThumbnail.h @@ -91,11 +91,11 @@ class JUCE_API AudioThumbnail : public ChangeBroadcaster @endcode You can pass a zero in here to clear the thumbnail. - - The source that is passed in will be deleted by this object when it is no - longer needed + The source that is passed in will be deleted by this object when it is no longer needed. + @returns true if the source could be opened as a valid audio file, false if this failed for + some reason. */ - void setSource (InputSource* newSource); + bool setSource (InputSource* newSource); /** Gives the thumbnail an AudioFormatReader to use directly. This will start parsing the audio in a background thread (unless the hash code @@ -177,6 +177,8 @@ class JUCE_API AudioThumbnail : public ChangeBroadcaster /** Returns true if the low res preview is fully generated. */ bool isFullyLoaded() const throw(); + /** Returns the hash code that was set by setSource() or setReader(). */ + int64 getHashCode() const; // (this is only public to avoid a VC6 bug) class LevelDataSource; @@ -207,7 +209,7 @@ class JUCE_API AudioThumbnail : public ChangeBroadcaster double sampleRate; CriticalSection lock; - void setDataSource (LevelDataSource* newSource); + bool setDataSource (LevelDataSource* newSource); void setLevels (const MinMaxValue* const* values, int thumbIndex, int numChans, int numValues); void createChannels (int length); diff --git a/src/audio/dsp/juce_Decibels.h b/src/audio/dsp/juce_Decibels.h new file mode 100644 index 000000000000..758008c1e301 --- /dev/null +++ b/src/audio/dsp/juce_Decibels.h @@ -0,0 +1,104 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-10 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE 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. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#ifndef __JUCE_DECIBELS_JUCEHEADER__ +#define __JUCE_DECIBELS_JUCEHEADER__ + +//============================================================================== +/** + This class contains some helpful static methods for dealing with decibel values. +*/ +class Decibels +{ +public: + //============================================================================== + /** Converts a dBFS value to its equivalent gain level. + + A gain of 1.0 = 0 dB, and lower gains map onto negative decibel values. Any + decibel value lower than minusInfinityDb will return a gain of 0. + */ + template + static Type decibelsToGain (const Type decibels, + const Type minusInfinityDb = (Type) defaultMinusInfinitydB) + { + return decibels > minusInfinityDb ? powf ((Type) 10.0, decibels * (Type) 0.05) + : Type(); + } + + /** Converts a gain level into a dBFS value. + + A gain of 1.0 = 0 dB, and lower gains map onto negative decibel values. + If the gain is 0 (or negative), then the method will return the value + provided as minusInfinityDb. + */ + template + static Type gainToDecibels (const Type gain, + const Type minusInfinityDb = (Type) defaultMinusInfinitydB) + { + return gain > Type() ? jmax (minusInfinityDb, (Type) std::log (gain) * (Type) 20.0) + : minusInfinityDb; + } + + //============================================================================== + /** Converts a decibel reading to a string, with the 'dB' suffix. + If the decibel value is lower than minusInfinityDb, the return value will + be "-INF dB". + */ + template + static const String toString (const Type decibels, + const int decimalPlaces = 2, + const Type minusInfinityDb = (Type) defaultMinusInfinitydB) + { + String s; + + if (decibels <= minusInfinityDb) + { + s = "-INF dB"; + } + else + { + if (decibels >= Type()) + s << '+'; + + s << String (decibels, decimalPlaces) << " dB"; + } + + return s; + } + + +private: + //============================================================================== + enum + { + defaultMinusInfinitydB = -100 + }; + + Decibels(); // This class can't be instantiated, it's just a holder for static methods.. + JUCE_DECLARE_NON_COPYABLE (Decibels); +}; + + +#endif // __JUCE_DECIBELS_JUCEHEADER__ diff --git a/src/core/juce_Time.h b/src/core/juce_Time.h index 42f2311fc445..55f91c1cd96d 100644 --- a/src/core/juce_Time.h +++ b/src/core/juce_Time.h @@ -314,19 +314,20 @@ class JUCE_API Time */ static int64 currentTimeMillis() throw(); - /** Returns the number of millisecs since system startup. + /** Returns the number of millisecs since a fixed event (usually system startup). - Should be accurate to within a few millisecs, depending on platform, + This returns a monotonically increasing value which it unaffected by changes to the + system clock. It should be accurate to within a few millisecs, depending on platform, hardware, etc. @see getApproximateMillisecondCounter */ static uint32 getMillisecondCounter() throw(); - /** Returns the number of millisecs since system startup. + /** Returns the number of millisecs since a fixed event (usually system startup). - Same as getMillisecondCounter(), but returns a more accurate value, using - the high-res timer. + This has the same function as getMillisecondCounter(), but returns a more accurate + value, using a higher-resolution timer if one is available. @see getMillisecondCounter */ diff --git a/src/gui/graphics/geometry/juce_Path.h b/src/gui/graphics/geometry/juce_Path.h index 8f4939e599bb..e2ade518de76 100644 --- a/src/gui/graphics/geometry/juce_Path.h +++ b/src/gui/graphics/geometry/juce_Path.h @@ -307,19 +307,13 @@ class JUCE_API Path //============================================================================== /** Adds a rectangle to the path. - - The rectangle is added as a new sub-path. (Any currently open paths will be - left open). - + The rectangle is added as a new sub-path. (Any currently open paths will be left open). @see addRoundedRectangle, addTriangle */ void addRectangle (float x, float y, float width, float height); /** Adds a rectangle to the path. - - The rectangle is added as a new sub-path. (Any currently open paths will be - left open). - + The rectangle is added as a new sub-path. (Any currently open paths will be left open). @see addRoundedRectangle, addTriangle */ template @@ -330,30 +324,45 @@ class JUCE_API Path } /** Adds a rectangle with rounded corners to the path. - - The rectangle is added as a new sub-path. (Any currently open paths will be - left open). - + The rectangle is added as a new sub-path. (Any currently open paths will be left open). @see addRectangle, addTriangle */ void addRoundedRectangle (float x, float y, float width, float height, float cornerSize); /** Adds a rectangle with rounded corners to the path. - - The rectangle is added as a new sub-path. (Any currently open paths will be - left open). - + The rectangle is added as a new sub-path. (Any currently open paths will be left open). @see addRectangle, addTriangle */ void addRoundedRectangle (float x, float y, float width, float height, float cornerSizeX, float cornerSizeY); + /** Adds a rectangle with rounded corners to the path. + The rectangle is added as a new sub-path. (Any currently open paths will be left open). + @see addRectangle, addTriangle + */ + template + void addRoundedRectangle (const Rectangle& rectangle, float cornerSizeX, float cornerSizeY) + { + addRoundedRectangle (static_cast (rectangle.getX()), static_cast (rectangle.getY()), + static_cast (rectangle.getWidth()), static_cast (rectangle.getHeight()), + cornerSizeX, cornerSizeY); + } + + /** Adds a rectangle with rounded corners to the path. + The rectangle is added as a new sub-path. (Any currently open paths will be left open). + @see addRectangle, addTriangle + */ + template + void addRoundedRectangle (const Rectangle& rectangle, float cornerSize) + { + addRoundedRectangle (rectangle, cornerSize, cornerSize); + } + /** Adds a triangle to the path. - The triangle is added as a new closed sub-path. (Any currently open paths will be - left open). + The triangle is added as a new closed sub-path. (Any currently open paths will be left open). Note that whether the vertices are specified in clockwise or anticlockwise order will affect how the triangle is filled when it overlaps other @@ -365,8 +374,7 @@ class JUCE_API Path /** Adds a quadrilateral to the path. - The quad is added as a new closed sub-path. (Any currently open paths will be - left open). + The quad is added as a new closed sub-path. (Any currently open paths will be left open). Note that whether the vertices are specified in clockwise or anticlockwise order will affect how the quad is filled when it overlaps other @@ -379,8 +387,7 @@ class JUCE_API Path /** Adds an ellipse to the path. - The shape is added as a new sub-path. (Any currently open paths will be - left open). + The shape is added as a new sub-path. (Any currently open paths will be left open). @see addArc */ diff --git a/src/gui/graphics/geometry/juce_Rectangle.h b/src/gui/graphics/geometry/juce_Rectangle.h index 2684a1006512..93d6b8ddbef2 100644 --- a/src/gui/graphics/geometry/juce_Rectangle.h +++ b/src/gui/graphics/geometry/juce_Rectangle.h @@ -621,8 +621,8 @@ class Rectangle { const int x1 = (int) std::floor (static_cast (x)); const int y1 = (int) std::floor (static_cast (y)); - const int x2 = (int) std::floor (static_cast (x + w + 0.9999f)); - const int y2 = (int) std::floor (static_cast (y + h + 0.9999f)); + const int x2 = (int) std::ceil (static_cast (x + w)); + const int y2 = (int) std::ceil (static_cast (y + h)); return Rectangle (x1, y1, x2 - x1, y2 - y1); } diff --git a/src/io/streams/juce_FileInputSource.cpp b/src/io/streams/juce_FileInputSource.cpp index f85550c540f2..4596cf26e5ca 100644 --- a/src/io/streams/juce_FileInputSource.cpp +++ b/src/io/streams/juce_FileInputSource.cpp @@ -32,8 +32,8 @@ BEGIN_JUCE_NAMESPACE //============================================================================== -FileInputSource::FileInputSource (const File& file_) - : file (file_) +FileInputSource::FileInputSource (const File& file_, bool useFileTimeInHashGeneration_) + : file (file_), useFileTimeInHashGeneration (useFileTimeInHashGeneration_) { } @@ -53,7 +53,12 @@ InputStream* FileInputSource::createInputStreamFor (const String& relatedItemPat int64 FileInputSource::hashCode() const { - return file.hashCode(); + int64 h = file.hashCode(); + + if (useFileTimeInHashGeneration) + h ^= file.getLastModificationTime().toMilliseconds(); + + return h; } diff --git a/src/io/streams/juce_FileInputSource.h b/src/io/streams/juce_FileInputSource.h index 8cb1e4e02352..e82e0788fb46 100644 --- a/src/io/streams/juce_FileInputSource.h +++ b/src/io/streams/juce_FileInputSource.h @@ -40,7 +40,7 @@ class JUCE_API FileInputSource : public InputSource { public: //============================================================================== - FileInputSource (const File& file); + FileInputSource (const File& file, bool useFileTimeInHashGeneration = false); ~FileInputSource(); InputStream* createInputStream(); @@ -50,6 +50,7 @@ class JUCE_API FileInputSource : public InputSource private: //============================================================================== const File file; + bool useFileTimeInHashGeneration; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileInputSource); }; diff --git a/src/juce_app_includes.h b/src/juce_app_includes.h index 9a7aa5213d80..7f3eb7db6322 100644 --- a/src/juce_app_includes.h +++ b/src/juce_app_includes.h @@ -140,6 +140,9 @@ #ifndef __JUCE_AUDIOSAMPLEBUFFER_JUCEHEADER__ #include "audio/dsp/juce_AudioSampleBuffer.h" #endif +#ifndef __JUCE_DECIBELS_JUCEHEADER__ + #include "audio/dsp/juce_Decibels.h" +#endif #ifndef __JUCE_IIRFILTER_JUCEHEADER__ #include "audio/dsp/juce_IIRFilter.h" #endif diff --git a/src/native/linux/juce_linux_SystemStats.cpp b/src/native/linux/juce_linux_SystemStats.cpp index bb8ae0c2688d..8a3bdf3fcbbf 100644 --- a/src/native/linux/juce_linux_SystemStats.cpp +++ b/src/native/linux/juce_linux_SystemStats.cpp @@ -69,27 +69,6 @@ namespace LinuxStatsHelpers return String::empty; } - - bool getTimeSinceStartup (timeval* const t) throw() - { - if (gettimeofday (t, 0) != 0) - return false; - - static unsigned int calibrate = 0; - static bool calibrated = false; - - if (! calibrated) - { - calibrated = true; - - struct sysinfo sysi; - if (sysinfo (&sysi) == 0) - calibrate = t->tv_sec - sysi.uptime; // Safe to assume system was not brought up earlier than 1970! - } - - t->tv_sec -= calibrate; - return true; - } } const String SystemStats::getCpuVendor() @@ -156,20 +135,18 @@ void PlatformUtilities::fpuReset() //============================================================================== uint32 juce_millisecondsSinceStartup() throw() { - timeval t; - if (LinuxStatsHelpers::getTimeSinceStartup (&t)) - return (uint32) (t.tv_sec * 1000 + (t.tv_usec / 1000)); + timespec t; + clock_gettime (CLOCK_MONOTONIC, &t); - return 0; + return t.tv_sec * 1000 + t.tv_nsec / 1000000; } int64 Time::getHighResolutionTicks() throw() { - timeval t; - if (LinuxStatsHelpers::getTimeSinceStartup (&t)) - return ((int64) t.tv_sec * (int64) 1000000) + (int64) t.tv_usec; + timespec t; + clock_gettime (CLOCK_MONOTONIC, &t); - return 0; + return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / (int64) 1000); } int64 Time::getHighResolutionTicksPerSecond() throw() diff --git a/src/native/windows/juce_win32_SystemStats.cpp b/src/native/windows/juce_win32_SystemStats.cpp index a10fc7a40028..3e41e1d779e3 100644 --- a/src/native/windows/juce_win32_SystemStats.cpp +++ b/src/native/windows/juce_win32_SystemStats.cpp @@ -224,7 +224,7 @@ int64 Time::getHighResolutionTicks() throw() LARGE_INTEGER ticks; QueryPerformanceCounter (&ticks); - const int64 mainCounterAsHiResTicks = (GetTickCount() * hiResTicksPerSecond) / 1000; + const int64 mainCounterAsHiResTicks = (juce_millisecondsSinceStartup() * hiResTicksPerSecond) / 1000; const int64 newOffset = mainCounterAsHiResTicks - ticks.QuadPart; // fix for a very obscure PCI hardware bug that can make the counter diff --git a/src/text/juce_String.cpp b/src/text/juce_String.cpp index 7613696001ae..6bb203e78e6f 100644 --- a/src/text/juce_String.cpp +++ b/src/text/juce_String.cpp @@ -212,12 +212,14 @@ String& String::operator= (const String& other) throw() { juce_wchar* const newText = other.text; StringHolder::retain (newText); - StringHolder::release (reinterpret_cast *> (&text)->exchange (newText)); + StringHolder::release (reinterpret_cast &> (text).exchange (newText)); return *this; } -String::String (const size_t numChars, const int /*dummyVariable*/) - : text (StringHolder::createUninitialised (numChars)) +inline String::Preallocation::Preallocation (const size_t numChars_) : numChars (numChars_) {} + +String::String (const Preallocation& preallocationSize) + : text (StringHolder::createUninitialised (preallocationSize.numChars)) { } @@ -272,7 +274,7 @@ String::String (const juce_wchar* const t, const size_t maxChars) const String String::charToString (const juce_wchar character) { - String result ((size_t) 1, (int) 0); + String result (Preallocation (1)); result.text[0] = character; result.text[1] = 0; return result; @@ -1104,7 +1106,7 @@ bool String::matchesWildcard (const String& wildcard, const bool ignoreCase) con const String String::repeatedString (const String& stringToRepeat, int numberOfTimesToRepeat) { const int len = stringToRepeat.length(); - String result ((size_t) (len * numberOfTimesToRepeat + 1), (int) 0); + String result (Preallocation (len * numberOfTimesToRepeat + 1)); juce_wchar* n = result.text; *n = 0; @@ -1125,7 +1127,7 @@ const String String::paddedLeft (const juce_wchar padCharacter, int minimumLengt if (len >= minimumLength || padCharacter == 0) return *this; - String result ((size_t) minimumLength + 1, (int) 0); + String result (Preallocation (minimumLength + 1)); juce_wchar* n = result.text; minimumLength -= len; @@ -1192,7 +1194,7 @@ const String String::replaceSection (int index, int numCharsToReplace, const Str if (newTotalLen <= 0) return String::empty; - String result ((size_t) newTotalLen, (int) 0); + String result (Preallocation ((size_t) newTotalLen)); StringHolder::copyChars (result.text, text, index); @@ -1566,7 +1568,7 @@ const String String::retainCharacters (const String& charactersToRetain) const if (isEmpty()) return empty; - String result (StringHolder::getAllocatedNumChars (text), (int) 0); + String result (Preallocation (StringHolder::getAllocatedNumChars (text))); juce_wchar* dst = result.text; const juce_wchar* src = text; @@ -1587,7 +1589,7 @@ const String String::removeCharacters (const String& charactersToRemove) const if (isEmpty()) return empty; - String result (StringHolder::getAllocatedNumChars (text), (int) 0); + String result (Preallocation (StringHolder::getAllocatedNumChars (text))); juce_wchar* dst = result.text; const juce_wchar* src = text; @@ -1675,7 +1677,7 @@ const String String::formatted (const juce_wchar* const pf, ... ) va_start (args, pf); size_t bufferSize = 256; - String result (bufferSize, (int) 0); + String result (Preallocation ((size_t) bufferSize)); result.text[0] = 0; for (;;) @@ -1801,9 +1803,7 @@ const String String::toHexString (const short number) return toHexString ((int) (unsigned short) number); } -const String String::toHexString (const unsigned char* data, - const int size, - const int groupSize) +const String String::toHexString (const unsigned char* data, const int size, const int groupSize) { if (size <= 0) return empty; @@ -1812,7 +1812,7 @@ const String String::toHexString (const unsigned char* data, if (groupSize > 0) numChars += size / groupSize; - String s ((size_t) numChars, (int) 0); + String s (Preallocation ((size_t) numChars)); juce_wchar* d = s.text; @@ -2067,7 +2067,7 @@ const String String::fromUTF8 (const char* const buffer, int bufferSizeBytes) if (buffer [numBytes] == 0) break; - String result ((size_t) numBytes + 1, (int) 0); + String result (Preallocation (numBytes + 1)); juce_wchar* dest = result.text; size_t i = 0; diff --git a/src/text/juce_String.h b/src/text/juce_String.h index 2e876d5b4955..19aff2aa5bbd 100644 --- a/src/text/juce_String.h +++ b/src/text/juce_String.h @@ -1042,8 +1042,14 @@ class JUCE_API String juce_wchar* text; //============================================================================== - // internal constructor that preallocates a certain amount of memory - String (size_t numChars, int dummyVariable); + struct Preallocation + { + explicit Preallocation (size_t); + size_t numChars; + }; + + // This constructor preallocates a certain amount of memory + explicit String (const Preallocation&); String (const String& stringToCopy, size_t charsToAllocate); void createInternal (const juce_wchar* text, size_t numChars);