Browse Source

Fix for audio plugin builds on win32. AudioProcessorGraph optimisations. Access to min/max values in audio thumbnails. More metadata support for wav and aiff formats.

tags/2021-05-28
Julian Storer 14 years ago
parent
commit
d97ce5f9ee
20 changed files with 3038 additions and 1708 deletions
  1. +1
    -1
      extras/audio plugin host/Source/FilterGraph.cpp
  2. +3
    -3
      extras/audio plugin host/Source/GraphEditorPanel.cpp
  3. +1447
    -793
      juce_amalgamated.cpp
  4. +43
    -39
      juce_amalgamated.h
  5. +29
    -18
      src/application/juce_Application.cpp
  6. +15
    -22
      src/application/juce_Application.h
  7. +322
    -9
      src/audio/audio_file_formats/juce_AiffAudioFormat.cpp
  8. +3
    -2
      src/audio/audio_file_formats/juce_AiffAudioFormat.h
  9. +22
    -4
      src/audio/audio_file_formats/juce_AudioThumbnail.cpp
  10. +9
    -2
      src/audio/audio_file_formats/juce_AudioThumbnail.h
  11. +247
    -25
      src/audio/audio_file_formats/juce_WavAudioFormat.cpp
  12. +3
    -0
      src/audio/plugin_client/juce_PluginHeaders.h
  13. +875
    -774
      src/audio/processors/juce_AudioProcessorGraph.cpp
  14. +6
    -3
      src/audio/processors/juce_AudioProcessorGraph.h
  15. +1
    -2
      src/events/juce_MessageManager.cpp
  16. +4
    -7
      src/events/juce_MessageManager.h
  17. +2
    -0
      src/gui/components/windows/juce_DocumentWindow.h
  18. +2
    -2
      src/gui/components/windows/juce_ResizableWindow.h
  19. +2
    -1
      src/gui/graphics/imaging/juce_CameraDevice.h
  20. +2
    -1
      src/threads/juce_TimeSliceThread.h

+ 1
- 1
extras/audio plugin host/Source/FilterGraph.cpp View File

@@ -295,7 +295,7 @@ static XmlElement* createNodeXml (AudioProcessorGraph::Node* const node) noexcep
}
XmlElement* e = new XmlElement ("FILTER");
e->setAttribute ("uid", (int) node->id);
e->setAttribute ("uid", (int) node->nodeId);
e->setAttribute ("x", node->properties ["x"].toString());
e->setAttribute ("y", node->properties ["y"].toString());
e->setAttribute ("uiLastX", node->properties ["uiLastX"].toString());


+ 3
- 3
extras/audio plugin host/Source/GraphEditorPanel.cpp View File

@@ -55,7 +55,7 @@ PluginWindow::PluginWindow (Component* const uiComp,
void PluginWindow::closeCurrentlyOpenWindowsFor (const uint32 nodeId)
{
for (int i = activePluginWindows.size(); --i >= 0;)
if (activePluginWindows.getUnchecked(i)->owner->id == nodeId)
if (activePluginWindows.getUnchecked(i)->owner->nodeId == nodeId)
delete activePluginWindows.getUnchecked(i);
}
@@ -839,9 +839,9 @@ void GraphEditorPanel::updateComponents()
{
const AudioProcessorGraph::Node::Ptr f (graph.getNode (i));
if (getComponentForFilter (f->id) == 0)
if (getComponentForFilter (f->nodeId) == 0)
{
FilterComponent* const comp = new FilterComponent (graph, f->id);
FilterComponent* const comp = new FilterComponent (graph, f->nodeId);
addAndMakeVisible (comp);
comp->update();
}


+ 1447
- 793
juce_amalgamated.cpp
File diff suppressed because it is too large
View File


+ 43
- 39
juce_amalgamated.h View File

@@ -73,7 +73,7 @@ namespace JuceDummyNamespace {}
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53
#define JUCE_BUILDNUMBER 73
#define JUCE_BUILDNUMBER 74

/** Current Juce version number.

@@ -23112,8 +23112,9 @@ public:
/** Returns one of the registered clients. */
TimeSliceClient* getClient (int index) const;

/** @internal */
#ifndef DOXYGEN
void run();
#endif

private:
CriticalSection callbackLock, listLock;
@@ -33344,8 +33345,7 @@ public:

@see MessageManager, DeletedAtShutdown
*/
class JUCE_API JUCEApplication : public ApplicationCommandTarget,
private ActionListener
class JUCE_API JUCEApplication : public ApplicationCommandTarget
{
protected:

@@ -33497,18 +33497,9 @@ public:
*/
const String getCommandLineParameters() const noexcept { return commandLineParameters; }

// These are used by the START_JUCE_APPLICATION() macro and aren't for public use.

/** @internal */
static int main (const String& commandLine);
/** @internal */
static int main (int argc, const char* argv[]);
/** @internal */
static void sendUnhandledException (const std::exception* e, const char* sourceFile, int lineNumber);

/** Returns true if this executable is running as an app (as opposed to being a plugin
or other kind of shared library. */
static inline bool isStandaloneApp() noexcept { return createInstance != 0; }
static inline bool isStandaloneApp() noexcept { return createInstance != 0; }

/** @internal */
ApplicationCommandTarget* getNextCommandTarget();
@@ -33518,26 +33509,28 @@ public:
void getAllCommands (Array <CommandID>& commands);
/** @internal */
bool perform (const InvocationInfo& info);
/** @internal */
void actionListenerCallback (const String& message);
/** @internal */

#ifndef DOXYGEN
// The following methods are internal calls - not for public use.
static int main (const String& commandLine);
static int main (int argc, const char* argv[]);
static void sendUnhandledException (const std::exception* e, const char* sourceFile, int lineNumber);
bool initialiseApp (const String& commandLine);
/** @internal */
int shutdownApp();
/** @internal */
static void appWillTerminateByForce();
/** @internal */
typedef JUCEApplication* (*CreateInstanceFunction)();
/** @internal */
static CreateInstanceFunction createInstance;
#endif

private:

static JUCEApplication* appInstance;

String commandLineParameters;
ScopedPointer<InterProcessLock> appLock;
ScopedPointer<ActionListener> broadcastCallback;
int appReturnValue;
bool stillInitialising;
ScopedPointer<InterProcessLock> appLock;
static JUCEApplication* appInstance;

JUCE_DECLARE_NON_COPYABLE (JUCEApplication);
};
@@ -36550,9 +36543,10 @@ public:
const Array <int> getPossibleBitDepths();
bool canDoStereo();
bool canDoMono();
#if JUCE_MAC

#if JUCE_MAC
bool canHandleFile (const File& fileToTest);
#endif
#endif

AudioFormatReader* createReaderFor (InputStream* sourceStream,
bool deleteStreamIfOpeningFails);
@@ -37224,12 +37218,19 @@ public:
*/
float getApproximatePeak() const;

/** Reads the approximate min and max levels from a section of the thumbnail.
The lowest and highest samples are returned in minValue and maxValue, but obviously
because the thumb only stores low-resolution data, these numbers will only be a rough
approximation of the true values.
*/
void getApproximateMinMax (double startTime, double endTime, int channelIndex,
float& minValue, float& maxValue) const noexcept;

/** Returns the hash code that was set by setSource() or setReader(). */
int64 getHashCode() const;

#ifndef DOXYGEN
// (this is only public to avoid a VC6 bug)
class LevelDataSource;
class LevelDataSource; // (this is only public to avoid a VC6 bug)
#endif

private:
@@ -47098,10 +47099,9 @@ public:
public:

/** The ID number assigned to this node.

This is assigned by the graph that owns it, and can't be changed.
*/
const uint32 id;
const uint32 nodeId;

/** The actual processor object that this node represents. */
AudioProcessor* getProcessor() const noexcept { return processor; }
@@ -47125,7 +47125,7 @@ public:
const ScopedPointer<AudioProcessor> processor;
bool isPrepared;

Node (uint32 id, AudioProcessor* processor);
Node (uint32 nodeId, AudioProcessor* processor) noexcept;

void prepare (double sampleRate, int blockSize, AudioProcessorGraph* graph);
void unprepare();
@@ -47141,6 +47141,9 @@ public:
{
public:

Connection (uint32 sourceNodeId, int sourceChannelIndex,
uint32 destNodeId, int destChannelIndex) noexcept;

/** The ID number of the node which is the input source for this connection.
@see AudioProcessorGraph::getNodeForId
*/
@@ -48766,8 +48769,7 @@ public:
@returns the value that the callback function returns.
@see MessageManagerLock
*/
void* callFunctionOnMessageThread (MessageCallbackFunction* callback,
void* userData);
void* callFunctionOnMessageThread (MessageCallbackFunction* callback, void* userData);

/** Returns true if the caller-thread is the message thread. */
bool isThisTheMessageThread() const noexcept;
@@ -48815,12 +48817,12 @@ public:
/** Deregisters a broadcast listener. */
void deregisterBroadcastListener (ActionListener* listener);

/** @internal */
#ifndef DOXYGEN
// Internal methods - do not use!
void deliverMessage (Message*);
/** @internal */
void deliverBroadcastMessage (const String&);
/** @internal */
~MessageManager() noexcept;
#endif

private:

@@ -48946,7 +48948,6 @@ public:
~MessageManagerLock() noexcept;

/** Returns true if the lock was successfully acquired.

(See the constructor that takes a Thread for more info).
*/
bool lockWasGained() const noexcept { return locked; }
@@ -56566,7 +56567,7 @@ protected:
/** @internal */
int getDesktopWindowStyleFlags() const;

#if JUCE_DEBUG
#if JUCE_DEBUG
/** Overridden to warn people about adding components directly to this component
instead of using setContentOwned().

@@ -56581,7 +56582,7 @@ protected:
a base-class method call to Component::addAndMakeVisible(), to side-step this warning.
*/
void addAndMakeVisible (Component* child, int zOrder = -1);
#endif
#endif

ScopedPointer <ResizableCornerComponent> resizableCorner;
ScopedPointer <ResizableBorderComponent> resizableBorder;
@@ -59438,6 +59439,7 @@ public:
and feel class how this is used. */
};

#ifndef DOXYGEN
/** @internal */
void paint (Graphics& g);
/** @internal */
@@ -59460,6 +59462,7 @@ public:
void parentHierarchyChanged();
/** @internal */
const Rectangle<int> getTitleBarArea();
#endif

private:

@@ -66942,8 +66945,9 @@ public:
void removeListener (Listener* listenerToRemove);

protected:
/** @internal */
#ifndef DOXYGEN
CameraDevice (const String& name, int index);
#endif

private:
void* internal;


+ 29
- 18
src/application/juce_Application.cpp View File

@@ -38,6 +38,22 @@ BEGIN_JUCE_NAMESPACE
extern void juce_initialiseMacMainMenu();
#endif
//==============================================================================
class AppBroadcastCallback : public ActionListener
{
public:
AppBroadcastCallback() { MessageManager::getInstance()->registerBroadcastListener (this); }
~AppBroadcastCallback() { MessageManager::getInstance()->deregisterBroadcastListener (this); }
void actionListenerCallback (const String& message)
{
JUCEApplication* const app = JUCEApplication::getInstance();
if (app != 0 && message.startsWith (app->getApplicationName() + "/"))
app->anotherInstanceStarted (message.substring (app->getApplicationName().length() + 1));
}
};
//==============================================================================
JUCEApplication::JUCEApplication()
: appReturnValue (0),
@@ -87,12 +103,6 @@ void JUCEApplication::setApplicationReturnValue (const int newReturnValue) noexc
appReturnValue = newReturnValue;
}
void JUCEApplication::actionListenerCallback (const String& message)
{
if (message.startsWith (getApplicationName() + "/"))
anotherInstanceStarted (message.substring (getApplicationName().length() + 1));
}
//==============================================================================
void JUCEApplication::unhandledException (const std::exception*,
const String&,
@@ -149,7 +159,7 @@ bool JUCEApplication::initialiseApp (const String& commandLine)
{
commandLineParameters = commandLine.trim();
#if ! JUCE_IOS
#if ! JUCE_IOS
jassert (appLock == nullptr); // initialiseApp must only be called once!
if (! moreThanOneInstanceAllowed())
@@ -165,17 +175,18 @@ bool JUCEApplication::initialiseApp (const String& commandLine)
return false;
}
}
#endif
#endif
// let the app do its setting-up..
initialise (commandLineParameters);
#if JUCE_MAC
#if JUCE_MAC
juce_initialiseMacMainMenu(); // needs to be called after the app object has created, to get its name
#endif
#endif
// register for broadcast new app messages
MessageManager::getInstance()->registerBroadcastListener (this);
#if ! JUCE_IOS
broadcastCallback = new AppBroadcastCallback();
#endif
stillInitialising = false;
return true;
@@ -185,7 +196,7 @@ int JUCEApplication::shutdownApp()
{
jassert (appInstance == this);
MessageManager::getInstance()->deregisterBroadcastListener (this);
broadcastCallback = nullptr;
JUCE_TRY
{
@@ -249,20 +260,20 @@ int JUCEApplication::main (int argc, const char* argv[])
{
JUCE_AUTORELEASEPOOL
#if ! JUCE_WINDOWS
#if ! JUCE_WINDOWS
jassert (createInstance != nullptr);
juce_Argv0 = argv[0];
#endif
#endif
#if JUCE_IOS
#if JUCE_IOS
return juce_iOSMain (argc, argv);
#else
#else
String cmd;
for (int i = 1; i < argc; ++i)
cmd << argv[i] << ' ';
return JUCEApplication::main (cmd);
#endif
#endif
}
#endif


+ 15
- 22
src/application/juce_Application.h View File

@@ -87,8 +87,7 @@
@see MessageManager, DeletedAtShutdown
*/
class JUCE_API JUCEApplication : public ApplicationCommandTarget,
private ActionListener
class JUCE_API JUCEApplication : public ApplicationCommandTarget
{
protected:
//==============================================================================
@@ -244,20 +243,11 @@ public:
*/
const String getCommandLineParameters() const noexcept { return commandLineParameters; }
//==============================================================================
// These are used by the START_JUCE_APPLICATION() macro and aren't for public use.
/** @internal */
static int main (const String& commandLine);
/** @internal */
static int main (int argc, const char* argv[]);
/** @internal */
static void sendUnhandledException (const std::exception* e, const char* sourceFile, int lineNumber);
/** Returns true if this executable is running as an app (as opposed to being a plugin
or other kind of shared library. */
static inline bool isStandaloneApp() noexcept { return createInstance != 0; }
static inline bool isStandaloneApp() noexcept { return createInstance != 0; }
//==============================================================================
/** @internal */
ApplicationCommandTarget* getNextCommandTarget();
/** @internal */
@@ -266,26 +256,29 @@ public:
void getAllCommands (Array <CommandID>& commands);
/** @internal */
bool perform (const InvocationInfo& info);
/** @internal */
void actionListenerCallback (const String& message);
/** @internal */
//==============================================================================
#ifndef DOXYGEN
// The following methods are internal calls - not for public use.
static int main (const String& commandLine);
static int main (int argc, const char* argv[]);
static void sendUnhandledException (const std::exception* e, const char* sourceFile, int lineNumber);
bool initialiseApp (const String& commandLine);
/** @internal */
int shutdownApp();
/** @internal */
static void appWillTerminateByForce();
/** @internal */
typedef JUCEApplication* (*CreateInstanceFunction)();
/** @internal */
static CreateInstanceFunction createInstance;
#endif
private:
//==============================================================================
static JUCEApplication* appInstance;
String commandLineParameters;
ScopedPointer<InterProcessLock> appLock;
ScopedPointer<ActionListener> broadcastCallback;
int appReturnValue;
bool stillInitialising;
ScopedPointer<InterProcessLock> appLock;
static JUCEApplication* appInstance;
JUCE_DECLARE_NON_COPYABLE (JUCEApplication);
};


+ 322
- 9
src/audio/audio_file_formats/juce_AiffAudioFormat.cpp View File

@@ -29,6 +29,7 @@ BEGIN_JUCE_NAMESPACE
#include "juce_AiffAudioFormat.h"
#include "../../io/streams/juce_BufferedInputStream.h"
#include "../../io/streams/juce_MemoryOutputStream.h"
#include "../../core/juce_PlatformUtilities.h"
#include "../../text/juce_LocalisedStrings.h"
@@ -37,6 +38,215 @@ BEGIN_JUCE_NAMESPACE
static const char* const aiffFormatName = "AIFF file";
static const char* const aiffExtensions[] = { ".aiff", ".aif", 0 };
//==============================================================================
namespace AiffFileHelpers
{
inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); }
#if JUCE_MSVC
#pragma pack (push, 1)
#define PACKED
#elif JUCE_GCC
#define PACKED __attribute__((packed))
#else
#define PACKED
#endif
//==============================================================================
struct InstChunk
{
struct Loop
{
uint16 type; // these are different in AIFF and WAV
uint16 startIdentifier;
uint16 endIdentifier;
} PACKED;
int8 baseNote;
int8 detune;
int8 lowNote;
int8 highNote;
int8 lowVelocity;
int8 highVelocity;
int16 gain;
Loop sustainLoop;
Loop releaseLoop;
void copyTo (StringPairArray& values) const
{
values.set ("MidiUnityNote", String (baseNote));
values.set ("Detune", String (detune));
values.set ("LowNote", String (lowNote));
values.set ("HighNote", String (highNote));
values.set ("LowVelocity", String (lowVelocity));
values.set ("HighVelocity", String (highVelocity));
values.set ("Gain", String ((int16) ByteOrder::swapIfLittleEndian ((uint16) gain)));
values.set ("NumSampleLoops", String (2)); // always 2 with AIFF, WAV can have more
values.set ("Loop0Type", String (ByteOrder::swapIfLittleEndian (sustainLoop.type)));
values.set ("Loop0StartIdentifier", String (ByteOrder::swapIfLittleEndian (sustainLoop.startIdentifier)));
values.set ("Loop0EndIdentifier", String (ByteOrder::swapIfLittleEndian (sustainLoop.endIdentifier)));
values.set ("Loop1Type", String (ByteOrder::swapIfLittleEndian (releaseLoop.type)));
values.set ("Loop1StartIdentifier", String (ByteOrder::swapIfLittleEndian (releaseLoop.startIdentifier)));
values.set ("Loop1EndIdentifier", String (ByteOrder::swapIfLittleEndian (releaseLoop.endIdentifier)));
}
static void create (MemoryBlock& block, const StringPairArray& values)
{
if (values.getAllKeys().contains ("MidiUnityNote", true))
{
block.setSize ((sizeof (InstChunk) + 3) & ~3, true);
InstChunk* const inst = static_cast <InstChunk*> (block.getData());
inst->baseNote = (int8) values.getValue ("MidiUnityNote", "60").getIntValue();
inst->detune = (int8) values.getValue ("Detune", "0").getIntValue();
inst->lowNote = (int8) values.getValue ("LowNote", "0").getIntValue();
inst->highNote = (int8) values.getValue ("HighNote", "127").getIntValue();
inst->lowVelocity = (int8) values.getValue ("LowVelocity", "1").getIntValue();
inst->highVelocity = (int8) values.getValue ("HighVelocity", "127").getIntValue();
inst->gain = (int16) ByteOrder::swapIfLittleEndian ((uint16) values.getValue ("Gain", "0").getIntValue());
inst->sustainLoop.type = ByteOrder::swapIfLittleEndian ((uint16) values.getValue ("Loop0Type", "0").getIntValue());
inst->sustainLoop.startIdentifier = ByteOrder::swapIfLittleEndian ((uint16) values.getValue ("Loop0StartIdentifier", "0").getIntValue());
inst->sustainLoop.endIdentifier = ByteOrder::swapIfLittleEndian ((uint16) values.getValue ("Loop0EndIdentifier", "0").getIntValue());
inst->releaseLoop.type = ByteOrder::swapIfLittleEndian ((uint16) values.getValue ("Loop1Type", "0").getIntValue());
inst->releaseLoop.startIdentifier = ByteOrder::swapIfLittleEndian ((uint16) values.getValue ("Loop1StartIdentifier", "0").getIntValue());
inst->releaseLoop.endIdentifier = ByteOrder::swapIfLittleEndian ((uint16) values.getValue ("Loop1EndIdentifier", "0").getIntValue());
}
}
} PACKED;
#if JUCE_MSVC
#pragma pack (pop)
#endif
#undef PACKED
//==============================================================================
namespace MarkChunk
{
bool metaDataContainsZeroIdentifiers (const StringPairArray& values)
{
// (zero cue identifiers are valid for WAV but not for AIFF)
const String cueString ("Cue");
const String noteString ("CueNote");
const String identifierString ("Identifier");
const StringArray& keys = values.getAllKeys();
for (int i = 0; i < keys.size(); ++i)
{
const String key (keys[i]);
if (key.startsWith (noteString))
continue; // zero identifier IS valid in a COMT chunk
if (key.startsWith (cueString) && key.contains (identifierString))
{
const int value = values.getValue (key, "-1").getIntValue();
if (value == 0)
return true;
}
}
return false;
}
void create (MemoryBlock& block, const StringPairArray& values)
{
const int numCues = values.getValue ("NumCuePoints", "0").getIntValue();
if (numCues > 0)
{
MemoryOutputStream out (block, false);
out.writeShortBigEndian ((short) numCues);
const int numCueLabels = values.getValue ("NumCueLabels", "0").getIntValue();
const int idOffset = metaDataContainsZeroIdentifiers (values) ? 1 : 0; // can't have zero IDs in AIFF
#if JUCE_DEBUG
Array<int> identifiers;
#endif
for (int i = 0; i < numCues; ++i)
{
const String prefixCue ("Cue" + String (i));
const String prefixLabel ("CueLabel" + String (i));
const int identifier = idOffset + values.getValue (prefixCue + "Identifier", "1").getIntValue();
#if JUCE_DEBUG
jassert (! identifiers.contains (identifier));
identifiers.add (identifier);
#endif
const int offset = values.getValue (prefixCue + "Offset", "0").getIntValue();
String label (prefixLabel);
for (int labelIndex = 0; labelIndex < numCueLabels; ++labelIndex)
{
const String prefixLabel ("CueLabel" + String (labelIndex));
const int labelIdentifier = idOffset + values.getValue (prefixLabel + "Identifier", "1").getIntValue();
if (labelIdentifier == identifier)
{
label = values.getValue (prefixLabel + "Text", label);
break;
}
}
out.writeShortBigEndian ((short) identifier);
out.writeIntBigEndian (offset);
const int labelLength = jmin (254, label.getNumBytesAsUTF8()); // seems to need null terminator even though it's a pstring
out.writeByte ((char) labelLength + 1);
out.write (label.toUTF8(), labelLength);
out.writeByte (0);
}
if ((out.getDataSize() & 1) != 0)
out.writeByte (0);
}
}
}
//==============================================================================
namespace COMTChunk
{
void create (MemoryBlock& block, const StringPairArray& values)
{
const int numNotes = values.getValue ("NumCueNotes", "0").getIntValue();
if (numNotes > 0)
{
MemoryOutputStream out (block, false);
out.writeShortBigEndian ((short) numNotes);
for (int i = 0; i < numNotes; ++i)
{
const String prefix ("CueNote" + String (i));
out.writeIntBigEndian (values.getValue (prefix + "TimeStamp", "0").getIntValue());
out.writeShortBigEndian ((short) values.getValue (prefix + "Identifier", "0").getIntValue());
const String comment (values.getValue (prefix + "Text", String::empty));
out.write (comment.toUTF8(), jmin (comment.getNumBytesAsUTF8(), 65534));
out.writeByte (0);
if ((out.getDataSize() & 1) != 0)
out.writeByte (0);
}
}
}
}
}
//==============================================================================
class AiffAudioFormatReader : public AudioFormatReader
@@ -50,6 +260,8 @@ public:
AiffAudioFormatReader (InputStream* in)
: AudioFormatReader (in, TRANS (aiffFormatName))
{
using namespace AiffFileHelpers;
if (input->readInt() == chunkName ("FORM"))
{
const int len = input->readIntBigEndian();
@@ -131,6 +343,67 @@ public:
dataChunkStart = input->getPosition() + 4 + offset;
lengthInSamples = (bytesPerFrame > 0) ? jmin (lengthInSamples, (int64) (length / bytesPerFrame)) : 0;
}
else if (type == chunkName ("MARK"))
{
const uint16 numCues = (uint16) input->readShortBigEndian();
// these two are always the same for AIFF-read files
metadataValues.set ("NumCuePoints", String (numCues));
metadataValues.set ("NumCueLabels", String (numCues));
for (uint16 i = 0; i < numCues; ++i)
{
uint16 identifier = (uint16) input->readShortBigEndian();
uint32 offset = (uint32) input->readIntBigEndian();
uint8 stringLength = (uint8) input->readByte();
MemoryBlock textBlock;
input->readIntoMemoryBlock (textBlock, stringLength);
// if the stringLength is even then read one more byte as the
// string needs to be an even number of bytes INCLUDING the
// leading length character in the pascal string
if ((stringLength & 1) == 0)
input->readByte();
const String text = String::fromUTF8 ((const char*)textBlock.getData(), stringLength);
const String prefixCue ("Cue" + String (i));
metadataValues.set (prefixCue + "Identifier", String (identifier));
metadataValues.set (prefixCue + "Offset", String (offset));
const String prefixLabel ("CueLabel" + String (i));
metadataValues.set (prefixLabel + "Identifier", String (identifier));
metadataValues.set (prefixLabel + "Text", text);
}
}
else if (type == chunkName ("COMT"))
{
const uint16 numNotes = (uint16) input->readShortBigEndian();
metadataValues.set ("NumCueNotes", String (numNotes));
for (uint16 i = 0; i < numNotes; ++i)
{
uint32 timestamp = (uint32) input->readIntBigEndian();
uint16 identifier = (uint16) input->readShortBigEndian(); // may be zero in this case
uint16 stringLength = (uint16) input->readShortBigEndian();
MemoryBlock textBlock;
input->readIntoMemoryBlock (textBlock, stringLength + (stringLength & 1));
const String text = String::fromUTF8 ((const char*)textBlock.getData(), stringLength);
const String prefix ("CueNote" + String (i));
metadataValues.set (prefix + "TimeStamp", String (timestamp));
metadataValues.set (prefix + "Identifier", String (identifier));
metadataValues.set (prefix + "Text", text);
}
}
else if (type == chunkName ("INST"))
{
HeapBlock <InstChunk> inst;
inst.calloc (jmax ((size_t) length + 1, sizeof (InstChunk)), 1);
input->read (inst, length);
inst->copyTo (metadataValues);
}
else if ((hasGotVer && hasGotData && hasGotType)
|| chunkEnd < input->getPosition()
|| input->isExhausted())
@@ -142,6 +415,9 @@ public:
}
}
}
if (metadataValues.size() > 0)
metadataValues.set ("MetaDataSource", "AIFF");
}
//==============================================================================
@@ -211,8 +487,6 @@ public:
}
private:
static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); }
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AiffAudioFormatReader);
};
@@ -221,12 +495,28 @@ class AiffAudioFormatWriter : public AudioFormatWriter
{
public:
//==============================================================================
AiffAudioFormatWriter (OutputStream* out, double sampleRate_, unsigned int numChans, int bits)
AiffAudioFormatWriter (OutputStream* out, double sampleRate_,
unsigned int numChans, int bits,
const StringPairArray& metadataValues)
: AudioFormatWriter (out, TRANS (aiffFormatName), sampleRate_, numChans, bits),
lengthInSamples (0),
bytesWritten (0),
writeFailed (false)
{
using namespace AiffFileHelpers;
if (metadataValues.size() > 0)
{
// The meta data should have been santised for the AIFF format.
// If it was originally sourced from a WAV file the MetaDataSource
// key should be removed (or set to "AIFF") once this has been done
jassert (metadataValues.getValue ("MetaDataSource", "None") != "WAV");
MarkChunk::create (markChunk, metadataValues);
COMTChunk::create (comtChunk, metadataValues);
InstChunk::create (instChunk, metadataValues);
}
headerPosition = out->getPosition();
writeHeader();
}
@@ -279,15 +569,15 @@ public:
}
private:
MemoryBlock tempBlock;
MemoryBlock tempBlock, markChunk, comtChunk, instChunk;
uint32 lengthInSamples, bytesWritten;
int64 headerPosition;
bool writeFailed;
static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); }
void writeHeader()
{
using namespace AiffFileHelpers;
const bool couldSeekOk = output->setPosition (headerPosition);
(void) couldSeekOk;
@@ -295,7 +585,9 @@ private:
// to be able to seek back to write the header
jassert (couldSeekOk);
const int headerLen = 54;
const int headerLen = 54 + (markChunk.getSize() > 0 ? markChunk.getSize() + 8 : 0)
+ (comtChunk.getSize() > 0 ? comtChunk.getSize() + 8 : 0)
+ (instChunk.getSize() > 0 ? instChunk.getSize() + 8 : 0);
int audioBytes = lengthInSamples * ((bitsPerSample * numChannels) / 8);
audioBytes += (audioBytes & 1);
@@ -351,6 +643,27 @@ private:
output->write (sampleRateBytes, 10);
if (markChunk.getSize() > 0)
{
output->writeInt (chunkName ("MARK"));
output->writeIntBigEndian ((int) markChunk.getSize());
output->write (markChunk.getData(), (int) markChunk.getSize());
}
if (comtChunk.getSize() > 0)
{
output->writeInt (chunkName ("COMT"));
output->writeIntBigEndian ((int) comtChunk.getSize());
output->write (comtChunk.getData(), (int) comtChunk.getSize());
}
if (instChunk.getSize() > 0)
{
output->writeInt (chunkName ("INST"));
output->writeIntBigEndian ((int) instChunk.getSize());
output->write (instChunk.getData(), (int) instChunk.getSize());
}
output->writeInt (chunkName ("SSND"));
output->writeIntBigEndian (audioBytes + 8);
output->writeInt (0);
@@ -416,11 +729,11 @@ AudioFormatWriter* AiffAudioFormat::createWriterFor (OutputStream* out,
double sampleRate,
unsigned int numberOfChannels,
int bitsPerSample,
const StringPairArray& /*metadataValues*/,
const StringPairArray& metadataValues,
int /*qualityOptionIndex*/)
{
if (getPossibleBitDepths().contains (bitsPerSample))
return new AiffAudioFormatWriter (out, sampleRate, numberOfChannels, bitsPerSample);
return new AiffAudioFormatWriter (out, sampleRate, numberOfChannels, bitsPerSample, metadataValues);
return nullptr;
}


+ 3
- 2
src/audio/audio_file_formats/juce_AiffAudioFormat.h View File

@@ -50,9 +50,10 @@ public:
const Array <int> getPossibleBitDepths();
bool canDoStereo();
bool canDoMono();
#if JUCE_MAC
#if JUCE_MAC
bool canHandleFile (const File& fileToTest);
#endif
#endif
//==============================================================================
AudioFormatReader* createReaderFor (InputStream* sourceStream,


+ 22
- 4
src/audio/audio_file_formats/juce_AudioThumbnail.cpp View File

@@ -38,7 +38,7 @@ struct AudioThumbnail::MinMaxValue
char minValue;
char maxValue;
MinMaxValue() : minValue (0), maxValue (0)
MinMaxValue() noexcept : minValue (0), maxValue (0)
{
}
@@ -281,7 +281,7 @@ public:
return data.size();
}
void getMinMax (int startSample, int endSample, MinMaxValue& result) noexcept
void getMinMax (int startSample, int endSample, MinMaxValue& result) const noexcept
{
if (startSample >= 0)
{
@@ -323,12 +323,12 @@ public:
dest[i] = source[i];
}
void resetPeak()
void resetPeak() noexcept
{
peakLevel = -1;
}
int getPeak()
int getPeak() noexcept
{
if (peakLevel < 0)
{
@@ -743,6 +743,24 @@ float AudioThumbnail::getApproximatePeak() const
return jlimit (0, 127, peak) / 127.0f;
}
void AudioThumbnail::getApproximateMinMax (const double startTime, const double endTime, const int channelIndex,
float& minValue, float& maxValue) const noexcept
{
MinMaxValue result;
const ThumbData* const data = channels [channelIndex];
if (data != nullptr && sampleRate > 0)
{
const int firstThumbIndex = (int) ((startTime * sampleRate) / samplesPerThumbSample);
const int lastThumbIndex = (int) (((endTime * sampleRate) + samplesPerThumbSample - 1) / samplesPerThumbSample);
data->getMinMax (jmax (0, firstThumbIndex), lastThumbIndex, result);
}
minValue = result.minValue / 128.0f;
maxValue = result.maxValue / 128.0f;
}
void AudioThumbnail::drawChannel (Graphics& g, const Rectangle<int>& area, double startTime,
double endTime, int channelNum, float verticalZoomFactor)
{


+ 9
- 2
src/audio/audio_file_formats/juce_AudioThumbnail.h View File

@@ -186,12 +186,19 @@ public:
*/
float getApproximatePeak() const;
/** Reads the approximate min and max levels from a section of the thumbnail.
The lowest and highest samples are returned in minValue and maxValue, but obviously
because the thumb only stores low-resolution data, these numbers will only be a rough
approximation of the true values.
*/
void getApproximateMinMax (double startTime, double endTime, int channelIndex,
float& minValue, float& maxValue) const noexcept;
/** Returns the hash code that was set by setSource() or setReader(). */
int64 getHashCode() const;
#ifndef DOXYGEN
// (this is only public to avoid a VC6 bug)
class LevelDataSource;
class LevelDataSource; // (this is only public to avoid a VC6 bug)
#endif
private:


+ 247
- 25
src/audio/audio_file_formats/juce_WavAudioFormat.cpp View File

@@ -29,6 +29,7 @@ BEGIN_JUCE_NAMESPACE
#include "juce_WavAudioFormat.h"
#include "../../io/streams/juce_BufferedInputStream.h"
#include "../../io/streams/juce_MemoryOutputStream.h"
#include "../../text/juce_LocalisedStrings.h"
#include "../../io/files/juce_FileInputStream.h"
#include "../../io/files/juce_TemporaryFile.h"
@@ -156,7 +157,7 @@ struct SMPLChunk
struct SampleLoop
{
uint32 identifier;
uint32 type;
uint32 type; // these are different in AIFF and WAV
uint32 start;
uint32 end;
uint32 fraction;
@@ -214,8 +215,6 @@ struct SMPLChunk
SMPLChunk* const s = static_cast <SMPLChunk*> (data.getData());
// Allow these calls to overwrite an extra byte at the end, which is fine as long
// as they get called in the right order..
s->manufacturer = ByteOrder::swapIfBigEndian ((uint32) values.getValue ("Manufacturer", "0").getIntValue());
s->product = ByteOrder::swapIfBigEndian ((uint32) values.getValue ("Product", "0").getIntValue());
s->samplePeriod = ByteOrder::swapIfBigEndian ((uint32) values.getValue ("SamplePeriod", "0").getIntValue());
@@ -241,6 +240,52 @@ struct SMPLChunk
}
} PACKED;
//==============================================================================
struct InstChunk
{
int8 baseNote;
int8 detune;
int8 gain;
int8 lowNote;
int8 highNote;
int8 lowVelocity;
int8 highVelocity;
void copyTo (StringPairArray& values) const
{
values.set ("MidiUnityNote", String (baseNote));
values.set ("Detune", String (detune));
values.set ("Gain", String (gain));
values.set ("LowNote", String (lowNote));
values.set ("HighNote", String (highNote));
values.set ("LowVelocity", String (lowVelocity));
values.set ("HighVelocity", String (highVelocity));
}
static MemoryBlock createFrom (const StringPairArray& values)
{
const StringArray& keys = values.getAllKeys();
if (! (keys.contains ("LowNote", true) && keys.contains ("HighNote", true)))
return MemoryBlock();
MemoryBlock data (8);
data.fillWith (0);
InstChunk* const inst = static_cast <InstChunk*> (data.getData());
inst->baseNote = (int8) values.getValue ("MidiUnityNote", "60").getIntValue();
inst->detune = (int8) values.getValue ("Detune", "0").getIntValue();
inst->gain = (int8) values.getValue ("Gain", "0").getIntValue();
inst->lowNote = (int8) values.getValue ("LowNote", "0").getIntValue();
inst->highNote = (int8) values.getValue ("HighNote", "127").getIntValue();
inst->lowVelocity = (int8) values.getValue ("LowVelocity", "1").getIntValue();
inst->highVelocity = (int8) values.getValue ("HighVelocity", "127").getIntValue();
return data;
}
} PACKED;
//==============================================================================
struct CueChunk
{
@@ -276,39 +321,118 @@ struct CueChunk
}
}
static MemoryBlock createFrom (const StringPairArray& values)
static void create (MemoryBlock& data, const StringPairArray& values)
{
const int numCues = values.getValue ("NumCuePoints", "0").getIntValue();
if (numCues <= 0)
return MemoryBlock();
if (numCues > 0)
{
const size_t sizeNeeded = sizeof (CueChunk) + (numCues - 1) * sizeof (Cue);
data.setSize ((sizeNeeded + 3) & ~3, true);
const size_t sizeNeeded = sizeof (CueChunk) + (numCues - 1) * sizeof (Cue);
MemoryBlock data ((sizeNeeded + 3) & ~3);
data.fillWith (0);
CueChunk* const c = static_cast <CueChunk*> (data.getData());
CueChunk* const c = static_cast <CueChunk*> (data.getData());
c->numCues = ByteOrder::swapIfBigEndian ((uint32) numCues);
c->numCues = ByteOrder::swapIfBigEndian ((uint32) numCues);
const String dataChunkID (chunkName ("data"));
const String dataChunkID (chunkName ("data"));
int nextOrder = 0;
for (int i = 0; i < numCues; ++i)
{
const String prefix ("Cue" + String(i));
c->cues[i].identifier = ByteOrder::swapIfBigEndian ((uint32) values.getValue (prefix + "Identifier", "0").getIntValue());
c->cues[i].order = ByteOrder::swapIfBigEndian ((uint32) values.getValue (prefix + "Order", "0").getIntValue());
c->cues[i].chunkID = ByteOrder::swapIfBigEndian ((uint32) values.getValue (prefix + "ChunkID", dataChunkID).getIntValue());
c->cues[i].chunkStart = ByteOrder::swapIfBigEndian ((uint32) values.getValue (prefix + "ChunkStart", "0").getIntValue());
c->cues[i].blockStart = ByteOrder::swapIfBigEndian ((uint32) values.getValue (prefix + "BlockStart", "0").getIntValue());
c->cues[i].offset = ByteOrder::swapIfBigEndian ((uint32) values.getValue (prefix + "Offset", "0").getIntValue());
}
#if JUCE_DEBUG
Array<int> identifiers;
#endif
return data;
for (int i = 0; i < numCues; ++i)
{
const String prefix ("Cue" + String (i));
uint32 identifier = values.getValue (prefix + "Identifier", "0").getIntValue();
#if JUCE_DEBUG
jassert (! identifiers.contains (identifier));
identifiers.add (identifier);
#endif
c->cues[i].identifier = ByteOrder::swapIfBigEndian ((uint32) identifier);
const int order = values.getValue (prefix + "Order", String (nextOrder)).getIntValue();
nextOrder = jmax (nextOrder, order) + 1;
c->cues[i].order = ByteOrder::swapIfBigEndian ((uint32) order);
c->cues[i].chunkID = ByteOrder::swapIfBigEndian ((uint32) values.getValue (prefix + "ChunkID", dataChunkID).getIntValue());
c->cues[i].chunkStart = ByteOrder::swapIfBigEndian ((uint32) values.getValue (prefix + "ChunkStart", "0").getIntValue());
c->cues[i].blockStart = ByteOrder::swapIfBigEndian ((uint32) values.getValue (prefix + "BlockStart", "0").getIntValue());
c->cues[i].offset = ByteOrder::swapIfBigEndian ((uint32) values.getValue (prefix + "Offset", "0").getIntValue());
}
}
}
} PACKED;
//==============================================================================
namespace ListChunk
{
void appendLabelOrNoteChunk (const StringPairArray& values, const String& prefix,
const int chunkType, MemoryOutputStream& out)
{
const String label (values.getValue (prefix + "Text", prefix));
const int labelLength = label.getNumBytesAsUTF8() + 1;
const int chunkLength = 4 + labelLength + (labelLength & 1);
out.writeInt (chunkType);
out.writeInt (chunkLength);
out.writeInt (values.getValue (prefix + "Identifier", "0").getIntValue());
out.write (label.toUTF8(), labelLength);
if ((out.getDataSize() & 1) != 0)
out.writeByte (0);
}
void appendExtraChunk (const StringPairArray& values, const String& prefix, MemoryOutputStream& out)
{
const String text (values.getValue (prefix + "Text", prefix));
const int textLength = text.getNumBytesAsUTF8() + 1; // include null terminator
uint32 chunkLength = textLength + 20 + (textLength & 1);
out.writeInt (chunkName ("ltxt"));
out.writeInt (chunkLength);
out.writeInt (values.getValue (prefix + "Identifier", "0").getIntValue());
out.writeInt (values.getValue (prefix + "SampleLength", "0").getIntValue());
out.writeInt (values.getValue (prefix + "Purpose", "0").getIntValue());
out.writeShort ((short) values.getValue (prefix + "Country", "0").getIntValue());
out.writeShort ((short) values.getValue (prefix + "Language", "0").getIntValue());
out.writeShort ((short) values.getValue (prefix + "Dialect", "0").getIntValue());
out.writeShort ((short) values.getValue (prefix + "CodePage", "0").getIntValue());
out.write (text.toUTF8(), textLength);
if ((out.getDataSize() & 1) != 0)
out.writeByte (0);
}
void create (MemoryBlock& block, const StringPairArray& values)
{
const int numCueLabels = values.getValue ("NumCueLabels", "0").getIntValue();
const int numCueNotes = values.getValue ("NumCueNotes", "0").getIntValue();
const int numCueRegions = values.getValue ("NumCueRegions", "0").getIntValue();
if (numCueLabels > 0 || numCueNotes > 0 || numCueRegions > 0)
{
MemoryOutputStream out (block, false);
int i;
for (i = 0; i < numCueLabels; ++i)
appendLabelOrNoteChunk (values, "CueLabel" + String (i), chunkName ("labl"), out);
for (i = 0; i < numCueNotes; ++i)
appendLabelOrNoteChunk (values, "CueNote" + String (i), chunkName ("note"), out);
for (i = 0; i < numCueRegions; ++i)
appendExtraChunk (values, "CueRegion" + String (i), out);
}
}
}
//==============================================================================
struct ExtensibleWavSubFormat
{
@@ -355,6 +479,9 @@ public:
int64 end = 0;
bool hasGotType = false;
bool hasGotData = false;
int cueNoteIndex = 0;
int cueLabelIndex = 0;
int cueRegionIndex = 0;
const int firstChunkType = input->readInt();
@@ -479,6 +606,13 @@ public:
input->read (smpl, length);
smpl->copyTo (metadataValues, length);
}
else if (chunkType == chunkName ("inst") || chunkType == chunkName ("INST")) // need to check which...
{
HeapBlock <InstChunk> inst;
inst.calloc (jmax ((size_t) length + 1, sizeof (InstChunk)), 1);
input->read (inst, length);
inst->copyTo (metadataValues);
}
else if (chunkType == chunkName ("cue "))
{
HeapBlock <CueChunk> cue;
@@ -486,6 +620,65 @@ public:
input->read (cue, length);
cue->copyTo (metadataValues, length);
}
else if (chunkType == chunkName ("LIST"))
{
if (input->readInt() == chunkName ("adtl"))
{
while (input->getPosition() < chunkEnd)
{
const int adtlChunkType = input->readInt();
const uint32 adtlLength = (uint32) input->readInt();
const int64 adtlChunkEnd = input->getPosition() + (adtlLength + (adtlLength & 1));
if (adtlChunkType == chunkName ("labl") || adtlChunkType == chunkName ("note"))
{
String prefix;
if (adtlChunkType == chunkName ("labl"))
prefix << "CueLabel" << cueLabelIndex++;
else if (adtlChunkType == chunkName ("note"))
prefix << "CueNote" << cueNoteIndex++;
const uint32 identifier = (uint32) input->readInt();
const uint32 stringLength = adtlLength - 4;
MemoryBlock textBlock;
input->readIntoMemoryBlock (textBlock, stringLength);
const String text (String::fromUTF8 (static_cast <const char*> (textBlock.getData()), textBlock.getSize()));
metadataValues.set (prefix + "Identifier", String (identifier));
metadataValues.set (prefix + "Text", text);
}
else if (adtlChunkType == chunkName ("ltxt"))
{
const String prefix ("CueRegion" + String (cueRegionIndex++));
const uint32 identifier = (uint32) input->readInt();
const uint32 sampleLength = (uint32) input->readInt();
const uint32 purpose = (uint32) input->readInt();
const uint16 country = (uint16) input->readInt();
const uint16 language = (uint16) input->readInt();
const uint16 dialect = (uint16) input->readInt();
const uint16 codePage = (uint16) input->readInt();
const uint32 stringLength = adtlLength - 20;
MemoryBlock textBlock;
input->readIntoMemoryBlock (textBlock, stringLength);
const String text = String::fromUTF8 ((const char*)textBlock.getData(), textBlock.getSize());
metadataValues.set (prefix + "Identifier", String (identifier));
metadataValues.set (prefix + "SampleLength", String (sampleLength));
metadataValues.set (prefix + "Purpose", String (purpose));
metadataValues.set (prefix + "Country", String (country));
metadataValues.set (prefix + "Language", String (language));
metadataValues.set (prefix + "Dialect", String (dialect));
metadataValues.set (prefix + "CodePage", String (codePage));
metadataValues.set (prefix + "Text", text);
}
input->setPosition (adtlChunkEnd);
}
}
}
else if (chunkEnd <= input->getPosition())
{
break;
@@ -494,6 +687,11 @@ public:
input->setPosition (chunkEnd);
}
}
if (cueLabelIndex > 0) metadataValues.set ("NumCueLabels", String (cueLabelIndex));
if (cueNoteIndex > 0) metadataValues.set ("NumCueNotes", String (cueNoteIndex));
if (cueRegionIndex > 0) metadataValues.set ("NumCueRegions", String (cueRegionIndex));
if (metadataValues.size() > 0) metadataValues.set ("MetaDataSource", "WAV");
}
//==============================================================================
@@ -576,9 +774,16 @@ public:
if (metadataValues.size() > 0)
{
// The meta data should have been santised for the WAV format.
// If it was originally sourced from an AIFF file the MetaDataSource
// key should be removed (or set to "WAV") once this has been done
jassert (metadataValues.getValue ("MetaDataSource", "None") != "AIFF");
bwavChunk = BWAVChunk::createFrom (metadataValues);
smplChunk = SMPLChunk::createFrom (metadataValues);
cueChunk = CueChunk ::createFrom (metadataValues);
instChunk = InstChunk::createFrom (metadataValues);
CueChunk ::create (cueChunk, metadataValues);
ListChunk::create (listChunk, metadataValues);
}
headerPosition = out->getPosition();
@@ -636,7 +841,7 @@ public:
private:
ScopedPointer<AudioData::Converter> converter;
MemoryBlock tempBlock, bwavChunk, smplChunk, cueChunk;
MemoryBlock tempBlock, bwavChunk, smplChunk, instChunk, cueChunk, listChunk;
uint64 lengthInSamples, bytesWritten;
int64 headerPosition;
bool writeFailed;
@@ -675,7 +880,9 @@ private:
+ 8 + audioDataSize + (audioDataSize & 1)
+ (bwavChunk.getSize() > 0 ? (8 + bwavChunk.getSize()) : 0)
+ (smplChunk.getSize() > 0 ? (8 + smplChunk.getSize()) : 0)
+ (instChunk.getSize() > 0 ? (8 + instChunk.getSize()) : 0)
+ (cueChunk .getSize() > 0 ? (8 + cueChunk .getSize()) : 0)
+ (listChunk.getSize() > 0 ? (12 + listChunk.getSize()) : 0)
+ (8 + 28); // (ds64 chunk)
riffChunkSize += (riffChunkSize & 0x1);
@@ -754,6 +961,13 @@ private:
output->write (smplChunk.getData(), (int) smplChunk.getSize());
}
if (instChunk.getSize() > 0)
{
output->writeInt (chunkName ("inst"));
output->writeInt (7);
output->write (instChunk.getData(), (int) instChunk.getSize());
}
if (cueChunk.getSize() > 0)
{
output->writeInt (chunkName ("cue "));
@@ -761,6 +975,14 @@ private:
output->write (cueChunk.getData(), (int) cueChunk.getSize());
}
if (listChunk.getSize() > 0)
{
output->writeInt (chunkName ("LIST"));
output->writeInt ((int) listChunk.getSize() + 4);
output->writeInt (chunkName ("adtl"));
output->write (listChunk.getData(), (int) listChunk.getSize());
}
output->writeInt (chunkName ("data"));
output->writeInt (isRF64 ? -1 : (int) (lengthInSamples * bytesPerFrame));


+ 3
- 0
src/audio/plugin_client/juce_PluginHeaders.h View File

@@ -24,6 +24,9 @@
*/
#include "juce_IncludeCharacteristics.h"
#define DONT_AUTOLINK_TO_JUCE_LIBRARY 1
#include "../../../juce.h"
#ifndef __JUCE_PLUGINHEADERS_JUCEHEADER__


+ 875
- 774
src/audio/processors/juce_AudioProcessorGraph.cpp
File diff suppressed because it is too large
View File


+ 6
- 3
src/audio/processors/juce_AudioProcessorGraph.h View File

@@ -71,10 +71,9 @@ public:
public:
//==============================================================================
/** The ID number assigned to this node.
This is assigned by the graph that owns it, and can't be changed.
*/
const uint32 id;
const uint32 nodeId;
/** The actual processor object that this node represents. */
AudioProcessor* getProcessor() const noexcept { return processor; }
@@ -99,7 +98,7 @@ public:
const ScopedPointer<AudioProcessor> processor;
bool isPrepared;
Node (uint32 id, AudioProcessor* processor);
Node (uint32 nodeId, AudioProcessor* processor) noexcept;
void prepare (double sampleRate, int blockSize, AudioProcessorGraph* graph);
void unprepare();
@@ -115,6 +114,10 @@ public:
struct JUCE_API Connection
{
public:
//==============================================================================
Connection (uint32 sourceNodeId, int sourceChannelIndex,
uint32 destNodeId, int destChannelIndex) noexcept;
//==============================================================================
/** The ID number of the node which is the input source for this connection.
@see AudioProcessorGraph::getNodeForId


+ 1
- 2
src/events/juce_MessageManager.cpp View File

@@ -42,10 +42,9 @@ static const int quitMessageId = 0xfffff321;
MessageManager::MessageManager() noexcept
: quitMessagePosted (false),
quitMessageReceived (false),
messageThreadId (Thread::getCurrentThreadId()),
threadWithLock (0)
{
messageThreadId = Thread::getCurrentThreadId();
if (JUCEApplication::isStandaloneApp())
Thread::setCurrentThreadName ("Juce Message Thread");
}


+ 4
- 7
src/events/juce_MessageManager.h View File

@@ -106,8 +106,7 @@ public:
@returns the value that the callback function returns.
@see MessageManagerLock
*/
void* callFunctionOnMessageThread (MessageCallbackFunction* callback,
void* userData);
void* callFunctionOnMessageThread (MessageCallbackFunction* callback, void* userData);
/** Returns true if the caller-thread is the message thread. */
bool isThisTheMessageThread() const noexcept;
@@ -157,12 +156,12 @@ public:
void deregisterBroadcastListener (ActionListener* listener);
//==============================================================================
/** @internal */
#ifndef DOXYGEN
// Internal methods - do not use!
void deliverMessage (Message*);
/** @internal */
void deliverBroadcastMessage (const String&);
/** @internal */
~MessageManager() noexcept;
#endif
private:
//==============================================================================
@@ -294,12 +293,10 @@ public:
//==============================================================================
/** Returns true if the lock was successfully acquired.
(See the constructor that takes a Thread for more info).
*/
bool lockWasGained() const noexcept { return locked; }
private:
class BlockingMessage;
friend class ReferenceCountedObjectPtr<BlockingMessage>;


+ 2
- 0
src/gui/components/windows/juce_DocumentWindow.h View File

@@ -229,6 +229,7 @@ public:
};
//==============================================================================
#ifndef DOXYGEN
/** @internal */
void paint (Graphics& g);
/** @internal */
@@ -251,6 +252,7 @@ public:
void parentHierarchyChanged();
/** @internal */
const Rectangle<int> getTitleBarArea();
#endif
private:
//==============================================================================


+ 2
- 2
src/gui/components/windows/juce_ResizableWindow.h View File

@@ -340,7 +340,7 @@ protected:
/** @internal */
int getDesktopWindowStyleFlags() const;
#if JUCE_DEBUG
#if JUCE_DEBUG
/** Overridden to warn people about adding components directly to this component
instead of using setContentOwned().
@@ -355,7 +355,7 @@ protected:
a base-class method call to Component::addAndMakeVisible(), to side-step this warning.
*/
void addAndMakeVisible (Component* child, int zOrder = -1);
#endif
#endif
ScopedPointer <ResizableCornerComponent> resizableCorner;
ScopedPointer <ResizableBorderComponent> resizableBorder;


+ 2
- 1
src/gui/graphics/imaging/juce_CameraDevice.h View File

@@ -140,8 +140,9 @@ public:
protected:
/** @internal */
#ifndef DOXYGEN
CameraDevice (const String& name, int index);
#endif
private:
void* internal;


+ 2
- 1
src/threads/juce_TimeSliceThread.h View File

@@ -123,8 +123,9 @@ public:
TimeSliceClient* getClient (int index) const;
//==============================================================================
/** @internal */
#ifndef DOXYGEN
void run();
#endif
//==============================================================================
private:


Loading…
Cancel
Save