9 #define MAX_NUM_VBAP_TRIPLETS 512
10 #define MIN_VOLUME_TO_LENGTH_RATIO 0.01
21 double inner = v1*v2/(v1.
len() * v2.
len());
24 else if (inner < -1.0)
26 return fabs(acos(inner) );
30 unsigned dimensions = m.
RowNo();
32 for (
unsigned i = 0; i < dimensions; i++)
33 for (
unsigned j = 0; j < dimensions; j++)
34 temp[i] += v(j) * m(j,i);
36 CPoint result(temp[0], temp[1], temp[2]);
100 printf(
"Max number of VBAP triplets exceeded. Triplet not added\n");
127 cout <<
"Number of SpeakerSets: " <<
mNumTriplets << endl;
129 cout <<
"Triple #" << i <<
": ";
135 unsigned dimensions =
mMode;
137 for (
unsigned i = 0; i < dimensions; i++) {
139 for (
unsigned j = 0; j < dimensions; j++)
147 CPoint cross((li^lj) ^ (ln^lm));
155 if (((ang_ci + ang_cj) == ang_ij) && ((ang_cn + ang_cm) == ang_nm) )
163 return (((ang_ci + ang_cj) == ang_ij) && ((ang_cn + ang_cm) == ang_nm) );
172 unsigned speakerMapping[numSpeakers];
173 float speakerAngles[numSpeakers];
176 logMsg(
"VBAP::finding loudspeaker pairs");
179 for (
unsigned i = 0; i < numSpeakers; i++) {
181 speakerMapping[i] = i;
185 for (
unsigned i = 1; i < numSpeakers; i++) {
189 indexAngle = speakerAngles[i];
190 index = speakerMapping[i];
193 while ((j > 0) && (speakerAngles[j-1] > indexAngle)) {
194 speakerAngles[j] = speakerAngles[j-1];
195 speakerMapping[j] = speakerMapping[j-1];
199 speakerAngles[j] = indexAngle;
200 speakerMapping[j] = index;
205 for (
unsigned i = 0; i < numSpeakers; i++)
209 for (
unsigned i = 1; i < numSpeakers; i++){
211 sPair->
nodes[0] = speakerMapping[i-1];
212 sPair->
nodes[1] = speakerMapping[i];
218 sPair->
nodes[0] = speakerMapping[numSpeakers-1];
219 sPair->
nodes[1] = speakerMapping[0];
229 for (
unsigned i = 0; i < numSpeakers; i++){
230 for (
unsigned j = i+1; j < numSpeakers; j++){
231 for (
unsigned k = j+1; k < numSpeakers; k++){
233 triplet->
nodes[0] = i;
234 triplet->
nodes[1] = j;
235 triplet->
nodes[2] = k;
250 float volume = fabsf(xprod * p2);
253 if (length > 0.00001)
254 ratio = volume / length;
267 SpeakerSet *currentOutterTriple, *currentInnerTriple;
290 bool removed =
false;
291 bool startOver =
false;
292 for (
unsigned j = 0; j < 3; j++) {
295 for (
unsigned k = 3; k < 6; k++) {
302 if (length1 > length2) {
317 if (startOver)
break;
326 for (
unsigned jj = 0; jj < numSpeakers; jj++) {
332 bool x_inside, y_inside, z_inside;
333 x_inside = (v.
x >= -1e-4);
334 y_inside = (v.
y >= -1e-4);
335 z_inside = (v.
z >= -1e-4);
337 if ((x_inside) && (y_inside) && ((
mMode == 2) || (z_inside) ) ) {
344 if (mNumTriplets == 0 )
345 throw LogicError(
"No SpeakerSets found. Check mode setting or speaker layout.");
391 this->nextBuffer(outputBuffer, 0);
395 unsigned numFrames = outputBuffer.mNumFrames;
396 unsigned numTriplets = mSpeakerSetLayout->mNumTriplets;
397 outputBuffer.zeroBuffers();
400 logMsg(
"VBAP::nextBuffer");
403 for (
unsigned i = 0; i < mSources.size(); i++) {
416 for (
unsigned count = 0; count < numTriplets; ++count) {
417 currentGains =
vectorMultiply(sourcePosition, (*(mSpeakerSetLayout->mTriplets[currentTripletIndex]->invL)) );
418 if ((currentGains.
x >= 0) && (currentGains.
y >= 0) && ((mMode == 2) || (currentGains.
z >= 0)) )
421 ++currentTripletIndex;
422 if (currentTripletIndex >= numTriplets)
423 currentTripletIndex = 0;
428 double soundPowerConstant = 1;
429 double gainScale = sqrt(soundPowerConstant) / currentGains.
len();
430 currentGains *= gainScale;
433 tcache->
gains[0] = currentGains.
x;
434 tcache->
gains[1] = currentGains.
y;
435 tcache->
gains[2] = currentGains.
z;
442 for (
unsigned j = 0; j < mMode; j++) {
446 for (
unsigned k = 0; k < numFrames; k++) {
447 *out1++ += tcache->
gains[j] * (*opp1++);
452 logMsg(
"Speaker Gains: %.2f, \t %.2f, \t %.2f", tcache->
gains[0], tcache->
gains[1], tcache->
gains[2]);
sample * SampleBuffer
1-channel buffer data type, vector of (sample)
void logMsg(const char *format,...)
These are the public logging messages.
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
double vecAngle(CPoint v1, CPoint v2)
~SpeakerSetLayout()
destructor
Speaker * speakerAtIndex(unsigned speakerIndex) const
Returns the speaker at the specified index.
bool evaluateCrossing(CPoint &li, CPoint &lj, CPoint &ln, CPoint &lm)
CSLMatrix * invL
pre-computed inverse matrix for this triplet
void nextBuffer(Buffer &outputBuffer)
Just as any Effect in CSL, this method gets called at runtime by the audio driver. Here is where the actual processing happens.
SpeakerSet(unsigned size=3)
matrixT Inv() _THROW_MATRIX_ERROR
VBAPMode mMode
Prints useful information about this VBAP instance.
virtual void nextBuffer(Buffer &outputBuffer, unsigned outBufNum)
really compute the next buffer given an offset base channel; this is called by nextBuffer, possibly multiple times
CPoint * position(unsigned channelNum=0)
Returns the distance from the center.
Base class for all panners. Handles source management and holds a speaker layout. ...
matrix< double > CSLMatrix
void addTriple(SpeakerSet *lst)
#define MAX_NUM_VBAP_TRIPLETS
VBAP.h – Vector Base Amplitude Panning class (v2 - Nov 2006) See the copyright notice and acknowledg...
#define MIN_VOLUME_TO_LENGTH_RATIO
COORD_TYPE distance(CPoint *)
Temp Spatial Sound Source.
void dump()
Print speaker information.
SpeakerLayout * mSpeakerLayout
If null, it will use the default layout by calling SpeakerLayout::defaultSpeakerLayout();.
virtual void * cache()
Returns an instance of it's cache data per sound source.
virtual bool isActive()
query whether I'm currently active (Envelopes can go inactive)
virtual void speakerLayoutChanged()
called when the speaker layout changes, so panners update precalculated data
virtual bool positionChanged()
Returns whether the sound source position changed since last block call.
void dump()
just print friendly info about the triplet
SpeakerSetLayout(SpeakerLayout *aLayout, VBAPMode mode=kAuto)
Constructors & destructor:
void invertTripleMatrix(SpeakerSet *lst)
SpeakerSetLayout * mSpeakerSetLayout
A reference to the layout that contains the speaker pairs or triplets.
void setCopyPolicy(BufferCopyPolicy ch)
get/set the receiver's buffer copy policy
unsigned * nodes
the index for each of the three speakers that represent the triplet
Vector Base Amplitude Panning.
Buffer – the multi-channel sample buffer class (passed around between generators and IO guys)...
SurroundPanner(unsigned numSpeakers=5, bool useSubwoofer=true)
The constructor defaults to a 5.1 setup.
unsigned numSpeakers() const
SpeakerLayout * mSpeakerLayout
ignore extra buffer channels
Groups two or three loudspeakers, and their inverse. Used for VBAP computations.
void findSpeakerTriplets()
void removeTriple(SpeakerSet *lst)
void setNumChannels(unsigned ch)
get/set the receiver's number of outputs
virtual ~SurroundPanner()
Only uses the horizontally placed speakers (zero elevation)
Base class of CSL exceptions (written upper-case). Has a string message.
CPoint vectorMultiply(CPoint &v, CSLMatrix &m)
Standard "Stereo Speaker Layout", where two speakers are positioned 30¼ left, 30¼ right and no elevat...
VBAP(VBAPMode mode=kAuto, SpeakerLayout *layout=SpeakerLayout::defaultSpeakerLayout())
Initializer for a VBAP Panner. Optionally a speaker layout can be specified. Defaults to auto...