2.5 Audio:
[blender.git] / intern / audaspace / intern / AUD_Mixer.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN LGPL LICENSE BLOCK *****
5  *
6  * Copyright 2009 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 Lesser General Public License as published by
12  * the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  * ***** END LGPL LICENSE BLOCK *****
24  */
25
26 #include "AUD_Mixer.h"
27 #include "AUD_SRCResampleFactory.h"
28 #include "AUD_LinearResampleFactory.h"
29 #include "AUD_ChannelMapperFactory.h"
30 #include "AUD_IReader.h"
31 #include "AUD_Buffer.h"
32
33 #include <cstring>
34
35 AUD_Mixer::AUD_Mixer()
36 {
37         m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
38
39         m_resampler = NULL;
40         m_mapper = NULL;
41 }
42
43 AUD_Mixer::~AUD_Mixer()
44 {
45         delete m_buffer; AUD_DELETE("buffer")
46
47
48         if(m_resampler)
49         {
50                 delete m_resampler; AUD_DELETE("factory")
51         }
52         if(m_mapper)
53         {
54                 delete m_mapper; AUD_DELETE("factory")
55         }
56 }
57
58 AUD_IReader* AUD_Mixer::prepare(AUD_IReader* reader)
59 {
60         m_resampler->setReader(reader);
61         reader = m_resampler->createReader();
62
63         if(reader != NULL && reader->getSpecs().channels != m_specs.channels)
64         {
65                 m_mapper->setReader(reader);
66                 reader = m_mapper->createReader();
67         }
68
69         return reader;
70 }
71
72 AUD_DeviceSpecs AUD_Mixer::getSpecs()
73 {
74         return m_specs;
75 }
76
77 void AUD_Mixer::setSpecs(AUD_DeviceSpecs specs)
78 {
79         m_specs = specs;
80
81         if(m_resampler)
82         {
83                 delete m_resampler; AUD_DELETE("factory")
84         }
85         if(m_mapper)
86         {
87                 delete m_mapper; AUD_DELETE("factory")
88         }
89
90         m_resampler = new AUD_MIXER_RESAMPLER(specs); AUD_NEW("factory")
91         m_mapper = new AUD_ChannelMapperFactory(specs); AUD_NEW("factory")
92
93         int bigendian = 1;
94         bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
95
96         switch(m_specs.format)
97         {
98         case AUD_FORMAT_U8:
99                 m_convert = AUD_convert_float_u8;
100                 break;
101         case AUD_FORMAT_S16:
102                 m_convert = AUD_convert_float_s16;
103                 break;
104         case AUD_FORMAT_S24:
105                 if(bigendian)
106                         m_convert = AUD_convert_float_s24_be;
107                 else
108                         m_convert = AUD_convert_float_s24_le;
109                 break;
110         case AUD_FORMAT_S32:
111                 m_convert = AUD_convert_float_s32;
112                 break;
113         case AUD_FORMAT_FLOAT32:
114                 m_convert = AUD_convert_copy<float>;
115                 break;
116         case AUD_FORMAT_FLOAT64:
117                 m_convert = AUD_convert_float_double;
118                 break;
119         default:
120                 break;
121         }
122 }
123
124 void AUD_Mixer::add(sample_t* buffer, int start, int length, float volume)
125 {
126         AUD_MixerBuffer buf;
127         buf.buffer = buffer;
128         buf.start = start;
129         buf.length = length;
130         buf.volume = volume;
131         m_buffers.push_back(buf);
132 }
133
134 void AUD_Mixer::superpose(data_t* buffer, int length, float volume)
135 {
136         AUD_MixerBuffer buf;
137
138         int channels = m_specs.channels;
139
140         if(m_buffer->getSize() < length * channels * 4)
141                 m_buffer->resize(length * channels * 4);
142
143         sample_t* out = m_buffer->getBuffer();
144         sample_t* in;
145
146         memset(out, 0, length * channels * 4);
147
148         int end;
149
150         while(!m_buffers.empty())
151         {
152                 buf = m_buffers.front();
153                 m_buffers.pop_front();
154
155                 end = buf.length * channels;
156                 in = buf.buffer;
157
158                 for(int i = 0; i < end; i++)
159                         out[i + buf.start * channels] += in[i] * buf.volume * volume;
160         }
161
162         m_convert(buffer, (data_t*) out, length * channels);
163 }