Skip to content

Commit a2f37f3

Browse files
authored
Merge pull request #2967 from PaulBoersma/master
quick fix to solve crash in Sound-to-Formant-robust
2 parents 57239f2 + 9b44c96 commit a2f37f3

10 files changed

Lines changed: 58 additions & 23 deletions

LPC/LPCFrameIntoFormantFrame.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ void LPCFrameIntoFormantFrame_init(LPCFrameIntoFormantFrame me, constLPC input,
110110
autoLPCFrameIntoFormantFrame LPCFrameIntoFormantFrame_create (constLPC input, mutableFormant output, double margin) {
111111
try {
112112
autoLPCFrameIntoFormantFrame me = Thing_new (LPCFrameIntoFormantFrame);
113-
LPCFrameIntoFormantFrame_init(me.get(), input, output, margin);
113+
LPCFrameIntoFormantFrame_init (me.get(), input, output, margin);
114114
return me;
115115
} catch (MelderError) {
116116
Melder_throw (U"LPCFrameIntoFormantFrame not created.");

LPC/SoundFrameIntoFormantFrame.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ void structSoundFrameIntoFormantFrame :: saveOutputFrame () {
6464
autoSoundFrameIntoFormantFrame SoundFrameIntoFormantFrame_create (autoSoundFrameIntoLPCFrame silpc, autoLPCFrameIntoFormantFrame lpcif) {
6565
try {
6666
autoSoundFrameIntoFormantFrame me = Thing_new (SoundFrameIntoFormantFrame);
67-
my soundIntoLPC.adoptFromAmbiguousOwner (silpc.releaseToAmbiguousOwner());
68-
my lpcIntoFormant.adoptFromAmbiguousOwner (lpcif.releaseToAmbiguousOwner());
67+
my soundIntoLPC = silpc.move();
68+
my lpcIntoFormant = lpcif.move();
6969
return me;
7070
} catch (MelderError) {
7171
Melder_throw (U"Cannot create SoundFrameIntoFormantFrame.");

LPC/SoundFrameIntoLPCFrame.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
Thing_implement (SoundFrameIntoLPCFrame, SoundFrameIntoSampledFrame, 0);
4242

4343
void structSoundFrameIntoLPCFrame :: allocateOutputFrames () {
44+
Melder_assert (our outputlpc);
4445
for (integer iframe = 1; iframe <= outputlpc -> nx; iframe ++)
4546
LPC_Frame_init (& outputlpc -> d_frames [iframe], outputlpc -> maxnCoefficients);
4647
}
@@ -88,7 +89,7 @@ bool structSoundFrameIntoLPCFrameAuto :: inputFrameToOutputFrame () {
8889
frameAnalysisInfo = 0;
8990
Melder_assert (lpcf -> nCoefficients > 0);
9091

91-
VEC x = soundFrame;
92+
VEC x = soundFrame;
9293

9394
/*
9495
Compute the autocorrelations

LPC/Sound_and_LPC.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ void checkLPCAnalysisParameters_e (double sound_dx, integer sound_nx, double phy
3434
"Either your sound is too short or your window is too long.");
3535
// we round the minimum duration to be able to use asserterror in testing scripts.
3636
conststring32 minimumDurationRounded = Melder_fixed (predictionOrder * sound_dx , 5);
37-
const integer approximateNumberOfSamplesPerWindow = Melder_roundDown (physicalAnalysisWidth / sound_dx);
37+
const integer approximateNumberOfSamplesPerWindow = Melder_iroundDown (physicalAnalysisWidth / sound_dx);
3838
Melder_require (approximateNumberOfSamplesPerWindow > predictionOrder,
3939
U"Analysis window duration too short. For a prediction order of ", predictionOrder,
4040
U", the analysis window duration should be greater than ", minimumDurationRounded,
@@ -197,7 +197,8 @@ void Sound_into_LPCrobust_common (constSound me, mutableLPC outputlpc, autoSound
197197
}
198198

199199
autoLPC Sound_to_LPC_robust (constSound me, int predictionOrder, double effectiveAnalysisWidth, double dt, double preEmphasisFrequency,
200-
double k_stdev, integer itermax, double tol, bool wantlocation) {
200+
double k_stdev, integer itermax, double tol, bool wantlocation)
201+
{
201202
try {
202203
const double physicalAnalysisWidth = getPhysicalAnalysisWidth (effectiveAnalysisWidth, kSound_windowShape::GAUSSIAN_2);
203204
autoSound emphasized = Sound_resampleAndOrPreemphasize (me, 0.0, 0, preEmphasisFrequency);

LPC/Sound_to_Formant_mt.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "Sound_to_Formant_mt.h"
2121
#include "SoundFrameIntoFormantFrame.h"
2222
#include "Sound_extensions.h"
23+
#include "LPC_and_Formant.h"
2324
/*
2425
Precondition:
2526
Sound already has the 'right' sampling frequency and has been pre-emphasized
@@ -95,6 +96,7 @@ autoFormant Sound_to_Formant_robust_mt (constSound me, double dt_in, double numb
9596
autoLPCAndSoundFramesIntoLPCFrameRobust lpcAndSoundIntoLPC = LPCAndSoundFramesIntoLPCFrameRobust_create (lpc.get(), me, outputLPC.get(),
9697
effectiveAnalysisWidth, windowShape, k_stdev, itermax, tol, location, wantlocation);
9798
autoSoundFrameIntoLPCFrame soundIntoLPC2 = SoundFrameIntoLPCFrameRobust_create (soundIntoLPC1.move(), lpcAndSoundIntoLPC.move());
99+
Melder_assert (soundIntoLPC2 -> outputlpc);
98100
autoLPCFrameIntoFormantFrame lpcFrameIntoFormant = LPCFrameIntoFormantFrame_create (outputLPC.get(), formant.get(), safetyMargin);
99101
autoSoundFrameIntoFormantFrame sif = SoundFrameIntoFormantFrame_create (soundIntoLPC2.move(), lpcFrameIntoFormant.move());
100102
autoSoundIntoFormantRobustStatus status = SoundIntoFormantRobustStatus_create (formant -> nx);
@@ -105,6 +107,33 @@ autoFormant Sound_to_Formant_robust_mt (constSound me, double dt_in, double numb
105107
Melder_throw (me, U": no robust Formant created.");
106108
}
107109
}
110+
111+
autoFormant Sound_to_Formant_robust (Sound me, double dt_in, double numberOfFormants, double maximumFrequency,
112+
double effectiveAnalysisWidth, double preEmphasisFrequency, double safetyMargin,
113+
double numberOfStandardDeviations, integer maximumNumberOfIterations, double tolerance,
114+
double location, bool wantlocation)
115+
{
116+
const double dt = dt_in > 0.0 ? dt_in : effectiveAnalysisWidth / 4.0;
117+
const double nyquist = 0.5 / my dx;
118+
const integer predictionOrder = Melder_ifloor (2 * numberOfFormants);
119+
try {
120+
autoSound sound;
121+
if (maximumFrequency <= 0.0 || fabs (maximumFrequency / nyquist - 1.0) < 1.0e-12)
122+
sound = Data_copy (me); // will be modified
123+
else
124+
sound = Sound_resample (me, maximumFrequency * 2.0, 50);
125+
126+
autoLPC lpc = Sound_to_LPC_auto (sound.get(), predictionOrder, effectiveAnalysisWidth, dt, preEmphasisFrequency);
127+
autoLPC lpcRobust = LPC_and_Sound_to_LPC_robust (lpc.get(), sound.get(), effectiveAnalysisWidth, preEmphasisFrequency,
128+
numberOfStandardDeviations, maximumNumberOfIterations, tolerance, wantlocation);
129+
autoFormant thee = LPC_to_Formant (lpcRobust.get(), safetyMargin);
130+
return thee;
131+
} catch (MelderError) {
132+
Melder_throw (me, U": no robust Formant created.");
133+
}
134+
}
135+
136+
108137
/*
109138
void Sound_into_Formant_robust_mt (constSound me, mutableFormant thee, double effectiveAnalysisWidth, integer numberOfPoles, double safetyMargin,
110139
double k_stdev, integer itermax, double tol, double location, bool wantlocation)

LPC/Sound_to_Formant_mt.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@
1818
* along with this work. If not, see <http://www.gnu.org/licenses/>.
1919
*/
2020

21-
/*
22-
djmw 20030815 GPL header
23-
*/
24-
2521
#include "LPC.h"
2622
#include "Formant.h"
2723
#include "Sound_and_LPC.h"
@@ -30,8 +26,15 @@ void Sound_into_Formant_robust_mt (constSound me, Formant out, double windowLeng
3026
integer numberOfPoles, double safetyMargin, double k, integer itermax, double tol, double location, bool wantlocation
3127
);
3228

29+
autoFormant Sound_to_Formant_robust (Sound me, double dt_in, double numberOfFormants, double maximumFrequency,
30+
double effectiveAnalysisWidth, double preEmphasisFrequency, double safetyMargin,
31+
double numberOfStandardDeviations, integer maximumNumberOfIterations, double tolerance,
32+
double location, bool wantlocation
33+
);
34+
3335
autoFormant Sound_to_Formant_robust_mt (constSound me, double dt, double numberOfFormants, double maximumFrequency,
34-
double windowLength, double preemphasisFrequency, double safetyMargin, double k, integer itermax, double tol,
36+
double windowLength, double preemphasisFrequency, double safetyMargin,
37+
double numberOfStandardDeviations, integer maximumNumberOfIterations, double tolerance,
3538
double location, bool wantlocation
3639
);
3740

LPC/praat_LPC_init.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1254,7 +1254,7 @@ FORM (CONVERT_EACH_TO_ONE__Sound_to_Formant_robust, U"Sound: To Formant (robust)
12541254
OK
12551255
DO
12561256
CONVERT_EACH_TO_ONE (Sound)
1257-
autoFormant result = Sound_to_Formant_robust_mt (me, timeStep, maximumNumberOfFormants, formantCeiling, windowLength,
1257+
autoFormant result = Sound_to_Formant_robust (me, timeStep, maximumNumberOfFormants, formantCeiling, windowLength,
12581258
preEmphasisFrequency, 50.0, numberOfStandardDeviations, maximumNumberOfIterations, tolerance, 0.0, true);
12591259
CONVERT_EACH_TO_ONE_END (my name.get())
12601260
}

fon/Sound.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,7 +1228,7 @@ autoSound Sound_filter_oneFormant (constSound me, double frequency, double bandw
12281228

12291229
void Sound_filterWithOneFormantInplace (mutableSound me, double frequency, double bandwidth) {
12301230
for (integer ichan = 1; ichan <= my ny; ichan ++) {
1231-
VEC channel = my z.row (ichan);
1231+
const VEC channel = my z.row (ichan);
12321232
VECfilterSecondOrderSection_fb_inplace (channel, my dx, frequency, bandwidth);
12331233
}
12341234
Matrix_scaleAbsoluteExtremum (me, 0.99);
@@ -1242,7 +1242,7 @@ void Sound_preEmphasize_inplace (mutableSound me, double cutoffFrequency) {
12421242
const double emphasisFactor = Sound_computeEmphasisFactor (me, cutoffFrequency);
12431243
if (emphasisFactor != 0.0) // OPTIMIZE; will happen for cut-off frequencies above 119 times the sampling frequency
12441244
for (integer channel = 1; channel <= my ny; channel ++) {
1245-
VEC s = my z.row (channel);
1245+
const VEC s = my z.row (channel);
12461246
for (integer i = my nx; i >= 2; i --)
12471247
s [i] -= emphasisFactor * s [i - 1];
12481248
}
@@ -1252,7 +1252,7 @@ void Sound_deEmphasize_inplace (Sound me, double cutoffFrequency) {
12521252
const double emphasisFactor = Sound_computeEmphasisFactor (me, cutoffFrequency);
12531253
if (emphasisFactor != 0.0) // OPTIMIZE; will happen for cut-off frequencies above 119 times the sampling frequency
12541254
for (integer channel = 1; channel <= my ny; channel ++) {
1255-
VEC s = my z.row (channel);
1255+
const VEC s = my z.row (channel);
12561256
for (integer i = 2; i <= my nx; i ++)
12571257
s [i] += emphasisFactor * s [i - 1];
12581258
}
@@ -1285,7 +1285,7 @@ void Sound_reverse (mutableSound me, double tmin, double tmax) {
12851285
integer itmin, itmax;
12861286
const integer n = Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax) / 2;
12871287
for (integer channel = 1; channel <= my ny; channel ++) {
1288-
double *amp = & my z [channel] [0];
1288+
double * const amp = & my z [channel] [0];
12891289
for (integer i = 0; i < n; i ++)
12901290
std::swap (amp [itmin + i], amp [itmax - i]);
12911291
}
@@ -1331,7 +1331,7 @@ autoSound Sounds_crossCorrelate_short (constSound me, constSound thee, double tm
13311331
}
13321332
}
13331333
if (mypower != 0.0 && thypower != 0.0) {
1334-
double factor = 1.0 / (sqrt (double (mypower)) * sqrt (double (thypower)));
1334+
const double factor = 1.0 / (sqrt (double (mypower)) * sqrt (double (thypower)));
13351335
for (integer i = 1; i <= nt; i ++) {
13361336
his z [1] [i] *= factor;
13371337
}

fon/Sound_to_Formant.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* Sound_to_Formant.cpp
22
*
3-
* Copyright (C) 1992-2008,2010-2012,2014-2021 Paul Boersma
3+
* Copyright (C) 1992-2008,2010-2012,2014-2021,2024,2025 Paul Boersma
44
*
55
* This code is free software; you can redistribute it and/or modify
66
* it under the terms of the GNU General Public License as published by
@@ -397,7 +397,7 @@ autoFormant Sound_to_Formant_willems (Sound me, double dt, double nFormants, dou
397397
try {
398398
return Sound_to_Formant_any (me, dt, Melder_iround (2.0 * nFormants), maximumFrequency, halfdt_window, 2, preemphasisFrequency, 50.0);
399399
} catch (MelderError) {
400-
Melder_throw (me, U": formant analysis (Burg) not performed.");
400+
Melder_throw (me, U": formant analysis (Willems) not performed.");
401401
}
402402
}
403403

sys/Thing.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* This code is free software; you can redistribute it and/or modify
88
* it under the terms of the GNU General Public License as published by
9-
* the Free Software Foundation; either version 2 of the License, or (at
9+
* the Free Software Foundation; either version 3 of the License, or (at
1010
* your option) any later version.
1111
*
1212
* This code is distributed in the hope that it will be useful, but
@@ -86,8 +86,8 @@ struct structThing {
8686
void operator delete (void *ptr, size_t /* size */) { Melder_free (ptr); }
8787

8888
/*
89-
If a Thing has members of type autoThing,
90-
then we want the destructors of autoThing to be called automatically whenever a Thing is `delete`d.
89+
If a Thing has members of type autoThing and/or autovector and/or automatrix and/or autostring,
90+
then we want the destructors of those objects to be called automatically whenever a Thing is `delete`d.
9191
For this to happen, it is necessary that every Thing itself has a destructor.
9292
We therefore define a destructor here,
9393
and we make it virtual to ensure that every subclass has its own automatic version.
@@ -97,7 +97,8 @@ struct structThing {
9797
virtual void v9_destroy () noexcept { }
9898
/*
9999
This method should destroy all members that are not destroyed automatically
100-
(any autoThing is destroyed automatically), and to remove dangling links to self.
100+
(any autoThing or autovector or automatrix or autostring is destroyed automatically),
101+
and to remove dangling links to self.
101102
Destroying *all* members means that we have to destroy all members that the
102103
derived class has added, as well as all members of the base class,
103104
and so on recursively; v9_destroy therefore has to call the inherited v9_destroy.

0 commit comments

Comments
 (0)