Skip to content
Commits on Source (4)
......@@ -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 ioutput = 1; ioutput <= my numberOfOutputs; ioutput ++)
sum += my activity [k + ioutput];
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 ioutput = 2; ioutput <= my numberOfOutputs; ioutput ++)
if (my activity [k + ioutput] > max) {
max = my activity [k + ioutput];
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 ilayer = 1; ilayer < layer; ilayer ++)
k += my numberOfUnitsInLayer [ilayer] + 1;
for (integer i = 1; i <= my numberOfUnitsInLayer [layer]; i ++)
activity [i] = my activity [k + i];
for (integer iunit = 1; iunit <= my numberOfUnitsInLayer [layer]; iunit ++)
activity [iunit] = my activity [k + iunit];
}
void FFNet_selectAllWeights (FFNet me) {
for (integer i = 1; i <= my numberOfWeights; i ++)
my wSelected [i] = 1;
for (integer iweight = 1; iweight <= my numberOfWeights; iweight ++)
my wSelected [iweight] = 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 numberOfSelectedWeights = 0;
for (integer iweight = 1; iweight <= my numberOfWeights; iweight ++)
if (my wSelected [iweight])
numberOfSelectedWeights ++;
return numberOfSelectedWeights;
}
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 iweight = 1; iweight <= my numberOfWeights; iweight ++)
my wSelected [iweight] = 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 ilayer = 1; ilayer < layer; ilayer ++)
node += my numberOfUnitsInLayer [ilayer] + 1;
for (integer inode = node + 1; inode <= node + my numberOfUnitsInLayer [layer]; inode ++)
my wSelected [my wLast [inode]] = 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 ilayer = 1; ilayer < layer; ilayer ++)
node += my numberOfUnitsInLayer [ilayer] + 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, integer 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 iunit = 1; iunit <= numberOfUnitsFrom - 1; iunit ++) {
Melder_sprint (label,40, U"L", layer - 1, U"-", iunit);
TableOfReal_setRowLabel (thee.get(), iunit, 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 iunit = 1; iunit <= numberOfUnitsTo; iunit ++) {
Melder_sprint (label,40, U"L", layer, U"-", iunit);
TableOfReal_setColumnLabel (thee.get(), iunit, label);
}
integer node = my numberOfInputs + 1 + 1;
for (integer i = 1; i < layer; i ++)
node += my numberOfUnitsInLayer [i] + 1;
for (integer ilayer = 1; ilayer < layer; ilayer ++)
node += my numberOfUnitsInLayer [ilayer] + 1;
for (integer i = 1; i <= numberOfUnitsTo; i ++, node ++) {
for (integer iunit = 1; iunit <= numberOfUnitsTo; iunit ++, node ++) {
integer k = 1;
for (integer j = my wFirst [node]; j <= my wLast [node]; j ++)
thy data [k ++] [i] = my w [j];
for (integer jnode = my wFirst [node]; jnode <= my wLast [node]; jnode ++)
thy data [k ++] [iunit] = my w [jnode];
}
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());
......
......@@ -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, integer 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, integer 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, integer toLayer, integer 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_ActivationList_Categories.cpp
*
* Copyright (C) 1997-2011, 2015-2018 David Weenink
* Copyright (C) 1997-2019 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_Eigen.cpp
*
* Copyright (C) 1994-2018 David Weenink
* Copyright (C) 1994-2019 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_Matrix.cpp
*
* Copyright (C) 1997-2018 David Weenink
* Copyright (C) 1997-2019 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_PatternList.cpp
*
* Copyright (C) 1997-2018 David Weenink
* Copyright (C) 1997-2019 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
......
......@@ -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].\nYou 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_PatternList_Categories.cpp
*
* Copyright (C) 1994-2018 David Weenink
* Copyright (C) 1994-2019 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());
}
......
/* praat_FFNet_init.cpp
*
* Copyright (C) 1994-2011, 2016-2017 David Weenink
* Copyright (C) 1994-2019 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 -";
......
......@@ -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) ||
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
This diff is collapsed.
/* Art_Speaker_Delta.cpp
*
* Copyright (C) 1992-2005,2009,2011,2016-2018 Paul Boersma
* Copyright (C) 1992-2005,2009,2011,2016-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
......@@ -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 -> tubes [itube]. Dyeq = 120 * f * (1 + art -> art [(int) kArt_muscle::LUNGS]);
/* Glottis. */
{
Delta_Tube t = delta -> tube + 36;
Delta_Tube t = & delta -> tubes [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 -> tubes [37];
t -> Dyeq = delta -> tubes [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 -> tubes [84]. Dyeq = 0.75 * 1 * f + 0.25 * delta -> tubes [36]. Dyeq;
delta -> tubes [85]. Dyeq = 0.50 * 1 * f + 0.50 * delta -> tubes [36]. Dyeq;
delta -> tubes [86]. Dyeq = 0.25 * 1 * f + 0.75 * delta -> tubes [36]. Dyeq;
delta -> tubes [84]. k1 = 0.75 * 160 + 0.25 * delta -> tubes [36]. k1;
delta -> tubes [85]. k1 = 0.50 * 160 + 0.50 * delta -> tubes [36]. k1;
delta -> tubes [86]. k1 = 0.25 * 160 + 0.75 * delta -> tubes [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 -> tubes [itube]. k3 = delta -> tubes [itube]. k1 *
(20 / delta -> tubes [itube]. Dz) * (20 / delta -> tubes [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 -> tubes [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 -> tubes [65]. Dxeq = delta -> tubes [51]. Dxeq = delta -> tubes [50]. Dxeq;
/* Voor [r]: thy tubes [60]. Brel = 0.1; thy tubes [60]. k1 = 3; */
/* Nasopharyngeal port. */
delta -> tube [65]. Dyeq = f * (18 - 25 * art -> art [(int) kArt_muscle::LEVATOR_PALATINI]); // 4.40
delta -> tubes [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 -> tubes [itube];
t -> s1 = 5e6 * t -> Dxeq * t -> Dzeq;
t -> s3 = t -> s1 / (0.9e-3 * 0.9e-3);
}
......
/* 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 -> tubes [37 + isection];
integer numberOfConstantSections = Melder_iround (tube -> Dxeq / sectionLength);
double constantArea = tube -> Dyeq * tube -> Dzeq;
for (integer jsection = 1; jsection <= numberOfConstantSections; jsection ++)
......
/* 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;
integer 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->tubes [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 -> tubes [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->tubes [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->tubes [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->tubes [iw1]. Dy;
if (iw2) w2 -> z [1] [sample] = delta->tubes [iw2]. Dy;
if (iw3) w3 -> z [1] [sample] = delta->tubes [iw3]. Dy;
if (ip1) p1 -> z [1] [sample] = delta->tubes [ip1]. DeltaP;
if (ip2) p2 -> z [1] [sample] = delta->tubes [ip2]. DeltaP;
if (ip3) p3 -> z [1] [sample] = delta->tubes [ip3]. DeltaP;
if (iv1) v1 -> z [1] [sample] = delta->tubes [iv1]. v;
if (iv2) v2 -> z [1] [sample] = delta->tubes [iv2]. v;
if (iv3) v3 -> z [1] [sample] = delta->tubes [iv3]. v;
}
for (int m = 1; m <= M; m ++) {
Delta_Tube t = delta->tube + m;
Delta_Tube t = & delta->tubes [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->tubes [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();
......
/* 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 = NUMvector <struct structDelta_Tube> (1, numberOfTubes);
my tubes = newvectorzero <structDelta_Tube> (numberOfTubes);
for (int itube = 1; itube <= numberOfTubes; itube ++) {
Delta_Tube t = & my tube [itube];
Delta_Tube t = & my tubes [itube];
t -> parallel = 1;
}
}
......
......@@ -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);
......
/* Speaker_to_Delta.cpp
*
* Copyright (C) 1992-2005,2006,2011,2015-2018 Paul Boersma
* Copyright (C) 1992-2005,2006,2011,2015-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
......@@ -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 tubes [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 tubes [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 tubes [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 tubes [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 tubes [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 tubes [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 tubes [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 tubes [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 tubes [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 tubes [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 tubes [79]. Dx = thy tubes [79]. Dxeq = 8.0 * f;
thy tubes [80]. Dx = thy tubes [80]. Dxeq = 7.0 * f;
thy tubes [81]. Dx = thy tubes [81]. Dxeq = 6.0 * f;
thy tubes [82]. Dx = thy tubes [82]. Dxeq = 5.0 * f;
thy tubes [83]. Dx = thy tubes [83]. Dxeq = 4.0 * f;
thy tubes [84]. Dx = thy tubes [84]. Dxeq = 0.75 * 4.0 * f + 0.25 * my lowerCord.thickness;
thy tubes [85]. Dx = thy tubes [85]. Dxeq = 0.50 * 4.0 * f + 0.50 * my lowerCord.thickness;
thy tubes [86]. Dx = thy tubes [86]. Dxeq = 0.25 * 4.0 * f + 0.75 * my lowerCord.thickness;
thy tubes [79]. Dy = thy tubes [79]. Dyeq = 11.0 * f;
thy tubes [80]. Dy = thy tubes [80]. Dyeq = 7.0 * f;
thy tubes [81]. Dy = thy tubes [81]. Dyeq = 4.0 * f;
thy tubes [82]. Dy = thy tubes [82]. Dyeq = 2.0 * f;
thy tubes [83]. Dy = thy tubes [83]. Dyeq = 1.0 * f;
thy tubes [84]. Dy = thy tubes [84]. Dyeq = 0.75 * f;
thy tubes [85]. Dy = thy tubes [85]. Dyeq = 0.50 * f;
thy tubes [86]. Dy = thy tubes [86]. Dyeq = 0.25 * f;
thy tubes [79]. Dz = thy tubes [79]. Dzeq = 16.0 * f;
thy tubes [80]. Dz = thy tubes [80]. Dzeq = 16.0 * f;
thy tubes [81]. Dz = thy tubes [81]. Dzeq = 16.0 * f;
thy tubes [82]. Dz = thy tubes [82]. Dzeq = 16.0 * f;
thy tubes [83]. Dz = thy tubes [83]. Dzeq = 16.0 * f;
thy tubes [84]. Dz = thy tubes [84]. Dzeq = 0.75 * 16.0 * f + 0.25 * my cord.length;
thy tubes [85]. Dz = thy tubes [85]. Dzeq = 0.50 * 16.0 * f + 0.50 * my cord.length;
thy tubes [86]. Dz = thy tubes [86]. Dzeq = 0.25 * 16.0 * f + 0.75 * my cord.length;
thy tubes [79]. k1 = 160.0;
thy tubes [80]. k1 = 160.0;
thy tubes [81]. k1 = 160.0;
thy tubes [82]. k1 = 160.0;
thy tubes [83]. k1 = 160.0;
thy tubes [84]. k1 = 0.75 * 160.0 * f + 0.25 * my lowerCord.k1;
thy tubes [85]. k1 = 0.50 * 160.0 * f + 0.50 * my lowerCord.k1;
thy tubes [86]. k1 = 0.25 * 160.0 * f + 0.75 * my lowerCord.k1;
thy tubes [79]. Brel = 0.7;
thy tubes [80]. Brel = 0.6;
thy tubes [81]. Brel = 0.5;
thy tubes [82]. Brel = 0.4;
thy tubes [83]. Brel = 0.3;
thy tubes [84]. Brel = 0.2;
thy tubes [85]. Brel = 0.2;
thy tubes [86]. Brel = 0.2;
for (integer itube = 79; itube <= 86; itube ++) {
Delta_Tube t = thy tube + itube;
Delta_Tube t = & thy tubes [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 tubes [79]. k1left1 = 0.0;
thy tubes [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 tubes [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 tubes [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 tubes [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 tubes [65]. Dy = thy tubes [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 tubes [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 tubes [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 tubes [36]. right1 = & thy tubes [38];
thy tubes [38]. left1 = & thy tubes [36];
/* Disconnect tube 37 on both sides. */
thy tube [37]. left1 = thy tube [37]. right1 = nullptr;
thy tubes [37]. left1 = thy tubes [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 tubes [31]. right1 = & thy tubes [79];
thy tubes [79]. left1 = & thy tubes [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 tubes [86]. right1 = & thy tubes [36];
thy tubes [36]. left1 = & thy tubes [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 tubes [32]. left1 = thy tubes [32]. right1 = nullptr;
thy tubes [33]. left1 = thy tubes [33]. right1 = nullptr;
thy tubes [34]. left1 = thy tubes [34]. right1 = nullptr;
thy tubes [35]. left1 = thy tubes [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 tubes [itube]. left1 = thy tubes [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 tubes [topOfTrachea - 1]. right2 = & thy tubes [87]; // trachea to shunt
thy tubes [87]. left1 = & thy tubes [topOfTrachea - 1]; // shunt to trachea
thy tubes [87]. Dxeq = thy tubes [topOfTrachea - 1]. Dxeq = thy tubes [topOfTrachea]. Dxeq; // equal length
thy tubes [87]. Dx = thy tubes [topOfTrachea - 1]. Dx = thy tubes [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 tubes [89]. right1 = & thy tubes [39]; // shunt to pharynx
thy tubes [39]. left2 = & thy tubes [89]; // pharynx to shunt
thy tubes [89]. Dxeq = thy tubes [39]. Dxeq = thy tubes [38]. Dxeq; // all three of equal length
thy tubes [89]. Dx = thy tubes [39]. Dx = thy tubes [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 tubes [itube]. left1 = thy tubes [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 tubes [50]. right2 = & thy tubes [65]; // pharynx to nose
thy tubes [65]. left1 = & thy tubes [50]; // nose to pharynx
thy tubes [65]. Dxeq = thy tubes [51]. Dxeq = thy tubes [50]. Dxeq; // all three must be of equal length
thy tubes [65]. Dx = thy tubes [51]. Dx = thy tubes [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 tubes [64]. right1 = nullptr; // radiation at the lips
thy tubes [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 tubes [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);
......