Skip to content
GitLab
Explore
Sign in
Register
Commits on Source
4
New upstream version 6.1.07
· a6b7f00d
Rafael Laboissière
authored
Nov 27, 2019
a6b7f00d
Merge tag 'upstream/6.1.07'
· 54117cc7
Rafael Laboissière
authored
Nov 27, 2019
Upstream version 6.1.07
54117cc7
d/What_s_new_.html: Update upstream changelog
· d66580be
Rafael Laboissière
authored
Nov 28, 2019
Gbp-Dch: Ignore
d66580be
Changelog entry for version 6.1.07-1
· 95b98d96
Rafael Laboissière
authored
Nov 28, 2019
Gbp-Dch: Ignore
95b98d96
Expand all
Show whitespace changes
Inline
Side-by-side
FFNet/FFNet.cpp
View file @
95b98d96
...
...
@@ -76,7 +76,7 @@ autostring32 FFNet_createNameFromTopology (FFNet me) {
/****** non-linearities ****************************************************/
static
double
sigmoid
(
FFNet
/*me*/
,
double
x
,
double
*
out_deriv
)
{
double
act
=
NUMsigmoid
(
x
);
const
double
act
=
NUMsigmoid
(
x
);
if
(
out_deriv
)
*
out_deriv
=
act
*
(
1.0
-
act
);
return
act
;
}
...
...
@@ -109,8 +109,8 @@ static double minimumCrossEntropy (FFNet me, constVEC& target) {
double
cost
=
0.0
;
for
(
integer
i
=
1
;
i
<=
my
numberOfOutputs
;
i
++
,
k
++
)
{
double
t1
=
1.0
-
target
[
i
];
double
o1
=
1.0
-
my
activity
[
k
];
const
double
t1
=
1.0
-
target
[
i
];
const
double
o1
=
1.0
-
my
activity
[
k
];
cost
-=
target
[
i
]
*
log
(
my
activity
[
k
])
+
t1
*
log
(
o1
);
my
error
[
k
]
=
-
t1
/
o1
+
target
[
i
]
/
my
activity
[
k
];
...
...
@@ -130,15 +130,15 @@ static void bookkeeping (FFNet me) {
numberOfWeights
+=
my
numberOfUnitsInLayer
[
i
]
*
(
numberOfUnitsInPreviousLayer
+
1
);
numberOfUnitsInPreviousLayer
=
my
numberOfUnitsInLayer
[
i
];
}
if
(
my
numberOfWeights
>
0
&&
my
numberOfWeights
!
=
numberOfWeights
)
Melder_throw
(
U"Number of weights is incorrect."
);
Melder_require
(
my
numberOfWeights
==
0
||
my
numberOfWeights
=
=
numberOfWeights
,
U"Number of weights is incorrect."
);
my
numberOfWeights
=
numberOfWeights
;
// The following test is essential because when an FFNet is read from file the w array already exists
if
(
!
my
w
.
at
)
{
if
(
!
my
w
.
at
)
my
w
=
newVECzero
(
my
numberOfWeights
);
}
my
activity
=
newVECzero
(
my
numberOfNodes
);
my
isbias
=
newINTVECzero
(
my
numberOfNodes
);
my
nodeFirst
=
newINTVECzero
(
my
numberOfNodes
);
...
...
@@ -180,7 +180,8 @@ void structFFNet :: v_info () {
our
structDaata
::
v_info
();
MelderInfo_writeLine
(
U"Number of layers: "
,
our
numberOfLayers
);
MelderInfo_writeLine
(
U"Total number of units: "
,
FFNet_getNumberOfUnits
(
this
));
MelderInfo_writeLine
(
U" Number of units in layer "
,
our
numberOfLayers
,
U" (output): "
,
our
numberOfUnitsInLayer
[
numberOfLayers
]);
MelderInfo_writeLine
(
U" Number of units in layer "
,
our
numberOfLayers
,
U" (output): "
,
our
numberOfUnitsInLayer
[
numberOfLayers
]);
for
(
integer
i
=
our
numberOfLayers
-
1
;
i
>=
1
;
i
--
)
MelderInfo_writeLine
(
U" Number of units in layer "
,
i
,
U" (hidden): "
,
our
numberOfUnitsInLayer
[
i
]);
MelderInfo_writeLine
(
U" Number of units in input: "
,
our
numberOfInputs
);
...
...
@@ -246,19 +247,18 @@ void FFNet_setNonLinearity (FFNet me, int nonLinearityType) {
void
FFNet_setCostFunction
(
FFNet
me
,
int
costType
)
{
my
costFunctionType
=
costType
;
if
(
costType
==
2
)
{
if
(
costType
==
2
)
my
costFunction
=
minimumCrossEntropy
;
}
else
{
else
my
costFunction
=
minimumSquaredError
;
}
my
cfClosure
=
nullptr
;
}
double
FFNet_getBias
(
FFNet
me
,
integer
layer
,
integer
unit
)
{
try
{
integer
node
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit
,
layer
);
const
integer
node
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit
,
layer
);
Melder_require
(
node
>
0
,
U"Not a valid unit / layer combination."
);
integer
bias_unit
=
my
wLast
[
node
];
const
integer
bias_unit
=
my
wLast
[
node
];
return
my
w
[
bias_unit
];
}
catch
(
MelderError
)
{
Melder_clearError
();
...
...
@@ -267,28 +267,33 @@ double FFNet_getBias (FFNet me, integer layer, integer unit) {
}
void
FFNet_setBias
(
FFNet
me
,
integer
layer
,
integer
unit
,
double
value
)
{
integer
node
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit
,
layer
);
Melder_require
(
node
>
0
,
U"Not a valid unit / layer combination."
);
integer
bias_unit
=
my
wLast
[
node
];
// ??? +1
const
integer
node
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit
,
layer
);
Melder_require
(
node
>
0
,
U"Not a valid unit / layer combination."
);
const
integer
bias_unit
=
my
wLast
[
node
];
// ??? +1
my
w
[
bias_unit
]
=
value
;
}
void
FFNet_setWeight
(
FFNet
me
,
integer
layer
,
integer
unit
,
integer
unit_from
,
double
value
)
{
integer
node
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit
,
layer
);
Melder_require
(
node
>
0
,
U"Not a valid unit / layer combination."
);
integer
nodef
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit_from
,
layer
-
1
);
Melder_require
(
nodef
>
0
,
U"Not a valid unit / layer combination."
);
integer
w_unit
=
my
wFirst
[
node
]
+
unit_from
-
1
;
const
integer
node
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit
,
layer
);
Melder_require
(
node
>
0
,
U"Not a valid unit / layer combination."
);
const
integer
nodef
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit_from
,
layer
-
1
);
Melder_require
(
nodef
>
0
,
U"Not a valid unit / layer combination."
);
const
integer
w_unit
=
my
wFirst
[
node
]
+
unit_from
-
1
;
my
w
[
w_unit
]
=
value
;
}
double
FFNet_getWeight
(
FFNet
me
,
integer
layer
,
integer
unit
,
integer
unit_from
)
{
integer
node
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit
,
layer
);
Melder_require
(
node
>
0
,
U"Not a valid unit / layer combination."
);
integer
nodef
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit_from
,
layer
-
1
);
Melder_require
(
nodef
>
0
,
U"Not a valid unit / layer combination."
);
integer
w_unit
=
my
wFirst
[
node
]
+
unit_from
-
1
;
const
integer
node
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit
,
layer
);
Melder_require
(
node
>
0
,
U"Not a valid unit / layer combination."
);
const
integer
nodef
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit_from
,
layer
-
1
);
Melder_require
(
nodef
>
0
,
U"Not a valid unit / layer combination."
);
const
integer
w_unit
=
my
wFirst
[
node
]
+
unit_from
-
1
;
return
my
w
[
w_unit
];
}
...
...
@@ -369,7 +374,7 @@ void FFNet_propagate (FFNet me, constVEC input, autoVEC *output) {
double
FFNet_computeError
(
FFNet
me
,
constVEC
target
)
{
Melder_assert
(
my
numberOfOutputs
==
target
.
size
);
// compute error at output layer
double
cost
=
my
costFunction
(
me
,
target
);
const
double
cost
=
my
costFunction
(
me
,
target
);
for
(
integer
i
=
1
;
i
<=
my
numberOfNodes
-
my
numberOfOutputs
;
i
++
)
my
error
[
i
]
=
0.0
;
...
...
@@ -392,102 +397,109 @@ void FFNet_computeDerivative (FFNet me) {
integer
k
=
1
;
for
(
integer
i
=
my
numberOfInputs
+
2
;
i
<=
my
numberOfNodes
;
i
++
)
{
if
(
!
my
isbias
[
i
])
for
(
integer
j
=
my
nodeFirst
[
i
];
j
<=
my
nodeLast
[
i
];
j
++
,
k
++
)
my
dwi
[
k
]
=
-
my
error
[
i
]
*
my
activity
[
j
];
for
(
integer
node
=
my
nodeFirst
[
i
];
node
<=
my
nodeLast
[
i
];
node
++
,
k
++
)
my
dwi
[
k
]
=
-
my
error
[
i
]
*
my
activity
[
node
];
}
}
/******* end operation ******************************************************/
integer
FFNet_getWinningUnit
(
FFNet
me
,
int
labeling
)
{
integer
pos
=
1
,
k
=
my
numberOfNodes
-
my
numberOfOutputs
;
integer
FFNet_getWinningUnit
(
FFNet
me
,
integer
labeling
)
{
const
integer
k
=
my
numberOfNodes
-
my
numberOfOutputs
;
integer
winningUnit
=
1
;
if
(
labeling
==
2
)
{
/* stochastic */
double
sum
=
0.0
;
for
(
integer
i
=
1
;
i
<=
my
numberOfOutputs
;
i
++
)
sum
+=
my
activity
[
k
+
i
];
for
(
integer
i
output
=
1
;
i
output
<=
my
numberOfOutputs
;
i
output
++
)
sum
+=
my
activity
[
k
+
i
output
];
double
random
=
NUMrandomUniform
(
0.0
,
sum
);
for
(
pos
=
my
numberOfOutputs
;
pos
>=
2
;
pos
--
)
{
if
(
random
>
(
sum
-=
my
activity
[
k
+
pos
]))
const
double
random
=
NUMrandomUniform
(
0.0
,
sum
);
for
(
winningUnit
=
my
numberOfOutputs
;
winningUnit
>=
2
;
winningUnit
--
)
{
if
(
random
>
(
sum
-=
my
activity
[
k
+
winningUnit
]))
break
;
}
}
else
{
/* winner-takes-all */
double
max
=
my
activity
[
k
+
1
];
for
(
integer
i
=
2
;
i
<=
my
numberOfOutputs
;
i
++
)
if
(
my
activity
[
k
+
i
]
>
max
)
{
max
=
my
activity
[
k
+
i
];
pos
=
i
;
for
(
integer
i
output
=
2
;
i
output
<=
my
numberOfOutputs
;
i
output
++
)
if
(
my
activity
[
k
+
i
output
]
>
max
)
{
max
=
my
activity
[
k
+
i
output
];
winningUnit
=
ioutput
;
}
}
return
pos
;
return
winningUnit
;
}
void
FFNet_propagateToLayer
(
FFNet
me
,
constVEC
input
,
VEC
activity
,
integer
layer
)
{
Melder_require
(
layer
>
0
,
U"Layer must be greater than zero."
);
Melder_require
(
layer
>
0
,
U"Layer must be greater than zero."
);
Melder_assert
(
my
numberOfUnitsInLayer
[
layer
]
==
activity
.
size
);
FFNet_propagate
(
me
,
input
,
nullptr
);
integer
k
=
my
numberOfInputs
+
1
;
for
(
integer
i
=
1
;
i
<
layer
;
i
++
)
k
+=
my
numberOfUnitsInLayer
[
i
]
+
1
;
for
(
integer
i
layer
=
1
;
i
layer
<
layer
;
i
layer
++
)
k
+=
my
numberOfUnitsInLayer
[
i
layer
]
+
1
;
for
(
integer
i
=
1
;
i
<=
my
numberOfUnitsInLayer
[
layer
];
i
++
)
activity
[
i
]
=
my
activity
[
k
+
i
];
for
(
integer
i
unit
=
1
;
i
unit
<=
my
numberOfUnitsInLayer
[
layer
];
i
unit
++
)
activity
[
i
unit
]
=
my
activity
[
k
+
i
unit
];
}
void
FFNet_selectAllWeights
(
FFNet
me
)
{
for
(
integer
i
=
1
;
i
<=
my
numberOfWeights
;
i
++
)
my
wSelected
[
i
]
=
1
;
for
(
integer
i
weight
=
1
;
i
weight
<=
my
numberOfWeights
;
i
weight
++
)
my
wSelected
[
i
weight
]
=
1
;
my
dimension
=
my
numberOfWeights
;
}
integer
FFNet_dimensionOfSearchSpace
(
FFNet
me
)
{
integer
n
=
0
;
for
(
integer
i
=
1
;
i
<=
my
numberOfWeights
;
i
++
)
if
(
my
wSelected
[
i
])
n
++
;
return
n
;
integer
n
umberOfSelectedWeights
=
0
;
for
(
integer
i
weight
=
1
;
i
weight
<=
my
numberOfWeights
;
i
weight
++
)
if
(
my
wSelected
[
i
weight
])
n
umberOfSelectedWeights
++
;
return
n
umberOfSelectedWeights
;
}
void
FFNet_selectBiasesInLayer
(
FFNet
me
,
integer
layer
)
{
if
(
layer
<
1
||
layer
>
my
numberOfLayers
)
return
;
for
(
integer
i
=
1
;
i
<=
my
numberOfWeights
;
i
++
)
my
wSelected
[
i
]
=
0.0
;
for
(
integer
i
weight
=
1
;
i
weight
<=
my
numberOfWeights
;
i
weight
++
)
my
wSelected
[
i
weight
]
=
0.0
;
integer
node
=
my
numberOfInputs
+
1
;
for
(
integer
i
=
1
;
i
<
layer
;
i
++
)
node
+=
my
numberOfUnitsInLayer
[
i
]
+
1
;
for
(
integer
i
=
node
+
1
;
i
<=
node
+
my
numberOfUnitsInLayer
[
layer
];
i
++
)
my
wSelected
[
my
wLast
[
i
]]
=
1
;
for
(
integer
i
layer
=
1
;
i
layer
<
layer
;
i
layer
++
)
node
+=
my
numberOfUnitsInLayer
[
i
layer
]
+
1
;
for
(
integer
i
node
=
node
+
1
;
i
node
<=
node
+
my
numberOfUnitsInLayer
[
layer
];
i
node
++
)
my
wSelected
[
my
wLast
[
i
node
]]
=
1
;
my
dimension
=
my
numberOfUnitsInLayer
[
layer
];
}
void
FFNet_weightConnectsUnits
(
FFNet
me
,
integer
index
,
integer
*
out_fromUnit
,
integer
*
out_toUnit
,
integer
*
out_layer
)
{
Melder_assert
(
index
>
0
&&
index
<=
my
numberOfWeights
);
integer
i
=
1
,
np
=
0
,
nw
=
my
numberOfUnitsInLayer
[
1
]
*
(
my
numberOfInputs
+
1
);
integer
layer
=
1
,
np
=
0
,
nw
=
my
numberOfUnitsInLayer
[
1
]
*
(
my
numberOfInputs
+
1
);
while
(
index
>
nw
)
{
i
++
;
nw
+=
(
np
=
my
numberOfUnitsInLayer
[
i
]
*
(
my
numberOfUnitsInLayer
[
i
-
1
]
+
1
));
layer
++
;
nw
+=
(
np
=
my
numberOfUnitsInLayer
[
layer
]
*
(
my
numberOfUnitsInLayer
[
layer
-
1
]
+
1
));
}
if
(
i
>
1
)
if
(
layer
>
1
)
index
-=
nw
-
np
;
integer
numberOfUnitsInPreviousLayer
=
(
i
==
1
?
my
numberOfInputs
:
my
numberOfUnitsInLayer
[
i
-
1
]
);
if
(
out_fromUnit
)
*
out_fromUnit
=
index
%
(
numberOfUnitsInPreviousLayer
+
1
);
if
(
out_toUnit
)
*
out_toUnit
=
(
index
-
1
)
/
(
numberOfUnitsInPreviousLayer
+
1
)
+
1
;
if
(
out_layer
)
*
out_layer
=
i
;
const
integer
numberOfUnitsInPreviousLayer
=
(
layer
==
1
?
my
numberOfInputs
:
my
numberOfUnitsInLayer
[
layer
-
1
]
);
if
(
out_fromUnit
)
*
out_fromUnit
=
index
%
(
numberOfUnitsInPreviousLayer
+
1
);
if
(
out_toUnit
)
*
out_toUnit
=
(
index
-
1
)
/
(
numberOfUnitsInPreviousLayer
+
1
)
+
1
;
if
(
out_layer
)
*
out_layer
=
layer
;
}
integer
FFNet_getNodeNumberFromUnitNumber
(
FFNet
me
,
integer
unit
,
integer
layer
)
{
if
(
layer
<
0
||
layer
>
my
numberOfLayers
||
layer
==
0
&&
unit
>
my
numberOfInputs
||
layer
>
0
&&
unit
>
my
numberOfUnitsInLayer
[
layer
])
if
(
layer
<
0
||
layer
>
my
numberOfLayers
||
(
layer
==
0
&&
unit
>
my
numberOfInputs
)
||
(
layer
>
0
&&
unit
>
my
numberOfUnitsInLayer
[
layer
]))
return
-
1
;
integer
node
=
unit
;
if
(
layer
>
0
)
{
node
+=
my
numberOfInputs
+
1
;
for
(
integer
i
=
1
;
i
<
layer
;
i
++
)
node
+=
my
numberOfUnitsInLayer
[
i
]
+
1
;
for
(
integer
i
layer
=
1
;
i
layer
<
layer
;
i
layer
++
)
node
+=
my
numberOfUnitsInLayer
[
i
layer
]
+
1
;
}
if
(
node
>
my
numberOfNodes
)
node
=
-
1
;
if
(
node
>
my
numberOfNodes
)
node
=
-
1
;
return
node
;
}
...
...
@@ -508,7 +520,7 @@ integer FFNet_getNumberOfHiddenumberOfLayers (FFNet me) {
return
my
numberOfLayers
-
1
;
}
integer
FFNet_getNumberOfUnitsInLayer
(
FFNet
me
,
int
layer
)
{
integer
FFNet_getNumberOfUnitsInLayer
(
FFNet
me
,
int
eger
layer
)
{
return
(
layer
<
0
||
layer
>
my
numberOfLayers
?
0
:
layer
==
0
?
my
numberOfInputs
:
my
numberOfUnitsInLayer
[
layer
]
);
}
...
...
@@ -519,72 +531,72 @@ double FFNet_getMinimum (FFNet me) {
void
FFNet_drawTopology
(
FFNet
me
,
Graphics
g
)
{
integer
maxNumOfUnits
=
my
numberOfInputs
;
int
dxIsFixed
=
1
;
double
dy
=
1.0
/
(
my
numberOfLayers
+
1
);
for
(
integer
i
=
1
;
i
<=
my
numberOfLayers
;
i
++
)
if
(
my
numberOfUnitsInLayer
[
i
]
>
maxNumOfUnits
)
maxNumOfUnits
=
my
numberOfUnitsInLayer
[
i
];
double
dx
=
1.0
/
maxNumOfUnits
;
double
radius
=
dx
/
10.0
;
bool
dxIsFixed
=
true
;
for
(
integer
layer
=
1
;
layer
<=
my
numberOfLayers
;
layer
++
)
if
(
my
numberOfUnitsInLayer
[
layer
]
>
maxNumOfUnits
)
maxNumOfUnits
=
my
numberOfUnitsInLayer
[
layer
];
const
double
dx
=
1.0
/
maxNumOfUnits
;
const
double
dy
=
1.0
/
(
my
numberOfLayers
+
1
);
const
double
radius
=
dx
/
10.0
;
Graphics_setInner
(
g
);
Graphics_setWindow
(
g
,
0.0
,
1.0
,
0.0
,
1.0
);
for
(
integer
i
=
0
;
i
<=
my
numberOfLayers
;
i
++
)
{
integer
numberOfUnitsInLayer
=
(
i
==
0
?
my
numberOfInputs
:
my
numberOfUnitsInLayer
[
i
]
);
double
dx2
=
dx
,
x2WC
,
y2WC
=
dy
/
2
+
i
*
dy
;
for
(
integer
layer
=
0
;
layer
<=
my
numberOfLayers
;
layer
++
)
{
const
integer
numberOfUnitsInLayer
=
(
layer
==
0
?
my
numberOfInputs
:
my
numberOfUnitsInLayer
[
layer
]
);
const
double
y2WC
=
dy
/
2
+
layer
*
dy
;
double
dx2
=
dx
,
x2WC
;
double
x2
=
(
maxNumOfUnits
-
numberOfUnitsInLayer
+
1
)
*
dx2
/
2
;
/* draw the units */
if
(
!
dxIsFixed
)
{
dx2
=
1.0
/
numberOfUnitsInLayer
;
x2
=
dx2
/
2.0
;
}
if
(
i
==
0
)
{
if
(
layer
==
0
)
{
Graphics_setTextAlignment
(
g
,
Graphics_CENTRE
,
Graphics_TOP
);
x2WC
=
x2
;
for
(
integer
j
=
1
;
j
<=
my
numberOfInputs
;
j
++
)
{
for
(
integer
input
=
1
;
input
<=
my
numberOfInputs
;
input
++
)
{
Graphics_arrow
(
g
,
x2WC
,
y2WC
-
radius
-
dy
/
4.0
,
x2WC
,
y2WC
-
radius
);
x2WC
+=
dx2
;
}
}
Graphics_setColour
(
g
,
Melder_RED
);
x2WC
=
x2
;
for
(
integer
j
=
1
;
j
<=
numberOfUnitsInLayer
;
j
++
)
{
for
(
integer
unit
=
1
;
unit
<=
numberOfUnitsInLayer
;
unit
++
)
{
Graphics_circle
(
g
,
x2WC
,
y2WC
,
radius
);
if
(
i
>
0
)
if
(
layer
>
0
)
Graphics_fillCircle
(
g
,
x2WC
,
y2WC
,
radius
);
x2WC
+=
dx2
;
}
Graphics_setColour
(
g
,
Melder_BLACK
);
if
(
i
>
0
)
{
integer
numberOfUnitsInLayer_m1
=
(
i
==
1
?
my
numberOfInputs
:
my
numberOfUnitsInLayer
[
i
-
1
]
);
if
(
layer
>
0
)
{
const
integer
numberOfUnitsInLayer_m1
=
(
layer
==
1
?
my
numberOfInputs
:
my
numberOfUnitsInLayer
[
layer
-
1
]
);
double
dx1
=
dx
;
double
x1
=
(
maxNumOfUnits
-
numberOfUnitsInLayer_m1
+
1
)
*
dx1
/
2.0
;
double
y1WC
=
y2WC
-
dy
;
const
double
y1WC
=
y2WC
-
dy
;
if
(
!
dxIsFixed
)
{
dx1
=
1.0
/
numberOfUnitsInLayer_m1
;
x1
=
dx1
/
2.0
;
}
x2WC
=
x2
;
for
(
integer
j
=
1
;
j
<=
numberOfUnitsInLayer
;
j
++
)
{
for
(
integer
unit
=
1
;
unit
<=
numberOfUnitsInLayer
;
unit
++
)
{
double
x1WC
=
x1
;
for
(
integer
k
=
1
;
k
<=
numberOfUnitsInLayer_m1
;
k
++
)
{
double
xd
=
x2WC
-
x1WC
;
double
cosa
=
xd
/
sqrt
(
xd
*
xd
+
dy
*
dy
);
double
sina
=
dy
/
sqrt
(
xd
*
xd
+
dy
*
dy
);
const
double
xd
=
x2WC
-
x1WC
;
const
double
cosa
=
xd
/
sqrt
(
xd
*
xd
+
dy
*
dy
);
const
double
sina
=
dy
/
sqrt
(
xd
*
xd
+
dy
*
dy
);
Graphics_line
(
g
,
x1WC
+
radius
*
cosa
,
y1WC
+
radius
*
sina
,
x2WC
-
radius
*
cosa
,
y2WC
-
radius
*
sina
);
x1WC
+=
dx1
;
}
x2WC
+=
dx2
;
}
}
if
(
i
==
my
numberOfLayers
)
{
if
(
layer
==
my
numberOfLayers
)
{
x2WC
=
x2
;
Graphics_setTextAlignment
(
g
,
Graphics_CENTRE
,
Graphics_BOTTOM
);
for
(
integer
j
=
1
;
j
<=
my
numberOfOutputs
;
j
++
)
{
for
(
integer
output
=
1
;
output
<=
my
numberOfOutputs
;
output
++
)
{
Graphics_arrow
(
g
,
x2WC
,
y2WC
+
radius
,
x2WC
,
y2WC
+
radius
+
dy
/
4.0
);
if
(
my
outputCategories
)
Categories_drawItem
(
my
outputCategories
.
get
(),
g
,
j
,
x2WC
,
y2WC
+
radius
+
dy
/
4.0
);
Categories_drawItem
(
my
outputCategories
.
get
(),
g
,
output
,
x2WC
,
y2WC
+
radius
+
dy
/
4.0
);
x2WC
+=
dx2
;
}
}
...
...
@@ -594,28 +606,29 @@ void FFNet_drawTopology (FFNet me, Graphics g) {
void
FFNet_drawActivation
(
FFNet
me
,
Graphics
g
)
{
integer
node
=
1
,
maxNumOfUnits
=
my
numberOfInputs
;
int
dxIsFixed
=
1
;
bool
dxIsFixed
=
true
;
MelderColour
colour
=
Graphics_inqColour
(
g
);
double
dy
=
1.0
/
(
my
numberOfLayers
+
1
);
const
double
dy
=
1.0
/
(
my
numberOfLayers
+
1
);
Graphics_setInner
(
g
);
Graphics_setWindow
(
g
,
0.0
,
1.0
,
0.0
,
1.0
);
for
(
integer
i
=
1
;
i
<=
my
numberOfLayers
;
i
++
)
if
(
my
numberOfUnitsInLayer
[
i
]
>
maxNumOfUnits
)
maxNumOfUnits
=
my
numberOfUnitsInLayer
[
i
];
double
dx
=
1.0
/
maxNumOfUnits
;
double
r1
=
dx
/
2.0
;
// May touch when neighbouring activities are both 1 (very rare).
for
(
integer
i
=
0
;
i
<=
my
numberOfLayers
;
i
++
,
node
++
)
{
integer
numberOfUnitsInLayer
=
(
i
==
0
?
my
numberOfInputs
:
my
numberOfUnitsInLayer
[
i
]
);
double
dx2
=
dx
,
x2WC
,
y2WC
=
dy
/
2.0
+
i
*
dy
;
for
(
integer
ilayer
=
1
;
ilayer
<=
my
numberOfLayers
;
ilayer
++
)
if
(
my
numberOfUnitsInLayer
[
ilayer
]
>
maxNumOfUnits
)
maxNumOfUnits
=
my
numberOfUnitsInLayer
[
ilayer
];
const
double
dx
=
1.0
/
maxNumOfUnits
;
const
double
r1
=
dx
/
2.0
;
// May touch when neighbouring activities are both 1 (very rare).
for
(
integer
ilayer
=
0
;
ilayer
<=
my
numberOfLayers
;
ilayer
++
,
node
++
)
{
const
integer
numberOfUnitsInLayer
=
(
ilayer
==
0
?
my
numberOfInputs
:
my
numberOfUnitsInLayer
[
ilayer
]
);
const
double
y2WC
=
dy
/
2.0
+
ilayer
*
dy
;
double
dx2
=
dx
,
x2WC
;
double
x2
=
(
maxNumOfUnits
-
numberOfUnitsInLayer
+
1
)
*
dx2
/
2.0
;
if
(
!
dxIsFixed
)
{
dx2
=
1.0
/
numberOfUnitsInLayer
;
x2
=
dx2
/
2.0
;
}
x2WC
=
x2
;
for
(
integer
j
=
1
;
j
<=
numberOfUnitsInLayer
;
j
++
,
node
++
)
{
for
(
integer
iunit
=
1
;
iunit
<=
numberOfUnitsInLayer
;
iunit
++
,
node
++
)
{
double
activity
=
my
activity
[
node
];
double
radius
=
r1
*
(
fabs
(
activity
)
<
0.05
?
0.05
:
fabs
(
activity
));
/*Graphics_setColour (g, activity < 0 ? Melder_BLACK : Melder_RED);*/
...
...
@@ -630,8 +643,9 @@ void FFNet_drawActivation (FFNet me, Graphics g) {
}
/* This routine is deprecated since praat-4.2.4 20040422 and will be removed in the future. */
void
FFNet_drawWeightsToLayer
(
FFNet
me
,
Graphics
g
,
int
layer
,
int
scaling
,
bool
garnish
)
{
Melder_require
(
layer
>
0
&&
layer
<=
my
numberOfLayers
,
U"Layer number should be between 1 and "
,
my
numberOfLayers
,
U"."
);
void
FFNet_drawWeightsToLayer
(
FFNet
me
,
Graphics
g
,
integer
layer
,
integer
scaling
,
bool
garnish
)
{
Melder_require
(
layer
>
0
&&
layer
<=
my
numberOfLayers
,
U"Layer number should be between 1 and "
,
my
numberOfLayers
,
U"."
);
autoMatrix
weights
=
FFNet_weightsToMatrix
(
me
,
layer
,
false
);
Matrix_scale
(
weights
.
get
(),
scaling
);
...
...
@@ -702,29 +716,29 @@ autoTableOfReal FFNet_extractWeights (FFNet me, integer layer) {
Melder_require
(
layer
>
0
&&
layer
<=
my
numberOfLayers
,
U"Layer number should be between 1 and "
,
my
numberOfLayers
,
U"."
);
integer
numberOfUnitsFrom
=
(
layer
==
1
?
my
numberOfInputs
+
1
:
my
numberOfUnitsInLayer
[
layer
-
1
]
+
1
);
integer
numberOfUnitsTo
=
my
numberOfUnitsInLayer
[
layer
];
const
integer
numberOfUnitsFrom
=
(
layer
==
1
?
my
numberOfInputs
+
1
:
my
numberOfUnitsInLayer
[
layer
-
1
]
+
1
);
const
integer
numberOfUnitsTo
=
my
numberOfUnitsInLayer
[
layer
];
autoTableOfReal
thee
=
TableOfReal_create
(
numberOfUnitsFrom
,
numberOfUnitsTo
);
char32
label
[
40
];
for
(
integer
i
=
1
;
i
<=
numberOfUnitsFrom
-
1
;
i
++
)
{
Melder_sprint
(
label
,
40
,
U"L"
,
layer
-
1
,
U"-"
,
i
);
TableOfReal_setRowLabel
(
thee
.
get
(),
i
,
label
);
for
(
integer
i
unit
=
1
;
i
unit
<=
numberOfUnitsFrom
-
1
;
i
unit
++
)
{
Melder_sprint
(
label
,
40
,
U"L"
,
layer
-
1
,
U"-"
,
i
unit
);
TableOfReal_setRowLabel
(
thee
.
get
(),
i
unit
,
label
);
}
TableOfReal_setRowLabel
(
thee
.
get
(),
numberOfUnitsFrom
,
U"Bias"
);
for
(
integer
i
=
1
;
i
<=
numberOfUnitsTo
;
i
++
)
{
Melder_sprint
(
label
,
40
,
U"L"
,
layer
,
U"-"
,
i
);
TableOfReal_setColumnLabel
(
thee
.
get
(),
i
,
label
);
for
(
integer
i
unit
=
1
;
i
unit
<=
numberOfUnitsTo
;
i
unit
++
)
{
Melder_sprint
(
label
,
40
,
U"L"
,
layer
,
U"-"
,
i
unit
);
TableOfReal_setColumnLabel
(
thee
.
get
(),
i
unit
,
label
);
}
integer
node
=
my
numberOfInputs
+
1
+
1
;
for
(
integer
i
=
1
;
i
<
layer
;
i
++
)
node
+=
my
numberOfUnitsInLayer
[
i
]
+
1
;
for
(
integer
i
layer
=
1
;
i
layer
<
layer
;
i
layer
++
)
node
+=
my
numberOfUnitsInLayer
[
i
layer
]
+
1
;
for
(
integer
i
=
1
;
i
<=
numberOfUnitsTo
;
i
++
,
node
++
)
{
for
(
integer
i
unit
=
1
;
i
unit
<=
numberOfUnitsTo
;
i
unit
++
,
node
++
)
{
integer
k
=
1
;
for
(
integer
j
=
my
wFirst
[
node
];
j
<=
my
wLast
[
node
];
j
++
)
thy
data
[
k
++
]
[
i
]
=
my
w
[
j
];
for
(
integer
j
node
=
my
wFirst
[
node
];
j
node
<=
my
wLast
[
node
];
j
node
++
)
thy
data
[
k
++
]
[
i
unit
]
=
my
w
[
j
node
];
}
return
thee
;
}
catch
(
MelderError
)
{
...
...
@@ -737,8 +751,9 @@ autoFFNet PatternList_Categories_to_FFNet (PatternList me, Categories you, integ
numberOfUnits1
=
numberOfUnits1
>
0
?
numberOfUnits1
:
0
;
numberOfUnits2
=
numberOfUnits2
>
0
?
numberOfUnits2
:
0
;
autoCategories
uniq
=
Categories_selectUniqueItems
(
you
);
integer
numberOfOutputs
=
uniq
->
size
;
Melder_require
(
numberOfOutputs
>
0
,
U"The Categories should not be empty."
);
const
integer
numberOfOutputs
=
uniq
->
size
;
Melder_require
(
numberOfOutputs
>
0
,
U"The Categories should not be empty."
);
autoFFNet
result
=
FFNet_create
(
my
nx
,
numberOfUnits1
,
numberOfUnits2
,
numberOfOutputs
,
false
);
FFNet_setOutputCategories
(
result
.
get
(),
uniq
.
get
());
autostring32
ffnetName
=
FFNet_createNameFromTopology
(
result
.
get
());
...
...
FFNet/FFNet.h
View file @
95b98d96
...
...
@@ -174,7 +174,7 @@ void FFNet_computeDerivative (FFNet me);
/* step (4) compute derivative in my dwi */
/* Precondition: step (3) */
integer
FFNet_getWinningUnit
(
FFNet
me
,
int
labeling
);
integer
FFNet_getWinningUnit
(
FFNet
me
,
int
eger
labeling
);
/* labeling = 1 : winner-takes-all */
/* labeling = 2 : stochastic */
...
...
@@ -202,7 +202,7 @@ integer FFNet_getNumberOfUnits (FFNet me);
integer
FFNet_getNumberOfHiddenumberOfLayers
(
FFNet
me
);
integer
FFNet_getNumberOfUnitsInLayer
(
FFNet
me
,
int
layer
);
integer
FFNet_getNumberOfUnitsInLayer
(
FFNet
me
,
int
eger
layer
);
double
FFNet_getMinimum
(
FFNet
me
);
...
...
@@ -210,7 +210,7 @@ void FFNet_drawTopology (FFNet me, Graphics g);
void
FFNet_drawActivation
(
FFNet
me
,
Graphics
g
);
void
FFNet_drawWeightsToLayer
(
FFNet
me
,
Graphics
g
,
int
toLayer
,
int
scaling
,
bool
garnish
);
void
FFNet_drawWeightsToLayer
(
FFNet
me
,
Graphics
g
,
int
eger
toLayer
,
int
eger
scaling
,
bool
garnish
);
/* Deprecated: the strengths of the weights that connect to the nodes in later 'layer' */
/* are drawn with boxes. The area of each box corresponds to the strength. */
/* Black boxes have negative strength? */
...
...
FFNet/FFNet_ActivationList_Categories.cpp
View file @
95b98d96
/* FFNet_ActivationList_Categories.cpp
*
* Copyright (C) 1997-201
1, 2015-2018
David Weenink
* Copyright (C) 1997-201
9
David Weenink
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -36,11 +36,11 @@ static integer winnerTakesAll (FFNet me, constVEC activation) {
}
static
integer
stochastic
(
FFNet
me
,
constVEC
activation
)
{
integer
i
;
double
range
=
0.0
,
lower
=
0.0
;
integer
i
;
for
(
i
=
1
;
i
<=
my
numberOfOutputs
;
i
++
)
range
+=
activation
[
i
];
double
number
=
NUMrandomUniform
(
0.0
,
range
);
const
double
number
=
NUMrandomUniform
(
0.0
,
range
);
for
(
i
=
1
;
i
<=
my
numberOfOutputs
;
i
++
)
{
lower
+=
activation
[
i
];
if
(
number
<
lower
)
break
;
...
...
@@ -59,7 +59,7 @@ autoCategories FFNet_ActivationList_to_Categories (FFNet me, ActivationList acti
autoCategories
thee
=
Categories_create
();
labelingFunction
=
labeling
==
2
?
stochastic
:
winnerTakesAll
;
for
(
integer
i
=
1
;
i
<=
activation
->
ny
;
i
++
)
{
integer
index
=
labelingFunction
(
me
,
activation
->
z
.
row
(
i
));
const
integer
index
=
labelingFunction
(
me
,
activation
->
z
.
row
(
i
));
autoSimpleString
item
=
Data_copy
(
my
outputCategories
->
at
[
index
]);
thy
addItem_move
(
item
.
move
());
}
...
...
@@ -75,14 +75,14 @@ autoActivationList FFNet_Categories_to_ActivationList (FFNet me, Categories thee
Melder_require
(
my
outputCategories
,
U"The FFNet does not have categories."
);
integer
nl
=
OrderedOfString_isSubsetOf
(
uniq
.
get
(),
my
outputCategories
.
get
(),
0
);
const
integer
nl
=
OrderedOfString_isSubsetOf
(
uniq
.
get
(),
my
outputCategories
.
get
(),
0
);
Melder_require
(
nl
>
0
,
U"The Categories should match the categories of the FFNet."
);
autoActivationList
him
=
ActivationList_create
(
thy
size
,
my
numberOfOutputs
);
for
(
integer
i
=
1
;
i
<=
thy
size
;
i
++
)
{
SimpleString
category
=
thy
at
[
i
];
integer
pos
=
OrderedOfString_indexOfItem_c
(
my
outputCategories
.
get
(),
category
->
string
.
get
());
const
integer
pos
=
OrderedOfString_indexOfItem_c
(
my
outputCategories
.
get
(),
category
->
string
.
get
());
if
(
pos
<
1
)
Melder_throw
(
U"The FFNet doesn't know the category "
,
category
->
string
.
get
(),
U"."
);
his
z
[
i
]
[
pos
]
=
1.0
;
...
...
FFNet/FFNet_Eigen.cpp
View file @
95b98d96
/* FFNet_Eigen.cpp
*
* Copyright (C) 1994-201
8
David Weenink
* Copyright (C) 1994-201
9
David Weenink
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -26,9 +26,9 @@
#include
"NUM2.h"
void
FFNet_Eigen_drawIntersection
(
FFNet
me
,
Eigen
eigen
,
Graphics
g
,
integer
pcx
,
integer
pcy
,
double
xmin
,
double
xmax
,
double
ymin
,
double
ymax
)
{
integer
ix
=
integer_abs
(
pcx
),
iy
=
integer_abs
(
pcy
);
integer
numberOfEigenvalues
=
eigen
->
numberOfEigenvalues
;
integer
dimension
=
eigen
->
dimension
;
const
integer
ix
=
integer_abs
(
pcx
),
iy
=
integer_abs
(
pcy
);
const
integer
numberOfEigenvalues
=
eigen
->
numberOfEigenvalues
;
const
integer
dimension
=
eigen
->
dimension
;
if
(
ix
>
numberOfEigenvalues
||
iy
>
numberOfEigenvalues
||
my
numberOfInputs
!=
dimension
)
return
;
...
...
@@ -49,24 +49,28 @@ void FFNet_Eigen_drawIntersection (FFNet me, Eigen eigen, Graphics g, integer pc
Graphics_setInner
(
g
);
Graphics_setWindow
(
g
,
xmin
,
xmax
,
ymin
,
ymax
);
for
(
integer
i
=
1
;
i
<=
my
numberOfUnitsInLayer
[
1
];
i
++
)
{
integer
unitOffset
=
my
numberOfInputs
+
1
;
double
c1
=
0.0
,
c2
=
0.0
,
bias
=
my
w
[
my
wLast
[
unitOffset
+
i
]];
const
integer
unitOffset
=
my
numberOfInputs
+
1
;
const
double
bias
=
my
w
[
my
wLast
[
unitOffset
+
i
]];
double
c1
=
0.0
,
c2
=
0.0
;
double
x
[
6
],
y
[
6
],
xs
[
3
],
ys
[
3
];
integer
ns
=
0
;
for
(
integer
j
=
1
;
j
<=
my
numberOfInputs
;
j
++
)
{
c1
+=
my
w
[
my
wFirst
[
unitOffset
+
i
]
+
j
-
1
]
*
eigen
->
eigenvectors
[
ix
]
[
j
];
c2
+=
my
w
[
my
wFirst
[
unitOffset
+
i
]
+
j
-
1
]
*
eigen
->
eigenvectors
[
iy
]
[
j
];
}
x
[
1
]
=
x
[
2
]
=
x
[
5
]
=
xmin
;
x
[
3
]
=
x
[
4
]
=
xmax
;
y
[
1
]
=
y
[
4
]
=
y
[
5
]
=
ymin
;
y
[
2
]
=
y
[
3
]
=
ymax
;
x
[
1
]
=
x
[
2
]
=
x
[
5
]
=
xmin
;
x
[
3
]
=
x
[
4
]
=
xmax
;
y
[
1
]
=
y
[
4
]
=
y
[
5
]
=
ymin
;
y
[
2
]
=
y
[
3
]
=
ymax
;
for
(
integer
j
=
1
;
j
<=
4
;
j
++
)
{
double
p1
=
c1
*
x
[
j
]
+
c2
*
y
[
j
]
+
bias
;
double
p2
=
c1
*
x
[
j
+
1
]
+
c2
*
y
[
j
+
1
]
+
bias
;
double
r
=
fabs
(
p1
)
/
(
fabs
(
p1
)
+
fabs
(
p2
));
const
double
p1
=
c1
*
x
[
j
]
+
c2
*
y
[
j
]
+
bias
;
const
double
p2
=
c1
*
x
[
j
+
1
]
+
c2
*
y
[
j
+
1
]
+
bias
;
const
double
r
=
fabs
(
p1
)
/
(
fabs
(
p1
)
+
fabs
(
p2
));
if
(
p1
*
p2
>
0
||
r
==
0.0
)
continue
;
if
(
++
ns
>
2
)
break
;
if
(
++
ns
>
2
)
break
;
xs
[
ns
]
=
x
[
j
]
+
(
x
[
j
+
1
]
-
x
[
j
])
*
r
;
ys
[
ns
]
=
y
[
j
]
+
(
y
[
j
+
1
]
-
y
[
j
])
*
r
;
...
...
@@ -86,11 +90,15 @@ void FFNet_Eigen_drawIntersection (FFNet me, Eigen eigen, Graphics g, integer pc
void
FFNet_Eigen_drawDecisionPlaneInEigenspace
(
FFNet
me
,
Eigen
thee
,
Graphics
g
,
integer
unit
,
integer
layer
,
integer
pcx
,
integer
pcy
,
double
xmin
,
double
xmax
,
double
ymin
,
double
ymax
)
{
if
(
layer
<
1
||
layer
>
my
numberOfLayers
)
return
;
if
(
unit
<
1
||
unit
>
my
numberOfUnitsInLayer
[
layer
])
return
;
if
(
pcx
>
thy
numberOfEigenvalues
||
pcy
>
thy
numberOfEigenvalues
)
return
;
integer
numberOfUnitsInLayer_m1
=
(
layer
==
1
?
my
numberOfInputs
:
my
numberOfUnitsInLayer
[
layer
-
1
]
);
if
(
numberOfUnitsInLayer_m1
!=
thy
dimension
)
return
;
if
(
layer
<
1
||
layer
>
my
numberOfLayers
)
return
;
if
(
unit
<
1
||
unit
>
my
numberOfUnitsInLayer
[
layer
])
return
;
if
(
pcx
>
thy
numberOfEigenvalues
||
pcy
>
thy
numberOfEigenvalues
)
return
;
const
integer
numberOfUnitsInLayer_m1
=
(
layer
==
1
?
my
numberOfInputs
:
my
numberOfUnitsInLayer
[
layer
-
1
]
);
if
(
numberOfUnitsInLayer_m1
!=
thy
dimension
)
return
;
double
x1
,
x2
,
y1
,
y2
;
...
...
@@ -106,8 +114,9 @@ void FFNet_Eigen_drawDecisionPlaneInEigenspace (FFNet me, Eigen thee, Graphics g
Graphics_setInner
(
g
);
Graphics_setWindow
(
g
,
xmin
,
xmax
,
ymin
,
ymax
);
integer
node
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit
,
layer
);
if
(
node
<
1
)
return
;
const
integer
node
=
FFNet_getNodeNumberFromUnitNumber
(
me
,
unit
,
layer
);
if
(
node
<
1
)
return
;
/*
Suppose p1 and p2 are the two points in the eigenplane, spanned by the eigenvectors
...
...
@@ -135,16 +144,18 @@ void FFNet_Eigen_drawDecisionPlaneInEigenspace (FFNet me, Eigen thee, Graphics g
Both planes are parallel, no intersection.
*/
integer
iw
=
my
wFirst
[
node
]
-
1
;
const
integer
iw
=
my
wFirst
[
node
]
-
1
;
double
we1
=
0.0
,
we2
=
0.0
;
for
(
integer
i
=
1
;
i
<=
numberOfUnitsInLayer_m1
;
i
++
)
{
we1
+=
my
w
[
iw
+
i
]
*
thy
eigenvectors
[
pcx
]
[
i
];
we2
+=
my
w
[
iw
+
i
]
*
thy
eigenvectors
[
pcy
]
[
i
];
}
double
bias
=
my
w
[
my
wLast
[
node
]];
x1
=
xmin
;
x2
=
xmax
;
y1
=
ymin
;
y2
=
ymax
;
const
double
bias
=
my
w
[
my
wLast
[
node
]];
x1
=
xmin
;
x2
=
xmax
;
y1
=
ymin
;
y2
=
ymax
;
if
(
we1
!=
0.0
)
{
x1
=
-
bias
/
we1
;
y1
=
0.0
;
...
...
@@ -159,7 +170,7 @@ void FFNet_Eigen_drawDecisionPlaneInEigenspace (FFNet me, Eigen thee, Graphics g
return
;
}
double
xi
[
3
],
yi
[
3
];
/* Intersections */
double
ni
=
NUMgetIntersectionsWithRectangle
(
x1
,
y1
,
x2
,
y2
,
xmin
,
ymin
,
xmax
,
ymax
,
xi
,
yi
);
const
double
ni
=
NUMgetIntersectionsWithRectangle
(
x1
,
y1
,
x2
,
y2
,
xmin
,
ymin
,
xmax
,
ymax
,
xi
,
yi
);
if
(
ni
==
2
)
Graphics_line
(
g
,
xi
[
1
],
yi
[
1
],
xi
[
2
],
yi
[
2
]);
else
...
...
FFNet/FFNet_Matrix.cpp
View file @
95b98d96
/* FFNet_Matrix.cpp
*
* Copyright (C) 1997-201
8
David Weenink
* Copyright (C) 1997-201
9
David Weenink
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -25,8 +25,9 @@
autoMatrix
FFNet_weightsToMatrix
(
FFNet
me
,
integer
layer
,
bool
deltaWeights
)
{
try
{
Melder_require
(
layer
>
0
&&
layer
<=
my
numberOfLayers
,
U"Layer should be in [1, "
,
my
numberOfLayers
,
U"]."
);
integer
numberOfUnitsInPreviousLayer
=
(
layer
==
1
?
my
numberOfInputs
:
my
numberOfUnitsInLayer
[
layer
-
1
]
);
Melder_require
(
layer
>
0
&&
layer
<=
my
numberOfLayers
,
U"Layer should be in [1, "
,
my
numberOfLayers
,
U"]."
);
const
integer
numberOfUnitsInPreviousLayer
=
(
layer
==
1
?
my
numberOfInputs
:
my
numberOfUnitsInLayer
[
layer
-
1
]
);
autoMatrix
thee
=
Matrix_create
(
0.5
,
my
numberOfUnitsInLayer
[
layer
]
+
0.5
,
my
numberOfUnitsInLayer
[
layer
],
1.0
,
1.0
,
0.5
,
numberOfUnitsInPreviousLayer
+
1
+
0.5
,
numberOfUnitsInPreviousLayer
+
1
,
1.0
,
1.0
);
...
...
@@ -52,7 +53,7 @@ autoFFNet FFNet_weightsFromMatrix (FFNet me, Matrix him, integer layer) {
Melder_require
(
my
numberOfUnitsInLayer
[
layer
]
==
his
nx
,
U"The number of columns ("
,
his
nx
,
U") should equal the number of units ("
,
my
numberOfUnitsInLayer
[
layer
],
U") in layer "
,
layer
,
U"."
);
integer
nunits
=
(
layer
==
1
?
my
numberOfInputs
+
1
:
my
numberOfUnitsInLayer
[
layer
-
1
]
+
1
);
const
integer
nunits
=
(
layer
==
1
?
my
numberOfInputs
+
1
:
my
numberOfUnitsInLayer
[
layer
-
1
]
+
1
);
Melder_require
(
nunits
==
his
ny
,
U"The number of rows ("
,
his
ny
,
U") should equal the number of units ("
,
nunits
,
U") in layer "
,
layer
-
1
,
U"."
);
...
...
FFNet/FFNet_PatternList.cpp
View file @
95b98d96
/* FFNet_PatternList.cpp
*
* Copyright (C) 1997-201
8
David Weenink
* Copyright (C) 1997-201
9
David Weenink
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
FFNet/FFNet_PatternList_ActivationList.cpp
View file @
95b98d96
...
...
@@ -111,15 +111,15 @@ static void _FFNet_PatternList_ActivationList_learn (FFNet me, PatternList patte
void
FFNet_PatternList_ActivationList_learnSD
(
FFNet
me
,
PatternList
p
,
ActivationList
a
,
integer
maxNumOfEpochs
,
double
tolerance
,
double
learningRate
,
double
momentum
,
int
costFunctionType
)
{
int
resetMinimizer
=
0
;
bool
resetMinimizer
=
false
;
/* Did we choose another minimizer */
if
(
my
minimizer
&&
!
Thing_isa
(
my
minimizer
.
get
(),
classSteepestDescentMinimizer
))
{
my
minimizer
.
reset
();
resetMinimizer
=
1
;
resetMinimizer
=
true
;
}
/* create the minimizer if it doesn't exist */
if
(
!
my
minimizer
)
{
resetMinimizer
=
1
;
resetMinimizer
=
true
;
my
minimizer
=
SteepestDescentMinimizer_create
(
my
dimension
,
me
,
func
,
dfunc_optimized
);
}
((
SteepestDescentMinimizer
)
my
minimizer
.
get
())
->
eta
=
learningRate
;
...
...
@@ -128,17 +128,17 @@ void FFNet_PatternList_ActivationList_learnSD (FFNet me, PatternList p, Activati
}
void
FFNet_PatternList_ActivationList_learnSM
(
FFNet
me
,
PatternList
p
,
ActivationList
a
,
integer
maxNumOfEpochs
,
double
tolerance
,
int
costFunctionType
)
{
int
resetMinimizer
=
0
;
bool
resetMinimizer
=
false
;
// Did we choose another minimizer
if
(
my
minimizer
.
get
()
&&
!
Thing_isa
(
my
minimizer
.
get
(),
classVDSmagtMinimizer
))
{
my
minimizer
.
reset
();
resetMinimizer
=
1
;
resetMinimizer
=
true
;
}
// create the minimizer if it doesn't exist
if
(
!
my
minimizer
.
get
())
{
resetMinimizer
=
1
;
resetMinimizer
=
true
;
my
minimizer
=
VDSmagtMinimizer_create
(
my
dimension
,
me
,
func
,
dfunc_optimized
);
}
_FFNet_PatternList_ActivationList_learn
(
me
,
p
,
a
,
maxNumOfEpochs
,
tolerance
,
costFunctionType
,
resetMinimizer
);
...
...
@@ -161,21 +161,20 @@ double FFNet_PatternList_ActivationList_getCosts_total (FFNet me, PatternList p,
}
double
FFNet_PatternList_ActivationList_getCosts_average
(
FFNet
me
,
PatternList
p
,
ActivationList
a
,
int
costFunctionType
)
{
double
costs
=
FFNet_PatternList_ActivationList_getCosts_total
(
me
,
p
,
a
,
costFunctionType
);
const
double
costs
=
FFNet_PatternList_ActivationList_getCosts_total
(
me
,
p
,
a
,
costFunctionType
);
return
(
isundef
(
costs
)
?
undefined
:
costs
/
p
->
ny
);
}
autoActivationList
FFNet_PatternList_to_ActivationList
(
FFNet
me
,
PatternList
p
,
integer
layer
)
{
try
{
if
(
layer
<
1
||
layer
>
my
numberOfLayers
)
{
if
(
layer
<
1
||
layer
>
my
numberOfLayers
)
layer
=
my
numberOfLayers
;
}
Melder_require
(
my
numberOfInputs
==
p
->
nx
,
U"The number of colums in the PatternList ("
,
p
->
nx
,
U") should equal the number of inputs in the FFNet ("
,
my
numberOfInputs
,
U")."
);
Melder_require
(
_PatternList_checkElements
(
p
),
U"All PatternList elements should be in the interval [0, 1].
\n
You could use
\"
Formula...
\"
to scale the PatternList values first."
);
integer
numberOfPatterns
=
p
->
ny
;
const
integer
numberOfPatterns
=
p
->
ny
;
autoActivationList
thee
=
ActivationList_create
(
numberOfPatterns
,
my
numberOfUnitsInLayer
[
layer
]);
for
(
integer
i
=
1
;
i
<=
numberOfPatterns
;
i
++
)
{
...
...
FFNet/FFNet_PatternList_Categories.cpp
View file @
95b98d96
/* FFNet_PatternList_Categories.cpp
*
* Copyright (C) 1994-201
8
David Weenink
* Copyright (C) 1994-201
9
David Weenink
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -47,7 +47,7 @@ double FFNet_PatternList_Categories_getCosts_total (FFNet me, PatternList p, Cat
}
double
FFNet_PatternList_Categories_getCosts_average
(
FFNet
me
,
PatternList
p
,
Categories
c
,
int
costFunctionType
)
{
double
costs
=
FFNet_PatternList_Categories_getCosts_total
(
me
,
p
,
c
,
costFunctionType
);
const
double
costs
=
FFNet_PatternList_Categories_getCosts_total
(
me
,
p
,
c
,
costFunctionType
);
return
(
isundef
(
costs
)
?
undefined
:
costs
/
p
->
ny
);
}
...
...
@@ -80,7 +80,7 @@ autoCategories FFNet_PatternList_to_Categories (FFNet me, PatternList thee, int
for
(
integer
k
=
1
;
k
<=
thy
ny
;
k
++
)
{
FFNet_propagate
(
me
,
thy
z
.
row
(
k
),
nullptr
);
integer
index
=
FFNet_getWinningUnit
(
me
,
labeling
);
const
integer
index
=
FFNet_getWinningUnit
(
me
,
labeling
);
autoSimpleString
item
=
Data_copy
(
my
outputCategories
->
at
[
index
]);
his
addItem_move
(
item
.
move
());
}
...
...
FFNet/praat_FFNet_init.cpp
View file @
95b98d96
/* praat_FFNet_init.cpp
*
* Copyright (C) 1994-201
1, 2016-2017
David Weenink
* Copyright (C) 1994-201
9
David Weenink
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -47,9 +47,6 @@
20040422, 2.4.04: FFNet_weightsToMatrix use FFNet_extractWeights
*/
#undef iam
#define iam iam_LOOP
static
char32
const
*
QUERY_BUTTON
=
U"Query -"
;
static
char32
const
*
DRAW_BUTTON
=
U"Draw -"
;
static
char32
const
*
MODIFY_BUTTON
=
U"Modify -"
;
...
...
LPC/Cepstrogram.cpp
View file @
95b98d96
...
...
@@ -65,7 +65,7 @@ autoPowerCepstrogram PowerCepstrogram_create (double tmin, double tmax, integer
}
void
PowerCepstrogram_paint
(
PowerCepstrogram
me
,
Graphics
g
,
double
tmin
,
double
tmax
,
double
qmin
,
double
qmax
,
double
dBmaximum
,
int
autoscaling
,
double
dynamicRangedB
,
double
dynamicCompression
,
bool
garnish
)
{
if
(
tmax
<=
tmin
)
{
tmin
=
my
xmin
;
tmax
=
my
xmax
;
}
Function_unidirectionalAutowindow
(
me
,
&
tmin
,
&
tmax
);
if
(
qmax
<=
qmin
)
{
qmin
=
my
ymin
;
qmax
=
my
ymax
;
}
integer
itmin
,
itmax
,
ifmin
,
ifmax
;
if
(
!
Matrix_getWindowSamplesX
(
me
,
tmin
-
0.49999
*
my
dx
,
tmax
+
0.49999
*
my
dx
,
&
itmin
,
&
itmax
)
||
...
...
LPC/Formant_extensions.cpp
View file @
95b98d96
...
...
@@ -21,11 +21,8 @@
void
Formant_formula
(
Formant
me
,
double
tmin
,
double
tmax
,
integer
formantmin
,
integer
formantmax
,
Interpreter
interpreter
,
conststring32
expression
)
{
try
{
Function_unidirectionalAutowindow
(
me
,
&
tmin
,
&
tmax
);
integer
numberOfPossibleFormants
=
my
maxnFormants
;
if
(
tmax
<=
tmin
)
{
tmin
=
my
xmin
;
tmax
=
my
xmax
;
}
if
(
formantmax
>=
formantmin
)
{
formantmin
=
1
;
formantmax
=
numberOfPossibleFormants
;
...
...
LPC/LPC.cpp
View file @
95b98d96
...
...
@@ -84,10 +84,7 @@ autoLPC LPC_create (double tmin, double tmax, integer nt, double dt, double t1,
}
void
LPC_drawGain
(
LPC
me
,
Graphics
g
,
double
tmin
,
double
tmax
,
double
gmin
,
double
gmax
,
bool
garnish
)
{
if
(
tmax
<=
tmin
)
{
tmin
=
my
xmin
;
tmax
=
my
xmax
;
}
Function_unidirectionalAutowindow
(
me
,
&
tmin
,
&
tmax
);
integer
itmin
,
itmax
;
if
(
!
Sampled_getWindowSamples
(
me
,
tmin
,
tmax
,
&
itmin
,
&
itmax
))
return
;
...
...
LPC/LineSpectralFrequencies.cpp
View file @
95b98d96
...
...
@@ -77,10 +77,7 @@ autoLineSpectralFrequencies LineSpectralFrequencies_create (double tmin, double
}
void
LineSpectralFrequencies_drawFrequencies
(
LineSpectralFrequencies
me
,
Graphics
g
,
double
tmin
,
double
tmax
,
double
fmin
,
double
fmax
,
bool
garnish
)
{
if
(
tmax
<=
tmin
)
{
tmin
=
my
xmin
;
tmax
=
my
xmax
;
}
Function_unidirectionalAutowindow
(
me
,
&
tmin
,
&
tmax
);
integer
itmin
,
itmax
;
if
(
!
Sampled_getWindowSamples
(
me
,
tmin
,
tmax
,
&
itmin
,
&
itmax
))
return
;
...
...
README.md
View file @
95b98d96
This diff is collapsed.
Click to expand it.
artsynth/Art_Speaker_Delta.cpp
View file @
95b98d96
/* Art_Speaker_Delta.cpp
*
* Copyright (C) 1992-2005,2009,2011,2016-201
8
Paul Boersma
* Copyright (C) 1992-2005,2009,2011,2016-201
9
Paul Boersma
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -27,12 +27,12 @@ void Art_Speaker_intoDelta (Art art, Speaker speaker, Delta delta)
/* Lungs. */
for
(
integer
itube
=
7
;
itube
<=
18
;
itube
++
)
delta
->
tube
[
itube
].
Dyeq
=
120
*
f
*
(
1
+
art
->
art
[(
int
)
kArt_muscle
::
LUNGS
]);
delta
->
tube
s
[
itube
].
Dyeq
=
120
*
f
*
(
1
+
art
->
art
[(
int
)
kArt_muscle
::
LUNGS
]);
/* Glottis. */
{
Delta_Tube
t
=
delta
->
tube
+
36
;
Delta_Tube
t
=
&
delta
->
tube
s
[
36
]
;
t
->
Dyeq
=
f
*
(
5
-
10
*
art
->
art
[(
int
)
kArt_muscle
::
INTERARYTENOID
]
+
3
*
art
->
art
[(
int
)
kArt_muscle
::
POSTERIOR_CRICOARYTENOID
]
-
3
*
art
->
art
[(
int
)
kArt_muscle
::
LATERAL_CRICOARYTENOID
]);
// 4.38
...
...
@@ -40,21 +40,21 @@ void Art_Speaker_intoDelta (Art art, Speaker speaker, Delta delta)
t
->
k3
=
t
->
k1
*
(
20
/
t
->
Dz
)
*
(
20
/
t
->
Dz
);
}
if
(
speaker
->
cord
.
numberOfMasses
>=
2
)
{
Delta_Tube
t
=
delta
->
tube
+
37
;
t
->
Dyeq
=
delta
->
tube
[
36
].
Dyeq
;
Delta_Tube
t
=
&
delta
->
tube
s
[
37
]
;
t
->
Dyeq
=
delta
->
tube
s
[
36
].
Dyeq
;
t
->
k1
=
speaker
->
upperCord
.
k1
*
(
1
+
art
->
art
[(
int
)
kArt_muscle
::
CRICOTHYROID
]);
t
->
k3
=
t
->
k1
*
(
20
/
t
->
Dz
)
*
(
20
/
t
->
Dz
);
}
if
(
speaker
->
cord
.
numberOfMasses
>=
10
)
{
delta
->
tube
[
84
].
Dyeq
=
0.75
*
1
*
f
+
0.25
*
delta
->
tube
[
36
].
Dyeq
;
delta
->
tube
[
85
].
Dyeq
=
0.50
*
1
*
f
+
0.50
*
delta
->
tube
[
36
].
Dyeq
;
delta
->
tube
[
86
].
Dyeq
=
0.25
*
1
*
f
+
0.75
*
delta
->
tube
[
36
].
Dyeq
;
delta
->
tube
[
84
].
k1
=
0.75
*
160
+
0.25
*
delta
->
tube
[
36
].
k1
;
delta
->
tube
[
85
].
k1
=
0.50
*
160
+
0.50
*
delta
->
tube
[
36
].
k1
;
delta
->
tube
[
86
].
k1
=
0.25
*
160
+
0.75
*
delta
->
tube
[
36
].
k1
;
delta
->
tube
s
[
84
].
Dyeq
=
0.75
*
1
*
f
+
0.25
*
delta
->
tube
s
[
36
].
Dyeq
;
delta
->
tube
s
[
85
].
Dyeq
=
0.50
*
1
*
f
+
0.50
*
delta
->
tube
s
[
36
].
Dyeq
;
delta
->
tube
s
[
86
].
Dyeq
=
0.25
*
1
*
f
+
0.75
*
delta
->
tube
s
[
36
].
Dyeq
;
delta
->
tube
s
[
84
].
k1
=
0.75
*
160
+
0.25
*
delta
->
tube
s
[
36
].
k1
;
delta
->
tube
s
[
85
].
k1
=
0.50
*
160
+
0.50
*
delta
->
tube
s
[
36
].
k1
;
delta
->
tube
s
[
86
].
k1
=
0.25
*
160
+
0.75
*
delta
->
tube
s
[
36
].
k1
;
for
(
integer
itube
=
84
;
itube
<=
86
;
itube
++
)
delta
->
tube
[
itube
].
k3
=
delta
->
tube
[
itube
].
k1
*
(
20
/
delta
->
tube
[
itube
].
Dz
)
*
(
20
/
delta
->
tube
[
itube
].
Dz
);
delta
->
tube
s
[
itube
].
k3
=
delta
->
tube
s
[
itube
].
k1
*
(
20
/
delta
->
tube
s
[
itube
].
Dz
)
*
(
20
/
delta
->
tube
s
[
itube
].
Dz
);
}
/* Vocal tract. */
...
...
@@ -62,7 +62,7 @@ void Art_Speaker_intoDelta (Art art, Speaker speaker, Delta delta)
bool
closed
[
40
];
Art_Speaker_meshVocalTract
(
art
,
speaker
,
xi
,
yi
,
xe
,
ye
,
xmm
,
ymm
,
closed
);
for
(
integer
itube
=
38
;
itube
<=
64
;
itube
++
)
{
Delta_Tube
t
=
delta
->
tube
+
itube
;
Delta_Tube
t
=
&
delta
->
tube
s
[
itube
]
;
integer
i
=
itube
-
37
;
double
dx
=
xmm
[
i
]
-
xmm
[
i
+
1
];
double
dy
=
ymm
[
i
]
-
ymm
[
i
+
1
];
...
...
@@ -70,17 +70,18 @@ void Art_Speaker_intoDelta (Art art, Speaker speaker, Delta delta)
dx
=
xe
[
i
]
-
xi
[
i
];
dy
=
ye
[
i
]
-
yi
[
i
];
t
->
Dyeq
=
sqrt
(
dx
*
dx
+
dy
*
dy
);
if
(
closed
[
i
])
t
->
Dyeq
=
-
t
->
Dyeq
;
if
(
closed
[
i
])
t
->
Dyeq
=
-
t
->
Dyeq
;
}
delta
->
tube
[
65
].
Dxeq
=
delta
->
tube
[
51
].
Dxeq
=
delta
->
tube
[
50
].
Dxeq
;
/* Voor [r]: thy tube [60]. Brel = 0.1; thy tube [60]. k1 = 3; */
delta
->
tube
s
[
65
].
Dxeq
=
delta
->
tube
s
[
51
].
Dxeq
=
delta
->
tube
s
[
50
].
Dxeq
;
/* Voor [r]: thy tube
s
[60]. Brel = 0.1; thy tube
s
[60]. k1 = 3; */
/* Nasopharyngeal port. */
delta
->
tube
[
65
].
Dyeq
=
f
*
(
18
-
25
*
art
->
art
[(
int
)
kArt_muscle
::
LEVATOR_PALATINI
]);
// 4.40
delta
->
tube
s
[
65
].
Dyeq
=
f
*
(
18
-
25
*
art
->
art
[(
int
)
kArt_muscle
::
LEVATOR_PALATINI
]);
// 4.40
for
(
integer
itube
=
1
;
itube
<=
delta
->
numberOfTubes
;
itube
++
)
{
Delta_Tube
t
=
delta
->
tube
+
itube
;
Delta_Tube
t
=
&
delta
->
tube
s
[
itube
]
;
t
->
s1
=
5e6
*
t
->
Dxeq
*
t
->
Dzeq
;
t
->
s3
=
t
->
s1
/
(
0.9e-3
*
0.9e-3
);
}
...
...
artsynth/Art_Speaker_to_VocalTract.cpp
View file @
95b98d96
/* Art_Speaker_to_VocalTract.cpp
*
* Copyright (C) 1992-2005,2008,2011,2015-2017 Paul Boersma
* Copyright (C) 1992-2005,2008,2011,2015-2017
,2019
Paul Boersma
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -28,7 +28,7 @@ autoVocalTract Art_Speaker_to_VocalTract (Art art, Speaker speaker) {
constexpr
double
sectionLength
=
0.001
;
// one millimetre
integer
numberOfSections
=
0
;
for
(
integer
isection
=
1
;
isection
<=
27
;
isection
++
)
{
Delta_Tube
tube
=
delta
->
tube
+
37
+
isection
;
Delta_Tube
tube
=
&
delta
->
tube
s
[
37
+
isection
]
;
integer
numberOfConstantSections
=
Melder_iround
(
tube
->
Dxeq
/
sectionLength
);
double
constantArea
=
tube
->
Dyeq
*
tube
->
Dzeq
;
for
(
integer
jsection
=
1
;
jsection
<=
numberOfConstantSections
;
jsection
++
)
...
...
artsynth/Artword_Speaker_to_Sound.cpp
View file @
95b98d96
/* Artword_Speaker_to_Sound.cpp
*
* Copyright (C) 1992-2005,2007,2008,2011,2012,2015-2017 Paul Boersma
* Copyright (C) 1992-2005,2007,2008,2011,2012,2015-2017
,2019
Paul Boersma
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -64,7 +64,7 @@ autoSound Artword_Speaker_to_Sound (Artword artword, Speaker speaker,
autoMelderMonitor
monitor
(
U"Articulatory synthesis"
);
Artword_intoArt
(
artword
,
art
.
get
(),
0.0
);
Art_Speaker_intoDelta
(
art
.
get
(),
speaker
,
delta
.
get
());
int
M
=
delta
->
numberOfTubes
;
int
eger
M
=
delta
->
numberOfTubes
;
autoSound
w1
,
w2
,
w3
,
p1
,
p2
,
p3
,
v1
,
v2
,
v3
;
if
(
iw1
>
0
&&
iw1
<=
M
)
w1
=
Sound_createSimple
(
1
,
artword
->
totalTime
,
fsamp
);
else
iw1
=
0
;
if
(
iw2
>
0
&&
iw2
<=
M
)
w2
=
Sound_createSimple
(
1
,
artword
->
totalTime
,
fsamp
);
else
iw2
=
0
;
...
...
@@ -82,7 +82,7 @@ autoSound Artword_Speaker_to_Sound (Artword artword, Speaker speaker,
}
totalVolume
=
0.0
;
for
(
int
m
=
1
;
m
<=
M
;
m
++
)
{
Delta_Tube
t
=
delta
->
tube
+
m
;
Delta_Tube
t
=
&
delta
->
tube
s
[
m
]
;
if
(
!
t
->
left1
&&
!
t
->
right1
)
continue
;
t
->
Dx
=
t
->
Dxeq
;
t
->
dDxdt
=
0.0
;
// 5.113 (numbers refer to equations in Boersma (1998)
t
->
Dy
=
t
->
Dyeq
;
t
->
dDydt
=
0.0
;
// 5.113
...
...
@@ -109,7 +109,7 @@ autoSound Artword_Speaker_to_Sound (Artword artword, Speaker speaker,
Graphics
graphics
=
monitor
.
graphics
();
double
area
[
1
+
78
];
for
(
int
i
=
1
;
i
<=
78
;
i
++
)
{
area
[
i
]
=
delta
->
tube
[
i
].
A
;
area
[
i
]
=
delta
->
tube
s
[
i
].
A
;
if
(
area
[
i
]
<
minTract
[
i
])
minTract
[
i
]
=
area
[
i
];
if
(
area
[
i
]
>
maxTract
[
i
])
maxTract
[
i
]
=
area
[
i
];
}
...
...
@@ -166,8 +166,9 @@ autoSound Artword_Speaker_to_Sound (Artword artword, Speaker speaker,
}
for
(
int
n
=
1
;
n
<=
oversampling
;
n
++
)
{
for
(
int
m
=
1
;
m
<=
M
;
m
++
)
{
Delta_Tube
t
=
delta
->
tube
+
m
;
if
(
!
t
->
left1
&&
!
t
->
right1
)
continue
;
Delta_Tube
t
=
&
delta
->
tubes
[
m
];
if
(
!
t
->
left1
&&
!
t
->
right1
)
continue
;
/* New geometry. */
...
...
@@ -250,7 +251,7 @@ autoSound Artword_Speaker_to_Sound (Artword artword, Speaker speaker,
#endif
}
for
(
int
m
=
1
;
m
<=
M
;
m
++
)
{
// compute Jleftnew and Qleftnew
Delta_Tube
l
=
delta
->
tube
+
m
,
r1
=
l
->
right1
,
r2
=
l
->
right2
,
r
=
r1
;
Delta_Tube
l
=
&
delta
->
tube
s
[
m
]
,
r1
=
l
->
right1
,
r2
=
l
->
right2
,
r
=
r1
;
Delta_Tube
l1
=
l
,
l2
=
r
?
r
->
left2
:
nullptr
;
if
(
!
l
->
left1
)
{
// closed boundary at the left side (diaphragm)?
if
(
!
r
)
continue
;
// tube not connected at all
...
...
@@ -365,24 +366,24 @@ autoSound Artword_Speaker_to_Sound (Artword artword, Speaker speaker,
if
(
n
==
(
oversampling
+
1
)
/
2
)
{
double
out
=
0.0
;
for
(
int
m
=
1
;
m
<=
M
;
m
++
)
{
Delta_Tube
t
=
delta
->
tube
+
m
;
Delta_Tube
t
=
&
delta
->
tube
s
[
m
]
;
out
+=
rho0
*
t
->
Dx
*
t
->
Dz
*
t
->
dDydt
*
Dt
*
1000.0
;
// radiation of wall movement, 5.140
if
(
!
t
->
right1
)
out
+=
t
->
Jrightnew
-
t
->
Jright
;
// radiation of open tube end
}
result
->
z
[
1
]
[
sample
]
=
out
/=
4.0
*
NUMpi
*
0.4
*
Dt
;
// at 0.4 metres
if
(
iw1
)
w1
->
z
[
1
]
[
sample
]
=
delta
->
tube
[
iw1
].
Dy
;
if
(
iw2
)
w2
->
z
[
1
]
[
sample
]
=
delta
->
tube
[
iw2
].
Dy
;
if
(
iw3
)
w3
->
z
[
1
]
[
sample
]
=
delta
->
tube
[
iw3
].
Dy
;
if
(
ip1
)
p1
->
z
[
1
]
[
sample
]
=
delta
->
tube
[
ip1
].
DeltaP
;
if
(
ip2
)
p2
->
z
[
1
]
[
sample
]
=
delta
->
tube
[
ip2
].
DeltaP
;
if
(
ip3
)
p3
->
z
[
1
]
[
sample
]
=
delta
->
tube
[
ip3
].
DeltaP
;
if
(
iv1
)
v1
->
z
[
1
]
[
sample
]
=
delta
->
tube
[
iv1
].
v
;
if
(
iv2
)
v2
->
z
[
1
]
[
sample
]
=
delta
->
tube
[
iv2
].
v
;
if
(
iv3
)
v3
->
z
[
1
]
[
sample
]
=
delta
->
tube
[
iv3
].
v
;
if
(
iw1
)
w1
->
z
[
1
]
[
sample
]
=
delta
->
tube
s
[
iw1
].
Dy
;
if
(
iw2
)
w2
->
z
[
1
]
[
sample
]
=
delta
->
tube
s
[
iw2
].
Dy
;
if
(
iw3
)
w3
->
z
[
1
]
[
sample
]
=
delta
->
tube
s
[
iw3
].
Dy
;
if
(
ip1
)
p1
->
z
[
1
]
[
sample
]
=
delta
->
tube
s
[
ip1
].
DeltaP
;
if
(
ip2
)
p2
->
z
[
1
]
[
sample
]
=
delta
->
tube
s
[
ip2
].
DeltaP
;
if
(
ip3
)
p3
->
z
[
1
]
[
sample
]
=
delta
->
tube
s
[
ip3
].
DeltaP
;
if
(
iv1
)
v1
->
z
[
1
]
[
sample
]
=
delta
->
tube
s
[
iv1
].
v
;
if
(
iv2
)
v2
->
z
[
1
]
[
sample
]
=
delta
->
tube
s
[
iv2
].
v
;
if
(
iv3
)
v3
->
z
[
1
]
[
sample
]
=
delta
->
tube
s
[
iv3
].
v
;
}
for
(
int
m
=
1
;
m
<=
M
;
m
++
)
{
Delta_Tube
t
=
delta
->
tube
+
m
;
Delta_Tube
t
=
&
delta
->
tube
s
[
m
]
;
t
->
Jleft
=
t
->
Jleftnew
;
t
->
Jright
=
t
->
Jrightnew
;
t
->
Qleft
=
t
->
Qleftnew
;
...
...
@@ -408,7 +409,7 @@ autoSound Artword_Speaker_to_Sound (Artword artword, Speaker speaker,
}
totalVolume
=
0.0
;
for
(
int
m
=
1
;
m
<=
M
;
m
++
)
totalVolume
+=
delta
->
tube
[
m
].
V
;
totalVolume
+=
delta
->
tube
s
[
m
].
V
;
//Melder_casual (U"Ending volume: ", totalVolume * 1000, U" litres.");
if
(
out_w1
)
*
out_w1
=
w1
.
move
();
if
(
out_w2
)
*
out_w2
=
w2
.
move
();
...
...
artsynth/Delta.cpp
View file @
95b98d96
/* Delta.cpp
*
* Copyright (C) 1992-2005,2011,2012,2014-2017 Paul Boersma
* Copyright (C) 1992-2005,2011,2012,2014-2017
,2019
Paul Boersma
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -20,17 +20,12 @@
Thing_implement
(
Delta
,
Thing
,
0
);
void
structDelta
::
v_destroy
()
noexcept
{
NUMvector_free
(
our
tube
,
1
);
Delta_Parent
::
v_destroy
();
}
void
Delta_init
(
Delta
me
,
integer
numberOfTubes
)
{
Melder_assert
(
numberOfTubes
>=
1
);
my
numberOfTubes
=
numberOfTubes
;
my
tube
=
NUM
vector
<
struct
structDelta_Tube
>
(
1
,
numberOfTubes
);
my
tube
s
=
new
vector
zero
<
structDelta_Tube
>
(
numberOfTubes
);
for
(
int
itube
=
1
;
itube
<=
numberOfTubes
;
itube
++
)
{
Delta_Tube
t
=
&
my
tube
[
itube
];
Delta_Tube
t
=
&
my
tube
s
[
itube
];
t
->
parallel
=
1
;
}
}
...
...
artsynth/Delta.h
View file @
95b98d96
...
...
@@ -2,7 +2,7 @@
#define _Delta_h_
/* Delta.h
*
* Copyright (C) 1992-2005,2007,2011,2015-2017 Paul Boersma
* Copyright (C) 1992-2005,2007,2011,2015-2017
,2019
Paul Boersma
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -54,10 +54,7 @@ struct structDelta_Tube
Thing_define
(
Delta
,
Thing
)
{
integer
numberOfTubes
;
// >= 1
struct
structDelta_Tube
*
tube
;
// tube [1..numberOfTubes]
void
v_destroy
()
noexcept
override
;
autovector
<
structDelta_Tube
>
tubes
;
};
void
Delta_init
(
Delta
me
,
integer
numberOfTubes
);
...
...
artsynth/Speaker_to_Delta.cpp
View file @
95b98d96
/* Speaker_to_Delta.cpp
*
* Copyright (C) 1992-2005,2006,2011,2015-201
8
Paul Boersma
* Copyright (C) 1992-2005,2006,2011,2015-201
9
Paul Boersma
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -30,7 +30,7 @@ autoDelta Speaker_to_Delta (Speaker me) {
/* Lungs: tubes 1..23. */
for
(
integer
itube
=
1
;
itube
<=
23
;
itube
++
)
{
Delta_Tube
t
=
thy
tube
+
itube
;
Delta_Tube
t
=
&
thy
tube
s
[
itube
]
;
t
->
Dx
=
t
->
Dxeq
=
10.0
*
f
;
t
->
Dy
=
t
->
Dyeq
=
100.0
*
f
;
t
->
Dz
=
t
->
Dzeq
=
230.0
*
f
;
...
...
@@ -44,7 +44,7 @@ autoDelta Speaker_to_Delta (Speaker me) {
/* Bronchi: tubes 24..29. */
for
(
integer
itube
=
24
;
itube
<=
29
;
itube
++
)
{
Delta_Tube
t
=
thy
tube
+
itube
;
Delta_Tube
t
=
&
thy
tube
s
[
itube
]
;
t
->
Dx
=
t
->
Dxeq
=
10.0
*
f
;
t
->
Dy
=
t
->
Dyeq
=
15.0
*
f
;
t
->
Dz
=
t
->
Dzeq
=
30.0
*
f
;
...
...
@@ -57,7 +57,7 @@ autoDelta Speaker_to_Delta (Speaker me) {
/* Trachea: tubes 30..35; four of these may be replaced by conus elasticus (see below). */
for
(
integer
itube
=
30
;
itube
<=
35
;
itube
++
)
{
Delta_Tube
t
=
thy
tube
+
itube
;
Delta_Tube
t
=
&
thy
tube
s
[
itube
]
;
t
->
Dx
=
t
->
Dxeq
=
10.0
*
f
;
t
->
Dy
=
t
->
Dyeq
=
15.0
*
f
;
t
->
Dz
=
t
->
Dzeq
=
16.0
*
f
;
...
...
@@ -77,19 +77,19 @@ autoDelta Speaker_to_Delta (Speaker me) {
{
22
,
12.0
,
12.0
,
5.0
},
{
23
,
12.0
,
12.0
,
3.0
},
{
24
,
18.0
,
9.0
,
2.0
},
{
25
,
18.0
,
19.0
,
2.0
},
{
}
};
for
(
integer
i
=
0
;
data
[
i
].
itube
;
i
++
)
{
Delta_Tube
t
=
thy
tube
+
data
[
i
].
itube
;
Delta_Tube
t
=
&
thy
tube
s
[
data
[
i
].
itube
]
;
t
->
Dy
=
t
->
Dyeq
=
data
[
i
].
Dy
*
f
;
t
->
Dz
=
t
->
Dzeq
=
data
[
i
].
Dz
*
f
;
t
->
parallel
=
data
[
i
].
parallel
;
}
for
(
integer
itube
=
26
;
itube
<=
35
;
itube
++
)
{
Delta_Tube
t
=
thy
tube
+
itube
;
Delta_Tube
t
=
&
thy
tube
s
[
itube
]
;
t
->
Dy
=
t
->
Dyeq
=
11.0
*
f
;
t
->
Dz
=
t
->
Dzeq
=
14.0
*
f
;
t
->
parallel
=
1
;
}
for
(
integer
itube
=
FIRST_TUBE
;
itube
<=
18
;
itube
++
)
{
Delta_Tube
t
=
thy
tube
+
itube
;
Delta_Tube
t
=
&
thy
tube
s
[
itube
]
;
t
->
Dx
=
t
->
Dxeq
=
10.0
*
f
;
t
->
mass
=
10.0
*
my
relativeSize
*
t
->
Dx
*
t
->
Dz
;
// 10 mm
t
->
k1
=
1e5
*
t
->
Dx
*
t
->
Dz
;
// elastic tissue: 1 mbar/mm
...
...
@@ -97,7 +97,7 @@ autoDelta Speaker_to_Delta (Speaker me) {
t
->
Brel
=
1.0
;
}
for
(
integer
itube
=
19
;
itube
<=
35
;
itube
++
)
{
Delta_Tube
t
=
thy
tube
+
itube
;
Delta_Tube
t
=
&
thy
tube
s
[
itube
]
;
t
->
Dx
=
t
->
Dxeq
=
10.0
*
f
;
t
->
mass
=
3.0
*
my
relativeSize
*
t
->
Dx
*
t
->
Dz
;
// 3 mm
t
->
k1
=
10e5
*
t
->
Dx
*
t
->
Dz
;
// cartilage: 10 mbar/mm
...
...
@@ -108,7 +108,7 @@ autoDelta Speaker_to_Delta (Speaker me) {
/* Glottis: tubes 36 and 37; the last one may be disconnected (see below). */
{
Delta_Tube
t
=
thy
tube
+
36
;
Delta_Tube
t
=
&
thy
tube
s
[
36
]
;
t
->
Dx
=
t
->
Dxeq
=
my
lowerCord
.
thickness
;
t
->
Dy
=
t
->
Dyeq
=
0.0
;
t
->
Dz
=
t
->
Dzeq
=
my
cord
.
length
;
...
...
@@ -122,7 +122,7 @@ autoDelta Speaker_to_Delta (Speaker me) {
* Fill in the values for the upper part of the glottis (tube 37) only if there is no one-mass model.
*/
if
(
my
cord
.
numberOfMasses
>=
2
)
{
Delta_Tube
t
=
thy
tube
+
37
;
Delta_Tube
t
=
&
thy
tube
s
[
37
]
;
t
->
Dx
=
t
->
Dxeq
=
my
upperCord
.
thickness
;
t
->
Dy
=
t
->
Dyeq
=
0.0
;
t
->
Dz
=
t
->
Dzeq
=
my
cord
.
length
;
...
...
@@ -132,66 +132,66 @@ autoDelta Speaker_to_Delta (Speaker me) {
t
->
Brel
=
0.2
;
/* Couple spring with lower cord. */
t
->
k1left1
=
thy
tube
[
36
].
k1right1
=
1.0
;
t
->
k1left1
=
thy
tube
s
[
36
].
k1right1
=
1.0
;
}
/*
* Fill in the values for the conus elasticus (tubes 79..86) only if we want to model it.
*/
if
(
my
cord
.
numberOfMasses
==
10
)
{
thy
tube
[
79
].
Dx
=
thy
tube
[
79
].
Dxeq
=
8.0
*
f
;
thy
tube
[
80
].
Dx
=
thy
tube
[
80
].
Dxeq
=
7.0
*
f
;
thy
tube
[
81
].
Dx
=
thy
tube
[
81
].
Dxeq
=
6.0
*
f
;
thy
tube
[
82
].
Dx
=
thy
tube
[
82
].
Dxeq
=
5.0
*
f
;
thy
tube
[
83
].
Dx
=
thy
tube
[
83
].
Dxeq
=
4.0
*
f
;
thy
tube
[
84
].
Dx
=
thy
tube
[
84
].
Dxeq
=
0.75
*
4.0
*
f
+
0.25
*
my
lowerCord
.
thickness
;
thy
tube
[
85
].
Dx
=
thy
tube
[
85
].
Dxeq
=
0.50
*
4.0
*
f
+
0.50
*
my
lowerCord
.
thickness
;
thy
tube
[
86
].
Dx
=
thy
tube
[
86
].
Dxeq
=
0.25
*
4.0
*
f
+
0.75
*
my
lowerCord
.
thickness
;
thy
tube
[
79
].
Dy
=
thy
tube
[
79
].
Dyeq
=
11.0
*
f
;
thy
tube
[
80
].
Dy
=
thy
tube
[
80
].
Dyeq
=
7.0
*
f
;
thy
tube
[
81
].
Dy
=
thy
tube
[
81
].
Dyeq
=
4.0
*
f
;
thy
tube
[
82
].
Dy
=
thy
tube
[
82
].
Dyeq
=
2.0
*
f
;
thy
tube
[
83
].
Dy
=
thy
tube
[
83
].
Dyeq
=
1.0
*
f
;
thy
tube
[
84
].
Dy
=
thy
tube
[
84
].
Dyeq
=
0.75
*
f
;
thy
tube
[
85
].
Dy
=
thy
tube
[
85
].
Dyeq
=
0.50
*
f
;
thy
tube
[
86
].
Dy
=
thy
tube
[
86
].
Dyeq
=
0.25
*
f
;
thy
tube
[
79
].
Dz
=
thy
tube
[
79
].
Dzeq
=
16.0
*
f
;
thy
tube
[
80
].
Dz
=
thy
tube
[
80
].
Dzeq
=
16.0
*
f
;
thy
tube
[
81
].
Dz
=
thy
tube
[
81
].
Dzeq
=
16.0
*
f
;
thy
tube
[
82
].
Dz
=
thy
tube
[
82
].
Dzeq
=
16.0
*
f
;
thy
tube
[
83
].
Dz
=
thy
tube
[
83
].
Dzeq
=
16.0
*
f
;
thy
tube
[
84
].
Dz
=
thy
tube
[
84
].
Dzeq
=
0.75
*
16.0
*
f
+
0.25
*
my
cord
.
length
;
thy
tube
[
85
].
Dz
=
thy
tube
[
85
].
Dzeq
=
0.50
*
16.0
*
f
+
0.50
*
my
cord
.
length
;
thy
tube
[
86
].
Dz
=
thy
tube
[
86
].
Dzeq
=
0.25
*
16.0
*
f
+
0.75
*
my
cord
.
length
;
thy
tube
[
79
].
k1
=
160.0
;
thy
tube
[
80
].
k1
=
160.0
;
thy
tube
[
81
].
k1
=
160.0
;
thy
tube
[
82
].
k1
=
160.0
;
thy
tube
[
83
].
k1
=
160.0
;
thy
tube
[
84
].
k1
=
0.75
*
160.0
*
f
+
0.25
*
my
lowerCord
.
k1
;
thy
tube
[
85
].
k1
=
0.50
*
160.0
*
f
+
0.50
*
my
lowerCord
.
k1
;
thy
tube
[
86
].
k1
=
0.25
*
160.0
*
f
+
0.75
*
my
lowerCord
.
k1
;
thy
tube
[
79
].
Brel
=
0.7
;
thy
tube
[
80
].
Brel
=
0.6
;
thy
tube
[
81
].
Brel
=
0.5
;
thy
tube
[
82
].
Brel
=
0.4
;
thy
tube
[
83
].
Brel
=
0.3
;
thy
tube
[
84
].
Brel
=
0.2
;
thy
tube
[
85
].
Brel
=
0.2
;
thy
tube
[
86
].
Brel
=
0.2
;
thy
tube
s
[
79
].
Dx
=
thy
tube
s
[
79
].
Dxeq
=
8.0
*
f
;
thy
tube
s
[
80
].
Dx
=
thy
tube
s
[
80
].
Dxeq
=
7.0
*
f
;
thy
tube
s
[
81
].
Dx
=
thy
tube
s
[
81
].
Dxeq
=
6.0
*
f
;
thy
tube
s
[
82
].
Dx
=
thy
tube
s
[
82
].
Dxeq
=
5.0
*
f
;
thy
tube
s
[
83
].
Dx
=
thy
tube
s
[
83
].
Dxeq
=
4.0
*
f
;
thy
tube
s
[
84
].
Dx
=
thy
tube
s
[
84
].
Dxeq
=
0.75
*
4.0
*
f
+
0.25
*
my
lowerCord
.
thickness
;
thy
tube
s
[
85
].
Dx
=
thy
tube
s
[
85
].
Dxeq
=
0.50
*
4.0
*
f
+
0.50
*
my
lowerCord
.
thickness
;
thy
tube
s
[
86
].
Dx
=
thy
tube
s
[
86
].
Dxeq
=
0.25
*
4.0
*
f
+
0.75
*
my
lowerCord
.
thickness
;
thy
tube
s
[
79
].
Dy
=
thy
tube
s
[
79
].
Dyeq
=
11.0
*
f
;
thy
tube
s
[
80
].
Dy
=
thy
tube
s
[
80
].
Dyeq
=
7.0
*
f
;
thy
tube
s
[
81
].
Dy
=
thy
tube
s
[
81
].
Dyeq
=
4.0
*
f
;
thy
tube
s
[
82
].
Dy
=
thy
tube
s
[
82
].
Dyeq
=
2.0
*
f
;
thy
tube
s
[
83
].
Dy
=
thy
tube
s
[
83
].
Dyeq
=
1.0
*
f
;
thy
tube
s
[
84
].
Dy
=
thy
tube
s
[
84
].
Dyeq
=
0.75
*
f
;
thy
tube
s
[
85
].
Dy
=
thy
tube
s
[
85
].
Dyeq
=
0.50
*
f
;
thy
tube
s
[
86
].
Dy
=
thy
tube
s
[
86
].
Dyeq
=
0.25
*
f
;
thy
tube
s
[
79
].
Dz
=
thy
tube
s
[
79
].
Dzeq
=
16.0
*
f
;
thy
tube
s
[
80
].
Dz
=
thy
tube
s
[
80
].
Dzeq
=
16.0
*
f
;
thy
tube
s
[
81
].
Dz
=
thy
tube
s
[
81
].
Dzeq
=
16.0
*
f
;
thy
tube
s
[
82
].
Dz
=
thy
tube
s
[
82
].
Dzeq
=
16.0
*
f
;
thy
tube
s
[
83
].
Dz
=
thy
tube
s
[
83
].
Dzeq
=
16.0
*
f
;
thy
tube
s
[
84
].
Dz
=
thy
tube
s
[
84
].
Dzeq
=
0.75
*
16.0
*
f
+
0.25
*
my
cord
.
length
;
thy
tube
s
[
85
].
Dz
=
thy
tube
s
[
85
].
Dzeq
=
0.50
*
16.0
*
f
+
0.50
*
my
cord
.
length
;
thy
tube
s
[
86
].
Dz
=
thy
tube
s
[
86
].
Dzeq
=
0.25
*
16.0
*
f
+
0.75
*
my
cord
.
length
;
thy
tube
s
[
79
].
k1
=
160.0
;
thy
tube
s
[
80
].
k1
=
160.0
;
thy
tube
s
[
81
].
k1
=
160.0
;
thy
tube
s
[
82
].
k1
=
160.0
;
thy
tube
s
[
83
].
k1
=
160.0
;
thy
tube
s
[
84
].
k1
=
0.75
*
160.0
*
f
+
0.25
*
my
lowerCord
.
k1
;
thy
tube
s
[
85
].
k1
=
0.50
*
160.0
*
f
+
0.50
*
my
lowerCord
.
k1
;
thy
tube
s
[
86
].
k1
=
0.25
*
160.0
*
f
+
0.75
*
my
lowerCord
.
k1
;
thy
tube
s
[
79
].
Brel
=
0.7
;
thy
tube
s
[
80
].
Brel
=
0.6
;
thy
tube
s
[
81
].
Brel
=
0.5
;
thy
tube
s
[
82
].
Brel
=
0.4
;
thy
tube
s
[
83
].
Brel
=
0.3
;
thy
tube
s
[
84
].
Brel
=
0.2
;
thy
tube
s
[
85
].
Brel
=
0.2
;
thy
tube
s
[
86
].
Brel
=
0.2
;
for
(
integer
itube
=
79
;
itube
<=
86
;
itube
++
)
{
Delta_Tube
t
=
thy
tube
+
itube
;
Delta_Tube
t
=
&
thy
tube
s
[
itube
]
;
t
->
mass
=
t
->
Dx
*
t
->
Dz
/
(
30.0
*
f
);
t
->
k3
=
t
->
k1
*
(
20.0
/
t
->
Dz
)
*
(
20.0
/
t
->
Dz
);
t
->
k1left1
=
t
->
k1right1
=
1.0
;
}
thy
tube
[
79
].
k1left1
=
0.0
;
thy
tube
[
36
].
k1left1
=
1.0
;
// the essence: couple spring with lower vocal cords
thy
tube
s
[
79
].
k1left1
=
0.0
;
thy
tube
s
[
36
].
k1left1
=
1.0
;
// the essence: couple spring with lower vocal cords
}
/*
...
...
@@ -199,7 +199,7 @@ autoDelta Speaker_to_Delta (Speaker me) {
*/
if
(
my
shunt
.
Dx
!=
0.0
)
{
for
(
integer
itube
=
87
;
itube
<=
89
;
itube
++
)
{
Delta_Tube
t
=
thy
tube
+
itube
;
Delta_Tube
t
=
&
thy
tube
s
[
itube
]
;
t
->
Dx
=
t
->
Dxeq
=
my
shunt
.
Dx
;
t
->
Dy
=
t
->
Dyeq
=
my
shunt
.
Dy
;
t
->
Dz
=
t
->
Dzeq
=
my
shunt
.
Dz
;
...
...
@@ -220,7 +220,7 @@ autoDelta Speaker_to_Delta (Speaker me) {
/* Pharynx and mouth: tubes 38..64. */
for
(
integer
itube
=
38
;
itube
<=
64
;
itube
++
)
{
Delta_Tube
t
=
thy
tube
+
itube
;
Delta_Tube
t
=
&
thy
tube
s
[
itube
]
;
integer
i
=
itube
-
37
;
dx
=
xmm
[
i
]
-
xmm
[
i
+
1
];
dy
=
ymm
[
i
]
-
ymm
[
i
+
1
];
...
...
@@ -241,7 +241,7 @@ autoDelta Speaker_to_Delta (Speaker me) {
/* Nose: tubes 65..78. */
for
(
integer
itube
=
65
;
itube
<=
78
;
itube
++
)
{
Delta_Tube
t
=
thy
tube
+
itube
;
Delta_Tube
t
=
&
thy
tube
s
[
itube
]
;
t
->
Dx
=
t
->
Dxeq
=
my
nose
.
Dx
;
t
->
Dy
=
t
->
Dyeq
=
my
nose
.
weq
[
itube
-
64
];
t
->
Dz
=
t
->
Dzeq
=
my
nose
.
Dz
;
...
...
@@ -250,14 +250,14 @@ autoDelta Speaker_to_Delta (Speaker me) {
t
->
k3
=
0.0
;
t
->
Brel
=
1.0
;
}
thy
tube
[
65
].
Dy
=
thy
tube
[
65
].
Dyeq
=
0.0
;
// override: nasopharyngeal port closed
thy
tube
s
[
65
].
Dy
=
thy
tube
s
[
65
].
Dyeq
=
0.0
;
// override: nasopharyngeal port closed
/* The default structure:
* every tube is connected on the left to the previous tube (index one lower).
* This corresponds to a two-mass model of the vocal cords without shunt.
*/
for
(
integer
itube
=
SMOOTH_LUNGS
?
FIRST_TUBE
:
1
;
itube
<=
thy
numberOfTubes
;
itube
++
)
{
Delta_Tube
t
=
thy
tube
+
itube
;
Delta_Tube
t
=
&
thy
tube
s
[
itube
]
;
t
->
s1
=
5e6
*
t
->
Dx
*
t
->
Dz
;
t
->
s3
=
t
->
s1
/
(
0.9e-3
*
0.9e-3
);
t
->
dy
=
1e-5
;
...
...
@@ -270,7 +270,7 @@ autoDelta Speaker_to_Delta (Speaker me) {
/* The leftmost boundary: the diaphragm (tube 1).
* Disconnect on the left.
*/
thy
tube
[
SMOOTH_LUNGS
?
FIRST_TUBE
:
1
].
left1
=
nullptr
;
// closed at diaphragm
thy
tube
s
[
SMOOTH_LUNGS
?
FIRST_TUBE
:
1
].
left1
=
nullptr
;
// closed at diaphragm
/* Optional one-mass model of the vocal cords.
* Short-circuit over tube 37 (upper glottis).
...
...
@@ -278,11 +278,11 @@ autoDelta Speaker_to_Delta (Speaker me) {
if
(
my
cord
.
numberOfMasses
==
1
)
{
/* Connect the right side of tube 36 to the left side of tube 38. */
thy
tube
[
36
].
right1
=
thy
tube
+
38
;
thy
tube
[
38
].
left1
=
thy
tube
+
36
;
thy
tube
s
[
36
].
right1
=
&
thy
tube
s
[
38
]
;
thy
tube
s
[
38
].
left1
=
&
thy
tube
s
[
36
]
;
/* Disconnect tube 37 on both sides. */
thy
tube
[
37
].
left1
=
thy
tube
[
37
].
right1
=
nullptr
;
thy
tube
s
[
37
].
left1
=
thy
tube
s
[
37
].
right1
=
nullptr
;
}
/* Optionally couple vocal cords with conus elasticus.
...
...
@@ -291,23 +291,23 @@ autoDelta Speaker_to_Delta (Speaker me) {
if
(
my
cord
.
numberOfMasses
==
10
)
{
/* Connect the right side of tube 31 to the left side of tube 79. */
thy
tube
[
31
].
right1
=
thy
tube
+
79
;
thy
tube
[
79
].
left1
=
thy
tube
+
31
;
thy
tube
s
[
31
].
right1
=
&
thy
tube
s
[
79
]
;
thy
tube
s
[
79
].
left1
=
&
thy
tube
s
[
31
]
;
/* Connect the right side of tube 86 to the left side of tube 36. */
thy
tube
[
86
].
right1
=
thy
tube
+
36
;
thy
tube
[
36
].
left1
=
thy
tube
+
86
;
thy
tube
s
[
86
].
right1
=
&
thy
tube
s
[
36
]
;
thy
tube
s
[
36
].
left1
=
&
thy
tube
s
[
86
]
;
/* Disconnect tubes 32..35 on both sides. */
thy
tube
[
32
].
left1
=
thy
tube
[
32
].
right1
=
nullptr
;
thy
tube
[
33
].
left1
=
thy
tube
[
33
].
right1
=
nullptr
;
thy
tube
[
34
].
left1
=
thy
tube
[
34
].
right1
=
nullptr
;
thy
tube
[
35
].
left1
=
thy
tube
[
35
].
right1
=
nullptr
;
thy
tube
s
[
32
].
left1
=
thy
tube
s
[
32
].
right1
=
nullptr
;
thy
tube
s
[
33
].
left1
=
thy
tube
s
[
33
].
right1
=
nullptr
;
thy
tube
s
[
34
].
left1
=
thy
tube
s
[
34
].
right1
=
nullptr
;
thy
tube
s
[
35
].
left1
=
thy
tube
s
[
35
].
right1
=
nullptr
;
}
else
{
/* Disconnect tubes 79..86 on both sides. */
for
(
integer
itube
=
79
;
itube
<=
86
;
itube
++
)
thy
tube
[
itube
].
left1
=
thy
tube
[
itube
].
right1
=
nullptr
;
thy
tube
s
[
itube
].
left1
=
thy
tube
s
[
itube
].
right1
=
nullptr
;
}
/* Optionally add a shunt parallel to the glottis.
...
...
@@ -319,41 +319,41 @@ autoDelta Speaker_to_Delta (Speaker me) {
/* Create a three-way interface below the shunt.
* Connect lowest shunt tube (87) with top of trachea (34/35 or 85/86).
*/
thy
tube
[
topOfTrachea
-
1
].
right2
=
thy
tube
+
87
;
// trachea to shunt
thy
tube
[
87
].
left1
=
thy
tube
+
topOfTrachea
-
1
;
// shunt to trachea
thy
tube
[
87
].
Dxeq
=
thy
tube
[
topOfTrachea
-
1
].
Dxeq
=
thy
tube
[
topOfTrachea
].
Dxeq
;
// equal length
thy
tube
[
87
].
Dx
=
thy
tube
[
topOfTrachea
-
1
].
Dx
=
thy
tube
[
topOfTrachea
].
Dx
;
thy
tube
s
[
topOfTrachea
-
1
].
right2
=
&
thy
tube
s
[
87
]
;
// trachea to shunt
thy
tube
s
[
87
].
left1
=
&
thy
tube
s
[
topOfTrachea
-
1
]
;
// shunt to trachea
thy
tube
s
[
87
].
Dxeq
=
thy
tube
s
[
topOfTrachea
-
1
].
Dxeq
=
thy
tube
s
[
topOfTrachea
].
Dxeq
;
// equal length
thy
tube
s
[
87
].
Dx
=
thy
tube
s
[
topOfTrachea
-
1
].
Dx
=
thy
tube
s
[
topOfTrachea
].
Dx
;
/* Create a three-way interface above the shunt.
* Connect highest shunt tube (89) with bottom of pharynx (38/39).
*/
thy
tube
[
89
].
right1
=
thy
tube
+
39
;
// shunt to pharynx
thy
tube
[
39
].
left2
=
thy
tube
+
89
;
// pharynx to shunt
thy
tube
[
89
].
Dxeq
=
thy
tube
[
39
].
Dxeq
=
thy
tube
[
38
].
Dxeq
;
// all three of equal length
thy
tube
[
89
].
Dx
=
thy
tube
[
39
].
Dx
=
thy
tube
[
38
].
Dx
;
thy
tube
s
[
89
].
right1
=
&
thy
tube
s
[
39
]
;
// shunt to pharynx
thy
tube
s
[
39
].
left2
=
&
thy
tube
s
[
89
]
;
// pharynx to shunt
thy
tube
s
[
89
].
Dxeq
=
thy
tube
s
[
39
].
Dxeq
=
thy
tube
s
[
38
].
Dxeq
;
// all three of equal length
thy
tube
s
[
89
].
Dx
=
thy
tube
s
[
39
].
Dx
=
thy
tube
s
[
38
].
Dx
;
}
else
{
/* Disconnect tubes 87..89 on both sides. */
for
(
integer
itube
=
87
;
itube
<=
89
;
itube
++
)
thy
tube
[
itube
].
left1
=
thy
tube
[
itube
].
right1
=
nullptr
;
thy
tube
s
[
itube
].
left1
=
thy
tube
s
[
itube
].
right1
=
nullptr
;
}
/* Create a three-way interface at the nasopharyngeal port.
* Connect tubes 50 (pharynx), 51 (mouth), and 65 (nose).
*/
thy
tube
[
50
].
right2
=
thy
tube
+
65
;
// pharynx to nose
thy
tube
[
65
].
left1
=
thy
tube
+
50
;
// nose to pharynx
thy
tube
[
65
].
Dxeq
=
thy
tube
[
51
].
Dxeq
=
thy
tube
[
50
].
Dxeq
;
// all three must be of equal length
thy
tube
[
65
].
Dx
=
thy
tube
[
51
].
Dx
=
thy
tube
[
50
].
Dx
;
thy
tube
s
[
50
].
right2
=
&
thy
tube
s
[
65
]
;
// pharynx to nose
thy
tube
s
[
65
].
left1
=
&
thy
tube
s
[
50
]
;
// nose to pharynx
thy
tube
s
[
65
].
Dxeq
=
thy
tube
s
[
51
].
Dxeq
=
thy
tube
s
[
50
].
Dxeq
;
// all three must be of equal length
thy
tube
s
[
65
].
Dx
=
thy
tube
s
[
51
].
Dx
=
thy
tube
s
[
50
].
Dx
;
/* The rightmost boundaries: the lips (tube 64) and the nostrils (tube 78).
* Disconnect on the right.
*/
thy
tube
[
64
].
right1
=
nullptr
;
// radiation at the lips
thy
tube
[
78
].
right1
=
nullptr
;
// radiation at the nostrils
thy
tube
s
[
64
].
right1
=
nullptr
;
// radiation at the lips
thy
tube
s
[
78
].
right1
=
nullptr
;
// radiation at the nostrils
for
(
integer
itube
=
1
;
itube
<=
thy
numberOfTubes
;
itube
++
)
{
Delta_Tube
t
=
thy
tube
+
itube
;
Delta_Tube
t
=
&
thy
tube
s
[
itube
]
;
Melder_assert
(
!
t
->
left1
||
t
->
left1
->
right1
==
t
||
t
->
left1
->
right2
==
t
);
Melder_assert
(
!
t
->
left2
||
t
->
left2
->
right1
==
t
);
Melder_assert
(
!
t
->
right1
||
t
->
right1
->
left1
==
t
||
t
->
right1
->
left2
==
t
);
...
...
Prev
1
2
3
4
5
…
9
Next