PackPtr PackNew(SymbolPtr msg, AtomCount argc, AtomPtr argv) { PackPtr self; TTValue v; TTErr err; self = PackPtr(object_alloc(sPackClass)); if (self) { object_obex_store((void*)self, _sym_dumpout, (ObjectPtr)outlet_new(self, NULL)); self->graphOutlets[0] = outlet_new(self, "graph.connect"); v.setSize(2); v.set(0, TT("graph.input")); v.set(1, TTUInt32(1)); err = TTObjectInstantiate(TT("graph.object"), (TTObjectPtr*)&self->graphObject, v); ((TTGraphInput*)self->graphObject->mKernel)->setOwner(self->graphObject); if (!self->graphObject->mKernel) { object_error(SELF, "cannot load Jamoma object"); return NULL; } self->graphDictionary = new TTDictionary; self->graphDictionary->setSchema(TT("none")); self->graphDictionary->append(TT("outlet"), 0); attr_args_process(self, argc, argv); self->qelem = qelem_new(self, (method)PackQFn); // PackStartTracking(self); defer_low(self, (method)PackStartTracking, NULL, 0, NULL); } return self; }
MidiOutPtr MidiOutNew(SymbolPtr msg, AtomCount argc, AtomPtr argv) { MidiOutPtr self; TTValue v; TTErr err; self = MidiOutPtr(object_alloc(sMidiOutClass)); if (self) { object_obex_store((void*)self, _sym_dumpout, (ObjectPtr)outlet_new(self, NULL)); // dumpout self->graphOutlets[0] = outlet_new(self, "graph.connect"); v.setSize(2); v.set(0, TT("midi.out")); v.set(1, TTUInt32(1)); err = TTObjectBaseInstantiate(TT("graph.object"), (TTObjectBasePtr*)&self->graphObject, v); if (!self->graphObject->mKernel) { object_error(SELF, "cannot load Jamoma object"); return NULL; } attr_args_process(self, argc, argv); } return self; }
OpPtr OpNew(SymbolPtr msg, AtomCount argc, AtomPtr argv) { OpPtr self; TTValue v; TTErr err; self = OpPtr(object_alloc(sOpClass)); if (self) { object_obex_store((void*)self, _sym_dumpout, (ObjectPtr)outlet_new(self, NULL)); // dumpout self->outlet = outlet_new(self, "audio.connect"); self->inlet = proxy_new(self, 1, &self->inletnum); v.setSize(2); v.set(0, TT("operator")); v.set(1, TTUInt32(1)); // we set it up with 1 inlet, and later modify to 2 inlets if the connection is made err = TTObjectInstantiate(TT("audio.object"), (TTObjectPtr*)&self->audioGraphObject, v); if (!self->audioGraphObject->getUnitGenerator()) { object_error(SELF, "cannot load Jamoma DSP object"); return NULL; } attr_args_process(self, argc, argv); } return self; }
UnpackPtr UnpackNew(SymbolPtr msg, AtomCount argc, AtomPtr argv) { UnpackPtr self; TTValue v; TTErr err; self = UnpackPtr(object_alloc(sUnpackClass)); if (self) { object_obex_store((void*)self, _sym_dumpout, (ObjectPtr)outlet_new(self, NULL)); // dumpout self->graphOutlets[0] = outlet_new(self, NULL); v.setSize(2); v.set(0, TT("graph.output")); v.set(1, TTUInt32(1)); err = TTObjectInstantiate(TT("graph.object"), (TTObjectPtr*)&self->graphObject, v); if (!self->graphObject->mKernel) { object_error(SELF, "cannot load Jamoma object"); return NULL; } err = TTObjectInstantiate(TT("Callback"), (TTObjectPtr*)&self->callback, kTTValNONE); self->callback->setAttributeValue(TT("Function"), TTPtr(&UnpackGraphCallback)); self->callback->setAttributeValue(TT("Baton"), TTPtr(self)); // dynamically add a message to the callback object so that it can handle the 'dictionaryReceived' notification self->callback->registerMessage(TT("dictionaryReceived"), (TTMethod)&TTCallback::notify, kTTMessagePassValue); // tell the graph object that we want to watch it self->graphObject->mKernel->registerObserverForNotifications(*self->callback); attr_args_process(self, argc, argv); } return self; }
TTEnvironment::TTEnvironment() : TTObject(kTTValNONE), mDebugBasic(false), mDebugMessaging(false), mSampleRate(0) { classes = new TTHash(); tags = new TTHash(); addAttribute(DebugBasic, kTypeBoolean); addAttribute(DebugMessaging, kTypeBoolean); addAttribute(SampleRate, kTypeUInt32); addMessageWithArgument(GetVersion); // can't use the SymbolCache here because it hasn't been initialized yet! setAttributeValue(TT("SampleRate"), TTUInt32(44100)); }
OpPtr OpNew(SymbolPtr msg, AtomCount argc, AtomPtr argv) { OpPtr self; TTValue v; TTErr err; self = OpPtr(pd_new(sOpClass)); if (self) { self->outlet = outlet_new(SELF, gensym("audio.connect")); v.setSize(2); v.set(0, TT("operator")); v.set(1, TTUInt32(1)); err = TTObjectInstantiate(TT("audio.object"), (TTObjectPtr*)&self->audioGraphObject, v); if (!self->audioGraphObject->getUnitGenerator()) { error("op≈: cannot load Jamoma DSP object"); return NULL; } } return self; }
void TTSpatDBAPRenderer::recalculateMatrixCoefficients(TTSpatSourceVector& aSources, TTSpatSinkVector& aSinks) { /* double k; // Scaling coefficient double k2inv; // Inverse square of the scaling constant k double dx, dy, dz; // Distance vector double r2; // Bluriness ratio double dia[MAX_NUM_DESTINATIONS]; // Distance to ith speaker to the power of x->a. t_atom a[3]; // Output array of atoms long i; r2 = x->blur[n] * x->variance; r2 = r2*r2; k2inv = 0; for (i=0; i<x->attr_num_destinations; i++) { dx = x->src_position[n].x - x->dst_position[i].x; dy = x->src_position[n].y - x->dst_position[i].y; dz = x->src_position[n].z - x->dst_position[i].z; dia[i] = pow(double(dx*dx + dy*dy + dz*dz + r2), double(0.5*x->a)); k2inv = k2inv + (x->src_weight[n][i]*x->src_weight[n][i])/(dia[i]*dia[i]); } k = sqrt(1./k2inv); k = k*x->master_gain*x->src_gain[n]*x->src_not_muted[n]; atom_setlong(&a[0], n); for (i=0; i<x->attr_num_destinations; i++) { atom_setlong(&a[1], i); atom_setfloat(&a[2], x->src_weight[n][i]*k/dia[i]); outlet_anything(x->outlet[0], _sym_list, 3, a); } */ TTFloat64 sourceX, sourceY, sourceZ; TTFloat64 sourceWidth; TTFloat64 sinkX, sinkY, sinkZ; TTFloat64 dx, dy, dz; TTFloat64 sqrDistance; TTFloat64 r2; // Bluriness ratio TTFloat64 k; // Scaling coefficient TTFloat64 k2inv; // Inverse square of the scaling constant k // TODO only resize if needed, check first! mMixerMatrixCoefficients->setRowCount(TTUInt32(aSources.size())); mMixerMatrixCoefficients->setColumnCount(TTUInt32(aSinks.size())); std::vector<TTFloat64> dia; dia.resize(aSinks.size()); TTFloat64 rolloffPowerFactor = log(pow(10., (mRolloff / 20.)))/log(2.); for (TTInt32 source=0; source < (TTInt32) aSources.size(); source++) { TTSpatDBAPSource* dbapSource = getDBAPSource(aSources, source); aSources[source].getPosition(sourceX, sourceY, sourceZ); dbapSource->getWidth(sourceWidth); r2 = sourceWidth * sourceWidth; // TODO: should be normalised with respect to x->variance // Iterate over sinks to calculate non-normalised gains for this source k2inv = 0; for (TTInt32 sink=0; sink < (TTInt32) aSinks.size(); sink++) { aSinks[sink].getPosition(sinkX, sinkY, sinkZ); dx = sourceX-sinkX; dy = sourceY-sinkY; dz = sourceZ-sinkZ; sqrDistance = (dx*dx + dy*dy + dz*dz + r2); dia[sink] = pow((dx*dx + dy*dy + dz*dz + r2), double(0.5*rolloffPowerFactor)); // TODO: Introduce weight in equation below k2inv = k2inv + 1/(dia[sink]*dia[sink]); } // Calculate normalising factor k = sqrt(1./k2inv); // TODO: This should also cater for gain and muting of source // Iterate over sinks again and normalise gains for (TTInt32 sink=0; sink < (TTInt32) aSinks.size(); sink++) { mMixerMatrixCoefficients->set2d(source, sink, k/dia[sink]); } } }
TTErr TTSampleMatrix::setLengthInSamples(const TTValue& newLengthInSamples) { TTValue v(TTUInt32(newLengthInSamples), mNumChannels); return setDimensions(v); }
TTErr TTSampleMatrix::setNumChannels(const TTValue& newNumChannels) { TTValue v(mLengthInSamples, TTUInt32(newNumChannels)); return setDimensions(v); }
TTErr TTSampleMatrix::test(TTValue& returnedTestInfo) { int errorCount = 0; int testAssertionCount = 0; // for tests TTInt16 numChannels = 2; TTUInt32 numSamples = 50000; // TODO: xcode says this is ambiguous when signed? TTFloat32 duration = 1500; int test9Index = 10; int test10Index = 11; TTInt32 test1Return, test2Return, test7Return; TTFloat32 test3Return, test6Return; TTSampleValue test9Return, test10Return, test11Return, test12return, test13return; TTTestLog("Test resizing of the SampleMatrix..."); // TEST 1: can we set the number of channels? this->setAttributeValue("numChannels", numChannels); this->getAttributeValue("numChannels", test1Return); TTBoolean result = { numChannels == test1Return }; TTTestAssertion("numChannels is set properly", result, testAssertionCount, errorCount); if(!result) { TTTestLog("Expected a value of %i, but returned value was %i", numChannels, test1Return); } // TEST 2: can we set the number of samples? //this->setAttributeValue("lengthInSamples", numSamples); // TODO: xcode says this is ambiguous? this->setLengthInSamples(numSamples); this->getAttributeValue("lengthInSamples", test2Return); TTBoolean result2 = { numSamples == test2Return }; TTTestAssertion("lengthInSamples is set properly", result2, testAssertionCount, errorCount); if(!result2) { TTTestLog("Expected a value of %i, but returned value was %i", numSamples, test2Return); } // TEST 3: is the length in sec computed properly after setting length in samples? TTFloat32 computedDuration3 = (numSamples / this->mSampleRate); this->getAttributeValue("lengthInSeconds", test3Return); TTBoolean result3 = TTTestFloatEquivalence(computedDuration3, test3Return); TTTestAssertion("after lengthInSamples is set, lengthInSeconds is correct", result3, testAssertionCount, errorCount); if(!result3) { TTTestLog("Expected a value of %f, but returned value was %f", computedDuration3, test3Return); } // TEST 4: is the matrix of samples the expected size? (lifted from TTMatrix.test.cpp) TTUInt32 computedDataSize4 = sizeof(TTFloat64) * numChannels * numSamples; TTBoolean result4 = { computedDataSize4 == this->mDataSize }; TTTestAssertion("correct amount of data storage calculated", result4, testAssertionCount, errorCount); if(!result4) { TTTestLog("Expected a value of %i, but returned value was %i", computedDataSize4, this->mDataSize); } // TEST 5: Is the component stride right? (lifted from TTMatrix.test.cpp) TTBoolean result5 = { sizeof(TTFloat64) == this->mComponentStride }; TTTestAssertion("correct byte-stride between values calculated", result5, testAssertionCount, errorCount); if(!result5) { TTTestLog("Expected a value of %i, but returned value was %i", sizeof(TTFloat64), this->mComponentStride); } // TEST 6: can we set the length in seconds? this->setAttributeValue("lengthInSeconds", duration); this->getAttributeValue("lengthInSeconds", test6Return); TTBoolean result6 = TTTestFloatEquivalence(duration, test6Return); TTTestAssertion("lengthInSeconds is set properly", result6, testAssertionCount, errorCount); if(!result6) { TTTestLog("Expected a value of %f, but returned value was %f", duration, test6Return); } // TEST 7: is the length in samples computed properly after setting length in ms? TTUInt32 computedSamples7 = TTUInt32(duration * this->mSampleRate); this->getAttributeValue("lengthInSamples", test7Return); TTBoolean result7 = { computedSamples7 == test7Return }; TTTestAssertion("after lengthInSeconds is set, lengthInSamples is correct", result7, testAssertionCount, errorCount); if(!result7) { TTTestLog("Expected a value of %i, but returned value was %i", computedSamples7, test7Return); } // TEST 8 (REPEAT TEST 4 WITH NEW SIZE): is the matrix of samples the expected size? TTUInt32 computedDataSize8 = sizeof(TTFloat64) * numChannels * test7Return; TTBoolean result8 = { computedDataSize8 == this->mDataSize }; TTTestAssertion("correct amount of data storage calculated with new length", result8, testAssertionCount, errorCount); if(!result8) { TTTestLog("Expected a value of %i, but returned value was %i", computedDataSize8, this->mDataSize); } // TEST 9 & 10: set the value of two consecutive samples TTSampleValue pokeValue9 = TTRandom64(); TTSampleValue pokeValue10 = TTRandom64(); this->poke(test9Index, 0, pokeValue9); this->poke(test10Index, 0, pokeValue10); this->peek(test9Index, 0, test9Return); this->peek(test10Index, 0, test10Return); TTBoolean result9 = { pokeValue9 == test9Return }; TTTestAssertion("set value one of two consecutive samples", result9, testAssertionCount, errorCount); if(!result9) { TTTestLog("Expected a value of %f, but returned value was %f", pokeValue9, test9Return); } TTBoolean result10 = { pokeValue10 == test10Return }; TTTestAssertion("set value two of two consecutive samples", result10, testAssertionCount, errorCount); if(!result10) { TTTestLog("Expected a value of %f, but returned value was %f", pokeValue10, test10Return); } // TEST 10a: confirm that pulling value via "peek" message works too TTValue input(test10Index); input.append(0); TTValue output; this->sendMessage("peek", input, output); TTBoolean result10a = { TTTestFloatEquivalence(pokeValue10, TTSampleValue(output)) }; TTTestAssertion("set value two of two consecutive samples", result10a, testAssertionCount, errorCount); if(!result10a) { TTTestLog("Expected a value of %f, but returned value was %f", pokeValue10, TTSampleValue(output)); } // TEST 11: test for interpolation between two consecutive samples TTFloat64 computedInterpFraction = TTRandom64(); TTFloat64 computedInterpIndex = test9Index + computedInterpFraction; TTSampleValue computedInterpValue11 = (computedInterpFraction * pokeValue10) + ((1.0 - computedInterpFraction) * pokeValue9); this->peeki(computedInterpIndex, 0, test11Return); TTBoolean result11 = TTTestFloatEquivalence(computedInterpValue11, test11Return); TTTestAssertion("interpolate between two consecutive samples", result11, testAssertionCount, errorCount); if(!result11) { TTTestLog("Expected a value of %f, but returned value was %f", computedInterpValue11, test11Return); } // TODO: inbounds testing on hold until sorted out at TTMatrix parent class // TEST 12 & 13: test whether out of bounds indices produce errors at head TTInt32 computedIndex12 = -1; // 1 before the head TTInt32 computedIndex13 = 0; // the head TTErr test12Err = this->peek(computedIndex12, 0, test12return); TTErr test13Err = this->peek(computedIndex13, 0, test13return); TTBoolean result12 = { test12Err == kTTErrOutOfBounds }; TTBoolean result13 = { test13Err == kTTErrNone }; TTTestAssertion("peeking sample before index 0 produces an error", result12, testAssertionCount, errorCount); if(!result12) { TTTestLog("Expected a value of %i, but returned value was %i", kTTErrOutOfBounds, test12Err); } TTTestAssertion("peeking sample at index 0 produces no error", result13, testAssertionCount, errorCount); if(!result13) { TTTestLog("Expected a value of %i, but returned value was %i", kTTErrNone, test13Err); } // TEST 14 & 15: test whether out of bounds indices produce errors at tail TTInt32 computedIndex14 = test7Return; // should be latest size in samples TTInt32 computedIndex15 = test7Return - 1; // the tail is actually one less TTErr test14Err = this->poke(computedIndex14, 0, test12return); TTErr test15Err = this->poke(computedIndex15, 0, test13return); TTBoolean result14 = { test14Err == kTTErrOutOfBounds }; TTBoolean result15 = { test15Err == kTTErrNone }; TTTestAssertion("poking sample after index max produces an error", result14, testAssertionCount, errorCount); if(!result14) { TTTestLog("Expected a value of %i, but returned value was %i", kTTErrOutOfBounds, test14Err); } TTTestAssertion("poking sample at index max produces no error", result15, testAssertionCount, errorCount); if(!result15) { TTTestLog("Expected a value of %i, but returned value was %i", kTTErrNone, test15Err); } // TEST 16 & 17: incrementing & decrementing userCount TTUInt16 test16expect = 4; TTUInt16 test17expect = 2; this->incrementUserCount(); this->incrementUserCount(); this->incrementUserCount(); this->incrementUserCount(); TTUInt16 test16return = this->mUserCount; this->decrementUserCount(); this->decrementUserCount(); TTUInt16 test17return = this->mUserCount; TTBoolean result16 = { test16expect == test16return }; TTBoolean result17 = { test17expect == test17return }; TTTestAssertion("incrementing userCount produces expected results", result16, testAssertionCount, errorCount); if(!result16) { TTTestLog("Expected a value of %i, but returned value was %i", test16expect, test16return); } TTTestAssertion("decrementing userCount produces expected results", result17, testAssertionCount, errorCount); if(!result17) { TTTestLog("Expected a value of %i, but returned value was %i", test17expect, test17return); } // TEST 18 & 19: setting & testing bufferPoolStage TTBoolean test18expect = true; TTBoolean test19expect = false; this->setBufferPoolStage(kSM_Active); TTBoolean test18return = this->isBufferPoolStage(kSM_Active); TTBoolean test19return = this->isBufferPoolStage(kSM_BecomingIdle); TTBoolean result18 = { test18expect == test18return }; TTBoolean result19 = { test19expect == test19return }; TTTestAssertion("reports bufferPoolStage as active", result18, testAssertionCount, errorCount); if(!result18) { TTTestLog("Expected a value of %i, but returned value was %i", test18expect, test18return); } TTTestAssertion("reports bufferPoolStage as NOT becoming idle", result19, testAssertionCount, errorCount); if(!result19) { TTTestLog("Expected a value of %i, but returned value was %i", test19expect, test19return); } /* int badSampleCount = 0; TTAudioObjectBasePtr samplematrixObject = NULL; TTAudioSignalPtr input = NULL; TTAudioSignalPtr output = NULL; // TODO: test filling with sine wave // TODO: test scaling (applying gain) // TODO: test normalizing (with optional arg, and also without an optional arg) TTObjectBaseInstantiate("samplematrix", &samplematrixObject, kTTVal1); TTObjectBaseRelease(&input); TTObjectBaseRelease(&output); TTObjectBaseRelease(&samplematrixObject); */ // Wrap up the test results to pass back to whoever called this test return TTTestFinish(testAssertionCount, errorCount, returnedTestInfo); }