1 /* ParamCurve.cpp
2  *
3  * Copyright (C) 1992-2012,2014,2015,2016,2017 Paul Boersma
4  *
5  * This code is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or (at
8  * your option) any later version.
9  *
10  * This code is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this work. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "ParamCurve.h"
20 
21 #include "oo_DESTROY.h"
22 #include "ParamCurve_def.h"
23 #include "oo_COPY.h"
24 #include "ParamCurve_def.h"
25 #include "oo_EQUAL.h"
26 #include "ParamCurve_def.h"
27 #include "oo_DESCRIPTION.h"
28 #include "ParamCurve_def.h"
29 #include "oo_CAN_WRITE_AS_ENCODING.h"
30 #include "ParamCurve_def.h"
31 
32 Thing_implement (ParamCurve, Function, 2);
33 
v_info()34 void structParamCurve :: v_info () {
35 	const MelderRealRange xextrema = NUMextrema (our x -> z.row (1));
36 	const MelderRealRange yextrema = NUMextrema (our y -> z.row (1));
37 	structDaata :: v_info ();
38 	MelderInfo_writeLine (U"Domain:");
39 	MelderInfo_writeLine (U"   tmin: ", our xmin);
40 	MelderInfo_writeLine (U"   tmax: ", our xmax);
41 	MelderInfo_writeLine (U"x sampling:");
42 	MelderInfo_writeLine (U"   Number of values of t in x: ", our x -> nx);
43 	MelderInfo_writeLine (U"   t step in x: ", our x -> dx, U" (sampling rate ", 1.0 / our x -> dx, U")");
44 	MelderInfo_writeLine (U"   First t in x: ", our x -> x1);
45 	MelderInfo_writeLine (U"x values:");
46 	MelderInfo_writeLine (U"   Minimum x: ", xextrema.min);
47 	MelderInfo_writeLine (U"   Maximum x: ", xextrema.max);
48 	MelderInfo_writeLine (U"y sampling:");
49 	MelderInfo_writeLine (U"   Number of values of t in y: ", our y -> nx);
50 	MelderInfo_writeLine (U"   t step in y: ", our y -> dx, U" (sampling rate ", 1.0 / our y -> dx, U")");
51 	MelderInfo_writeLine (U"   First t in y: ", our y -> x1);
52 	MelderInfo_writeLine (U"y values:");
53 	MelderInfo_writeLine (U"   Minimum y: ", yextrema.min);
54 	MelderInfo_writeLine (U"   Maximum y: ", yextrema.max);
55 }
56 
v_writeText(MelderFile file)57 void structParamCurve :: v_writeText (MelderFile file) {
58 	Data_writeText (our x.get(), file);
59 	Data_writeText (our y.get(), file);
60 }
61 
v_readText(MelderReadText text,int formatVersion)62 void structParamCurve :: v_readText (MelderReadText text, int formatVersion) {
63 	our x = Thing_new (Sound);
64 	our y = Thing_new (Sound);
65 	Data_readText (our x.get(), text, formatVersion);
66 	Data_readText (our y.get(), text, formatVersion);
67 	our xmin = our x -> xmin > our y -> xmin ? our x -> xmin : our y -> xmin;
68 	our xmax = our x -> xmax < our y -> xmax ? our x -> xmax : our y -> xmax;
69 }
70 
v_writeBinary(FILE * f)71 void structParamCurve :: v_writeBinary (FILE *f) {
72 	Data_writeBinary (x.get(), f);
73 	Data_writeBinary (y.get(), f);
74 }
75 
v_readBinary(FILE * f,int)76 void structParamCurve :: v_readBinary (FILE *f, int /*formatVersion*/) {
77 	our x = Thing_new (Sound);
78 	our y = Thing_new (Sound);
79 	Data_readBinary (our x.get(), f, 2);
80 	Data_readBinary (our y.get(), f, 2);
81 	our xmin = our x -> xmin > our y -> xmin ? our x -> xmin : our y -> xmin;
82 	our xmax = our x -> xmax < our y -> xmax ? our x -> xmax : our y -> xmax;
83 }
84 
ParamCurve_init(ParamCurve me,Sound x,Sound y)85 void ParamCurve_init (ParamCurve me, Sound x, Sound y) {
86 	if (x -> xmax <= y -> xmin || x -> xmin >= y -> xmax)
87 		Melder_throw (U"Domains do not overlap.");
88 	my x = Data_copy (x);
89 	my y = Data_copy (y);
90 	my xmin = x -> xmin > y -> xmin ? x -> xmin : y -> xmin;
91 	my xmax = x -> xmax < y -> xmax ? x -> xmax : y -> xmax;
92 }
93 
ParamCurve_create(Sound x,Sound y)94 autoParamCurve ParamCurve_create (Sound x, Sound y) {
95 	try {
96 		autoParamCurve me = Thing_new (ParamCurve);
97 		ParamCurve_init (me.get(), x, y);
98 		return me;
99 	} catch (MelderError) {
100 		Melder_throw (U"ParamCurve not created.");
101 	}
102 }
103 
ParamCurve_draw(ParamCurve me,Graphics g,double t1,double t2,double dt,double x1,double x2,double y1,double y2,bool garnish)104 void ParamCurve_draw (ParamCurve me, Graphics g, double t1, double t2, double dt,
105 	double x1, double x2, double y1, double y2, bool garnish)
106 {
107 	if (t2 <= t1) {
108 		double tx1 = my x -> x1;
109 		double ty1 = my y -> x1;
110 		double tx2 = my x -> x1 + (my x -> nx - 1) * my x -> dx;
111 		double ty2 = my y -> x1 + (my y -> nx - 1) * my y -> dx;
112 		t1 = tx1 > ty1 ? tx1 : ty1;
113 		t2 = tx2 < ty2 ? tx2 : ty2;
114 	}
115 	if (x2 <= x1) Matrix_getWindowExtrema (my x.get(), 0, 0, 1, 1, & x1, & x2);
116 	if (x1 == x2) { x1 -= 1.0; x2 += 1.0; }
117 	if (y2 <= y1) Matrix_getWindowExtrema (my y.get(), 0, 0, 1, 1, & y1, & y2);
118 	if (y1 == y2) { y1 -= 1.0; y2 += 1.0; }
119 	if (dt <= 0.0)
120 		dt = my x -> dx < my y -> dx ? my x -> dx : my y -> dx;
121 	integer numberOfPoints = Melder_iceiling ((t2 - t1) / dt) + 1;
122 	if (numberOfPoints > 0) {
123 		autoVEC x = raw_VEC (numberOfPoints);
124 		autoVEC y = raw_VEC (numberOfPoints);
125 		for (integer i = 1; i <= numberOfPoints; i ++) {
126 			double t = i == numberOfPoints ? t2 : t1 + (i - 1) * dt;
127 			double index = Sampled_xToIndex (my x.get(), t);
128 			x [i] = NUM_interpolate_sinc (my x -> z.row (1), index, 50);
129 			index = Sampled_xToIndex (my y.get(), t);
130 			y [i] = NUM_interpolate_sinc (my y -> z.row (1), index, 50);
131 		}
132 		Graphics_setWindow (g, x1, x2, y1, y2);
133 		Graphics_setInner (g);
134 		Graphics_polyline (g, numberOfPoints, & x [1], & y [1]);
135 		Graphics_unsetInner (g);
136 	}
137 	if (garnish) {
138 		Graphics_drawInnerBox (g);
139 		Graphics_marksBottom (g, 2, true, true, false);
140 		Graphics_marksLeft (g, 2, true, true, false);
141 	}
142 }
143 
ParamCurve_swapXY(ParamCurve me)144 void ParamCurve_swapXY (ParamCurve me) {
145 	autoSound help = my x.move();
146 	my x = my y.move();
147 	my y = help.move();
148 }
149 
150 /* End of file ParamCurve.cpp */
151