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.);
	}
}
Example #2
0
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);
        }
    }
}