3D Audio GSoC:
[blender.git] / intern / audaspace / intern / AUD_ChannelMapperReader.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * Copyright 2009-2011 Jörg Hermann Müller
7  *
8  * This file is part of AudaSpace.
9  *
10  * Audaspace is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * AudaSpace is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Audaspace; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file audaspace/intern/AUD_ChannelMapperReader.cpp
28  *  \ingroup audaspaceintern
29  */
30
31 #include <cmath>
32
33 #ifndef M_PI
34 #define M_PI 3.14159265358979323846
35 #endif
36
37 #ifndef M_PI_2
38 #define M_PI_2 1.57079632679489661923
39 #endif
40
41 #include "AUD_ChannelMapperReader.h"
42
43 AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_Reference<AUD_IReader> reader,
44                                                                                                  AUD_Channels channels) :
45                 AUD_EffectReader(reader), m_target_channels(channels),
46         m_source_channels(AUD_CHANNELS_INVALID), m_mapping(0), m_map_size(0), m_mono_angle(0)
47 {
48 }
49
50 AUD_ChannelMapperReader::~AUD_ChannelMapperReader()
51 {
52         delete[] m_mapping;
53 }
54
55 void AUD_ChannelMapperReader::setChannels(AUD_Channels channels)
56 {
57         m_target_channels = channels;
58         calculateMapping();
59 }
60
61 void AUD_ChannelMapperReader::setMonoAngle(float angle)
62 {
63         m_mono_angle = angle;
64         if(m_source_channels == AUD_CHANNELS_MONO)
65                 calculateMapping();
66 }
67
68 float AUD_ChannelMapperReader::angleDistance(float alpha, float beta)
69 {
70         alpha = fabs(alpha - beta);
71
72         if(alpha > M_PI)
73                 alpha = fabs(alpha - 2 * M_PI);
74
75         return alpha;
76 }
77
78 #include <iostream>
79
80 void AUD_ChannelMapperReader::calculateMapping()
81 {
82         if(m_map_size < m_source_channels * m_target_channels)
83         {
84                 delete[] m_mapping;
85                 m_mapping = new float[m_source_channels * m_target_channels];
86                 m_map_size = m_source_channels * m_target_channels;
87         }
88
89         for(int i = 0; i < m_source_channels * m_target_channels; i++)
90                 m_mapping[i] = 0;
91
92         const AUD_Channel* source_channels = CHANNEL_MAPS[m_source_channels - 1];
93         const AUD_Channel* target_channels = CHANNEL_MAPS[m_target_channels - 1];
94
95         int lfe = -1;
96
97         for(int i = 0; i < m_target_channels; i++)
98         {
99                 if(target_channels[i] == AUD_CHANNEL_LFE)
100                 {
101                         lfe = i;
102                         break;
103                 }
104         }
105
106         const float* source_angles = CHANNEL_ANGLES[m_source_channels - 1];
107         const float* target_angles = CHANNEL_ANGLES[m_target_channels - 1];
108
109         if(m_source_channels == AUD_CHANNELS_MONO)
110                 source_angles = &m_mono_angle;
111
112         int channel_min1, channel_min2;
113         float angle_min1, angle_min2, angle;
114
115         for(int i = 0; i < m_source_channels; i++)
116         {
117                 if(source_channels[i] == AUD_CHANNEL_LFE)
118                 {
119                         if(lfe != -1)
120                                 m_mapping[lfe * m_source_channels + i] = 1;
121
122                         continue;
123                 }
124
125                 channel_min1 = channel_min2 = -1;
126                 angle_min1 = angle_min2 = 2 * M_PI;
127
128                 for(int j = 0; j < m_target_channels; j++)
129                 {
130                         angle = angleDistance(source_angles[i], target_angles[j]);
131                         if(angle < angle_min1)
132                         {
133                                 channel_min2 = channel_min1;
134                                 angle_min2 = angle_min1;
135
136                                 channel_min1 = j;
137                                 angle_min1 = angle;
138                         }
139                         else if(angle < angle_min2)
140                         {
141                                 channel_min2 = j;
142                                 angle_min2 = angle;
143                         }
144                 }
145
146                 angle = angle_min1 + angle_min2;
147                 if(channel_min2 == -1 || angle == 0)
148                 {
149                         m_mapping[channel_min1 * m_source_channels + i] = 1;
150                 }
151                 else
152                 {
153                         m_mapping[channel_min1 * m_source_channels + i] = cos(M_PI_2 * angle_min1 / angle);
154                         m_mapping[channel_min2 * m_source_channels + i] = cos(M_PI_2 * angle_min2 / angle);
155                 }
156         }
157
158         /* AUD_XXX for(int i = 0; i < m_source_channels; i++)
159         {
160                 for(int j = 0; j < m_target_channels; j++)
161                 {
162                         std::cout << m_mapping[i * m_source_channels + j] << " ";
163                 }
164                 std::cout << std::endl;
165         }*/
166 }
167
168 AUD_Specs AUD_ChannelMapperReader::getSpecs() const
169 {
170         AUD_Specs specs = m_reader->getSpecs();
171         specs.channels = m_target_channels;
172         return specs;
173 }
174
175 void AUD_ChannelMapperReader::read(int& length, bool& eos, sample_t* buffer)
176 {
177         AUD_Channels channels = m_reader->getSpecs().channels;
178         if(channels != m_source_channels)
179         {
180                 m_source_channels = channels;
181                 calculateMapping();
182         }
183
184         if(m_source_channels == m_target_channels)
185         {
186                 m_reader->read(length, eos, buffer);
187                 return;
188         }
189
190         m_buffer.assureSize(length * channels * sizeof(sample_t));
191
192         sample_t* in = m_buffer.getBuffer();
193
194         m_reader->read(length, eos, in);
195
196         sample_t sum;
197
198         for(int i = 0; i < length; i++)
199         {
200                 for(int j = 0; j < m_target_channels; j++)
201                 {
202                         sum = 0;
203                         for(int k = 0; k < m_source_channels; k++)
204                                 sum += m_mapping[j * m_source_channels + k] * in[i * m_source_channels + k];
205                         buffer[i * m_target_channels + j] = sum;
206                 }
207         }
208 }
209
210 const AUD_Channel AUD_ChannelMapperReader::MONO_MAP[] =
211 {
212         AUD_CHANNEL_FRONT_CENTER
213 };
214
215 const AUD_Channel AUD_ChannelMapperReader::STEREO_MAP[] =
216 {
217         AUD_CHANNEL_FRONT_LEFT,
218         AUD_CHANNEL_FRONT_RIGHT
219 };
220
221 const AUD_Channel AUD_ChannelMapperReader::STEREO_LFE_MAP[] =
222 {
223         AUD_CHANNEL_FRONT_LEFT,
224         AUD_CHANNEL_FRONT_RIGHT,
225         AUD_CHANNEL_LFE
226 };
227
228 const AUD_Channel AUD_ChannelMapperReader::SURROUND4_MAP[] =
229 {
230         AUD_CHANNEL_FRONT_LEFT,
231         AUD_CHANNEL_FRONT_RIGHT,
232         AUD_CHANNEL_REAR_LEFT,
233         AUD_CHANNEL_REAR_RIGHT
234 };
235
236 const AUD_Channel AUD_ChannelMapperReader::SURROUND5_MAP[] =
237 {
238         AUD_CHANNEL_FRONT_LEFT,
239         AUD_CHANNEL_FRONT_RIGHT,
240         AUD_CHANNEL_FRONT_CENTER,
241         AUD_CHANNEL_REAR_LEFT,
242         AUD_CHANNEL_REAR_RIGHT
243 };
244
245 const AUD_Channel AUD_ChannelMapperReader::SURROUND51_MAP[] =
246 {
247         AUD_CHANNEL_FRONT_LEFT,
248         AUD_CHANNEL_FRONT_RIGHT,
249         AUD_CHANNEL_FRONT_CENTER,
250         AUD_CHANNEL_LFE,
251         AUD_CHANNEL_REAR_LEFT,
252         AUD_CHANNEL_REAR_RIGHT
253 };
254
255 const AUD_Channel AUD_ChannelMapperReader::SURROUND61_MAP[] =
256 {
257         AUD_CHANNEL_FRONT_LEFT,
258         AUD_CHANNEL_FRONT_RIGHT,
259         AUD_CHANNEL_FRONT_CENTER,
260         AUD_CHANNEL_LFE,
261         AUD_CHANNEL_REAR_CENTER,
262         AUD_CHANNEL_REAR_LEFT,
263         AUD_CHANNEL_REAR_RIGHT
264 };
265
266 const AUD_Channel AUD_ChannelMapperReader::SURROUND71_MAP[] =
267 {
268         AUD_CHANNEL_FRONT_LEFT,
269         AUD_CHANNEL_FRONT_RIGHT,
270         AUD_CHANNEL_FRONT_CENTER,
271         AUD_CHANNEL_LFE,
272         AUD_CHANNEL_REAR_LEFT,
273         AUD_CHANNEL_REAR_RIGHT,
274         AUD_CHANNEL_SIDE_LEFT,
275         AUD_CHANNEL_SIDE_RIGHT
276 };
277
278 const AUD_Channel* AUD_ChannelMapperReader::CHANNEL_MAPS[] =
279 {
280         AUD_ChannelMapperReader::MONO_MAP,
281         AUD_ChannelMapperReader::STEREO_MAP,
282         AUD_ChannelMapperReader::STEREO_LFE_MAP,
283         AUD_ChannelMapperReader::SURROUND4_MAP,
284         AUD_ChannelMapperReader::SURROUND5_MAP,
285         AUD_ChannelMapperReader::SURROUND51_MAP,
286         AUD_ChannelMapperReader::SURROUND61_MAP,
287         AUD_ChannelMapperReader::SURROUND71_MAP
288 };
289
290 const float AUD_ChannelMapperReader::MONO_ANGLES[] =
291 {
292         0.0f * M_PI / 180.0f
293 };
294
295 const float AUD_ChannelMapperReader::STEREO_ANGLES[] =
296 {
297         -90.0f * M_PI / 180.0f,
298          90.0f * M_PI / 180.0f
299 };
300
301 const float AUD_ChannelMapperReader::STEREO_LFE_ANGLES[] =
302 {
303    -90.0f * M_PI / 180.0f,
304         90.0f * M_PI / 180.0f,
305          0.0f * M_PI / 180.0f
306 };
307
308 const float AUD_ChannelMapperReader::SURROUND4_ANGLES[] =
309 {
310          -45.0f * M_PI / 180.0f,
311           45.0f * M_PI / 180.0f,
312         -135.0f * M_PI / 180.0f,
313          135.0f * M_PI / 180.0f
314 };
315
316 const float AUD_ChannelMapperReader::SURROUND5_ANGLES[] =
317 {
318          -30.0f * M_PI / 180.0f,
319           30.0f * M_PI / 180.0f,
320            0.0f * M_PI / 180.0f,
321         -110.0f * M_PI / 180.0f,
322          110.0f * M_PI / 180.0f
323 };
324
325 const float AUD_ChannelMapperReader::SURROUND51_ANGLES[] =
326 {
327           -30.0f * M_PI / 180.0f,
328            30.0f * M_PI / 180.0f,
329            0.0f * M_PI / 180.0f,
330            0.0f * M_PI / 180.0f,
331         -110.0f * M_PI / 180.0f,
332          110.0f * M_PI / 180.0f
333 };
334
335 const float AUD_ChannelMapperReader::SURROUND61_ANGLES[] =
336 {
337           -30.0f * M_PI / 180.0f,
338            30.0f * M_PI / 180.0f,
339            0.0f * M_PI / 180.0f,
340            0.0f * M_PI / 180.0f,
341          180.0f * M_PI / 180.0f,
342         -110.0f * M_PI / 180.0f,
343          110.0f * M_PI / 180.0f
344 };
345
346 const float AUD_ChannelMapperReader::SURROUND71_ANGLES[] =
347 {
348           -30.0f * M_PI / 180.0f,
349            30.0f * M_PI / 180.0f,
350            0.0f * M_PI / 180.0f,
351            0.0f * M_PI / 180.0f,
352         -110.0f * M_PI / 180.0f,
353          110.0f * M_PI / 180.0f
354         -150.0f * M_PI / 180.0f,
355          150.0f * M_PI / 180.0f
356 };
357
358 const float* AUD_ChannelMapperReader::CHANNEL_ANGLES[] =
359 {
360         AUD_ChannelMapperReader::MONO_ANGLES,
361         AUD_ChannelMapperReader::STEREO_ANGLES,
362         AUD_ChannelMapperReader::STEREO_LFE_ANGLES,
363         AUD_ChannelMapperReader::SURROUND4_ANGLES,
364         AUD_ChannelMapperReader::SURROUND5_ANGLES,
365         AUD_ChannelMapperReader::SURROUND51_ANGLES,
366         AUD_ChannelMapperReader::SURROUND61_ANGLES,
367         AUD_ChannelMapperReader::SURROUND71_ANGLES
368 };