Merge lp:~mixxxdevelopers/mixxx/features_hydra into lp:~mixxxdevelopers/mixxx/trunk
- features_hydra
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 2721 |
Proposed branch: | lp:~mixxxdevelopers/mixxx/features_hydra |
Merge into: | lp:~mixxxdevelopers/mixxx/trunk |
Diff against target: |
923 lines (+456/-204) 9 files modified
mixxx/build/depends.py (+0/-1) mixxx/src/engine/enginechannel.cpp (+0/-11) mixxx/src/engine/enginechannel.h (+0/-3) mixxx/src/engine/enginemaster.cpp (+210/-98) mixxx/src/engine/enginemaster.h (+57/-9) mixxx/src/engine/enginevolume.cpp (+0/-42) mixxx/src/engine/enginevolume.h (+0/-36) mixxx/src/sampleutil.cpp (+149/-0) mixxx/src/sampleutil.h (+40/-4) |
To merge this branch: | bzr merge lp:~mixxxdevelopers/mixxx/features_hydra |
Related bugs: | |
Related blueprints: |
Multiple Decks
(Medium)
Hydra Optimizations
(Essential)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Albert Santoni | Approve | ||
Review via email: mp+55693@code.launchpad.net |
Commit message
Description of the change
Threw together some quick engine changes, but I'd like a review on them because they're substantial:
* Delete EngineVolume -- it was a trivial wrapper around a ControlLogpotmeter
* Make per-channel volume a gain factor when mixing the master output. This eliminates some hackyness w/ EngineChannel:
* Eliminate use of QList in EngineMaster:
RJ Skerry-Ryan (rryan) wrote : | # |
- 2721. By RJ Skerry-Ryan
-
More improvements to EngineMaster. Headphone mixing now goes through the fast-path of mixing channels instead of being added one by one (this has the added benefit of unifying the mixing code used for both the master and headphone channels). Added special-casing for the mixing of up to 7 channels. Folded the master volume into the master mixing step so we save a pass over the buffer there.
RJ Skerry-Ryan (rryan) wrote : | # |
Many more improvements now. I think this tightens up the EngineMaster code quite a bit. Headphone and master mixing are both done through the same codepath now. I also shaved another pass off by folding the master volume into the master mixing step. Headphone mixing is now faster because it uses the hard-coded mixing steps instead of the N-pass adding.
- 2722. By RJ Skerry-Ryan
-
Forgot a return value, and for some braindead reason GCC compiled it.
Albert Santoni (gamegod) wrote : | # |
I checked the coefficients and looked over the code, didn't see anything that looks out of place. Though we haven't measured the performance gains, this is definitely a step in the right direction.
Thanks RJ!
Preview Diff
1 | === modified file 'mixxx/build/depends.py' | |||
2 | --- mixxx/build/depends.py 2011-03-29 08:45:42 +0000 | |||
3 | +++ mixxx/build/depends.py 2011-04-01 04:36:32 +0000 | |||
4 | @@ -358,7 +358,6 @@ | |||
5 | 358 | "engine/enginefilter.cpp", | 358 | "engine/enginefilter.cpp", |
6 | 359 | "engine/engineobject.cpp", | 359 | "engine/engineobject.cpp", |
7 | 360 | "engine/enginepregain.cpp", | 360 | "engine/enginepregain.cpp", |
8 | 361 | "engine/enginevolume.cpp", | ||
9 | 362 | "engine/enginechannel.cpp", | 361 | "engine/enginechannel.cpp", |
10 | 363 | "engine/enginemaster.cpp", | 362 | "engine/enginemaster.cpp", |
11 | 364 | "engine/enginedelay.cpp", | 363 | "engine/enginedelay.cpp", |
12 | 365 | 364 | ||
13 | === modified file 'mixxx/src/engine/enginechannel.cpp' | |||
14 | --- mixxx/src/engine/enginechannel.cpp 2011-03-13 00:21:05 +0000 | |||
15 | +++ mixxx/src/engine/enginechannel.cpp 2011-04-01 04:36:32 +0000 | |||
16 | @@ -22,7 +22,6 @@ | |||
17 | 22 | #include "enginechannel.h" | 22 | #include "enginechannel.h" |
18 | 23 | #include "engineclipping.h" | 23 | #include "engineclipping.h" |
19 | 24 | #include "enginepregain.h" | 24 | #include "enginepregain.h" |
20 | 25 | #include "enginevolume.h" | ||
21 | 26 | #include "engineflanger.h" | 25 | #include "engineflanger.h" |
22 | 27 | #include "enginefilterblock.h" | 26 | #include "enginefilterblock.h" |
23 | 28 | #include "enginevumeter.h" | 27 | #include "enginevumeter.h" |
24 | @@ -39,7 +38,6 @@ | |||
25 | 39 | m_pClipping = new EngineClipping(group); | 38 | m_pClipping = new EngineClipping(group); |
26 | 40 | m_pBuffer = new EngineBuffer(group, pConfig); | 39 | m_pBuffer = new EngineBuffer(group, pConfig); |
27 | 41 | m_pVinylSoundEmu = new EngineVinylSoundEmu(pConfig, group); | 40 | m_pVinylSoundEmu = new EngineVinylSoundEmu(pConfig, group); |
28 | 42 | m_pVolume = new EngineVolume(ConfigKey(group, "volume")); | ||
29 | 43 | m_pVUMeter = new EngineVuMeter(group); | 41 | m_pVUMeter = new EngineVuMeter(group); |
30 | 44 | m_pPFL = new ControlPushButton(ConfigKey(group, "pfl")); | 42 | m_pPFL = new ControlPushButton(ConfigKey(group, "pfl")); |
31 | 45 | m_pPFL->setToggleButton(true); | 43 | m_pPFL->setToggleButton(true); |
32 | @@ -54,7 +52,6 @@ | |||
33 | 54 | delete m_pFlanger; | 52 | delete m_pFlanger; |
34 | 55 | delete m_pPregain; | 53 | delete m_pPregain; |
35 | 56 | delete m_pVinylSoundEmu; | 54 | delete m_pVinylSoundEmu; |
36 | 57 | delete m_pVolume; | ||
37 | 58 | delete m_pVUMeter; | 55 | delete m_pVUMeter; |
38 | 59 | delete m_pPFL; | 56 | delete m_pPFL; |
39 | 60 | } | 57 | } |
40 | @@ -82,14 +79,6 @@ | |||
41 | 82 | m_pClipping->process(pOut, pOut, iBufferSize); | 79 | m_pClipping->process(pOut, pOut, iBufferSize); |
42 | 83 | // Update VU meter | 80 | // Update VU meter |
43 | 84 | m_pVUMeter->process(pOut, pOut, iBufferSize); | 81 | m_pVUMeter->process(pOut, pOut, iBufferSize); |
44 | 85 | // Apply channel volume if we aren't PFL | ||
45 | 86 | if (!isPFL()) { | ||
46 | 87 | m_pVolume->process(pOut, pOut, iBufferSize); | ||
47 | 88 | } | ||
48 | 89 | } | ||
49 | 90 | |||
50 | 91 | void EngineChannel::applyVolume(CSAMPLE *pBuff, const int iBufferSize) const { | ||
51 | 92 | m_pVolume->process(pBuff, pBuff, iBufferSize); | ||
52 | 93 | } | 82 | } |
53 | 94 | 83 | ||
54 | 95 | EngineBuffer* EngineChannel::getEngineBuffer() { | 84 | EngineBuffer* EngineChannel::getEngineBuffer() { |
55 | 96 | 85 | ||
56 | === modified file 'mixxx/src/engine/enginechannel.h' | |||
57 | --- mixxx/src/engine/enginechannel.h 2011-03-13 00:21:05 +0000 | |||
58 | +++ mixxx/src/engine/enginechannel.h 2011-04-01 04:36:32 +0000 | |||
59 | @@ -27,7 +27,6 @@ | |||
60 | 27 | class EngineBuffer; | 27 | class EngineBuffer; |
61 | 28 | class EngineFilterBlock; | 28 | class EngineFilterBlock; |
62 | 29 | class EngineClipping; | 29 | class EngineClipping; |
63 | 30 | class EngineVolume; | ||
64 | 31 | class EngineFlanger; | 30 | class EngineFlanger; |
65 | 32 | class EngineVuMeter; | 31 | class EngineVuMeter; |
66 | 33 | class EngineVinylSoundEmu; | 32 | class EngineVinylSoundEmu; |
67 | @@ -50,7 +49,6 @@ | |||
68 | 50 | virtual const QString& getGroup(); | 49 | virtual const QString& getGroup(); |
69 | 51 | 50 | ||
70 | 52 | virtual void process(const CSAMPLE *pIn, const CSAMPLE *pOut, const int iBufferSize); | 51 | virtual void process(const CSAMPLE *pIn, const CSAMPLE *pOut, const int iBufferSize); |
71 | 53 | virtual void applyVolume(CSAMPLE *pBuff, const int iBufferSize) const; | ||
72 | 54 | 52 | ||
73 | 55 | // TODO(XXX) This hack needs to be removed. | 53 | // TODO(XXX) This hack needs to be removed. |
74 | 56 | virtual EngineBuffer* getEngineBuffer(); | 54 | virtual EngineBuffer* getEngineBuffer(); |
75 | @@ -68,7 +66,6 @@ | |||
76 | 68 | EngineFlanger* m_pFlanger; | 66 | EngineFlanger* m_pFlanger; |
77 | 69 | EnginePregain* m_pPregain; | 67 | EnginePregain* m_pPregain; |
78 | 70 | EngineVinylSoundEmu* m_pVinylSoundEmu; | 68 | EngineVinylSoundEmu* m_pVinylSoundEmu; |
79 | 71 | EngineVolume* m_pVolume; | ||
80 | 72 | EngineVuMeter* m_pVUMeter; | 69 | EngineVuMeter* m_pVUMeter; |
81 | 73 | }; | 70 | }; |
82 | 74 | 71 | ||
83 | 75 | 72 | ||
84 | === modified file 'mixxx/src/engine/enginemaster.cpp' | |||
85 | --- mixxx/src/engine/enginemaster.cpp 2010-12-16 16:29:53 +0000 | |||
86 | +++ mixxx/src/engine/enginemaster.cpp 2011-04-01 04:36:32 +0000 | |||
87 | @@ -21,12 +21,12 @@ | |||
88 | 21 | 21 | ||
89 | 22 | #include "controlpushbutton.h" | 22 | #include "controlpushbutton.h" |
90 | 23 | #include "configobject.h" | 23 | #include "configobject.h" |
91 | 24 | #include "controllogpotmeter.h" | ||
92 | 24 | #include "controlpotmeter.h" | 25 | #include "controlpotmeter.h" |
93 | 25 | #include "enginebuffer.h" | 26 | #include "enginebuffer.h" |
94 | 26 | #include "enginemaster.h" | 27 | #include "enginemaster.h" |
95 | 27 | #include "engine/engineworkerscheduler.h" | 28 | #include "engine/engineworkerscheduler.h" |
96 | 28 | #include "enginebuffer.h" | 29 | #include "enginebuffer.h" |
97 | 29 | #include "enginevolume.h" | ||
98 | 30 | #include "enginechannel.h" | 30 | #include "enginechannel.h" |
99 | 31 | #include "engineclipping.h" | 31 | #include "engineclipping.h" |
100 | 32 | #include "enginevumeter.h" | 32 | #include "enginevumeter.h" |
101 | @@ -66,7 +66,7 @@ | |||
102 | 66 | m_pBalance = new ControlPotmeter(ConfigKey(group, "balance"), -1., 1.); | 66 | m_pBalance = new ControlPotmeter(ConfigKey(group, "balance"), -1., 1.); |
103 | 67 | 67 | ||
104 | 68 | // Master volume | 68 | // Master volume |
106 | 69 | volume = new EngineVolume(ConfigKey(group,"volume"), 5.); | 69 | m_pMasterVolume = new ControlLogpotmeter(ConfigKey(group, "volume"), 5.); |
107 | 70 | 70 | ||
108 | 71 | // Clipping | 71 | // Clipping |
109 | 72 | clipping = new EngineClipping(group); | 72 | clipping = new EngineClipping(group); |
110 | @@ -75,7 +75,7 @@ | |||
111 | 75 | vumeter = new EngineVuMeter(group); | 75 | vumeter = new EngineVuMeter(group); |
112 | 76 | 76 | ||
113 | 77 | // Headphone volume | 77 | // Headphone volume |
115 | 78 | head_volume = new EngineVolume(ConfigKey(group, "headVolume"), 5.); | 78 | m_pHeadVolume = new ControlLogpotmeter(ConfigKey(group, "headVolume"), 5.); |
116 | 79 | 79 | ||
117 | 80 | // Headphone mix (left/right) | 80 | // Headphone mix (left/right) |
118 | 81 | head_mix = new ControlPotmeter(ConfigKey(group, "headMix"),-1.,1.); | 81 | head_mix = new ControlPotmeter(ConfigKey(group, "headMix"),-1.,1.); |
119 | @@ -105,34 +105,24 @@ | |||
120 | 105 | delete crossfader; | 105 | delete crossfader; |
121 | 106 | delete m_pBalance; | 106 | delete m_pBalance; |
122 | 107 | delete head_mix; | 107 | delete head_mix; |
125 | 108 | delete volume; | 108 | delete m_pMasterVolume; |
126 | 109 | delete head_volume; | 109 | delete m_pHeadVolume; |
127 | 110 | delete clipping; | 110 | delete clipping; |
128 | 111 | delete head_clipping; | 111 | delete head_clipping; |
129 | 112 | delete sidechain; | 112 | delete sidechain; |
130 | 113 | 113 | ||
131 | 114 | |||
132 | 115 | SampleUtil::free(m_pHead); | 114 | SampleUtil::free(m_pHead); |
133 | 116 | SampleUtil::free(m_pMaster); | 115 | SampleUtil::free(m_pMaster); |
134 | 117 | 116 | ||
145 | 118 | 117 | QMutableListIterator<ChannelInfo*> channel_it(m_channels); | |
136 | 119 | QMutableListIterator<CSAMPLE*> buffer_it(m_channelBuffers); | ||
137 | 120 | while (buffer_it.hasNext()) { | ||
138 | 121 | CSAMPLE* buffer = buffer_it.next(); | ||
139 | 122 | buffer_it.remove(); | ||
140 | 123 | SampleUtil::free(buffer); | ||
141 | 124 | } | ||
142 | 125 | |||
143 | 126 | |||
144 | 127 | QMutableListIterator<EngineChannel*> channel_it(m_channels); | ||
146 | 128 | while (channel_it.hasNext()) { | 118 | while (channel_it.hasNext()) { |
148 | 129 | EngineChannel* channel = channel_it.next(); | 119 | ChannelInfo* pChannelInfo = channel_it.next(); |
149 | 130 | channel_it.remove(); | 120 | channel_it.remove(); |
151 | 131 | delete channel; | 121 | SampleUtil::free(pChannelInfo->m_pBuffer); |
152 | 122 | delete pChannelInfo->m_pChannel; | ||
153 | 123 | delete pChannelInfo->m_pVolumeControl; | ||
154 | 124 | delete pChannelInfo; | ||
155 | 132 | } | 125 | } |
156 | 133 | |||
157 | 134 | |||
158 | 135 | |||
159 | 136 | } | 126 | } |
160 | 137 | 127 | ||
161 | 138 | const CSAMPLE* EngineMaster::getMasterBuffer() const | 128 | const CSAMPLE* EngineMaster::getMasterBuffer() const |
162 | @@ -145,6 +135,167 @@ | |||
163 | 145 | return m_pHead; | 135 | return m_pHead; |
164 | 146 | } | 136 | } |
165 | 147 | 137 | ||
166 | 138 | void EngineMaster::mixChannels(unsigned int channelBitvector, unsigned int maxChannels, | ||
167 | 139 | CSAMPLE* pOutput, unsigned int iBufferSize, | ||
168 | 140 | GainCalculator* pGainCalculator) { | ||
169 | 141 | // Common case: 2 decks, 4 samplers, 1 mic | ||
170 | 142 | ChannelInfo* pChannel1 = NULL; | ||
171 | 143 | ChannelInfo* pChannel2 = NULL; | ||
172 | 144 | ChannelInfo* pChannel3 = NULL; | ||
173 | 145 | ChannelInfo* pChannel4 = NULL; | ||
174 | 146 | ChannelInfo* pChannel5 = NULL; | ||
175 | 147 | ChannelInfo* pChannel6 = NULL; | ||
176 | 148 | ChannelInfo* pChannel7 = NULL; | ||
177 | 149 | |||
178 | 150 | unsigned int totalActive = 0; | ||
179 | 151 | for (unsigned int i = 0; i < maxChannels; ++i) { | ||
180 | 152 | if ((channelBitvector & (1 << i)) == 0) { | ||
181 | 153 | continue; | ||
182 | 154 | } | ||
183 | 155 | |||
184 | 156 | ++totalActive; | ||
185 | 157 | |||
186 | 158 | if (pChannel1 == NULL) { | ||
187 | 159 | pChannel1 = m_channels[i]; | ||
188 | 160 | } else if (pChannel2 == NULL) { | ||
189 | 161 | pChannel2 = m_channels[i]; | ||
190 | 162 | } else if (pChannel3 == NULL) { | ||
191 | 163 | pChannel3 = m_channels[i]; | ||
192 | 164 | } else if (pChannel4 == NULL) { | ||
193 | 165 | pChannel4 = m_channels[i]; | ||
194 | 166 | } else if (pChannel5 == NULL) { | ||
195 | 167 | pChannel5 = m_channels[i]; | ||
196 | 168 | } else if (pChannel6 == NULL) { | ||
197 | 169 | pChannel6 = m_channels[i]; | ||
198 | 170 | } else if (pChannel7 == NULL) { | ||
199 | 171 | pChannel7 = m_channels[i]; | ||
200 | 172 | } | ||
201 | 173 | } | ||
202 | 174 | |||
203 | 175 | if (totalActive == 0) { | ||
204 | 176 | SampleUtil::applyGain(pOutput, 0.0f, iBufferSize); | ||
205 | 177 | } else if (totalActive == 1) { | ||
206 | 178 | CSAMPLE* pBuffer1 = pChannel1->m_pBuffer; | ||
207 | 179 | double gain1 = pGainCalculator->getGain(pChannel1); | ||
208 | 180 | SampleUtil::copyWithGain(pOutput, | ||
209 | 181 | pBuffer1, gain1, | ||
210 | 182 | iBufferSize); | ||
211 | 183 | } else if (totalActive == 2) { | ||
212 | 184 | CSAMPLE* pBuffer1 = pChannel1->m_pBuffer; | ||
213 | 185 | double gain1 = pGainCalculator->getGain(pChannel1); | ||
214 | 186 | CSAMPLE* pBuffer2 = pChannel2->m_pBuffer; | ||
215 | 187 | double gain2 = pGainCalculator->getGain(pChannel2); | ||
216 | 188 | SampleUtil::copy2WithGain(pOutput, | ||
217 | 189 | pBuffer1, gain1, | ||
218 | 190 | pBuffer2, gain2, | ||
219 | 191 | iBufferSize); | ||
220 | 192 | } else if (totalActive == 3) { | ||
221 | 193 | CSAMPLE* pBuffer1 = pChannel1->m_pBuffer; | ||
222 | 194 | double gain1 = pGainCalculator->getGain(pChannel1); | ||
223 | 195 | CSAMPLE* pBuffer2 = pChannel2->m_pBuffer; | ||
224 | 196 | double gain2 = pGainCalculator->getGain(pChannel2); | ||
225 | 197 | CSAMPLE* pBuffer3 = pChannel3->m_pBuffer; | ||
226 | 198 | double gain3 = pGainCalculator->getGain(pChannel3); | ||
227 | 199 | |||
228 | 200 | SampleUtil::copy3WithGain(pOutput, | ||
229 | 201 | pBuffer1, gain1, | ||
230 | 202 | pBuffer2, gain2, | ||
231 | 203 | pBuffer3, gain3, | ||
232 | 204 | iBufferSize); | ||
233 | 205 | } else if (totalActive == 4) { | ||
234 | 206 | CSAMPLE* pBuffer1 = pChannel1->m_pBuffer; | ||
235 | 207 | double gain1 = pGainCalculator->getGain(pChannel1); | ||
236 | 208 | CSAMPLE* pBuffer2 = pChannel2->m_pBuffer; | ||
237 | 209 | double gain2 = pGainCalculator->getGain(pChannel2); | ||
238 | 210 | CSAMPLE* pBuffer3 = pChannel3->m_pBuffer; | ||
239 | 211 | double gain3 = pGainCalculator->getGain(pChannel3); | ||
240 | 212 | CSAMPLE* pBuffer4 = pChannel4->m_pBuffer; | ||
241 | 213 | double gain4 = pGainCalculator->getGain(pChannel4); | ||
242 | 214 | SampleUtil::copy4WithGain(pOutput, | ||
243 | 215 | pBuffer1, gain1, | ||
244 | 216 | pBuffer2, gain2, | ||
245 | 217 | pBuffer3, gain3, | ||
246 | 218 | pBuffer4, gain4, | ||
247 | 219 | iBufferSize); | ||
248 | 220 | } else if (totalActive == 5) { | ||
249 | 221 | CSAMPLE* pBuffer1 = pChannel1->m_pBuffer; | ||
250 | 222 | double gain1 = pGainCalculator->getGain(pChannel1); | ||
251 | 223 | CSAMPLE* pBuffer2 = pChannel2->m_pBuffer; | ||
252 | 224 | double gain2 = pGainCalculator->getGain(pChannel2); | ||
253 | 225 | CSAMPLE* pBuffer3 = pChannel3->m_pBuffer; | ||
254 | 226 | double gain3 = pGainCalculator->getGain(pChannel3); | ||
255 | 227 | CSAMPLE* pBuffer4 = pChannel4->m_pBuffer; | ||
256 | 228 | double gain4 = pGainCalculator->getGain(pChannel4); | ||
257 | 229 | CSAMPLE* pBuffer5 = pChannel5->m_pBuffer; | ||
258 | 230 | double gain5 = pGainCalculator->getGain(pChannel5); | ||
259 | 231 | |||
260 | 232 | SampleUtil::copy5WithGain(pOutput, | ||
261 | 233 | pBuffer1, gain1, | ||
262 | 234 | pBuffer2, gain2, | ||
263 | 235 | pBuffer3, gain3, | ||
264 | 236 | pBuffer4, gain4, | ||
265 | 237 | pBuffer5, gain5, | ||
266 | 238 | iBufferSize); | ||
267 | 239 | } else if (totalActive == 6) { | ||
268 | 240 | CSAMPLE* pBuffer1 = pChannel1->m_pBuffer; | ||
269 | 241 | double gain1 = pGainCalculator->getGain(pChannel1); | ||
270 | 242 | CSAMPLE* pBuffer2 = pChannel2->m_pBuffer; | ||
271 | 243 | double gain2 = pGainCalculator->getGain(pChannel2); | ||
272 | 244 | CSAMPLE* pBuffer3 = pChannel3->m_pBuffer; | ||
273 | 245 | double gain3 = pGainCalculator->getGain(pChannel3); | ||
274 | 246 | CSAMPLE* pBuffer4 = pChannel4->m_pBuffer; | ||
275 | 247 | double gain4 = pGainCalculator->getGain(pChannel4); | ||
276 | 248 | CSAMPLE* pBuffer5 = pChannel5->m_pBuffer; | ||
277 | 249 | double gain5 = pGainCalculator->getGain(pChannel5); | ||
278 | 250 | CSAMPLE* pBuffer6 = pChannel6->m_pBuffer; | ||
279 | 251 | double gain6 = pGainCalculator->getGain(pChannel6); | ||
280 | 252 | SampleUtil::copy6WithGain(pOutput, | ||
281 | 253 | pBuffer1, gain1, | ||
282 | 254 | pBuffer2, gain2, | ||
283 | 255 | pBuffer3, gain3, | ||
284 | 256 | pBuffer4, gain4, | ||
285 | 257 | pBuffer5, gain5, | ||
286 | 258 | pBuffer6, gain6, | ||
287 | 259 | iBufferSize); | ||
288 | 260 | } else if (totalActive == 7) { | ||
289 | 261 | CSAMPLE* pBuffer1 = pChannel1->m_pBuffer; | ||
290 | 262 | double gain1 = pGainCalculator->getGain(pChannel1); | ||
291 | 263 | CSAMPLE* pBuffer2 = pChannel2->m_pBuffer; | ||
292 | 264 | double gain2 = pGainCalculator->getGain(pChannel2); | ||
293 | 265 | CSAMPLE* pBuffer3 = pChannel3->m_pBuffer; | ||
294 | 266 | double gain3 = pGainCalculator->getGain(pChannel3); | ||
295 | 267 | CSAMPLE* pBuffer4 = pChannel4->m_pBuffer; | ||
296 | 268 | double gain4 = pGainCalculator->getGain(pChannel4); | ||
297 | 269 | CSAMPLE* pBuffer5 = pChannel5->m_pBuffer; | ||
298 | 270 | double gain5 = pGainCalculator->getGain(pChannel5); | ||
299 | 271 | CSAMPLE* pBuffer6 = pChannel6->m_pBuffer; | ||
300 | 272 | double gain6 = pGainCalculator->getGain(pChannel6); | ||
301 | 273 | CSAMPLE* pBuffer7 = pChannel7->m_pBuffer; | ||
302 | 274 | double gain7 = pGainCalculator->getGain(pChannel7); | ||
303 | 275 | SampleUtil::copy7WithGain(pOutput, | ||
304 | 276 | pBuffer1, gain1, | ||
305 | 277 | pBuffer2, gain2, | ||
306 | 278 | pBuffer3, gain3, | ||
307 | 279 | pBuffer4, gain4, | ||
308 | 280 | pBuffer5, gain5, | ||
309 | 281 | pBuffer6, gain6, | ||
310 | 282 | pBuffer7, gain7, | ||
311 | 283 | iBufferSize); | ||
312 | 284 | } else { | ||
313 | 285 | // Set pOutput to all 0s | ||
314 | 286 | SampleUtil::applyGain(pOutput, 0.0f, iBufferSize); | ||
315 | 287 | |||
316 | 288 | for (unsigned int i = 0; i < maxChannels; ++i) { | ||
317 | 289 | if (channelBitvector & (1 << i)) { | ||
318 | 290 | ChannelInfo* pChannelInfo = m_channels[i]; | ||
319 | 291 | CSAMPLE* pBuffer = pChannelInfo->m_pBuffer; | ||
320 | 292 | double gain = pGainCalculator->getGain(pChannelInfo); | ||
321 | 293 | SampleUtil::addWithGain(pOutput, pBuffer, gain, iBufferSize); | ||
322 | 294 | } | ||
323 | 295 | } | ||
324 | 296 | } | ||
325 | 297 | } | ||
326 | 298 | |||
327 | 148 | void EngineMaster::process(const CSAMPLE *, const CSAMPLE *pOut, const int iBufferSize) | 299 | void EngineMaster::process(const CSAMPLE *, const CSAMPLE *pOut, const int iBufferSize) |
328 | 149 | { | 300 | { |
329 | 150 | CSAMPLE **pOutput = (CSAMPLE**)pOut; | 301 | CSAMPLE **pOutput = (CSAMPLE**)pOut; |
330 | @@ -152,7 +303,10 @@ | |||
331 | 152 | 303 | ||
332 | 153 | // Prepare each channel for output | 304 | // Prepare each channel for output |
333 | 154 | 305 | ||
335 | 155 | QList<QPair<CSAMPLE*, EngineChannel::ChannelOrientation> > masterChannels; | 306 | // Bitvector of enabled channels |
336 | 307 | const unsigned int maxChannels = 32; | ||
337 | 308 | unsigned int masterOutput = 0; | ||
338 | 309 | unsigned int headphoneOutput = 0; | ||
339 | 156 | 310 | ||
340 | 157 | // Compute headphone mix | 311 | // Compute headphone mix |
341 | 158 | // Head phone left/right mix | 312 | // Head phone left/right mix |
342 | @@ -162,88 +316,43 @@ | |||
343 | 162 | // qDebug() << "head val " << cf_val << ", head " << chead_gain | 316 | // qDebug() << "head val " << cf_val << ", head " << chead_gain |
344 | 163 | // << ", master " << cmaster_gain; | 317 | // << ", master " << cmaster_gain; |
345 | 164 | 318 | ||
355 | 165 | // we have to copy PFL channels to the headphone buffer here before we | 319 | QList<ChannelInfo*>::iterator it = m_channels.begin(); |
356 | 166 | // process the master mix, as PFL channels don't have their fader volume | 320 | for (unsigned int channel_number = 0; |
357 | 167 | // applied but the master channels do -- bkgood | 321 | it != m_channels.end(); ++it, ++channel_number) { |
358 | 168 | SampleUtil::applyGain(m_pHead, 0.0f, iBufferSize); | 322 | ChannelInfo* pChannelInfo = *it; |
359 | 169 | 323 | EngineChannel* pChannel = pChannelInfo->m_pChannel; | |
360 | 170 | for (int channel_number = 0; channel_number < m_channels.size(); ++channel_number) { | 324 | |
361 | 171 | EngineChannel* channel = m_channels[channel_number]; | 325 | if (!pChannel->isActive()) { |
353 | 172 | |||
354 | 173 | if (!channel->isActive()) { | ||
362 | 174 | continue; | 326 | continue; |
363 | 175 | } | 327 | } |
364 | 176 | 328 | ||
367 | 177 | CSAMPLE* buffer = m_channelBuffers[channel_number]; | 329 | masterOutput |= (1 << channel_number); |
368 | 178 | channel->process(NULL, buffer, iBufferSize); | 330 | |
369 | 331 | // Process the buffer | ||
370 | 332 | pChannel->process(NULL, pChannelInfo->m_pBuffer, iBufferSize); | ||
371 | 179 | 333 | ||
372 | 180 | // If the channel is enabled for previewing in headphones, copy it | 334 | // If the channel is enabled for previewing in headphones, copy it |
373 | 181 | // over to the headphone buffer | 335 | // over to the headphone buffer |
379 | 182 | if (channel->isPFL()) { | 336 | if (pChannel->isPFL()) { |
380 | 183 | SampleUtil::addWithGain(m_pHead, buffer, chead_gain, iBufferSize); | 337 | headphoneOutput |= (1 << channel_number); |
376 | 184 | // EngineChannel doesn't apply the volume if it knows it's PFL, | ||
377 | 185 | // so apply it | ||
378 | 186 | channel->applyVolume(buffer, iBufferSize); | ||
381 | 187 | } | 338 | } |
382 | 188 | |||
383 | 189 | // Add the channel to the list of master output channels. | ||
384 | 190 | masterChannels.push_back( | ||
385 | 191 | QPair<CSAMPLE*, EngineChannel::ChannelOrientation>( | ||
386 | 192 | buffer, channel->getOrientation())); | ||
387 | 193 | } | 339 | } |
388 | 194 | 340 | ||
390 | 195 | // Perform the master mix. | 341 | // Mix all the enabled headphone channels together. |
391 | 342 | m_headphoneGain.setGain(chead_gain); | ||
392 | 343 | mixChannels(headphoneOutput, maxChannels, m_pHead, iBufferSize, &m_headphoneGain); | ||
393 | 196 | 344 | ||
396 | 197 | // Crossfader and Transform buttons | 345 | // Calculate the crossfader gains for left and right side of the crossfader |
395 | 198 | //set gain levels; | ||
397 | 199 | float c1_gain, c2_gain; | 346 | float c1_gain, c2_gain; |
398 | 200 | EngineXfader::getXfadeGains(c1_gain, c2_gain, | 347 | EngineXfader::getXfadeGains(c1_gain, c2_gain, |
399 | 201 | crossfader->get(), xFaderCurve->get(), | 348 | crossfader->get(), xFaderCurve->get(), |
400 | 202 | xFaderCalibration->get()); | 349 | xFaderCalibration->get()); |
401 | 203 | 350 | ||
445 | 204 | if (masterChannels.size() == 0) { | 351 | // Now set the gains for overall volume and the left, center, right gains. |
446 | 205 | SampleUtil::applyGain(m_pMaster, 0.0f, iBufferSize); | 352 | m_masterGain.setGains(m_pMasterVolume->get(), c1_gain, 1.0, c2_gain); |
447 | 206 | } else if (masterChannels.size() == 1) { | 353 | |
448 | 207 | QPair<CSAMPLE*, EngineChannel::ChannelOrientation>& channel = | 354 | // Perform the master mix |
449 | 208 | masterChannels[0]; | 355 | mixChannels(masterOutput, maxChannels, m_pMaster, iBufferSize, &m_masterGain); |
407 | 209 | CSAMPLE* buffer = channel.first; | ||
408 | 210 | EngineChannel::ChannelOrientation orientation = channel.second; | ||
409 | 211 | |||
410 | 212 | // Apply gain | ||
411 | 213 | double gain = gainForOrientation(orientation, c1_gain, 1.0f, c2_gain); | ||
412 | 214 | SampleUtil::copyWithGain(m_pMaster, buffer, gain, iBufferSize); | ||
413 | 215 | } else if (masterChannels.size() == 2) { | ||
414 | 216 | QPair<CSAMPLE*, EngineChannel::ChannelOrientation> channel1 = | ||
415 | 217 | masterChannels[0]; | ||
416 | 218 | QPair<CSAMPLE*, EngineChannel::ChannelOrientation> channel2 = | ||
417 | 219 | masterChannels[1]; | ||
418 | 220 | CSAMPLE* buffer1 = channel1.first; | ||
419 | 221 | CSAMPLE* buffer2 = channel2.first; | ||
420 | 222 | EngineChannel::ChannelOrientation orientation1 = channel1.second; | ||
421 | 223 | EngineChannel::ChannelOrientation orientation2 = channel2.second; | ||
422 | 224 | double gain1 = gainForOrientation(orientation1, c1_gain, 1.0f, c2_gain); | ||
423 | 225 | double gain2 = gainForOrientation(orientation2, c1_gain, 1.0f, c2_gain); | ||
424 | 226 | |||
425 | 227 | SampleUtil::copy2WithGain(m_pMaster, | ||
426 | 228 | buffer1, gain1, | ||
427 | 229 | buffer2, gain2, | ||
428 | 230 | iBufferSize); | ||
429 | 231 | } else { | ||
430 | 232 | // Set m_pMaster to all 0s | ||
431 | 233 | SampleUtil::applyGain(m_pMaster, 0.0f, iBufferSize); | ||
432 | 234 | |||
433 | 235 | for (int i = 0; i < masterChannels.size(); ++i) { | ||
434 | 236 | QPair<CSAMPLE*, EngineChannel::ChannelOrientation> channel = | ||
435 | 237 | masterChannels[i]; | ||
436 | 238 | CSAMPLE* buffer = channel.first; | ||
437 | 239 | EngineChannel::ChannelOrientation orientation = channel.second; | ||
438 | 240 | double gain = gainForOrientation(orientation, c1_gain, 1.0f, c2_gain); | ||
439 | 241 | SampleUtil::addWithGain(m_pMaster, buffer, gain, iBufferSize); | ||
440 | 242 | } | ||
441 | 243 | } | ||
442 | 244 | |||
443 | 245 | // Master volume | ||
444 | 246 | volume->process(m_pMaster, m_pMaster, iBufferSize); | ||
450 | 247 | 356 | ||
451 | 248 | #ifdef __LADSPA__ | 357 | #ifdef __LADSPA__ |
452 | 249 | // LADPSA master effects | 358 | // LADPSA master effects |
453 | @@ -278,7 +387,7 @@ | |||
454 | 278 | SampleUtil::addWithGain(m_pHead, m_pMaster, cmaster_gain, iBufferSize); | 387 | SampleUtil::addWithGain(m_pHead, m_pMaster, cmaster_gain, iBufferSize); |
455 | 279 | 388 | ||
456 | 280 | // Head volume and clipping | 389 | // Head volume and clipping |
458 | 281 | head_volume->process(m_pHead, m_pHead, iBufferSize); | 390 | SampleUtil::applyGain(m_pHead, m_pHeadVolume->get(), iBufferSize); |
459 | 282 | head_clipping->process(m_pHead, m_pHead, iBufferSize); | 391 | head_clipping->process(m_pHead, m_pHead, iBufferSize); |
460 | 283 | 392 | ||
461 | 284 | //Master/headphones interleaving is now done in | 393 | //Master/headphones interleaving is now done in |
462 | @@ -290,18 +399,21 @@ | |||
463 | 290 | } | 399 | } |
464 | 291 | 400 | ||
465 | 292 | void EngineMaster::addChannel(EngineChannel* pChannel) { | 401 | void EngineMaster::addChannel(EngineChannel* pChannel) { |
471 | 293 | CSAMPLE* pChannelBuffer = SampleUtil::alloc(MAX_BUFFER_LEN); | 402 | ChannelInfo* pChannelInfo = new ChannelInfo(); |
472 | 294 | memset(pChannelBuffer, 0, sizeof(CSAMPLE) * MAX_BUFFER_LEN); | 403 | pChannelInfo->m_pChannel = pChannel; |
473 | 295 | m_channelBuffers.push_back(pChannelBuffer); | 404 | pChannelInfo->m_pVolumeControl = new ControlLogpotmeter( |
474 | 296 | m_channels.push_back(pChannel); | 405 | ConfigKey(pChannel->getGroup(), pChannel->getGroup()), 1.0); |
475 | 297 | pChannel->getEngineBuffer()->bindWorkers(m_pWorkerScheduler); | 406 | pChannelInfo->m_pBuffer = SampleUtil::alloc(MAX_BUFFER_LEN); |
476 | 407 | memset(pChannelInfo->m_pBuffer, 0, sizeof(CSAMPLE) * MAX_BUFFER_LEN); | ||
477 | 408 | m_channels.push_back(pChannelInfo); | ||
478 | 409 | pChannelInfo->m_pChannel->getEngineBuffer()->bindWorkers(m_pWorkerScheduler); | ||
479 | 298 | 410 | ||
480 | 299 | // TODO(XXX) WARNING HUGE HACK ALERT In the case of 2-decks, this code hooks | 411 | // TODO(XXX) WARNING HUGE HACK ALERT In the case of 2-decks, this code hooks |
481 | 300 | // the two EngineBuffers together so they can beat-sync off of each other. | 412 | // the two EngineBuffers together so they can beat-sync off of each other. |
482 | 301 | // rryan 6/2010 | 413 | // rryan 6/2010 |
483 | 302 | if (m_channels.length() == 2) { | 414 | if (m_channels.length() == 2) { |
486 | 303 | EngineBuffer *pBuffer1 = m_channels[0]->getEngineBuffer(); | 415 | EngineBuffer *pBuffer1 = m_channels[0]->m_pChannel->getEngineBuffer(); |
487 | 304 | EngineBuffer *pBuffer2 = m_channels[1]->getEngineBuffer(); | 416 | EngineBuffer *pBuffer2 = m_channels[1]->m_pChannel->getEngineBuffer(); |
488 | 305 | pBuffer1->setOtherEngineBuffer(pBuffer2); | 417 | pBuffer1->setOtherEngineBuffer(pBuffer2); |
489 | 306 | pBuffer2->setOtherEngineBuffer(pBuffer1); | 418 | pBuffer2->setOtherEngineBuffer(pBuffer1); |
490 | 307 | } | 419 | } |
491 | @@ -313,7 +425,7 @@ | |||
492 | 313 | 425 | ||
493 | 314 | const CSAMPLE* EngineMaster::getChannelBuffer(unsigned int i) const { | 426 | const CSAMPLE* EngineMaster::getChannelBuffer(unsigned int i) const { |
494 | 315 | if (i < numChannels()) { | 427 | if (i < numChannels()) { |
496 | 316 | return m_channelBuffers[i]; | 428 | return m_channels[i]->m_pBuffer; |
497 | 317 | } | 429 | } |
498 | 318 | return NULL; | 430 | return NULL; |
499 | 319 | } | 431 | } |
500 | 320 | 432 | ||
501 | === modified file 'mixxx/src/engine/enginemaster.h' | |||
502 | --- mixxx/src/engine/enginemaster.h 2010-10-27 18:28:54 +0000 | |||
503 | +++ mixxx/src/engine/enginemaster.h 2011-04-01 04:36:32 +0000 | |||
504 | @@ -18,12 +18,14 @@ | |||
505 | 18 | #ifndef ENGINEMASTER_H | 18 | #ifndef ENGINEMASTER_H |
506 | 19 | #define ENGINEMASTER_H | 19 | #define ENGINEMASTER_H |
507 | 20 | 20 | ||
508 | 21 | #include <QMap> | ||
509 | 22 | |||
510 | 23 | #include "controlobject.h" | ||
511 | 21 | #include "engine/engineobject.h" | 24 | #include "engine/engineobject.h" |
512 | 22 | #include "engine/enginechannel.h" | 25 | #include "engine/enginechannel.h" |
513 | 23 | 26 | ||
514 | 24 | class EngineWorkerScheduler; | 27 | class EngineWorkerScheduler; |
515 | 25 | class EngineBuffer; | 28 | class EngineBuffer; |
516 | 26 | class EngineVolume; | ||
517 | 27 | class EngineChannel; | 29 | class EngineChannel; |
518 | 28 | class EngineClipping; | 30 | class EngineClipping; |
519 | 29 | class EngineFlanger; | 31 | class EngineFlanger; |
520 | @@ -33,7 +35,6 @@ | |||
521 | 33 | class EngineVuMeter; | 35 | class EngineVuMeter; |
522 | 34 | class ControlPotmeter; | 36 | class ControlPotmeter; |
523 | 35 | class ControlPushButton; | 37 | class ControlPushButton; |
524 | 36 | class ControlObject; | ||
525 | 37 | class EngineVinylSoundEmu; | 38 | class EngineVinylSoundEmu; |
526 | 38 | class EngineSideChain; | 39 | class EngineSideChain; |
527 | 39 | 40 | ||
528 | @@ -55,20 +56,64 @@ | |||
529 | 55 | // only call it before the engine has started mixing. | 56 | // only call it before the engine has started mixing. |
530 | 56 | void addChannel(EngineChannel* pChannel); | 57 | void addChannel(EngineChannel* pChannel); |
531 | 57 | 58 | ||
536 | 58 | static double gainForOrientation(EngineChannel::ChannelOrientation orientation, | 59 | static inline double gainForOrientation(EngineChannel::ChannelOrientation orientation, |
537 | 59 | double leftGain, | 60 | double leftGain, |
538 | 60 | double centerGain, | 61 | double centerGain, |
539 | 61 | double rightGain); | 62 | double rightGain); |
540 | 62 | 63 | ||
541 | 63 | private: | 64 | private: |
543 | 64 | QList<EngineChannel*> m_channels; | 65 | struct ChannelInfo { |
544 | 66 | EngineChannel* m_pChannel; | ||
545 | 67 | CSAMPLE* m_pBuffer; | ||
546 | 68 | ControlObject* m_pVolumeControl; | ||
547 | 69 | }; | ||
548 | 70 | |||
549 | 71 | class GainCalculator { | ||
550 | 72 | public: | ||
551 | 73 | virtual double getGain(ChannelInfo* pChannelInfo) = 0; | ||
552 | 74 | }; | ||
553 | 75 | class ConstantGainCalculator : public GainCalculator { | ||
554 | 76 | public: | ||
555 | 77 | inline double getGain(ChannelInfo* pChannelInfo) { | ||
556 | 78 | return m_dGain; | ||
557 | 79 | } | ||
558 | 80 | inline double setGain(double dGain) { | ||
559 | 81 | m_dGain = dGain; | ||
560 | 82 | } | ||
561 | 83 | private: | ||
562 | 84 | double m_dGain; | ||
563 | 85 | }; | ||
564 | 86 | class OrientationVolumeGainCalculator : public GainCalculator { | ||
565 | 87 | public: | ||
566 | 88 | inline double getGain(ChannelInfo* pChannelInfo) { | ||
567 | 89 | double channelVolume = pChannelInfo->m_pVolumeControl->get(); | ||
568 | 90 | double orientationGain = EngineMaster::gainForOrientation( | ||
569 | 91 | pChannelInfo->m_pChannel->getOrientation(), | ||
570 | 92 | m_dLeftGain, m_dCenterGain, m_dRightGain); | ||
571 | 93 | return m_dVolume * channelVolume * orientationGain; | ||
572 | 94 | } | ||
573 | 95 | |||
574 | 96 | inline void setGains(double dVolume, double leftGain, double centerGain, double rightGain) { | ||
575 | 97 | m_dVolume = dVolume; | ||
576 | 98 | m_dLeftGain = leftGain; | ||
577 | 99 | m_dCenterGain = centerGain; | ||
578 | 100 | m_dRightGain = rightGain; | ||
579 | 101 | } | ||
580 | 102 | private: | ||
581 | 103 | double m_dVolume, m_dLeftGain, m_dCenterGain, m_dRightGain; | ||
582 | 104 | }; | ||
583 | 105 | |||
584 | 106 | void mixChannels(unsigned int channelBitvector, unsigned int maxChannels, | ||
585 | 107 | CSAMPLE* pOutput, unsigned int iBufferSize, GainCalculator* pGainCalculator); | ||
586 | 108 | |||
587 | 109 | |||
588 | 110 | QList<ChannelInfo*> m_channels; | ||
589 | 65 | 111 | ||
590 | 66 | CSAMPLE *m_pMaster, *m_pHead; | 112 | CSAMPLE *m_pMaster, *m_pHead; |
591 | 67 | QList<CSAMPLE*> m_channelBuffers; | ||
592 | 68 | 113 | ||
593 | 69 | EngineWorkerScheduler *m_pWorkerScheduler; | 114 | EngineWorkerScheduler *m_pWorkerScheduler; |
594 | 70 | 115 | ||
596 | 71 | EngineVolume *volume, *head_volume; | 116 | ControlObject *m_pMasterVolume, *m_pHeadVolume; |
597 | 72 | EngineClipping *clipping, *head_clipping; | 117 | EngineClipping *clipping, *head_clipping; |
598 | 73 | #ifdef __LADSPA__ | 118 | #ifdef __LADSPA__ |
599 | 74 | EngineLADSPA *ladspa; | 119 | EngineLADSPA *ladspa; |
600 | @@ -78,6 +123,9 @@ | |||
601 | 78 | 123 | ||
602 | 79 | ControlPotmeter *crossfader, *head_mix, | 124 | ControlPotmeter *crossfader, *head_mix, |
603 | 80 | *m_pBalance, *xFaderCurve, *xFaderCalibration; | 125 | *m_pBalance, *xFaderCurve, *xFaderCalibration; |
604 | 126 | |||
605 | 127 | ConstantGainCalculator m_headphoneGain; | ||
606 | 128 | OrientationVolumeGainCalculator m_masterGain; | ||
607 | 81 | }; | 129 | }; |
608 | 82 | 130 | ||
609 | 83 | #endif | 131 | #endif |
610 | 84 | 132 | ||
611 | === removed file 'mixxx/src/engine/enginevolume.cpp' | |||
612 | --- mixxx/src/engine/enginevolume.cpp 2010-06-02 21:26:29 +0000 | |||
613 | +++ mixxx/src/engine/enginevolume.cpp 1970-01-01 00:00:00 +0000 | |||
614 | @@ -1,42 +0,0 @@ | |||
615 | 1 | /*************************************************************************** | ||
616 | 2 | enginevolume.cpp - description | ||
617 | 3 | ------------------- | ||
618 | 4 | copyright : (C) 2002 by Tue and Ken Haste Andersen | ||
619 | 5 | email : | ||
620 | 6 | ***************************************************************************/ | ||
621 | 7 | |||
622 | 8 | /*************************************************************************** | ||
623 | 9 | * * | ||
624 | 10 | * This program is free software; you can redistribute it and/or modify * | ||
625 | 11 | * it under the terms of the GNU General Public License as published by * | ||
626 | 12 | * the Free Software Foundation; either version 2 of the License, or * | ||
627 | 13 | * (at your option) any later version. * | ||
628 | 14 | * * | ||
629 | 15 | ***************************************************************************/ | ||
630 | 16 | |||
631 | 17 | #include "enginevolume.h" | ||
632 | 18 | #include "controllogpotmeter.h" | ||
633 | 19 | #include "configobject.h" | ||
634 | 20 | #include "sampleutil.h" | ||
635 | 21 | |||
636 | 22 | /*---------------------------------------------------------------- | ||
637 | 23 | Volume effect. | ||
638 | 24 | ----------------------------------------------------------------*/ | ||
639 | 25 | EngineVolume::EngineVolume(ConfigKey key, double maxval) | ||
640 | 26 | { | ||
641 | 27 | potmeter = new ControlLogpotmeter(key, maxval); | ||
642 | 28 | } | ||
643 | 29 | |||
644 | 30 | EngineVolume::~EngineVolume() | ||
645 | 31 | { | ||
646 | 32 | delete potmeter; | ||
647 | 33 | } | ||
648 | 34 | |||
649 | 35 | void EngineVolume::process(const CSAMPLE * pIn, const CSAMPLE * pOut, const int iBufferSize) | ||
650 | 36 | { | ||
651 | 37 | CSAMPLE * pOutput = (CSAMPLE *)pOut; | ||
652 | 38 | double volume = potmeter->get(); | ||
653 | 39 | |||
654 | 40 | // SampleUtil handles aliased buffers and gains of 1 or 0. | ||
655 | 41 | SampleUtil::copyWithGain(pOutput, pIn, volume, iBufferSize); | ||
656 | 42 | } | ||
657 | 43 | 0 | ||
658 | === removed file 'mixxx/src/engine/enginevolume.h' | |||
659 | --- mixxx/src/engine/enginevolume.h 2009-01-24 04:39:32 +0000 | |||
660 | +++ mixxx/src/engine/enginevolume.h 1970-01-01 00:00:00 +0000 | |||
661 | @@ -1,36 +0,0 @@ | |||
662 | 1 | /*************************************************************************** | ||
663 | 2 | enginevolume.h - description | ||
664 | 3 | ------------------- | ||
665 | 4 | copyright : (C) 2002 by Tue and Ken Haste Andersen | ||
666 | 5 | email : | ||
667 | 6 | ***************************************************************************/ | ||
668 | 7 | |||
669 | 8 | /*************************************************************************** | ||
670 | 9 | * * | ||
671 | 10 | * This program is free software; you can redistribute it and/or modify * | ||
672 | 11 | * it under the terms of the GNU General Public License as published by * | ||
673 | 12 | * the Free Software Foundation; either version 2 of the License, or * | ||
674 | 13 | * (at your option) any later version. * | ||
675 | 14 | * * | ||
676 | 15 | ***************************************************************************/ | ||
677 | 16 | |||
678 | 17 | #ifndef ENGINEVOLUME_H | ||
679 | 18 | #define ENGINEVOLUME_H | ||
680 | 19 | |||
681 | 20 | #include "engineobject.h" | ||
682 | 21 | |||
683 | 22 | class ControlLogpotmeter; | ||
684 | 23 | class ConfigKey; | ||
685 | 24 | |||
686 | 25 | class EngineVolume : public EngineObject { | ||
687 | 26 | public: | ||
688 | 27 | EngineVolume(ConfigKey key, double maxval=1.); | ||
689 | 28 | ~EngineVolume(); | ||
690 | 29 | void process(const CSAMPLE *pIn, const CSAMPLE *pOut, const int iBufferSize); | ||
691 | 30 | |||
692 | 31 | private: | ||
693 | 32 | CSAMPLE *buffer; | ||
694 | 33 | ControlLogpotmeter *potmeter; | ||
695 | 34 | }; | ||
696 | 35 | |||
697 | 36 | #endif | ||
698 | 37 | 0 | ||
699 | === modified file 'mixxx/src/sampleutil.cpp' | |||
700 | --- mixxx/src/sampleutil.cpp 2010-06-02 11:16:22 +0000 | |||
701 | +++ mixxx/src/sampleutil.cpp 2011-04-01 04:36:32 +0000 | |||
702 | @@ -489,6 +489,155 @@ | |||
703 | 489 | } | 489 | } |
704 | 490 | 490 | ||
705 | 491 | // static | 491 | // static |
706 | 492 | void SampleUtil::copy4WithGain(CSAMPLE* pDest, | ||
707 | 493 | const CSAMPLE* pSrc1, CSAMPLE gain1, | ||
708 | 494 | const CSAMPLE* pSrc2, CSAMPLE gain2, | ||
709 | 495 | const CSAMPLE* pSrc3, CSAMPLE gain3, | ||
710 | 496 | const CSAMPLE* pSrc4, CSAMPLE gain4, | ||
711 | 497 | int iNumSamples) { | ||
712 | 498 | if (gain1 == 0.0f) { | ||
713 | 499 | return copy3WithGain(pDest, pSrc2, gain2, pSrc3, gain3, pSrc4, gain4, iNumSamples); | ||
714 | 500 | } | ||
715 | 501 | if (gain2 == 0.0f) { | ||
716 | 502 | return copy3WithGain(pDest, pSrc1, gain1, pSrc3, gain3, pSrc4, gain4, iNumSamples); | ||
717 | 503 | } | ||
718 | 504 | if (gain3 == 0.0f) { | ||
719 | 505 | return copy3WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc4, gain4, iNumSamples); | ||
720 | 506 | } | ||
721 | 507 | if (gain4 == 0.0f) { | ||
722 | 508 | return copy3WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc3, gain3, iNumSamples); | ||
723 | 509 | } | ||
724 | 510 | if (m_sOptimizationsOn) { | ||
725 | 511 | // TODO(rryan) implement SSE for this? worth it? | ||
726 | 512 | } | ||
727 | 513 | for (int i = 0; i < iNumSamples; ++i) { | ||
728 | 514 | pDest[i] = pSrc1[i] * gain1 + pSrc2[i] * gain2 + pSrc3[i] * gain3 + pSrc4[i] * gain4; | ||
729 | 515 | } | ||
730 | 516 | } | ||
731 | 517 | |||
732 | 518 | // static | ||
733 | 519 | void SampleUtil::copy5WithGain(CSAMPLE* pDest, | ||
734 | 520 | const CSAMPLE* pSrc1, CSAMPLE gain1, | ||
735 | 521 | const CSAMPLE* pSrc2, CSAMPLE gain2, | ||
736 | 522 | const CSAMPLE* pSrc3, CSAMPLE gain3, | ||
737 | 523 | const CSAMPLE* pSrc4, CSAMPLE gain4, | ||
738 | 524 | const CSAMPLE* pSrc5, CSAMPLE gain5, | ||
739 | 525 | int iNumSamples) { | ||
740 | 526 | if (gain1 == 0.0f) { | ||
741 | 527 | return copy4WithGain(pDest, pSrc2, gain2, pSrc3, gain3, pSrc4, gain4, pSrc5, gain5, iNumSamples); | ||
742 | 528 | } | ||
743 | 529 | if (gain2 == 0.0f) { | ||
744 | 530 | return copy4WithGain(pDest, pSrc1, gain1, pSrc3, gain3, pSrc4, gain4, pSrc5, gain5, iNumSamples); | ||
745 | 531 | } | ||
746 | 532 | if (gain3 == 0.0f) { | ||
747 | 533 | return copy4WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc4, gain4, pSrc5, gain5, iNumSamples); | ||
748 | 534 | } | ||
749 | 535 | if (gain4 == 0.0f) { | ||
750 | 536 | return copy4WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc3, gain3, pSrc5, gain5, iNumSamples); | ||
751 | 537 | } | ||
752 | 538 | if (gain5 == 0.0f) { | ||
753 | 539 | return copy4WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc3, gain3, pSrc4, gain4, iNumSamples); | ||
754 | 540 | } | ||
755 | 541 | |||
756 | 542 | if (m_sOptimizationsOn) { | ||
757 | 543 | // TODO(rryan) implement SSE for this? worth it? | ||
758 | 544 | } | ||
759 | 545 | |||
760 | 546 | for (int i = 0; i < iNumSamples; ++i) { | ||
761 | 547 | pDest[i] = pSrc1[i] * gain1 + pSrc2[i] * gain2 + pSrc3[i] * gain3 + pSrc4[i] * gain4 + pSrc5[i] * gain5; | ||
762 | 548 | } | ||
763 | 549 | } | ||
764 | 550 | |||
765 | 551 | // static | ||
766 | 552 | void SampleUtil::copy6WithGain(CSAMPLE* pDest, | ||
767 | 553 | const CSAMPLE* pSrc1, CSAMPLE gain1, | ||
768 | 554 | const CSAMPLE* pSrc2, CSAMPLE gain2, | ||
769 | 555 | const CSAMPLE* pSrc3, CSAMPLE gain3, | ||
770 | 556 | const CSAMPLE* pSrc4, CSAMPLE gain4, | ||
771 | 557 | const CSAMPLE* pSrc5, CSAMPLE gain5, | ||
772 | 558 | const CSAMPLE* pSrc6, CSAMPLE gain6, | ||
773 | 559 | int iNumSamples) { | ||
774 | 560 | if (gain1 == 0.0f) { | ||
775 | 561 | return copy5WithGain(pDest, pSrc2, gain2, pSrc3, gain3, pSrc4, gain4, | ||
776 | 562 | pSrc5, gain5, pSrc6, gain6, iNumSamples); | ||
777 | 563 | } | ||
778 | 564 | if (gain2 == 0.0f) { | ||
779 | 565 | return copy5WithGain(pDest, pSrc1, gain1, pSrc3, gain3, pSrc4, gain4, | ||
780 | 566 | pSrc5, gain5, pSrc6, gain6, iNumSamples); | ||
781 | 567 | } | ||
782 | 568 | if (gain3 == 0.0f) { | ||
783 | 569 | return copy5WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc4, gain4, | ||
784 | 570 | pSrc5, gain5, pSrc6, gain6, iNumSamples); | ||
785 | 571 | } | ||
786 | 572 | if (gain4 == 0.0f) { | ||
787 | 573 | return copy5WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc3, gain3, | ||
788 | 574 | pSrc5, gain5, pSrc6, gain6, iNumSamples); | ||
789 | 575 | } | ||
790 | 576 | if (gain5 == 0.0f) { | ||
791 | 577 | return copy5WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc3, gain3, | ||
792 | 578 | pSrc4, gain4, pSrc6, gain6, iNumSamples); | ||
793 | 579 | } | ||
794 | 580 | if (gain6 == 0.0f) { | ||
795 | 581 | return copy5WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc3, gain3, | ||
796 | 582 | pSrc4, gain4, pSrc5, gain5, iNumSamples); | ||
797 | 583 | } | ||
798 | 584 | if (m_sOptimizationsOn) { | ||
799 | 585 | // TODO(rryan) implement SSE for this? worth it? | ||
800 | 586 | } | ||
801 | 587 | for (int i = 0; i < iNumSamples; ++i) { | ||
802 | 588 | pDest[i] = pSrc1[i] * gain1 + pSrc2[i] * gain2 + pSrc3[i] * gain3 + | ||
803 | 589 | pSrc4[i] * gain4 + pSrc5[i] * gain5 + pSrc6[i] * gain6; | ||
804 | 590 | } | ||
805 | 591 | } | ||
806 | 592 | |||
807 | 593 | // static | ||
808 | 594 | void SampleUtil::copy7WithGain(CSAMPLE* pDest, | ||
809 | 595 | const CSAMPLE* pSrc1, CSAMPLE gain1, | ||
810 | 596 | const CSAMPLE* pSrc2, CSAMPLE gain2, | ||
811 | 597 | const CSAMPLE* pSrc3, CSAMPLE gain3, | ||
812 | 598 | const CSAMPLE* pSrc4, CSAMPLE gain4, | ||
813 | 599 | const CSAMPLE* pSrc5, CSAMPLE gain5, | ||
814 | 600 | const CSAMPLE* pSrc6, CSAMPLE gain6, | ||
815 | 601 | const CSAMPLE* pSrc7, CSAMPLE gain7, | ||
816 | 602 | int iNumSamples) { | ||
817 | 603 | if (gain1 == 0.0f) { | ||
818 | 604 | return copy6WithGain(pDest, pSrc2, gain2, pSrc3, gain3, pSrc4, gain4, | ||
819 | 605 | pSrc5, gain5, pSrc6, gain6, pSrc7, gain7, iNumSamples); | ||
820 | 606 | } | ||
821 | 607 | if (gain2 == 0.0f) { | ||
822 | 608 | return copy6WithGain(pDest, pSrc1, gain1, pSrc3, gain3, pSrc4, gain4, | ||
823 | 609 | pSrc5, gain5, pSrc6, gain6, pSrc7, gain7, iNumSamples); | ||
824 | 610 | } | ||
825 | 611 | if (gain3 == 0.0f) { | ||
826 | 612 | return copy6WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc4, gain4, | ||
827 | 613 | pSrc5, gain5, pSrc6, gain6, pSrc7, gain7, iNumSamples); | ||
828 | 614 | } | ||
829 | 615 | if (gain4 == 0.0f) { | ||
830 | 616 | return copy6WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc3, gain3, | ||
831 | 617 | pSrc5, gain5, pSrc6, gain6, pSrc7, gain7, iNumSamples); | ||
832 | 618 | } | ||
833 | 619 | if (gain5 == 0.0f) { | ||
834 | 620 | return copy6WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc3, gain3, | ||
835 | 621 | pSrc4, gain4, pSrc6, gain6, pSrc7, gain7, iNumSamples); | ||
836 | 622 | } | ||
837 | 623 | if (gain6 == 0.0f) { | ||
838 | 624 | return copy6WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc3, gain3, | ||
839 | 625 | pSrc4, gain4, pSrc5, gain5, pSrc7, gain7, iNumSamples); | ||
840 | 626 | } | ||
841 | 627 | if (gain7 == 0.0f) { | ||
842 | 628 | return copy6WithGain(pDest, pSrc1, gain1, pSrc2, gain2, pSrc3, gain3, | ||
843 | 629 | pSrc4, gain4, pSrc5, gain5, pSrc6, gain6, iNumSamples); | ||
844 | 630 | } | ||
845 | 631 | if (m_sOptimizationsOn) { | ||
846 | 632 | // TODO(rryan) implement SSE for this? worth it? | ||
847 | 633 | } | ||
848 | 634 | for (int i = 0; i < iNumSamples; ++i) { | ||
849 | 635 | pDest[i] = pSrc1[i] * gain1 + pSrc2[i] * gain2 + pSrc3[i] * gain3 + | ||
850 | 636 | pSrc4[i] * gain4 + pSrc5[i] * gain5 + pSrc6[i] * gain6 + pSrc7[i] * gain7; | ||
851 | 637 | } | ||
852 | 638 | } | ||
853 | 639 | |||
854 | 640 | // static | ||
855 | 492 | void SampleUtil::convert(CSAMPLE* pDest, const SAMPLE* pSrc, | 641 | void SampleUtil::convert(CSAMPLE* pDest, const SAMPLE* pSrc, |
856 | 493 | int iNumSamples) { | 642 | int iNumSamples) { |
857 | 494 | if (m_sOptimizationsOn) { | 643 | if (m_sOptimizationsOn) { |
858 | 495 | 644 | ||
859 | === modified file 'mixxx/src/sampleutil.h' | |||
860 | --- mixxx/src/sampleutil.h 2010-06-01 07:23:52 +0000 | |||
861 | +++ mixxx/src/sampleutil.h 2011-04-01 04:36:32 +0000 | |||
862 | @@ -73,21 +73,57 @@ | |||
863 | 73 | static void copyWithGain(CSAMPLE* pDest, const CSAMPLE* pSrc, | 73 | static void copyWithGain(CSAMPLE* pDest, const CSAMPLE* pSrc, |
864 | 74 | CSAMPLE gain, int iNumSamples); | 74 | CSAMPLE gain, int iNumSamples); |
865 | 75 | 75 | ||
868 | 76 | // Copy to pDest, each sample of pSrc1 multiplied by gain1 plus pSrc2 | 76 | // Copies the sum of each channel, multiplied by its gain into pDest |
867 | 77 | // multiplied by gain2 | ||
869 | 78 | static void copy2WithGain(CSAMPLE* pDest, | 77 | static void copy2WithGain(CSAMPLE* pDest, |
870 | 79 | const CSAMPLE* pSrc1, CSAMPLE gain1, | 78 | const CSAMPLE* pSrc1, CSAMPLE gain1, |
871 | 80 | const CSAMPLE* pSrc2, CSAMPLE gain2, | 79 | const CSAMPLE* pSrc2, CSAMPLE gain2, |
872 | 81 | int iNumSamples); | 80 | int iNumSamples); |
873 | 82 | 81 | ||
876 | 83 | // Copy to pDest, each sample of pSrc1 multiplied by gain1 plus pSrc2 | 82 | // Copies the sum of each channel, multiplied by its gain into pDest |
875 | 84 | // multiplied by gain2 plus pSrc3 multiplied by gain3 | ||
877 | 85 | static void copy3WithGain(CSAMPLE* pDest, | 83 | static void copy3WithGain(CSAMPLE* pDest, |
878 | 86 | const CSAMPLE* pSrc1, CSAMPLE gain1, | 84 | const CSAMPLE* pSrc1, CSAMPLE gain1, |
879 | 87 | const CSAMPLE* pSrc2, CSAMPLE gain2, | 85 | const CSAMPLE* pSrc2, CSAMPLE gain2, |
880 | 88 | const CSAMPLE* pSrc3, CSAMPLE gain3, | 86 | const CSAMPLE* pSrc3, CSAMPLE gain3, |
881 | 89 | int iNumSamples); | 87 | int iNumSamples); |
882 | 90 | 88 | ||
883 | 89 | // Copies the sum of each channel, multiplied by its gain into pDest | ||
884 | 90 | static void copy4WithGain(CSAMPLE* pDest, | ||
885 | 91 | const CSAMPLE* pSrc1, CSAMPLE gain1, | ||
886 | 92 | const CSAMPLE* pSrc2, CSAMPLE gain2, | ||
887 | 93 | const CSAMPLE* pSrc3, CSAMPLE gain3, | ||
888 | 94 | const CSAMPLE* pSrc4, CSAMPLE gain4, | ||
889 | 95 | int iNumSamples); | ||
890 | 96 | |||
891 | 97 | // Copies the sum of each channel, multiplied by its gain into pDest | ||
892 | 98 | static void copy5WithGain(CSAMPLE* pDest, | ||
893 | 99 | const CSAMPLE* pSrc1, CSAMPLE gain1, | ||
894 | 100 | const CSAMPLE* pSrc2, CSAMPLE gain2, | ||
895 | 101 | const CSAMPLE* pSrc3, CSAMPLE gain3, | ||
896 | 102 | const CSAMPLE* pSrc4, CSAMPLE gain4, | ||
897 | 103 | const CSAMPLE* pSrc5, CSAMPLE gain5, | ||
898 | 104 | int iNumSamples); | ||
899 | 105 | |||
900 | 106 | // Copies the sum of each channel, multiplied by its gain into pDest | ||
901 | 107 | static void copy6WithGain(CSAMPLE* pDest, | ||
902 | 108 | const CSAMPLE* pSrc1, CSAMPLE gain1, | ||
903 | 109 | const CSAMPLE* pSrc2, CSAMPLE gain2, | ||
904 | 110 | const CSAMPLE* pSrc3, CSAMPLE gain3, | ||
905 | 111 | const CSAMPLE* pSrc4, CSAMPLE gain4, | ||
906 | 112 | const CSAMPLE* pSrc5, CSAMPLE gain5, | ||
907 | 113 | const CSAMPLE* pSrc6, CSAMPLE gain6, | ||
908 | 114 | int iNumSamples); | ||
909 | 115 | |||
910 | 116 | // Copies the sum of each channel, multiplied by its gain into pDest | ||
911 | 117 | static void copy7WithGain(CSAMPLE* pDest, | ||
912 | 118 | const CSAMPLE* pSrc1, CSAMPLE gain1, | ||
913 | 119 | const CSAMPLE* pSrc2, CSAMPLE gain2, | ||
914 | 120 | const CSAMPLE* pSrc3, CSAMPLE gain3, | ||
915 | 121 | const CSAMPLE* pSrc4, CSAMPLE gain4, | ||
916 | 122 | const CSAMPLE* pSrc5, CSAMPLE gain5, | ||
917 | 123 | const CSAMPLE* pSrc6, CSAMPLE gain6, | ||
918 | 124 | const CSAMPLE* pSrc7, CSAMPLE gain7, | ||
919 | 125 | int iNumSamples); | ||
920 | 126 | |||
921 | 91 | // Convert a buffer of SAMPLEs to a buffer of CSAMPLEs. Does not work | 127 | // Convert a buffer of SAMPLEs to a buffer of CSAMPLEs. Does not work |
922 | 92 | // in-place! pDest and pSrc must not be aliased. | 128 | // in-place! pDest and pSrc must not be aliased. |
923 | 93 | static void convert(CSAMPLE* pDest, const SAMPLE* pSrc, int iNumSamples); | 129 | static void convert(CSAMPLE* pDest, const SAMPLE* pSrc, int iNumSamples); |
BTW, the EngineMaster tests still pass, so I'm pretty confident this is fine for our uses. Something should be done about the 16-deck limit. With an int64, we could support 64-decks. We could also use two to get 128, but those aren't realistic cases for Mixxx right now so I didn't bother.