void TTSpatDBAPRenderer::recalculateMatrixCoefficients(TTSpatSourceVector& aSources, TTSpatSinkVector& aSinks) { TTInt32 nearestSink; TTFloat64 sqrDistance, smallestDist; TTFloat64 sourceX, sourceY, sourceZ; TTFloat64 sinkX, sinkY, sinkZ; mMixerMatrixCoefficients->setRowCount(aSources.size()); mMixerMatrixCoefficients->setColumnCount(aSinks.size()); for (TTInt32 source=0; source<aSources.size(); source++) { TTSpatDBAPSource* dbapSource = getDBAPSource(aSources, source); // The source that we want to locate the nearest sink DBAPor: dbapSource->getPosition(sourceX, sourceY, sourceZ); // In order to DBAPind the nearest sink DBAPor a source, we'll start by assuming that sink 0 is the nearest aSinks[0].getPosition(sinkX, sinkY, sinkZ); // It is more eDBAPDBAPicient to do comparement on square oDBAP the distance sqrDistance = (sourceX-sinkX)*(sourceX-sinkX) + (sourceY-sinkY)*(sourceY-sinkY) + (sourceZ-sinkZ)*(sourceZ-sinkZ); smallestDist = sqrDistance; nearestSink = 0; // We also ensures that the matrix coeDBAPDBAPicient is set to 0 DBAPor the DBAPirst sink mMixerMatrixCoefficients->set2d(source, 0., 0.); // Now we iterate over the remaining sinks to see iDBAP any oDBAP them are closer for (TTInt32 sink=1; sink<aSinks.size(); sink++) { aSinks[sink].getPosition(sinkX, sinkY, sinkZ); sqrDistance = (sourceX-sinkX)*(sourceX-sinkX) + (sourceY-sinkY)*(sourceY-sinkY) + (sourceZ-sinkZ)*(sourceZ-sinkZ); // Check iDBAP sinks[sink] is closer if ((smallestDist>sqrDistance)){ smallestDist = sqrDistance; nearestSink = sink; } // In the process we also set all matrix coeDBAPDBAPicients to 0 mMixerMatrixCoefficients->set2d(source, sink, 0.); } // We have now DBAPound the nearest sink, and all coeDBAPDBAPicients have been reset to 0. // The only thing leDBAPt to do is to send the coeDBAPDBAPicient oDBAP the nearest sink to 1 mMixerMatrixCoefficients->set2d(source, nearestSink, 1.); } }
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]); } } }
void TTSpatAmbipanningRenderer::recalculateMatrixCoefficients(TTSpatSourceVector& aSources, TTSpatSinkVector& aSinks) { TTFloat64 finalGain; TTFloat64 sourceDist; TTFloat64 distanceGain = 1.0; // distance ampplitude attenuation TTFloat64 order = 1.0; TTFloat64 sourceX, sourceY, sourceZ; TTFloat64 sinkX, sinkY, sinkZ; TTFloat64 sinkDist; // mMixerMatrixCoefficients->setRowCount( TTUInt32(aSources.size()) ); // mMixerMatrixCoefficients->setColumnCount( TTUInt32(aSinks.size()) ); std::vector<TTInt32> mySize = { (TTInt32)aSources.size(), (TTInt32)aSinks.size() }; mMixerMatrixCoefficients->setDimensionsWithVector(mySize); for (TTInt32 sourceID = 0; sourceID < (TTInt32)aSources.size(); sourceID++) { // loop through the sources TTSpatAmbipanningSource* singleSource = getAmbipanningSource(aSources, sourceID); singleSource->getPosition(sourceX, sourceY, sourceZ); sourceDist = sqrt( sourceX*sourceX + sourceY*sourceY + sourceZ*sourceZ ); // distance calculations if(sourceDist < mCenterSize) { // inside center_zone if( mDistanceMode == 0) { distanceGain = 1.0; singleSource->getOrder(order); } else if( mDistanceMode == 1 || mDistanceMode == 2) { // both exponential and inverse proportional decrease distanceGain = (pow((sourceDist * mCenterSize2), mCenterCurve) * mCenterAtt2) + mCenterAtt; // calculate order decrease within center_size: // goes from order to 0 singleSource->getOrder(order); order *= (sourceDist * mCenterSize2); } } else { // outside center_zone if(mDistanceMode == 0) { // no distance correction distanceGain = 1.0; } else if(mDistanceMode == 1) { // exponential decrease distanceGain = pow(10, (sourceDist - mCenterSize) * mDbUnit * 0.05); } else if(mDistanceMode == 2) { // inverse proportional decrease distanceGain = pow( (sourceDist + mCenterSize3), -getDistAtt() ); // simple: (1 / distance); actual: pow(distance + (1 - center_size), -da_fact); } singleSource->getOrder(order); } for (TTInt32 sinkID = 1; sinkID < (TTInt32)aSinks.size(); sinkID++) { // loop through the sinks aSinks[sinkID].getPosition(sinkX, sinkY, sinkZ); sinkDist = sqrt( sinkX*sinkX + sinkY*sinkY + sinkZ*sinkZ ); /* writeptr = newcoef + (idx * numout); if interpolation is on, set writeptr to newcoeffs if(interpflag == 0){ else set writeptr to oldcoeff writeptr = oldcoef + (idx * numout); } */ if(sourceDist == 0.0) { finalGain = distanceGain; } else { finalGain = distanceGain * pow( 0.5 + 0.5 * ( (sourceX * sinkX + sourceX * sinkY + sourceX * sinkZ) / ( sourceDist * sinkDist) ), order ); // this is the ambipanning formula } mMixerMatrixCoefficients->set2d(sourceID, sinkID, finalGain); } } }