2 * OpenAL cross platform audio library
3 * Copyright (C) 2011 by Chris Robinson.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
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 GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
28 #include "alc/effects/base.h"
30 #include "core/bufferline.h"
31 #include "core/devformat.h"
32 #include "core/device.h"
33 #include "core/effects/base.h"
34 #include "core/effectslot.h"
35 #include "core/mixer.h"
36 #include "intrusive_ptr.h"
44 using uint
= unsigned int;
46 struct DedicatedState final
: public EffectState
{
47 /* The "dedicated" effect can output to the real output, so should have
48 * gains for all possible output channels and not just the main ambisonic
51 std::array
<float,MaxOutputChannels
> mCurrentGains
{};
52 std::array
<float,MaxOutputChannels
> mTargetGains
{};
55 void deviceUpdate(const DeviceBase
*device
, const BufferStorage
*buffer
) final
;
56 void update(const ContextBase
*context
, const EffectSlot
*slot
, const EffectProps
*props_
,
57 const EffectTarget target
) final
;
58 void process(const size_t samplesToDo
, const al::span
<const FloatBufferLine
> samplesIn
,
59 const al::span
<FloatBufferLine
> samplesOut
) final
;
62 void DedicatedState::deviceUpdate(const DeviceBase
*, const BufferStorage
*)
64 std::fill(mCurrentGains
.begin(), mCurrentGains
.end(), 0.0f
);
67 void DedicatedState::update(const ContextBase
*, const EffectSlot
*slot
,
68 const EffectProps
*props_
, const EffectTarget target
)
70 std::fill(mTargetGains
.begin(), mTargetGains
.end(), 0.0f
);
72 auto &props
= std::get
<DedicatedProps
>(*props_
);
73 const float Gain
{slot
->Gain
* props
.Gain
};
75 if(props
.Target
== DedicatedProps::Dialog
)
77 /* Dialog goes to the front-center speaker if it exists, otherwise it
78 * plays from the front-center location.
80 const size_t idx
{target
.RealOut
? target
.RealOut
->ChannelIndex
[FrontCenter
]
81 : InvalidChannelIndex
};
82 if(idx
!= InvalidChannelIndex
)
84 mOutTarget
= target
.RealOut
->Buffer
;
85 mTargetGains
[idx
] = Gain
;
89 static constexpr auto coeffs
= CalcDirectionCoeffs(std::array
{0.0f
, 0.0f
, -1.0f
});
91 mOutTarget
= target
.Main
->Buffer
;
92 ComputePanGains(target
.Main
, coeffs
, Gain
, mTargetGains
);
95 else if(props
.Target
== DedicatedProps::Lfe
)
97 const size_t idx
{target
.RealOut
? target
.RealOut
->ChannelIndex
[LFE
] : InvalidChannelIndex
};
98 if(idx
!= InvalidChannelIndex
)
100 mOutTarget
= target
.RealOut
->Buffer
;
101 mTargetGains
[idx
] = Gain
;
106 void DedicatedState::process(const size_t samplesToDo
, const al::span
<const FloatBufferLine
> samplesIn
, const al::span
<FloatBufferLine
> samplesOut
)
108 MixSamples(al::span
{samplesIn
[0]}.first(samplesToDo
), samplesOut
, mCurrentGains
, mTargetGains
,
113 struct DedicatedStateFactory final
: public EffectStateFactory
{
114 al::intrusive_ptr
<EffectState
> create() override
115 { return al::intrusive_ptr
<EffectState
>{new DedicatedState
{}}; }
120 EffectStateFactory
*DedicatedStateFactory_getFactory()
122 static DedicatedStateFactory DedicatedFactory
{};
123 return &DedicatedFactory
;