Jamoma API  0.6.0.a19
TTAudioGraphInlet.h
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup audioGraphLibrary
4  *
5  * @brief Defines a single 'inlet' from an individual AudioGraph object
6  *
7  * @details TTAudioGraphObject maintains a vector of these inlets.
8  * The relationship of an inlet to other parts of the audio graph hierarchy is as follows:
9  *
10  * - A graph may have many objects.
11  * - An object may have many inlets.
12  * - An inlet may have many signals (sources) connected.
13  * - A signal may have many channels.
14  *
15  * @authors Timothy Place, Trond Lossius, Nathan Wolek
16  *
17  * @copyright Copyright © 2010, Timothy Place @n
18  * This code is licensed under the terms of the "New BSD License" @n
19  * http://creativecommons.org/licenses/BSD/
20  */
21 
22 
23 #ifndef __TTAUDIOGRAPH_INLET_H__
24 #define __TTAUDIOGRAPH_INLET_H__
25 
26 #include "TTAudioGraph.h"
27 #include "TTAudioGraphObject.h"
28 #include "TTAudioGraphSource.h"
29 
30 
31 /******************************************************************************************/
32 
33 /** This object represents a single 'inlet' to a TTAudioGraphObject.
34  * TTAudioGraphObject maintains a vector of these inlets.
35  *
36  * The relationship of an inlet to other parts of the audio graph hierarchy is as follows:
37  *
38  * - A graph may have many objects.
39  * - An object may have many inlets.
40  * - An inlet may have many signals connected.
41  * - A signal may have many channels.
42  *
43 */
45 
46 protected:
47 
48  TTAudioGraphSourceVector mSourceObjects; ///< A vector of object pointers from which we pull our source samples using the ::getAudioOutput() method.
49  TTAudioSignalPtr mBufferedInput; ///< Summed samples from all sources.
50  TTAudioSignalPtr mDirectInput; ///< Pointer to the (non-buffered) input samples if there was no requirement to sum them.
51  TTBoolean mClean; ///<
52 
53 public:
54 
56  mBufferedInput(NULL),
57  mDirectInput(NULL),
58  mClean(NO)
59  {
60  createBuffer();
61  }
62 
63  /** Object destructor.
64  */
66  {
67  TTObjectBaseRelease(&mBufferedInput);
68  }
69 
70 
71  // Copying Functions are critical due to use by std::vector
72  // At least on the Mac, a call to std::vector::resize() does not simply construct N objects.
73  // For example, mInlets.resize(2) in TTAudioGraphObject() will construct 1 object,
74  // and then copy it to get the second object rather than constructing the second object!
75  // Because of that, we have to be super careful!
76  //
77  // If an object were to be copied, you'd think that you'd want to keep a reference to the audio signal.
78  // But when are constructing initially (e.g. by the resize) we actually want a whole new audio signal!
79  //
80  // We need to be on the alert for strange behaviors caused by this situation.
81  // At some point perhaps we should switch to just using a vector of pointers, though there are sensitive issues there too...
82 
83 
84  TTAudioGraphInlet(const TTAudioGraphInlet& original) :
85  mBufferedInput(NULL),
86  mDirectInput(NULL),
87  mClean(NO)
88  {
89  createBuffer();
90  mSourceObjects = original.mSourceObjects;
91  //mBufferedInput = TTObjectBaseReference(original.mBufferedInput);
92  (*mBufferedInput) = (*original.mBufferedInput);
93  mClean = original.mClean;
94  }
95 
96 
97  /** The copy assignment constructor doesn't appear to be involved, at least with resizes, on the Mac...
98  */
100  {
101  TTObjectBaseRelease(&mBufferedInput);
102 
103  mSourceObjects = source.mSourceObjects;
104  mBufferedInput = TTObjectBaseReference(source.mBufferedInput);
105  mClean = source.mClean;
106 
107  return *this;
108  }
109 
110 
111  /* Create a buffer that will be used to sum samples from all sources arriving at this inlet.
112  */
113  void createBuffer()
114  {
115  TTObjectBaseInstantiate(kTTSym_audiosignal, &mBufferedInput, 1);
116  // alloc to set up a default buffer
117  mBufferedInput->setAttributeValue(TT("maxNumChannels"), 1);
118  mBufferedInput->setAttributeValue(TT("numChannels"), 1);
119  mBufferedInput->allocWithVectorSize(64);
120  }
121 
122 
123  // Graph Methods
124 
125  /** Reset the graph by dropping all connections to all sources in preparation of a rebuilding of all of the graph.
126  */
127  void reset()
128  {
129  mSourceObjects.clear();
130  }
131 
132  /** Establish a connection from an output of an upstream node to one of the inlets of this node so that processing might occur.
133  @param anObject Reference to an upstream node.
134  @param fromOutletNumber The outlet of the upstrem node that the connection is being made from.
135  @return #TTErr error code if the method fails to execute, else #kTTErrNone.
136  */
137  TTErr connect(TTAudioGraphObjectBasePtr anObject, TTUInt16 fromOutletNumber)
138  {
139  TTUInt16 size = mSourceObjects.size();
140 
141  // make sure the connection doesn't already exist
142  for (TTAudioGraphSourceIter source = mSourceObjects.begin(); source != mSourceObjects.end(); source++) {
143  if (source->match(anObject, fromOutletNumber))
144  return kTTErrNone;
145  }
146 
147  // create the connection
148  mSourceObjects.resize(size+1);
149  mSourceObjects[size].connect(anObject, fromOutletNumber);
150  mSourceObjects[size].setOwner(this);
151  return kTTErrNone;
152  }
153 
154 
155  /** Drop a connection from an upstream node.
156  @param anObject Reference to an upstream node.
157  @param fromOutletNumber The outlet of the upstrem node that the connection for which the connection will be dropped.
158  @return #TTErr error code if the method fails to execute, else #kTTErrNone.
159  */
160  TTErr drop(TTAudioGraphObjectBasePtr anObject, TTUInt16 fromOutletNumber)
161  {
162  for (TTAudioGraphSourceIter source = mSourceObjects.begin(); source != mSourceObjects.end(); source++) {
163  if (source->match(anObject, fromOutletNumber)) {
164  drop(*source);
165  break;
166  }
167  }
168  return kTTErrNone;
169  }
170 
171 
172  /** Drop a connection (if any) to an upstream source.
173  This method is called if a node is being destroyed to ensure that no stray connections from it are left behind.
174  @param aSource The potential upstream node (source) for which all connections are to be dropped.
175  */
176  void drop(TTAudioGraphSource& aSource)
177  {
178  TTAudioGraphSourceIter iter = find(mSourceObjects.begin(), mSourceObjects.end(), aSource);
179 
180  if (iter != mSourceObjects.end())
181  mSourceObjects.erase(iter);
182  }
183 
184 
185  /** Just before audio processing, a preprocess() method is propagated up the audio graph chain from the terminal object.
186  This can be used to zero buffers and also sets flags that indicate each object’s processing state.
187  It is of no consequence if an object receives multiple preprocess calls, such as would happen if there are multiple terminal nodes.
188  @param initData
189  */
191  {
192  mBufferedInput->clear();
193  for (TTAudioGraphSourceIter source = mSourceObjects.begin(); source != mSourceObjects.end(); source++)
194  source->preprocess(initData);
195  mClean = YES;
196  }
197 
198 
199  /** With the objects in the graph prepared by the preprocess() call, the audio can be pulled from nodes connected upstream using the process() call on each source.
200  When asked for a vector of audio by the unit generator, the inlets each request audio from each of their sources (other objects’ outlets).
201  If an inlet has multiple sources, those sources are summed.
202  When all of the inlets have performed this operation, then the unit generator proceeds to process the audio buffered in the inlets and fills the buffers in the outlets.
203  Sources manage a one-to-one connection between an inlet and an upstream object's outlet; inlets may have zero or more sources.
204 
205  @param sampleStamp (Trond will document this)
206  @return #TTErr error code if the method fails to execute, else #kTTErrNone.
207  */
208  TTErr process(TTUInt64 sampleStamp)
209  {
210  int err = kTTErrNone;
211  TTAudioSignalPtr sourceAudioOutput;
212 
213  if (mSourceObjects.size() == 1) {
214  // here we optimize the operation:
215  // if there is only one connection to the inlet, then we don't need to copy the samples in the buffer
216  // instead we just reference the pointer to the beginning of the buffer
217  err = mSourceObjects[0].process(mDirectInput, sampleStamp);
218  }
219  else {
220  for (TTAudioGraphSourceIter source = mSourceObjects.begin(); source != mSourceObjects.end(); source++) {
221  err |= (*source).process(sourceAudioOutput, sampleStamp);
222  // Buffering sample values from the first connection
223  if (mClean) {
224  (*mBufferedInput) = (*sourceAudioOutput);
225  mClean = NO;
226  }
227  // Adding sample values from the remaining connections
228  else
229  (*mBufferedInput) += (*sourceAudioOutput);
230  mDirectInput = NULL;
231  }
232  }
233  return (TTErr)err;
234  }
235 
236 
237  /** Get the most recently processed audio for this inlet as summerized from all connected upstream nodes.
238  @return Pointer to the audio buffer used for summerizing signals from connected upstream nodes.
239  */
241  {
242  if (mDirectInput)
243  return mDirectInput;
244  else
245  return mBufferedInput;
246  }
247 
248 
249  /** Prepare for a request that wants to descibe all of the graph.
250  The request for preparing to describe the graph is propagated to all nodes that are connected upstream.
251  */
253  {
254  // Currently this method is doing nothing put propagating the request to the upstream neighboors of the node.
255  for (TTAudioGraphSourceIter source = mSourceObjects.begin(); source != mSourceObjects.end(); source++)
256  source->prepareDescription();
257  }
258 
259 
260  /** The node is requested to declare itself as part of an action to describe all of the audio graph.
261  As part of this action the request is also propagated to its upstream neighboors, and retrieved information on the graph is passed back down again to the sink(s) of the graph.
262  @param descs Pointer to the graph description vector used by the downstream neighboor(s) to retrieve information on this node and its upstesream connections.
263  */
264  void getDescriptions(TTAudioGraphDescriptionVector& descs)
265  {
266  for (TTAudioGraphSourceIter source = mSourceObjects.begin(); source != mSourceObjects.end(); source++) {
268 
269  source->getDescription(desc);
270  descs.push_back(desc);
271  }
272  }
273 
274 };
275 
276 
277 #endif // __TTAUDIOGRAPH_INLET_H__
~TTAudioGraphInlet()
Object destructor.
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
TTErr drop(TTAudioGraphObjectBasePtr anObject, TTUInt16 fromOutletNumber)
Drop a connection from an upstream node.
std::uint16_t TTUInt16
16 bit unsigned integer
Definition: TTBase.h:176
TTAudioGraphInlet & operator=(const TTAudioGraphInlet &source)
The copy assignment constructor doesn't appear to be involved, at least with resizes, on the Mac...
TTErr TTObjectBaseRelease(TTObjectBasePtr *anObject)
DEPRECATED.
TTAudioSignalPtr getBuffer()
Get the most recently processed audio for this inlet as summerized from all connected upstream nodes...
TTErr process(TTUInt64 sampleStamp)
With the objects in the graph prepared by the preprocess() call, the audio can be pulled from nodes c...
std::uint64_t TTUInt64
64 bit unsigned integer
Definition: TTBase.h:180
TTAudioSignalPtr mDirectInput
Pointer to the (non-buffered) input samples if there was no requirement to sum them.
TTAudioSignalPtr mBufferedInput
Summed samples from all sources.
void reset()
Reset the graph by dropping all connections to all sources in preparation of a rebuilding of all of t...
Represents one connection between two AudioGraph objects.
This object provides a description of a TTAudioGraphObject and its sources.
Registers classes for the primary AudioGraph library.
TTErr setAttributeValue(const TTSymbol name, TTValue &value)
Set an attribute value for an object.
#define TT
This macro is defined as a shortcut for doing a lookup in the symbol table.
Definition: TTSymbol.h:155
void getDescriptions(TTAudioGraphDescriptionVector &descs)
The node is requested to declare itself as part of an action to describe all of the audio graph...
TTErr clear()
Zero out all of the sample values in the audio signal.
TTErr TTObjectBaseInstantiate(const TTSymbol className, TTObjectBasePtr *returnedObjectPtr, const TTValue arguments)
DEPRECATED.
This object represents a single 'inlet' to a TTAudioGraphObject.
The TTAudioSignal class represents N vectors of audio samples for M channels.
Definition: TTAudioSignal.h:57
Wraps an object from Jamoma DSP to function within AudioGraph.
void prepareDescriptions()
Prepare for a request that wants to descibe all of the graph.
void preprocess(const TTAudioGraphPreprocessData &initData)
Just before audio processing, a preprocess() method is propagated up the audio graph chain from the t...
TTErr connect(TTAudioGraphObjectBasePtr anObject, TTUInt16 fromOutletNumber)
Establish a connection from an output of an upstream node to one of the inlets of this node so that p...
TTAudioGraphSourceVector::iterator TTAudioGraphSourceIter
An iterator on TTAudioGraphSourceVector.
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
The TTAudioGraphObjectBase wraps a TTDSP object such that it is possible to build a dynamic graph of ...
[doxygenAppendixC_bitmaskExample]
Definition: TTAudioGraph.h:81
TTObjectBasePtr TTObjectBaseReference(TTObjectBasePtr anObject)
DEPRECATED.
TTAudioGraphSource represents one link from a TTAudioGraphInlet of a TTAudioGraphObjectBase to a TTAu...
No Error.
Definition: TTBase.h:343
TTAudioGraphSourceVector mSourceObjects
A vector of object pointers from which we pull our source samples using the ::getAudioOutput() method...
TTErr allocWithVectorSize(const TTUInt16 newVectorSize)
Allocate memory for all channels at the specified vectorsize, if the vectorsize is different from the...
void drop(TTAudioGraphSource &aSource)
Drop a connection (if any) to an upstream source.
std::vector< TTAudioGraphSource > TTAudioGraphSourceVector
A vector of #TTAudioGraphSources.