source: trunk/src/3rdparty/phonon/ds9/volumeeffect.cpp

Last change on this file was 561, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 9.6 KB
Line 
1/* This file is part of the KDE project.
2
3Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
5This library is free software: you can redistribute it and/or modify
6it under the terms of the GNU Lesser General Public License as published by
7the Free Software Foundation, either version 2.1 or 3 of the License.
8
9This library is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU Lesser General Public License for more details.
13
14You should have received a copy of the GNU Lesser General Public License
15along with this library. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "volumeeffect.h"
19#include "qbasefilter.h"
20#include "qmeminputpin.h"
21
22#include <QtCore/qmath.h> //for sqrt
23
24QT_BEGIN_NAMESPACE
25
26#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
27
28
29namespace Phonon
30{
31 namespace DS9
32 {
33 /**************************************************************************
34 * curve functions
35 *************************************************************************/
36
37 static qreal curveValueFadeIn3dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
38 {
39 return (fadeStart + fadeDiff * sqrt(completed));
40 }
41 static qreal curveValueFadeOut3dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
42 {
43 return (fadeStart + fadeDiff * (1.0 - sqrt(1.0 - completed)));
44 }
45 // in == out for a linear fade
46 static qreal curveValueFade6dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
47 {
48 return (fadeStart + fadeDiff * completed);
49 }
50 static qreal curveValueFadeIn9dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
51 {
52 return (fadeStart + fadeDiff * pow(completed, 1.5));
53 }
54 static qreal curveValueFadeOut9dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
55 {
56 return (fadeStart + fadeDiff * (1.0 - pow(1.0 - completed, 1.5)));
57 }
58 static qreal curveValueFadeIn12dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
59 {
60 return (fadeStart + fadeDiff * completed * completed);
61 }
62 static qreal curveValueFadeOut12dB(const qreal fadeStart, const qreal fadeDiff, const qreal completed)
63 {
64 const qreal x = 1.0 - completed;
65 return (fadeStart + fadeDiff * (1.0 - x * x));
66 }
67
68 static const QVector<AM_MEDIA_TYPE> audioMediaType()
69 {
70 QVector<AM_MEDIA_TYPE> ret;
71 AM_MEDIA_TYPE mt = { MEDIATYPE_Audio, MEDIASUBTYPE_PCM, 1, 0, 1, GUID_NULL, 0, 0, 0};
72 ret << mt;
73 return ret;
74 }
75
76 class VolumeMemInputPin : public QMemInputPin
77 {
78 public:
79 VolumeMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt, QPin *output) : QMemInputPin(parent, mt, true /*transform*/, output)
80 {
81 }
82
83 ~VolumeMemInputPin()
84 {
85 }
86
87 STDMETHODIMP NotifyAllocator(IMemAllocator *alloc, BOOL b)
88 {
89 ALLOCATOR_PROPERTIES prop;
90 HRESULT hr = alloc->GetProperties(&prop);
91 if (SUCCEEDED(hr) && prop.cBuffers > 1) {
92 //this allows to reduce the latency for sound
93 //the problem is that too low numbers makes the whole thing fail...
94 ALLOCATOR_PROPERTIES actual;
95 prop.cBuffers = 1;
96 alloc->SetProperties(&prop, &actual);
97 }
98 return QMemInputPin::NotifyAllocator(alloc, b);
99 }
100
101 };
102
103 class VolumeMemOutputPin : public QPin
104 {
105 public:
106 VolumeMemOutputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt) : QPin(parent, PINDIR_OUTPUT, mt)
107 {
108 }
109
110 ~VolumeMemOutputPin()
111 {
112 }
113
114 };
115
116 class VolumeEffectFilter : public QBaseFilter
117 {
118 public:
119 VolumeEffectFilter(VolumeEffect *);
120
121 //reimplementation
122 virtual HRESULT processSample(IMediaSample *);
123
124 private:
125 void treatOneSamplePerChannel(BYTE **buffer, int sampleSize, int channelCount, int frequency);
126
127 QMemInputPin *m_input;
128 QPin *m_output;
129 VolumeEffect *m_volumeEffect;
130 };
131
132 VolumeEffectFilter::VolumeEffectFilter(VolumeEffect *ve) : QBaseFilter(CLSID_NULL),
133 m_volumeEffect(ve)
134 {
135 QVector<AM_MEDIA_TYPE> mt;
136
137 //creating the output
138 m_output = new VolumeMemOutputPin(this, mt);
139
140 //then creating the input
141 mt << audioMediaType();
142 m_input = new VolumeMemInputPin(this, mt, m_output);
143 }
144
145 void VolumeEffectFilter::treatOneSamplePerChannel(BYTE **buffer, int sampleSize, int channelCount, int frequency)
146 {
147 float volume = m_volumeEffect->volume();
148 if (m_volumeEffect->m_fading) {
149 const qreal lastSample = m_volumeEffect->m_fadeDuration * frequency / 1000;
150 const qreal completed = qreal(m_volumeEffect->m_fadeSamplePosition++) / lastSample;
151
152 if (qFuzzyCompare(completed, qreal(1.))) {
153 m_volumeEffect->setVolume(m_volumeEffect->m_targetVolume);
154 m_volumeEffect->m_fading = false; //we end the fading effect
155 } else {
156 volume = m_volumeEffect->m_fadeCurveFn(m_volumeEffect->m_initialVolume,
157 m_volumeEffect->m_targetVolume - m_volumeEffect->m_initialVolume,
158 completed);
159 }
160 }
161
162 for(int c = 0; c < channelCount; ++c) {
163 switch (sampleSize)
164 {
165 case 2:
166 {
167 short *shortBuffer = reinterpret_cast<short*>(*buffer);
168 *shortBuffer *= qRound(volume);
169 }
170 break;
171 case 1:
172 **buffer *= qRound(volume);
173 break;
174 default:
175 break;
176 }
177
178 *buffer += sampleSize;
179 }
180 }
181
182 HRESULT VolumeEffectFilter::processSample(IMediaSample * ms)
183 {
184 BYTE *buffer = 0;
185 ms->GetPointer(&buffer);
186 if (buffer) {
187 const AM_MEDIA_TYPE &mt = m_output->connectedType();
188 if (mt.formattype != FORMAT_WaveFormatEx) {
189 return VFW_E_INVALIDMEDIATYPE;
190 }
191 WAVEFORMATEX *format = reinterpret_cast<WAVEFORMATEX*>(mt.pbFormat);
192 const int channelCount = format->nChannels;
193 const int sampleSize = format->wBitsPerSample / 8; //...in bytes
194
195
196 const BYTE *end = buffer + ms->GetActualDataLength();
197 while (buffer < end) {
198 treatOneSamplePerChannel(&buffer, sampleSize, channelCount, format->nSamplesPerSec);
199 }
200 }
201
202 return S_OK;
203 }
204
205 VolumeEffect::VolumeEffect(QObject *parent) : Effect(parent),
206 m_volume(1), m_fadeCurve(Phonon::VolumeFaderEffect::Fade3Decibel),
207 m_fading(false), m_initialVolume(0), m_targetVolume(0), m_fadeDuration(0),
208 m_fadeSamplePosition(0)
209 {
210 //creation of the effects
211 for(int i = 0; i < FILTER_COUNT; ++i) {
212 VolumeEffectFilter *f = new VolumeEffectFilter(this);
213 m_filters[i] = Filter(f);
214 }
215 }
216
217 float VolumeEffect::volume() const
218 {
219 return m_volume;
220 }
221
222 void VolumeEffect::setVolume(float newVolume)
223 {
224 m_volume = newVolume;
225 }
226
227 Phonon::VolumeFaderEffect::FadeCurve VolumeEffect::fadeCurve() const
228 {
229 return m_fadeCurve;
230 }
231
232 void VolumeEffect::setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve curve)
233 {
234 m_fadeCurve = curve;
235 }
236
237
238 void VolumeEffect::fadeTo(float vol, int duration)
239 {
240 m_fading = true; //will be set back to false when fading is finished
241 m_targetVolume = vol;
242 m_fadeSamplePosition = 0;
243 m_initialVolume = m_volume;
244 m_fadeDuration = duration;
245
246 //in or out?
247 const bool in = vol > m_volume;
248
249 switch(m_fadeCurve)
250 {
251 case Phonon::VolumeFaderEffect::Fade6Decibel:
252 m_fadeCurveFn = curveValueFade6dB;
253 break;
254 case Phonon::VolumeFaderEffect::Fade9Decibel:
255 if (in) {
256 m_fadeCurveFn = curveValueFadeIn9dB;
257 } else {
258 m_fadeCurveFn = curveValueFadeOut9dB;
259 }
260 break;
261 case Phonon::VolumeFaderEffect::Fade12Decibel:
262 if (in) {
263 m_fadeCurveFn = curveValueFadeIn12dB;
264 } else {
265 m_fadeCurveFn = curveValueFadeOut12dB;
266 }
267 break;
268 case Phonon::VolumeFaderEffect::Fade3Decibel:
269 default:
270 if (in) {
271 m_fadeCurveFn = curveValueFadeIn3dB;
272 } else {
273 m_fadeCurveFn = curveValueFadeOut3dB;
274 }
275 break;
276 }
277 }
278 }
279}
280
281#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
282
283QT_END_NAMESPACE
284
285#include "moc_volumeeffect.cpp"
Note: See TracBrowser for help on using the repository browser.