Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Institute of Technical Acoustics (ITA)
ITADSP
Commits
b38e94c9
Commit
b38e94c9
authored
Feb 12, 2020
by
Dipl.-Ing. Jonas Stienen
Browse files
Adding turbine feature
parent
85ab6f58
Changes
2
Hide whitespace changes
Inline
Side-by-side
tests/pd/ITADSP_pd_forced_flame.cpp
View file @
b38e94c9
#
include
<
ITAAudiofileWriter
.
h
>
#include
<ITAStringUtils.h>
#include
<ITAStopWatch.h>
#include
<ITAConstants.h>
#include
<ITASampleBuffer.h>
#include
<ITAStopWatch.h>
#include
<ITAStringUtils.h>
#include
<VistaTools/VistaRandomNumberGenerator.h>
#include
<DspFilters/Butterworth.h>
#include
<algorithm>
#include
<atomic>
#include
<iostream>
...
...
@@ -19,36 +21,56 @@ const int g_iIIRFilterOrder = 1;
const
int
g_iChannels
=
1
;
/**
* Manual implementation of the "
forced flam
e" pure data patch from Andy Farnell's Designing Sound
*/
* Manual implementation of the "
jet engin
e" pure data patch
(combining "forced flame" and "turbine")
from Andy Farnell's Designing Sound
*/
namespace
ITADSP
{
namespace
PD
{
class
C
ForcedFlam
e
class
C
JetEngin
e
{
public:
inline
C
ForcedFlam
e
(
float
fInlet
Init
=
0.1
f
)
inline
C
JetEngin
e
(
float
RPM
Init
=
500.0
f
)
{
m_vfTurbineModeFrequencies
=
{
3097.0
f
,
4495.0
f
,
5588.0
f
,
7414.0
f
,
11000.0
f
};
m_vfTurbineModeAmplitudes
=
{
0.25
f
,
0.25
f
,
1.0
f
,
0.4
f
,
0.4
f
};
m_vfTurbineModePhaseShift
=
{
0
,
0
,
0
,
0
,
0
};
m_vfRPMRange
=
{
500.0
f
,
6000.0
f
};
const
float
fCenterFrequency1
=
8000.0
f
;
const
float
fQ1
=
0.5
f
;
m_o
BandPassFilter
1
.
setup
(
g_iIIRFilterOrder
,
float
(
g_dSampleRate
),
fCenterFrequency1
,
fCenterFrequency1
/
fQ1
);
m_o
ForcedFlameBP
1
.
setup
(
g_iIIRFilterOrder
,
float
(
g_dSampleRate
),
fCenterFrequency1
,
fCenterFrequency1
/
fQ1
);
const
float
fCutoffFrequency1
=
120.0
f
;
m_oHighPassFilter1
.
setup
(
g_iIIRFilterOrder
,
float
(
g_dSampleRate
),
fCutoffFrequency1
);
m_oForcedFlameHP1
.
setup
(
g_iIIRFilterOrder
,
float
(
g_dSampleRate
),
fCutoffFrequency1
);
const
float
fLPCutoffFrequency1
=
11000.0
f
;
m_oJetEngineLP1
.
setup
(
g_iIIRFilterOrder
,
float
(
g_dSampleRate
),
fLPCutoffFrequency1
);
Set
Inlet
(
fInlet
Init
);
Set
RPM
(
RPM
Init
);
};
inline
virtual
~
CForcedFlame
()
{};
virtual
void
SetInlet
(
float
fInletValue
);
inline
virtual
~
CJetEngine
()
{};
virtual
void
SetRPM
(
float
fInletValue
);
virtual
void
Process
(
float
*
pfOutputBuffer
,
int
iNumSamples
);
protected:
void
UpdateForcedFlame
(
float
fRPM
);
void
UpdateTurbine
(
float
fRPM
);
private:
VistaRandomNumberGenerator
oRNG
;
SimpleFilter
<
Butterworth
::
BandPass
<
g_iIIRFilterOrder
>
,
g_iChannels
>
m_oBandPassFilter1
,
m_oBandPassFilter2
,
m_oBandPassFilter3
;
SimpleFilter
<
Butterworth
::
HighPass
<
g_iIIRFilterOrder
>
,
g_iChannels
>
m_oHighPassFilter1
;
SimpleFilter
<
Butterworth
::
BandPass
<
g_iIIRFilterOrder
>
,
g_iChannels
>
m_oForcedFlameBP1
,
m_oForcedFlameBP2
,
m_oForcedFlameBP3
;
SimpleFilter
<
Butterworth
::
HighPass
<
g_iIIRFilterOrder
>
,
g_iChannels
>
m_oForcedFlameHP1
;
SimpleFilter
<
Butterworth
::
LowPass
<
g_iIIRFilterOrder
>
,
g_iChannels
>
m_oJetEngineLP1
;
std
::
vector
<
float
>
m_vfTurbineModeFrequencies
,
m_vfRPMRange
,
m_vfTurbineModePhaseShift
,
m_vfTurbineModeAmplitudes
;
float
m_fTempSample
;
};
}
}
...
...
@@ -57,49 +79,114 @@ int main( int, char** )
{
ITASampleBuffer
oOutputBuffer
(
g_iOutputLengthSamples
);
ITADSP
::
PD
::
CForcedFlame
oPatch
(
0.5
f
);
float
fRPM
=
2500.
f
;
ITADSP
::
PD
::
CJetEngine
oPatch
(
fRPM
);
oPatch
.
Process
(
oOutputBuffer
.
GetData
(),
g_iOutputLengthSamples
);
string
sFilePath
=
"ITADSP_pd_
forced_flam
e_out.wav"
;
string
sFilePath
=
"ITADSP_pd_
jet_engin
e_out.wav"
;
writeAudiofile
(
sFilePath
,
&
oOutputBuffer
,
g_dSampleRate
,
ITAQuantization
::
ITA_FLOAT
);
cout
<<
"Exported result to "
<<
sFilePath
<<
endl
;
return
255
;
}
void
ITADSP
::
PD
::
CForcedFlame
::
Process
(
float
*
pfOutputBuffer
,
int
iNumSamples
)
void
ITADSP
::
PD
::
CJetEngine
::
SetRPM
(
float
fRPM
)
{
UpdateForcedFlame
(
fRPM
);
UpdateTurbine
(
fRPM
);
}
void
ITADSP
::
PD
::
CJetEngine
::
UpdateForcedFlame
(
float
fRPM
)
{
assert
(
m_vfRPMRange
.
size
()
==
2
);
float
fValidRPM
=
std
::
min
(
std
::
max
(
m_vfRPMRange
[
0
],
fRPM
),
m_vfRPMRange
[
1
]
);
// Normalize input
const
float
fNormalizedFlameControl
=
std
::
max
(
0.1
f
,
fValidRPM
/
m_vfRPMRange
[
1
]
);
const
float
fCenterFrequency2
=
fNormalizedFlameControl
*
fNormalizedFlameControl
*
150.0
f
;
m_oForcedFlameBP2
.
setup
(
g_iIIRFilterOrder
,
float
(
g_dSampleRate
),
fCenterFrequency2
,
fCenterFrequency2
/
1.0
f
);
const
float
fCenterFrequency3
=
fNormalizedFlameControl
*
12000.0
f
;
const
float
fQ3
=
0.6
f
;
m_oForcedFlameBP3
.
setup
(
g_iIIRFilterOrder
,
float
(
g_dSampleRate
),
fCenterFrequency3
,
fCenterFrequency3
/
fQ3
);
}
void
ITADSP
::
PD
::
CJetEngine
::
UpdateTurbine
(
float
fRPM
)
{
assert
(
m_vfRPMRange
.
size
()
==
2
);
float
fValidRPM
=
std
::
min
(
std
::
max
(
m_vfRPMRange
[
0
],
fRPM
),
m_vfRPMRange
[
1
]
);
// Normalize input
const
float
fNormalizedTurbineControl
=
std
::
max
(
0.1
f
,
fValidRPM
/
m_vfRPMRange
[
1
]
);
for
(
auto
&
v
:
m_vfTurbineModeFrequencies
)
v
*=
fNormalizedTurbineControl
;
}
void
ITADSP
::
PD
::
CJetEngine
::
Process
(
float
*
pfOutputBuffer
,
int
iNumSamples
)
{
float
*
pfTempSampleAlias
=
&
m_fTempSample
;
// We need this ref pointer for Dsp functions, but its ugly we dont use it apart from that
for
(
int
n
=
0
;
n
<
iNumSamples
;
n
++
)
{
float
*
p
fCurrentSample
(
&
(
pfOutputBuffer
[
n
]
)
);
float
&
fCurrentSample
(
pfOutputBuffer
[
n
]
);
*
pfCurrentSample
=
oRNG
.
GenerateFloat
(
-
1.0
f
,
1.0
f
);
// noise~
// Forced flame
m_
oBandPassFilter1
.
process
(
1
,
&
pfCurrentSample
);
// bd~ 8000 0.5
m_
fTempSample
=
oRNG
.
GenerateFloat
(
-
1.0
f
,
1.0
f
);
// noise~
m_o
BandPassFilter2
.
process
(
1
,
&
pf
Current
Sample
);
//
vcf~ 0 1 (real part only = band pass)
m_o
ForcedFlameBP1
.
process
(
1
,
&
pf
Temp
Sample
Alias
);
//
bd~ 8000 0.5
m_o
HighPassFilter1
.
process
(
1
,
&
pf
Current
Sample
);
//
hip~ 120
m_o
ForcedFlameBP2
.
process
(
1
,
&
pf
Temp
Sample
Alias
);
//
vcf~ 0 1 (real part only = band pass)
*
pfCurrentSample
*=
120.0
f
;
//
*
~ 120
m_oForcedFlameHP1
.
process
(
1
,
&
pfTempSampleAlias
)
;
//
hip
~ 120
*
pfCurrentSample
=
(
*
pfCurrentSample
<
-
1.0
f
)
?
-
1
:
(
(
*
pfCurrentSample
>
1
)
?
1
:
*
pfCurrentSample
);
// clip~ -1 1
m_fTempSample
*=
120.0
f
;
// *~ 120
m_oBandPassFilter3
.
process
(
1
,
&
pfCurrentSample
);
// vcf~ 0 0.6 (real part only = band pass)
}
}
m_fTempSample
=
(
m_fTempSample
<
-
1.0
f
)
?
-
1
:
(
(
m_fTempSample
>
1
)
?
1
:
m_fTempSample
);
// clip~ -1 1
void
ITADSP
::
PD
::
CForcedFlame
::
SetInlet
(
float
fInlet
)
{
if
(
fInlet
<
0.1
f
)
fInlet
=
0.1
f
;
else
if
(
fInlet
>
1.0
f
)
fInlet
=
1.0
f
;
m_oForcedFlameBP3
.
process
(
1
,
&
pfTempSampleAlias
);
// vcf~ 0 0.6 (real part only = band pass)
const
float
fCenterFrequency2
=
fInlet
*
fInlet
*
150.0
f
;
m_oBandPassFilter2
.
setup
(
g_iIIRFilterOrder
,
float
(
g_dSampleRate
),
fCenterFrequency2
,
fCenterFrequency2
/
1.0
f
);
fCurrentSample
=
m_fTempSample
;
// override buffer
const
float
fCenterFrequency3
=
fInlet
*
12000.0
f
;
const
float
fQ3
=
0.6
f
;
m_oBandPassFilter3
.
setup
(
g_iIIRFilterOrder
,
float
(
g_dSampleRate
),
fCenterFrequency3
,
fCenterFrequency3
/
fQ3
);
// Turbine (adds to output buffer)
m_fTempSample
=
0.0
f
;
assert
(
m_vfTurbineModeFrequencies
.
size
()
==
m_vfTurbineModePhaseShift
.
size
()
);
for
(
int
i
=
0
;
i
<
m_vfTurbineModeFrequencies
.
size
();
i
++
)
{
const
float
&
fFrequency
(
m_vfTurbineModeFrequencies
[
i
]
);
const
float
&
fPhaseShift
(
m_vfTurbineModePhaseShift
[
i
]
);
const
float
&
fAmplitude
(
m_vfTurbineModeAmplitudes
[
i
]
);
const
int
iPeriodLengthSamples
=
(
int
)
round
(
g_dSampleRate
/
fFrequency
);
const
float
t
=
fmodf
(
ITAConstants
::
TWO_PI_F_L
/
float
(
iPeriodLengthSamples
)
*
float
(
n
),
ITAConstants
::
TWO_PI_F
);
m_fTempSample
+=
fAmplitude
*
sin
(
t
+
fPhaseShift
);
// all osc~ and *~
}
m_fTempSample
=
(
m_fTempSample
<
-
0.9
f
)
?
-
0.9
f
:
(
(
m_fTempSample
>
0.9
f
)
?
0.9
f
:
m_fTempSample
);
// clip~ -0.9 0.9
// Jet engine
fCurrentSample
+=
m_fTempSample
*
0.1
f
;
// combine turbine and flame with factor *~ 0.5 from jet engine patch
m_oJetEngineLP1
.
process
(
1
,
&
pfTempSampleAlias
);
// ~lop 11000
fCurrentSample
*=
0.2
f
;
// *~0.2
}
// Update phases for turbine
for
(
int
i
=
0
;
i
<
m_vfTurbineModeFrequencies
.
size
();
i
++
)
{
const
float
&
fFrequency
(
m_vfTurbineModeFrequencies
[
i
]
);
float
&
fPhaseShift
(
m_vfTurbineModePhaseShift
[
i
]
);
const
int
iPeriodLengthSamples
=
(
int
)
round
(
g_dSampleRate
/
fFrequency
);
fPhaseShift
=
fmodf
(
ITAConstants
::
TWO_PI_F_L
/
float
(
iPeriodLengthSamples
)
*
iNumSamples
+
fPhaseShift
,
ITAConstants
::
TWO_PI_F
);
}
}
tests/pd/ITADSP_pd_forced_flame.m
View file @
b38e94c9
ita_read_wav( 'ITADSP_pd_forced_flame_out.wav' )
ITADSP_pd_forced_flame_out.pt
ITADSP_pd_forced_flame_out.play
\ No newline at end of file
jet_engine = ita_read( 'ITADSP_pd_jet_engine_out.wav' )
jet_engine.pt
jet_engine.play
\ No newline at end of file
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment