CSL 5.2

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

Ambisonic.h
Go to the documentation of this file.
1 //
2 // Ambisonic.h -- Higher Order Ambisonic abstract base class for all Ambisonic effects and panners.
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 // Higher Order Ambisonic classes written by Jorge Castellanos, Graham Wakefield, Florian Hollerweger, 2005
5 //
6 // Encapsulates parameters regarding the ambisonic order of the class (including hybrid orders)
7 //
8 // CONVENTIONS USED IN THIS CODE:
9 // ------------------------------
10 //
11 // ***coordinate system***
12 // Left oriented
13 // Azimuth = 0 on the x/z plane and increasing towards the positive y direction
14 // Elevation = 0 on x/y plane and increasing towards the positive z direction
15 // Internal angle representation: spherical radians
16 //
17 // ***encoding convention***
18 // following the Furse-Malham set (Ambisonic channel weighting for uniform energy distribution)
19 //
20 // ***abbreviations used in code and comments***
21 // M ... Ambisonic order (in uniform order system)
22 // M_h ... horizontal Ambisonic order (in hybrid order systems)
23 // M_v ... horizontal Ambisonic order (in hybrid order systems)
24 // N ... total number of Ambisonic encoded channels (horizontal and vertical)
25 // N_h ... number of horizontal Ambisonic channels (in hybrid order systems)
26 // N_v ... number of vertical Ambisonic channels (in hybrid order systems)
27 // L ... number of available loudspeakers
28 //
29 // ***ordering and naming of Ambisonic channels = spherical harmonics***
30 // These conventions follow the ones used in the thesis by Jerome Daniel.
31 // The 3rd order naming convention (which Daniel doesn't provide) follows the one used in the thesis of David Malham.
32 // Watch out for different conventions in other papers!
33 // index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
34 // M (order) 0 1 1 1 2 2 2 2 2 3 3 3 3 3 3 3
35 // m (=M) 0 1 1 1 2 2 2 2 2 3 3 3 3 3 3 3
36 // n 0 1 1 0 2 2 1 1 0 3 3 2 2 1 1 0
37 // sigma '1' 1 -1 '1' 1 -1 1 -1 '1' 1 -1 1 -1 1 -1 '1'
38 // name W X Y Z U V S T R P Q N O L M K
39 // hor/vert/omni om h h v h h v v v h h v v v v v
40 //
41
42 #ifndef CSL_AMBISONIC_H
43 #define CSL_AMBISONIC_H
44
45 #include "CSL_Core.h"
46 #include "CPoint.h"
47 #include "SpatialSource.h"
48 #include "SpeakerLayout.h"
49
50 #define HOA_MAX_ORDER 2 // maximum order that the CSL HOA will handle
51
52 namespace csl {
53
54 /// Ambisonic order structure (separate definition for horizontal and vertical order):
55 /// \relates AmbisonicUnitGenerator
56
57 class AmbisonicOrder {
58 public:
59 AmbisonicOrder(unsigned hOrder = 0, unsigned vOrder = 0) : horizontalOrder(hOrder), verticalOrder(vOrder) { };
60 ~AmbisonicOrder() { };
61
62 unsigned horizontalOrder;
63 unsigned verticalOrder;
64 bool isUniform; ///< Returns true if horizontal and verical orders are identical.
65 };
66
67 /// Ambisonic Abstract Base Class.
68
69 class AmbisonicUnitGenerator : public UnitGenerator {
70 public:
71
72 // Constructors & destructor:
73 AmbisonicUnitGenerator(unsigned order = 0); ///< Initialize with uniform Ambisonic order. Defaults to zeroth order.
74 AmbisonicUnitGenerator(unsigned horder, unsigned vorder); ///< Initialize with hybrid Ambisonic order
75 AmbisonicUnitGenerator(AmbisonicOrder order); ///<
76 virtual ~AmbisonicUnitGenerator();
77
78 AmbisonicOrder order() { return mOrder; }; ///< Returns the Ambisonic order.
79
80 protected:
81 void setOrder(AmbisonicOrder order);
82
83 AmbisonicOrder mOrder; ///< the order of the Unit Generator
84
85 // returns the Ambisonic order from the number of Ambisonic channels: M = floor(sqrt(N) - 1)
86 // NOTE - only works for uniform horizontal and vertical order (whereas ambiguity occurs in hybrid order systems)!
87 unsigned channelsToUniformOrder(const unsigned channels);
88
89 /// Compares the horizontal and vertical Ambisonic order of a hybrid order and returns the largest
90 unsigned greaterOrder(const AmbisonicOrder order);
91
92 /// Returns the number of Ambisonic channels from a hybrid Ambisonic order: N = 2*M_h + 1 + (M_v + 1)^2 - (2*M_v + 1)
93 unsigned orderToChannels(const AmbisonicOrder order);
94
95 /// Returns the number of Ambisonic channels corresponding to a uniform Ambisonic order: N = (M+1)^2
96 unsigned orderToChannels(unsigned order);
97
98 /// Returns the number of horizontal Ambisonic channels from a hybrid Ambisonic order: N_h = 2*M_h + 1
99 unsigned orderToHorizontalChannels(const AmbisonicOrder order);
100
101 /// Returns the number of vertical Ambisonic channels from a hybrid Ambisonic order: N_v = (M_v + 1)^2 - (2*M_v + 1)
102 unsigned orderToVerticalChannels(const AmbisonicOrder order);
103
104 /// Calculates a lookup table to map Ambisonic channel index to actually used UnitGenerator channel
105 void channelIndexer(unsigned *indexArray);
106
107 /// Calculates a lookup table to map actually used UnitGenerator channel to Ambisonic channel index
108 void invChannelIndexer(unsigned *indexArray);
109
110 private:
111
112 void initOrder(); // generic initialisation function
113
114 };
115
116 // AmbisonicEncoder -- Higher Order Ambisonic encoding class
117 //
118 // Higher Order Ambisonic class for positioning mono sound sources into an Ambisonic encoded soundfield.
119 // The position information is fed to the encoder as two multichannel framestreams (azimuth and elevation).
120 // It is possible to specify either one uniform Ambisonic order or to define the horizontal and vertical
121 // order separately (hybrid order encoding). If no order(s) is/are specified, first order Ambisonic will be used (B-Format).
122
123 class AmbisonicEncoder : public AmbisonicUnitGenerator {
124 public:
125
126 AmbisonicEncoder(); ///< Default constructor
127 AmbisonicEncoder(SpatialSource &input, unsigned order = 1); ///< Initialize with uniform Ambisonic order
128 AmbisonicEncoder(SpatialSource &input, unsigned horder, unsigned vorder); ///< Initialize with hybrid Ambisonic order
129
130 virtual ~AmbisonicEncoder(); ///< Destructor
131
132 void setInput(SpatialSource &input); ///< Set my input
133 SpatialSource *input() { return (SpatialSource *)mInputPort->mUGen; };
134
135 /// Does the DSP processing for the Ambisonic Encoder.
136 virtual void nextBuffer(Buffer &outputBuffer, unsigned outBufNum) throw (CException);
137
138 protected:
139 SampleBuffer mWeights; ///< Encoding weights for each order (per source)
140 Port *mInputPort; ///< Holds the input to be encoded.
141 void initialize(); ///< Initializing method called by constructors
142 };
143
144 /// Flag for the decoding method
145
146 typedef enum {
147 kPSEUDOINVERSE = 0,
148 kPROJECTION
149 } AmbisonicDecoderMethod;
150
151 /// Flag for the decoder flavour
152
153 typedef enum {
154 kBASIC = 0,
155 kINPHASE,
156 kMAXRE
157 } AmbisonicDecoderFlavour;
158
159 //
160 // AmbisonicDecoder -- Higher Order Ambisonic Decoding class
161 //
162 // Higher Order Ambisonic class for decoding an Ambisonic encoded soundfield (e.g. the output of the AmbisonicEncoder or
163 // the AmbisonicRotator) to a loudspeaker layout specified by SpeakerLayout. The Ambisonic order at which the decoder
164 // oprates is derived by the following criteria: If no order is specified in the constructor, the order of the Ambisonic
165 // encoded input is used. This order can be downgraded either by specifying a lower order in the constructor
166 // (obviously, it cannot be increased). The decoder might further decrease the given order to match the maximum
167 // order reproducable on the available loudspeaker layout. One out of two different decoding methods can be chosen by
168 // using the flags kPROJECTION, kPSEUDOINVERSE in the constructor. One out of three available decoder flavors can
169 // be applied by using the flags kBASIC, kINPHASE, kMAXRE.
170 //
171
172 class AmbisonicDecoder : public AmbisonicUnitGenerator {
173 public:
174 // Constructors & destructor:
175 /// Defaults to standard speaker layout as defined in "HOA_SpeakerLayout" class and to Ambisonic order of encoded input
176 AmbisonicDecoder(AmbisonicUnitGenerator &input,
177 SpeakerLayout *layout = SpeakerLayout::defaultSpeakerLayout(),
178 AmbisonicDecoderMethod method = kPROJECTION,
179 AmbisonicDecoderFlavour flavour = kBASIC);
180 /// Initializes with uniform Ambisonic order, defaults to standard speaker layout as defined in "HOA_SpeakerLayout" class
181 AmbisonicDecoder(UnitGenerator &input, unsigned order,
182 SpeakerLayout *layout = SpeakerLayout::defaultSpeakerLayout(),
183 AmbisonicDecoderMethod method = kPROJECTION,
184 AmbisonicDecoderFlavour flavour = kBASIC);
185 /// Initializes with hybrid Ambisonic order
186 AmbisonicDecoder(UnitGenerator &input, unsigned hOrder, unsigned vOrder,
187 SpeakerLayout *layout = SpeakerLayout::defaultSpeakerLayout(),
188 AmbisonicDecoderMethod method = kPROJECTION,
189 AmbisonicDecoderFlavour flavour = kBASIC);
190
191 ~AmbisonicDecoder(); ///< Destructor
192
193 /// Does the DSP processing for the Ambisonic Decoder.
194 virtual void nextBuffer(Buffer &outputBuffer, unsigned outBufNum) throw (CException);
195
196 protected:
197
198 Port *mInputPort;
199 float mNumChannelsInv; // inverse of the numbers of loudspeakers (used for normalization)
200 int *mIOChannelMap; // lookup table from index of actually used Ambisonic channel input Ambisonic channel index
201 SampleBufferVector mDecodingMatrix; // deccoding matrix D
202 SpeakerLayout *mSpeakerLayout; // loudspeaker layout provided by "HOA_SpeakerLayout" class
203 AmbisonicDecoderMethod mDecodingMethod; // decoding method: projection or pseudoinverse
204 AmbisonicDecoderFlavour mDecoderFlavour; // decoder flavour: basic, in-phase or max-rE
205
206
207 /// initializing method called by constructors
208 void initialize(UnitGenerator &input, AmbisonicDecoderMethod method, AmbisonicDecoderFlavour flavour);
209
210 void asProjection(); ///< Create the decoding matrix "D" using the projection method
211 void asPseudoInverse(); ///< create the decoding matrix "D" using the pseudoinverse method
212
213 void makeInPhase(unsigned greaterOrder); ///< Adjusts the decoding matrix D for in-phase flavour
214 void makeMaxRE(unsigned greaterOrder); ///< Adjusts the decoding matrix D for Max rE flavour
215
216 void makeTransposedReEncodingMatrix(float **transposeMatrix); ///< Utility method that creates the transposed re-encoding matrix C'
217
218 };
219
220 }
221
222 #endif