~ubuntu-branches/ubuntu/oneiric/phonon/oneiric-201108111512

« back to all changes in this revision

Viewing changes to ds9/volumeeffect.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2011-01-24 10:12:11 UTC
  • mfrom: (0.5.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110124101211-w9rew7q0dmwbwhqx
Tags: 4:4.7.0really4.4.4-0ubuntu1
* New upstream release
* Xine and GStreamer backends now split out source, remove build-deps and
  binary packages from debian/control
* Remove 02_no_rpath.patch, now upstream
* Disable kubuntu04_no_va_mangle.patch, no longer applies
* Remove kubuntu_05_gst_codec_installer_window_id.diff, kubuntu_06_forward_events.diff,
  kubuntu_07_include_fix.diff, gstreamer now separate

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*  This file is part of the KDE project.
2
 
 
3
 
Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
 
 
5
 
This library is free software: you can redistribute it and/or modify
6
 
it under the terms of the GNU Lesser General Public License as published by
7
 
the Free Software Foundation, either version 2.1 or 3 of the License.
8
 
 
9
 
This library is distributed in the hope that it will be useful,
10
 
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
GNU Lesser General Public License for more details.
13
 
 
14
 
You should have received a copy of the GNU Lesser General Public License
15
 
along 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
 
 
24
 
QT_BEGIN_NAMESPACE
25
 
 
26
 
#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
27
 
 
28
 
 
29
 
namespace 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
 
 
283
 
QT_END_NAMESPACE
284
 
 
285
 
#include "moc_volumeeffect.cpp"