3 This software is being provided to you, the licensee, by Ville Pulkki,
4 under the following license. By obtaining, using and/or copying this
5 software, you agree that you have read, understood, and will comply
6 with these terms and conditions: Permission to use, copy, modify and
7 distribute, including the right to grant others rights to distribute
8 at any tier, this software and its documentation for any purpose and
9 without fee or royalty is hereby granted, provided that you agree to
10 comply with the following copyright notice and statements, including
11 the disclaimer, and that the same appear on ALL copies of the software
12 and documentation, including modifications that you make for internal
13 use or for distribution:
15 Copyright 1998 by Ville Pulkki, Helsinki University of Technology. All
18 The software may be used, distributed, and included to commercial
19 products without any charges. When included to a commercial product,
20 the method "Vector Base Amplitude Panning" and its developer Ville
21 Pulkki must be referred to in documentation.
23 This software is provided "as is", and Ville Pulkki or Helsinki
24 University of Technology make no representations or warranties,
25 expressed or implied. By way of example, but not limitation, Helsinki
26 University of Technology or Ville Pulkki make no representations or
27 warranties of merchantability or fitness for any particular purpose or
28 that the use of the licensed software or documentation will not
29 infringe any third party patents, copyrights, trademarks or other
30 rights. The name of Ville Pulkki or Helsinki University of Technology
31 may not be used in advertising or publicity pertaining to distribution
43 #include "pbd/cartesian.h"
45 #include "ardour/speakers.h"
46 #include "ardour/vbap.h"
47 #include "ardour/vbap_speakers.h"
48 #include "ardour/audio_buffer.h"
49 #include "ardour/buffer_set.h"
52 using namespace ARDOUR;
55 string VBAPanner::name = X_("VBAP");
57 VBAPanner::VBAPanner (Panner& parent, Evoral::Parameter param, Speakers& s)
58 : StreamPanner (parent, param)
60 , _speakers (VBAPSpeakers::instance (s))
64 VBAPanner::~VBAPanner ()
69 VBAPanner::mark_dirty ()
77 /* force 2D for now */
85 VBAPanner::compute_gains (double gains[3], int speaker_ids[3], int azi, int ele)
87 /* calculates gain factors using loudspeaker setup and given direction */
92 double big_sm_g, gtmp[3];
94 azi_ele_to_cart (azi,ele, cartdir[0], cartdir[1], cartdir[2]);
97 for (i = 0; i < _speakers.n_tuples(); i++) {
101 for (j = 0; j < _speakers.dimension(); j++) {
105 for (k = 0; k < _speakers.dimension(); k++) {
106 gtmp[j] += cartdir[k] * _speakers.matrix(i)[j*_speakers.dimension()+k];
109 if (gtmp[j] < small_g) {
114 if (small_g > big_sm_g) {
121 speaker_ids[0] = _speakers.speaker_for_tuple (i, 0);
122 speaker_ids[1] = _speakers.speaker_for_tuple (i, 1);
124 if (_speakers.dimension() == 3) {
126 speaker_ids[2] = _speakers.speaker_for_tuple (i, 2);
134 power = sqrt (gains[0]*gains[0] + gains[1]*gains[1] + gains[2]*gains[2]);
144 VBAPanner::do_distribute (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_coefficient, nframes_t nframes)
150 Sample* const src = srcbuf.data();
153 uint32_t n_audio = obufs.count().n_audio();
156 if ((was_dirty = _dirty)) {
157 compute_gains (desired_gains, desired_outputs, _angles.azi, _angles.ele);
158 cerr << " @ " << _angles.azi << " /= " << _angles.ele
160 << desired_outputs[0] + 1 << ' '
161 << desired_outputs[1] + 1 << ' '
163 << desired_gains[0] << ' '
164 << desired_gains[1] << ' '
170 for (uint32_t o = 0; o < n_audio; ++o) {
175 /* VBAP may distribute the signal across up to 3 speakers depending on
176 the configuration of the speakers.
179 for (int o = 0; o < 3; ++o) {
180 if (desired_outputs[o] != -1) {
184 /* XXX TODO: interpolate across changes in gain and/or outputs
187 dst = obufs.get_audio(desired_outputs[o]).data();
189 pan = gain_coefficient * desired_gains[o];
190 mix_buffers_with_gain (dst+n,src+n,nframes-n,pan);
196 for (uint32_t o = 0; o < n_audio; ++o) {
198 /* VBAP decided not to deliver any audio to this output, so we write silence */
199 dst = obufs.get_audio(o).data();
200 memset (dst, 0, sizeof (Sample) * nframes);
205 memcpy (gains, desired_gains, sizeof (gains));
206 memcpy (outputs, desired_outputs, sizeof (outputs));
211 VBAPanner::do_distribute_automated (AudioBuffer& src, BufferSet& obufs,
212 nframes_t start, nframes_t end, nframes_t nframes, pan_t** buffers)
217 VBAPanner::get_state ()
223 VBAPanner::state (bool full_state)
225 XMLNode& node (StreamPanner::get_state());
226 node.add_property (X_("type"), VBAPanner::name);
231 VBAPanner::set_state (const XMLNode& node, int /*version*/)
237 VBAPanner::factory (Panner& parent, Evoral::Parameter param, Speakers& s)
239 return new VBAPanner (parent, param, s);