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"
31 #include "core/bufferline.h"
32 #include "core/devformat.h"
33 #include "core/device.h"
34 #include "core/effectslot.h"
35 #include "core/mixer.h"
36 #include "intrusive_ptr.h"
43 using uint
= unsigned int;
45 struct DedicatedState final
: public EffectState
{
46 float mCurrentGains
[MAX_OUTPUT_CHANNELS
];
47 float mTargetGains
[MAX_OUTPUT_CHANNELS
];
50 void deviceUpdate(const DeviceBase
*device
, const Buffer
&buffer
) override
;
51 void update(const ContextBase
*context
, const EffectSlot
*slot
, const EffectProps
*props
,
52 const EffectTarget target
) override
;
53 void process(const size_t samplesToDo
, const al::span
<const FloatBufferLine
> samplesIn
,
54 const al::span
<FloatBufferLine
> samplesOut
) override
;
56 DEF_NEWDEL(DedicatedState
)
59 void DedicatedState::deviceUpdate(const DeviceBase
*, const Buffer
&)
61 std::fill(std::begin(mCurrentGains
), std::end(mCurrentGains
), 0.0f
);
64 void DedicatedState::update(const ContextBase
*, const EffectSlot
*slot
,
65 const EffectProps
*props
, const EffectTarget target
)
67 std::fill(std::begin(mTargetGains
), std::end(mTargetGains
), 0.0f
);
69 const float Gain
{slot
->Gain
* props
->Dedicated
.Gain
};
71 if(slot
->EffectType
== EffectSlotType::DedicatedLFE
)
73 const uint idx
{!target
.RealOut
? INVALID_CHANNEL_INDEX
:
74 GetChannelIdxByName(*target
.RealOut
, LFE
)};
75 if(idx
!= INVALID_CHANNEL_INDEX
)
77 mOutTarget
= target
.RealOut
->Buffer
;
78 mTargetGains
[idx
] = Gain
;
81 else if(slot
->EffectType
== EffectSlotType::DedicatedDialog
)
83 /* Dialog goes to the front-center speaker if it exists, otherwise it
84 * plays from the front-center location. */
85 const uint idx
{!target
.RealOut
? INVALID_CHANNEL_INDEX
:
86 GetChannelIdxByName(*target
.RealOut
, FrontCenter
)};
87 if(idx
!= INVALID_CHANNEL_INDEX
)
89 mOutTarget
= target
.RealOut
->Buffer
;
90 mTargetGains
[idx
] = Gain
;
94 const auto coeffs
= CalcDirectionCoeffs({0.0f
, 0.0f
, -1.0f
}, 0.0f
);
96 mOutTarget
= target
.Main
->Buffer
;
97 ComputePanGains(target
.Main
, coeffs
.data(), Gain
, mTargetGains
);
102 void DedicatedState::process(const size_t samplesToDo
, const al::span
<const FloatBufferLine
> samplesIn
, const al::span
<FloatBufferLine
> samplesOut
)
104 MixSamples({samplesIn
[0].data(), samplesToDo
}, samplesOut
, mCurrentGains
, mTargetGains
,
109 struct DedicatedStateFactory final
: public EffectStateFactory
{
110 al::intrusive_ptr
<EffectState
> create() override
111 { return al::intrusive_ptr
<EffectState
>{new DedicatedState
{}}; }
116 EffectStateFactory
*DedicatedStateFactory_getFactory()
118 static DedicatedStateFactory DedicatedFactory
{};
119 return &DedicatedFactory
;