Skip to content

Commit 1157475

Browse files
committed
Duck filter
1 parent 365018a commit 1157475

File tree

4 files changed

+227
-2
lines changed

4 files changed

+227
-2
lines changed

demos/megademo/radiogaga.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ freely, subject to the following restrictions:
3333
#include "soloud.h"
3434
#include "soloud_speech.h"
3535
#include "soloud_wav.h"
36+
#include "soloud_duckfilter.h"
3637

3738
namespace radiogaga
3839
{
@@ -50,6 +51,8 @@ namespace radiogaga
5051
SoLoud::handle gSpeechqueuehandle;
5152
SoLoud::handle gIntrohandle;
5253

54+
SoLoud::DuckFilter gDuckFilter;
55+
5356
const char *phrase[19] =
5457
{
5558
"............................",
@@ -78,7 +81,7 @@ namespace radiogaga
7881
gSoloud.init();
7982
gSoloud.setVisualizationEnable(1);
8083

81-
gSoloud.play(gSpeechBus, 0.5f);
84+
SoLoud::handle speechBusHandle = gSoloud.play(gSpeechBus, 0.5f);
8285

8386
gSoloud.play(gMusicBus);
8487

@@ -113,6 +116,9 @@ namespace radiogaga
113116
gSpeechBus.setVisualizationEnable(1);
114117
gMusicBus.setVisualizationEnable(1);
115118

119+
gDuckFilter.setParams(&gSoloud, speechBusHandle);
120+
gMusicBus.setFilter(0, &gDuckFilter);
121+
116122
gIntro.setText("Eat, Sleep, Rave, Repeat");
117123
gIntro.setLooping(true);
118124
gIntro.setLoopPoint(1.45f);

include/soloud_bus.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ namespace SoLoud
3333

3434
class BusInstance : public AudioSourceInstance
3535
{
36+
public:
3637
Bus *mParent;
3738
unsigned int mScratchSize;
3839
AlignedFloatBuffer mScratch;
39-
public:
40+
4041
// Approximate volume for channels.
4142
float mVisualizationChannelVolume[MAX_CHANNELS];
4243
// Mono-mixed wave data for visualization and for visualization FFT input

include/soloud_duckfilter.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
SoLoud audio engine
3+
Copyright (c) 2013-2021 Jari Komppa
4+
5+
This software is provided 'as-is', without any express or implied
6+
warranty. In no event will the authors be held liable for any damages
7+
arising from the use of this software.
8+
9+
Permission is granted to anyone to use this software for any purpose,
10+
including commercial applications, and to alter it and redistribute it
11+
freely, subject to the following restrictions:
12+
13+
1. The origin of this software must not be misrepresented; you must not
14+
claim that you wrote the original software. If you use this software
15+
in a product, an acknowledgment in the product documentation would be
16+
appreciated but is not required.
17+
18+
2. Altered source versions must be plainly marked as such, and must not be
19+
misrepresented as being the original software.
20+
21+
3. This notice may not be removed or altered from any source
22+
distribution.
23+
*/
24+
25+
#ifndef SOLOUD_DUCKFILTER_H
26+
#define SOLOUD_DUCKFILTER_H
27+
28+
#include "soloud.h"
29+
30+
namespace SoLoud
31+
{
32+
class DuckFilter;
33+
34+
class DuckFilterInstance : public FilterInstance
35+
{
36+
handle mListenTo;
37+
Soloud* mSoloud;
38+
float mCurrentLevel;
39+
public:
40+
virtual void filter(float *aBuffer, unsigned int aSamples, unsigned int aBufferSize, unsigned int aChannels, float aSamplerate, time aTime);
41+
virtual ~DuckFilterInstance();
42+
DuckFilterInstance(DuckFilter *aParent);
43+
};
44+
45+
class DuckFilter : public Filter
46+
{
47+
public:
48+
enum FILTERATTRIBUTE
49+
{
50+
WET = 0,
51+
ONRAMP,
52+
OFFRAMP,
53+
LEVEL
54+
};
55+
Soloud* mSoloud;
56+
float mOnRamp;
57+
float mOffRamp;
58+
float mLevel;
59+
handle mListenTo;
60+
virtual int getParamCount();
61+
virtual const char* getParamName(unsigned int aParamIndex);
62+
virtual unsigned int getParamType(unsigned int aParamIndex);
63+
virtual float getParamMax(unsigned int aParamIndex);
64+
virtual float getParamMin(unsigned int aParamIndex);
65+
virtual FilterInstance *createInstance();
66+
DuckFilter();
67+
result setParams(Soloud* aSoloud, handle aListenTo, float aOnRamp = 0.1f, float aOffRamp = 0.5f, float aLevel = 0.1f);
68+
};
69+
}
70+
71+
#endif

src/filter/soloud_duckfilter.cpp

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
SoLoud audio engine
3+
Copyright (c) 2013-2021 Jari Komppa
4+
5+
This software is provided 'as-is', without any express or implied
6+
warranty. In no event will the authors be held liable for any damages
7+
arising from the use of this software.
8+
9+
Permission is granted to anyone to use this software for any purpose,
10+
including commercial applications, and to alter it and redistribute it
11+
freely, subject to the following restrictions:
12+
13+
1. The origin of this software must not be misrepresented; you must not
14+
claim that you wrote the original software. If you use this software
15+
in a product, an acknowledgment in the product documentation would be
16+
appreciated but is not required.
17+
18+
2. Altered source versions must be plainly marked as such, and must not be
19+
misrepresented as being the original software.
20+
21+
3. This notice may not be removed or altered from any source
22+
distribution.
23+
*/
24+
25+
#include "soloud.h"
26+
#include "soloud_duckfilter.h"
27+
28+
namespace SoLoud
29+
{
30+
DuckFilterInstance::DuckFilterInstance(DuckFilter *aParent)
31+
{
32+
initParams(4);
33+
mParam[DuckFilter::ONRAMP] = aParent->mOnRamp;
34+
mParam[DuckFilter::OFFRAMP] = aParent->mOffRamp;
35+
mParam[DuckFilter::LEVEL] = aParent->mLevel;
36+
mListenTo = aParent->mListenTo;
37+
mSoloud = aParent->mSoloud;
38+
mCurrentLevel = 1;
39+
}
40+
41+
void DuckFilterInstance::filter(float *aBuffer, unsigned int aSamples, unsigned int aBufferSize, unsigned int aChannels, float aSamplerate, double aTime)
42+
{
43+
updateParams(aTime);
44+
float onramp_step = 1;
45+
if (mParam[DuckFilter::ONRAMP] > 0.01)
46+
onramp_step = (1.0f - mParam[DuckFilter::LEVEL]) / (mParam[DuckFilter::ONRAMP] * aSamplerate);
47+
float offramp_step = 1;
48+
if (mParam[DuckFilter::OFFRAMP] > 0.01)
49+
offramp_step = (1.0f - mParam[DuckFilter::LEVEL]) / (mParam[DuckFilter::OFFRAMP] * aSamplerate);
50+
51+
int soundOn = 0;
52+
if (mSoloud)
53+
{
54+
int voiceno = mSoloud->getVoiceFromHandle_internal(mListenTo);
55+
if (voiceno != -1)
56+
{
57+
BusInstance* bi = (BusInstance*)mSoloud->mVoice[voiceno];
58+
float v = 0;
59+
for (unsigned int i = 0; i < bi->mChannels; i++)
60+
v += bi->mVisualizationChannelVolume[i];
61+
if (v > 0.01f)
62+
soundOn = 1;
63+
}
64+
}
65+
float level = mCurrentLevel;
66+
for (unsigned int j = 0; j < aChannels; j++)
67+
{
68+
level = mCurrentLevel;
69+
int bchofs = j * aBufferSize;
70+
for (unsigned int i = 0; i < aSamples; i++)
71+
{
72+
if (soundOn && level > mParam[DuckFilter::LEVEL])
73+
level -= onramp_step;
74+
if (!soundOn && level < 1)
75+
level += offramp_step;
76+
if (level < mParam[DuckFilter::LEVEL]) level = mParam[DuckFilter::LEVEL];
77+
if (level > 1) level = 1;
78+
aBuffer[i + bchofs] += (-aBuffer[i + bchofs] + aBuffer[i + bchofs] * level) * mParam[DuckFilter::WET];
79+
}
80+
}
81+
mCurrentLevel = level;
82+
}
83+
84+
DuckFilterInstance::~DuckFilterInstance()
85+
{
86+
}
87+
88+
DuckFilter::DuckFilter()
89+
{
90+
mSoloud = 0;
91+
mOnRamp = 0.1f;
92+
mOffRamp = 0.5f;
93+
mLevel = 0.5f;
94+
}
95+
96+
result DuckFilter::setParams(Soloud* aSoloud, handle aListenTo, float aOnRamp, float aOffRamp, float aLevel)
97+
{
98+
if (aOnRamp < 0.0f || aOffRamp < 0.0f || aLevel < 0.0f || aSoloud == 0 || !aSoloud->isValidVoiceHandle(aListenTo))
99+
return INVALID_PARAMETER;
100+
101+
mListenTo = aListenTo;
102+
mOnRamp = aOnRamp;
103+
mOffRamp = aOffRamp;
104+
mLevel = aLevel;
105+
mSoloud = aSoloud;
106+
107+
return 0;
108+
}
109+
110+
int DuckFilter::getParamCount()
111+
{
112+
return 4;
113+
}
114+
115+
const char* DuckFilter::getParamName(unsigned int aParamIndex)
116+
{
117+
if (aParamIndex > 3)
118+
return 0;
119+
const char *names[4] = {
120+
"Wet",
121+
"OnRamp",
122+
"OffRamp",
123+
"Level"
124+
};
125+
return names[aParamIndex];
126+
}
127+
128+
unsigned int DuckFilter::getParamType(unsigned int aParamIndex)
129+
{
130+
return FLOAT_PARAM;
131+
}
132+
133+
float DuckFilter::getParamMax(unsigned int aParamIndex)
134+
{
135+
return 1;
136+
}
137+
138+
float DuckFilter::getParamMin(unsigned int aParamIndex)
139+
{
140+
return 0;
141+
}
142+
143+
FilterInstance *DuckFilter::createInstance()
144+
{
145+
return new DuckFilterInstance(this);
146+
}
147+
}

0 commit comments

Comments
 (0)