コード例 #1
0
ファイル: PointEditor.cpp プロジェクト: danrasband/libpraat
void structPointEditor :: v_draw () {
	PointProcess point = (PointProcess) data;
	Sound sound = d_sound.data;
	Graphics_setColour (d_graphics, Graphics_WHITE);
	Graphics_setWindow (d_graphics, 0, 1, 0, 1);
	Graphics_fillRectangle (d_graphics, 0, 1, 0, 1);
	double minimum = -1.0, maximum = +1.0;
	if (sound != NULL && (p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_BY_WINDOW || p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_BY_WINDOW_AND_CHANNEL)) {
		long first, last;
		if (Sampled_getWindowSamples (sound, d_startWindow, d_endWindow, & first, & last) >= 1) {
			Matrix_getWindowExtrema (sound, first, last, 1, 1, & minimum, & maximum);
		}
	}
	Graphics_setWindow (d_graphics, d_startWindow, d_endWindow, minimum, maximum);
	Graphics_setColour (d_graphics, Graphics_BLACK);
	if (sound != NULL) {
		long first, last;
		if (Sampled_getWindowSamples (sound, d_startWindow, d_endWindow, & first, & last) > 1) {
			Graphics_setLineType (d_graphics, Graphics_DOTTED);
			Graphics_line (d_graphics, d_startWindow, 0.0, d_endWindow, 0.0);
			Graphics_setLineType (d_graphics, Graphics_DRAWN);      
			Graphics_function (d_graphics, sound -> z [1], first, last,
				Sampled_indexToX (sound, first), Sampled_indexToX (sound, last));
		}
	}
	Graphics_setColour (d_graphics, Graphics_BLUE);
	Graphics_setWindow (d_graphics, d_startWindow, d_endWindow, -1.0, +1.0);
	for (long i = 1; i <= point -> nt; i ++) {
		double t = point -> t [i];
		if (t >= d_startWindow && t <= d_endWindow)
			Graphics_line (d_graphics, t, -0.9, t, +0.9);
	}
	Graphics_setColour (d_graphics, Graphics_BLACK);
	v_updateMenuItems_file ();
}
コード例 #2
0
ファイル: Art_Speaker.cpp プロジェクト: READSEARCH/praat
void Art_Speaker_drawMesh (Art art, Speaker speaker, Graphics graphics) {
	double xi [40], yi [40], xe [40], ye [40], xmm [40], ymm [40];
	int closed [40];
	int i;
	Graphics_Viewport previous;
	int oldLineType = Graphics_inqLineType (graphics);
	Art_Speaker_meshVocalTract (art, speaker, xi, yi, xe, ye, xmm, ymm, closed);
	previous = Graphics_insetViewport (graphics, 0.1, 0.9, 0.1, 0.9);   /* Must be square. */
	Graphics_setWindow (graphics, -0.05, 0.05, -0.05, 0.05);

	/* Mesh lines. */
	for (i = 1; i <= Art_Speaker_meshCount; i ++)
		Graphics_line (graphics, xi [i], yi [i], xe [i], ye [i]);

	/* Radii. */
	Graphics_setLineType (graphics, Graphics_DOTTED);
	for (i = 1; i <= Art_Speaker_meshCount; i ++)
		if (xe [i] <= 0.0 && ye [i] >= 0.0)
			Graphics_line (graphics, 0.0, 0.0, 0.9 * xi [i], 0.9 * yi [i]);
	Graphics_setLineType (graphics, oldLineType);

	/* Lengths. */
	for (i = 1; i <= Art_Speaker_meshCount; i ++)
		Graphics_line (graphics, xmm [i], ymm [i], xmm [i + 1], ymm [i + 1]);

	for (i = 1; i <= Art_Speaker_meshCount + 1; i ++)
		Graphics_speckle (graphics, xmm [i], ymm [i]);
	Graphics_setTextAlignment (graphics, Graphics_LEFT, Graphics_HALF);
	Graphics_text (graphics, 0.0, 0.0, U"O");   // origin
	Graphics_resetViewport (graphics, previous);
}
コード例 #3
0
void Graphics_quantileQuantilePlot (Graphics g, long numberOfQuantiles, double xdata[], long xnumberOfData, double ydata[], long ynumberOfData, double xmin, double xmax, double ymin, double ymax, int labelSize, const char32 *plotLabel) {
	int fontSize = Graphics_inqFontSize (g);

	Graphics_setTextAlignment (g, Graphics_CENTRE, Graphics_HALF);
	Graphics_setFontSize (g, labelSize);
	autoNUMvector<double> xsorted (NUMvector_copy<double> (xdata, 1, xnumberOfData), 1);
	autoNUMvector<double> ysorted (NUMvector_copy<double> (ydata, 1, ynumberOfData), 1);
	NUMsort_d (xnumberOfData, xsorted.peek());
	NUMsort_d (ynumberOfData, ysorted.peek());

	long numberOfData = xnumberOfData < ynumberOfData ? xnumberOfData : ynumberOfData;
	numberOfQuantiles = numberOfData < numberOfQuantiles ? numberOfData : numberOfQuantiles;
	double un = pow (0.5, 1.0 / numberOfQuantiles);
	double u1 = 1.0 - un;
	if (xmin == xmax) {
		xmin = NUMquantile (xnumberOfData, xsorted.peek(), u1);
		xmax = NUMquantile (xnumberOfData, xsorted.peek(), un);
	}
	if (ymin == ymax) {
		ymin = NUMquantile (ynumberOfData, ysorted.peek(), u1);
		ymax = NUMquantile (ynumberOfData, ysorted.peek(), un);
	}
	for (long i = 1; i <= numberOfQuantiles; i++) {
		double ui = i == 1 ? u1 : (i == numberOfQuantiles ? un : (i - 0.3175) / (numberOfQuantiles + 0.365));
		double qx = NUMquantile (xnumberOfData, xsorted.peek(), ui);
		double qy = NUMquantile (ynumberOfData, ysorted.peek(), ui);
		if (qx < xmin || qx > xmax || qy < ymin || qy > ymax) continue; // outside area
		Graphics_text (g, qx, qy, plotLabel);
	}
	Graphics_setLineType (g, Graphics_DOTTED);
	Graphics_line (g, xmin, ymin, xmax, ymax);
	Graphics_setLineType (g, Graphics_DRAWN);
	Graphics_setFontSize (g, fontSize);
}
コード例 #4
0
static void Pitch_line (Pitch me, Graphics g, double tmin, double fleft, double tmax, double fright,
	int nonPeriodicLineType)
{
	/*
	 * f = fleft + (t - tmin) * (fright - fleft) / (tmax - tmin);
	 */
	int lineType = Graphics_inqLineType (g);
	double lineWidth = Graphics_inqLineWidth (g);
	double slope = (fright - fleft) / (tmax - tmin);
	long imin = Sampled_xToNearestIndex (me, tmin);
	if (imin < 1) imin = 1;
	long imax = Sampled_xToNearestIndex (me, tmax);
	if (imax > my nx) imax = my nx;
	for (long i = imin; i <= imax; i ++) {
		double tleft, tright;
		if (! Pitch_isVoiced_i (me, i)) {
			if (nonPeriodicLineType == 2) continue;
			Graphics_setLineType (g, Graphics_DOTTED);
			Graphics_setLineWidth (g, 0.67 * lineWidth);
		} else if (nonPeriodicLineType != 2) {
			Graphics_setLineWidth (g, 2 * lineWidth);
		}
		tleft = Sampled_indexToX (me, i) - 0.5 * my dx, tright = tleft + my dx;
		if (tleft < tmin) tleft = tmin;
		if (tright > tmax) tright = tmax;
		Graphics_line (g, tleft, fleft + (tleft - tmin) * slope,
			tright, fleft + (tright - tmin) * slope);
		Graphics_setLineType (g, lineType);
		Graphics_setLineWidth (g, lineWidth);
	}
}
コード例 #5
0
ファイル: PointProcess.cpp プロジェクト: READSEARCH/praat
void PointProcess_draw (PointProcess me, Graphics g, double tmin, double tmax, bool garnish) {
	if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; }
	Graphics_setWindow (g, tmin, tmax, -1.0, 1.0);
	if (my nt) {
		long imin = PointProcess_getHighIndex (me, tmin);
		long imax = PointProcess_getLowIndex  (me, tmax);
		int lineType = Graphics_inqLineType (g);
		Graphics_setLineType (g, Graphics_DOTTED);
		Graphics_setInner (g);
		for (long i = imin; i <= imax; i ++) {
			Graphics_line (g, my t [i], -1.0, my t [i], 1.0);
		}
		Graphics_setLineType (g, lineType);
		Graphics_unsetInner (g);
	}
	if (garnish) {
		Graphics_drawInnerBox (g);
		Graphics_textBottom (g, true, U"Time (s)");
		Graphics_marksBottom (g, 2, true, true, false);
	}
}
コード例 #6
0
ファイル: Pitch_Intensity.cpp プロジェクト: Crisil/praat
void Pitch_Intensity_draw (Pitch pitch, Intensity intensity, Graphics g,
	double f1, double f2, double s1, double s2, int garnish, int connect)
{
	if (f2 <= f1) Pitch_getExtrema (pitch, & f1, & f2);
	if (f1 == 0.0) return;   /* All voiceless. */
	if (f1 == f2) { f1 -= 1.0; f2 += 1.0; }
	if (s2 <= s1) Matrix_getWindowExtrema (intensity, 0, 0, 1, 1, & s1, & s2);
	if (s1 == s2) { s1 -= 1.0; s2 += 1.0; }
	Graphics_setWindow (g, f1, f2, s1, s2);
	Graphics_setInner (g);
	long previousI = 0;
	double previousX = NUMundefined, previousY = NUMundefined;
	for (long i = 1; i <= pitch -> nx; i ++) {
		double t = Sampled_indexToX (pitch, i);
		double x = pitch -> frame [i]. candidate [1]. frequency;
		double y = Sampled_getValueAtX (intensity, t, Pitch_LEVEL_FREQUENCY, kPitch_unit_HERTZ, TRUE);
		if (x == 0) {
			continue;   /* Voiceless. */
		}
		if (connect & 1) Graphics_speckle (g, x, y);
		if ((connect & 2) && NUMdefined (previousX)) {
			if (previousI >= 1 && previousI < i - 1) {
				Graphics_setLineType (g, Graphics_DOTTED);
			}
			Graphics_line (g, previousX, previousY, x, y);
			Graphics_setLineType (g, Graphics_DRAWN);
		}
		previousX = x;
		previousY = y;
		previousI = i;
	}
	Graphics_unsetInner (g);
	if (garnish) {
		Graphics_drawInnerBox (g);
		Graphics_textBottom (g, 1, L"Fundamental frequency (Hz)");
		Graphics_marksBottom (g, 2, 1, 1, 0);
		Graphics_textLeft (g, 1, L"Intensity (dB)");
		Graphics_marksLeft (g, 2, 1, 1, 0);
	}
}
コード例 #7
0
ファイル: Graphics_extensions.cpp プロジェクト: Crisil/praat
void Graphics_lagPlot (Graphics g, double data[], long numberOfData, double xmin, double xmax, long lag, int labelSize, const wchar_t *plotLabel) {
	if (lag < 0 || lag >= numberOfData) {
		return;
	}
	int fontSize = Graphics_inqFontSize (g);
	Graphics_setFontSize (g, labelSize);
	Graphics_setTextAlignment (g, Graphics_CENTRE, Graphics_HALF);
	// plot x[i] vertically and x[i-lag] horizontally
	for (long i = 1; i <= numberOfData - lag; i++) {
		double x = data[i + lag], y = data[i];
		if (x >= xmin && x <= xmax && y >= xmin && y <= xmax) {
			Graphics_text (g, x, y, plotLabel);
		}
	}
	Graphics_setLineType (g, Graphics_DRAWN);
	Graphics_setFontSize (g, fontSize);
}
コード例 #8
0
void structPitchEditor :: v_draw () {
    Pitch pitch = (Pitch) our data;
    long it, it1, it2;
    double dyUnv, dyIntens;

    Graphics_setWindow (our d_graphics, 0, 1, 0, 1);
    Graphics_setColour (our d_graphics, Graphics_WHITE);
    Graphics_fillRectangle (our d_graphics, 0, 1, 0, 1);
    Graphics_setColour (our d_graphics, Graphics_BLACK);
    Graphics_rectangle (our d_graphics, 0, 1, 0, 1);

    dyUnv = Graphics_dyMMtoWC (our d_graphics, HEIGHT_UNV);
    dyIntens = Graphics_dyMMtoWC (our d_graphics, HEIGHT_INTENS);

    Sampled_getWindowSamples (pitch, our d_startWindow, our d_endWindow, & it1, & it2);

    /*
     * Show pitch.
     */
    {
        long df =
            pitch -> ceiling > 10000 ? 2000 :
            pitch -> ceiling > 5000 ? 1000 :
            pitch -> ceiling > 2000 ? 500 :
            pitch -> ceiling > 800 ? 200 :
            pitch -> ceiling > 400 ? 100 :
            50;
        double radius;
        Graphics_Viewport previous;
        previous = Graphics_insetViewport (our d_graphics, 0, 1, dyUnv, 1 - dyIntens);
        Graphics_setWindow (our d_graphics, our d_startWindow, our d_endWindow, 0, pitch -> ceiling);
        radius = Graphics_dxMMtoWC (our d_graphics, RADIUS);

        /* Horizontal hair at current pitch. */

        if (our d_startSelection == our d_endSelection && our d_startSelection >= our d_startWindow && our d_startSelection <= our d_endWindow) {
            double f = Pitch_getValueAtTime (pitch, our d_startSelection, kPitch_unit_HERTZ, Pitch_LINEAR);
            if (NUMdefined (f)) {
                Graphics_setColour (our d_graphics, Graphics_RED);
                Graphics_line (our d_graphics, our d_startWindow - radius, f, our d_endWindow, f);
                Graphics_setTextAlignment (our d_graphics, Graphics_RIGHT, Graphics_HALF);
                Graphics_text1 (our d_graphics, our d_startWindow - radius, f, Melder_fixed (f, 2));
            }
        }

        /* Horizontal scaling lines. */

        Graphics_setColour (our d_graphics, Graphics_BLUE);
        Graphics_setLineType (our d_graphics, Graphics_DOTTED);
        Graphics_setTextAlignment (our d_graphics, Graphics_LEFT, Graphics_HALF);
        for (long f = df; f <= pitch -> ceiling; f += df) {
            Graphics_line (our d_graphics, our d_startWindow, f, our d_endWindow, f);
            Graphics_text2 (our d_graphics, our d_endWindow + radius/2, f, Melder_integer (f), L" Hz");
        }
        Graphics_setLineType (our d_graphics, Graphics_DRAWN);

        /* Show candidates. */

        for (it = it1; it <= it2; it ++) {
            Pitch_Frame frame = & pitch -> frame [it];
            double t = Sampled_indexToX (pitch, it);
            double f = frame -> candidate [1]. frequency;
            if (f > 0.0 && f < pitch -> ceiling) {
                Graphics_setColour (our d_graphics, Graphics_MAGENTA);
                Graphics_fillCircle_mm (our d_graphics, t, f, RADIUS * 2);
            }
            Graphics_setColour (our d_graphics, Graphics_BLACK);
            Graphics_setTextAlignment (our d_graphics, Graphics_CENTRE, Graphics_HALF);
            for (int icand = 1; icand <= frame -> nCandidates; icand ++) {
                int strength = (int) floor (10 * frame -> candidate [icand]. strength + 0.5);
                f = frame -> candidate [icand]. frequency;
                if (strength > 9) strength = 9;
                if (f > 0 && f <= pitch -> ceiling) Graphics_text1 (our d_graphics, t, f, Melder_integer (strength));
            }
        }
        Graphics_resetViewport (our d_graphics, previous);
    }

    /*
     * Show intensity.
     */
    {
        Graphics_Viewport previous = Graphics_insetViewport (our d_graphics, 0, 1, 1 - dyIntens, 1);
        Graphics_setWindow (our d_graphics, our d_startWindow, our d_endWindow, 0, 1);
        Graphics_setColour (our d_graphics, Graphics_BLACK);
        Graphics_setTextAlignment (our d_graphics, Graphics_RIGHT, Graphics_HALF);
        Graphics_text (our d_graphics, our d_startWindow, 0.5, L"intens");
        Graphics_setTextAlignment (our d_graphics, Graphics_LEFT, Graphics_HALF);
        Graphics_text (our d_graphics, our d_endWindow, 0.5, L"intens");
        Graphics_setTextAlignment (our d_graphics, Graphics_CENTRE, Graphics_HALF);
        for (it = it1; it <= it2; it ++) {
            Pitch_Frame frame = & pitch -> frame [it];
            double t = Sampled_indexToX (pitch, it);
            int strength = (int) floor (10 * frame -> intensity + 0.5);   // map 0.0-1.0 to 0-9
            if (strength > 9) strength = 9;
            Graphics_text1 (our d_graphics, t, 0.5, Melder_integer (strength));
        }
        Graphics_resetViewport (our d_graphics, previous);
    }

    if (it1 > 1) it1 -= 1;
    if (it2 < pitch -> nx) it2 += 1;

    /*
     * Show voicelessness.
     */
    {
        Graphics_Viewport previous = Graphics_insetViewport (our d_graphics, 0, 1, 0, dyUnv);
        Graphics_setColour (our d_graphics, Graphics_BLUE);
        Graphics_line (our d_graphics, our d_startWindow, 1, our d_endWindow, 1);
        Graphics_setTextAlignment (our d_graphics, Graphics_RIGHT, Graphics_HALF);
        Graphics_text (our d_graphics, our d_startWindow, 0.5, L"Unv");
        Graphics_setTextAlignment (our d_graphics, Graphics_LEFT, Graphics_HALF);
        Graphics_text (our d_graphics, our d_endWindow, 0.5, L"Unv");
        for (it = it1; it <= it2; it ++) {
            Pitch_Frame frame = & pitch -> frame [it];
            double t = Sampled_indexToX (pitch, it), tleft = t - 0.5 * pitch -> dx, tright = t + 0.5 * pitch -> dx;
            double f = frame -> candidate [1]. frequency;
            if ((f > 0.0 && f < pitch -> ceiling) || tright <= our d_startWindow || tleft >= our d_endWindow) continue;
            if (tleft < our d_startWindow) tleft = our d_startWindow;
            if (tright > our d_endWindow) tright = our d_endWindow;
            Graphics_fillRectangle (our d_graphics, tleft, tright, 0, 1);
        }
        Graphics_setColour (our d_graphics, Graphics_BLACK);
        Graphics_resetViewport (our d_graphics, previous);
    }
}
コード例 #9
0
ファイル: TimeSoundEditor.cpp プロジェクト: motiz88/praat
void TimeSoundEditor_drawSound (TimeSoundEditor me, double globalMinimum, double globalMaximum) {
	Sound sound = my d_sound.data;
	LongSound longSound = my d_longSound.data;
	Melder_assert (!! sound != !! longSound);
	int nchan = sound ? sound -> ny : longSound -> numberOfChannels;
	bool cursorVisible = my d_startSelection == my d_endSelection && my d_startSelection >= my d_startWindow && my d_startSelection <= my d_endWindow;
	Graphics_setColour (my d_graphics, Graphics_BLACK);
	bool fits;
	try {
		fits = sound ? true : LongSound_haveWindow (longSound, my d_startWindow, my d_endWindow);
	} catch (MelderError) {
		bool outOfMemory = !! str32str (Melder_getError (), U"memory");
		if (Melder_debug == 9) Melder_flushError (); else Melder_clearError ();
		Graphics_setWindow (my d_graphics, 0.0, 1.0, 0.0, 1.0);
		Graphics_setTextAlignment (my d_graphics, Graphics_CENTRE, Graphics_HALF);
		Graphics_text (my d_graphics, 0.5, 0.5, outOfMemory ? U"(out of memory)" : U"(cannot read sound file)");
		return;
	}
	if (! fits) {
		Graphics_setWindow (my d_graphics, 0.0, 1.0, 0.0, 1.0);
		Graphics_setTextAlignment (my d_graphics, Graphics_CENTRE, Graphics_HALF);
		Graphics_text (my d_graphics, 0.5, 0.5, U"(window too large; zoom in to see the data)");
		return;
	}
	long first, last;
	if (Sampled_getWindowSamples (sound ? (Sampled) sound : (Sampled) longSound, my d_startWindow, my d_endWindow, & first, & last) <= 1) {
		Graphics_setWindow (my d_graphics, 0.0, 1.0, 0.0, 1.0);
		Graphics_setTextAlignment (my d_graphics, Graphics_CENTRE, Graphics_HALF);
		Graphics_text (my d_graphics, 0.5, 0.5, U"(zoom out to see the data)");
		return;
	}
	const int numberOfVisibleChannels = nchan > 8 ? 8 : nchan;
	const int firstVisibleChannel = my d_sound.channelOffset + 1;
	int lastVisibleChannel = my d_sound.channelOffset + numberOfVisibleChannels;
	if (lastVisibleChannel > nchan) lastVisibleChannel = nchan;
	double maximumExtent = 0.0, visibleMinimum = 0.0, visibleMaximum = 0.0;
	if (my p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_BY_WINDOW) {
		if (longSound)
			LongSound_getWindowExtrema (longSound, my d_startWindow, my d_endWindow, firstVisibleChannel, & visibleMinimum, & visibleMaximum);
		else
			Matrix_getWindowExtrema (sound, first, last, firstVisibleChannel, firstVisibleChannel, & visibleMinimum, & visibleMaximum);
		for (int ichan = firstVisibleChannel + 1; ichan <= lastVisibleChannel; ichan ++) {
			double visibleChannelMinimum, visibleChannelMaximum;
			if (longSound)
				LongSound_getWindowExtrema (longSound, my d_startWindow, my d_endWindow, ichan, & visibleChannelMinimum, & visibleChannelMaximum);
			else
				Matrix_getWindowExtrema (sound, first, last, ichan, ichan, & visibleChannelMinimum, & visibleChannelMaximum);
			if (visibleChannelMinimum < visibleMinimum)
				visibleMinimum = visibleChannelMinimum;
			if (visibleChannelMaximum > visibleMaximum)
				visibleMaximum = visibleChannelMaximum;
		}
		maximumExtent = visibleMaximum - visibleMinimum;
	}
	for (int ichan = firstVisibleChannel; ichan <= lastVisibleChannel; ichan ++) {
		double cursorFunctionValue = longSound ? 0.0 :
			Vector_getValueAtX (sound, 0.5 * (my d_startSelection + my d_endSelection), ichan, 70);
		/*
		 * BUG: this will only work for mono or stereo, until Graphics_function16 handles quadro.
		 */
		double ymin = (double) (numberOfVisibleChannels - ichan + my d_sound.channelOffset) / numberOfVisibleChannels;
		double ymax = (double) (numberOfVisibleChannels + 1 - ichan + my d_sound.channelOffset) / numberOfVisibleChannels;
		Graphics_Viewport vp = Graphics_insetViewport (my d_graphics, 0, 1, ymin, ymax);
		bool horizontal = false;
		double minimum = sound ? globalMinimum : -1.0, maximum = sound ? globalMaximum : 1.0;
		if (my p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_BY_WINDOW) {
			if (nchan > 2) {
				if (longSound) {
					LongSound_getWindowExtrema (longSound, my d_startWindow, my d_endWindow, ichan, & minimum, & maximum);
				} else {
					Matrix_getWindowExtrema (sound, first, last, ichan, ichan, & minimum, & maximum);
				}
				if (maximumExtent > 0.0) {
					double middle = 0.5 * (minimum + maximum);
					minimum = middle - 0.5 * maximumExtent;
					maximum = middle + 0.5 * maximumExtent;
				}
			} else {
				minimum = visibleMinimum;
				maximum = visibleMaximum;
			}
		} else if (my p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_BY_WINDOW_AND_CHANNEL) {
			if (longSound) {
				LongSound_getWindowExtrema (longSound, my d_startWindow, my d_endWindow, ichan, & minimum, & maximum);
			} else {
				Matrix_getWindowExtrema (sound, first, last, ichan, ichan, & minimum, & maximum);
			}
		} else if (my p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_FIXED_HEIGHT) {
			if (longSound) {
				LongSound_getWindowExtrema (longSound, my d_startWindow, my d_endWindow, ichan, & minimum, & maximum);
			} else {
				Matrix_getWindowExtrema (sound, first, last, ichan, ichan, & minimum, & maximum);
			}
			double channelExtent = my p_sound_scaling_height;
			double middle = 0.5 * (minimum + maximum);
			minimum = middle - 0.5 * channelExtent;
			maximum = middle + 0.5 * channelExtent;
		} else if (my p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy_FIXED_RANGE) {
			minimum = my p_sound_scaling_minimum;
			maximum = my p_sound_scaling_maximum;
		}
		if (minimum == maximum) { horizontal = true; minimum -= 1.0; maximum += 1.0;}
		Graphics_setWindow (my d_graphics, my d_startWindow, my d_endWindow, minimum, maximum);
		if (horizontal) {
			Graphics_setTextAlignment (my d_graphics, Graphics_RIGHT, Graphics_HALF);
			double mid = 0.5 * (minimum + maximum);
			Graphics_text (my d_graphics, my d_startWindow, mid, Melder_float (Melder_half (mid)));
		} else {
			if (! cursorVisible || ! NUMdefined (cursorFunctionValue) || Graphics_dyWCtoMM (my d_graphics, cursorFunctionValue - minimum) > 5.0) {
				Graphics_setTextAlignment (my d_graphics, Graphics_RIGHT, Graphics_BOTTOM);
				Graphics_text (my d_graphics, my d_startWindow, minimum, Melder_float (Melder_half (minimum)));
			}
			if (! cursorVisible || ! NUMdefined (cursorFunctionValue) || Graphics_dyWCtoMM (my d_graphics, maximum - cursorFunctionValue) > 5.0) {
				Graphics_setTextAlignment (my d_graphics, Graphics_RIGHT, Graphics_TOP);
				Graphics_text (my d_graphics, my d_startWindow, maximum, Melder_float (Melder_half (maximum)));
			}
		}
		if (minimum < 0 && maximum > 0 && ! horizontal) {
			Graphics_setWindow (my d_graphics, 0, 1, minimum, maximum);
			if (! cursorVisible || ! NUMdefined (cursorFunctionValue) || fabs (Graphics_dyWCtoMM (my d_graphics, cursorFunctionValue - 0.0)) > 3.0) {
				Graphics_setTextAlignment (my d_graphics, Graphics_RIGHT, Graphics_HALF);
				Graphics_text (my d_graphics, 0, 0, U"0");
			}
			Graphics_setColour (my d_graphics, Graphics_CYAN);
			Graphics_setLineType (my d_graphics, Graphics_DOTTED);
			Graphics_line (my d_graphics, 0, 0, 1, 0);
			Graphics_setLineType (my d_graphics, Graphics_DRAWN);
		}
		/*
		 * Garnish the drawing area of each channel.
		 */
		Graphics_setWindow (my d_graphics, 0, 1, 0, 1);
		Graphics_setColour (my d_graphics, Graphics_CYAN);
		Graphics_innerRectangle (my d_graphics, 0, 1, 0, 1);
		Graphics_setColour (my d_graphics, Graphics_BLACK);
		if (nchan > 1) {
			Graphics_setTextAlignment (my d_graphics, Graphics_LEFT, Graphics_HALF);
			const char32 *channelName = my v_getChannelName (ichan);
			static MelderString channelLabel;
			MelderString_copy (& channelLabel, ( channelName ? U"ch" : U"Channel " ), ichan);
			if (channelName)
				MelderString_append (& channelLabel, U": ", channelName);
			if (ichan > 8 && ichan - my d_sound.channelOffset == 1) {
				MelderString_append (& channelLabel, U" " UNITEXT_UPWARDS_ARROW);
			} else if (ichan >= 8 && ichan - my d_sound.channelOffset == 8 && ichan < nchan) {
				MelderString_append (& channelLabel, U" " UNITEXT_DOWNWARDS_ARROW);
			}
			Graphics_text (my d_graphics, 1, 0.5, channelLabel.string);
		}
		/*
		 * Draw a very thin separator line underneath.
		 */
		if (ichan < nchan) {
			/*Graphics_setColour (d_graphics, Graphics_BLACK);*/
			Graphics_line (my d_graphics, 0, 0, 1, 0);
		}
		/*
		 * Draw the samples.
		 */
		/*if (ichan == 1) FunctionEditor_SoundAnalysis_drawPulses (this);*/
		if (sound) {
			Graphics_setWindow (my d_graphics, my d_startWindow, my d_endWindow, minimum, maximum);
			if (cursorVisible && NUMdefined (cursorFunctionValue))
				FunctionEditor_drawCursorFunctionValue (me, cursorFunctionValue, Melder_float (Melder_half (cursorFunctionValue)), U"");
			Graphics_setColour (my d_graphics, Graphics_BLACK);
			Graphics_function (my d_graphics, sound -> z [ichan], first, last,
				Sampled_indexToX (sound, first), Sampled_indexToX (sound, last));
		} else {
			Graphics_setWindow (my d_graphics, my d_startWindow, my d_endWindow, minimum * 32768, maximum * 32768);
			Graphics_function16 (my d_graphics,
				longSound -> buffer - longSound -> imin * nchan + (ichan - 1), nchan - 1, first, last,
				Sampled_indexToX (longSound, first), Sampled_indexToX (longSound, last));
		}
		Graphics_resetViewport (my d_graphics, vp);
	}
	Graphics_setWindow (my d_graphics, 0.0, 1.0, 0.0, 1.0);
	Graphics_rectangle (my d_graphics, 0.0, 1.0, 0.0, 1.0);
}
コード例 #10
0
ファイル: Graphics_extensions.cpp プロジェクト: Crisil/praat
void Graphics_boxAndWhiskerPlot (Graphics g, double data[], long ndata, double x, double r, double w, double ymin, double ymax) {
	int lineType = Graphics_inqLineType (g);

	Melder_assert (r > 0 && w > 0);
	if (ndata < 3) {
		return;
	}
	/*
		Sort the data (ascending: data[1] <= ... <= data[ndata]).
		Get the median (q50) and the upper and lower quartile points
		(q25 and q75).
		Now q25 and q75 are the lower and upper hinges, respectively.
		The fances can be calcultaed from q25 and q75.
		The spread is defined as the interquartile range or midrange
		|q75 - q25|.
		The fences are defined as:
		(lower/upper) innerfence = (lower/upper) hinge +/- 1.5 hspread
		(lower/upper) outerfence = (lower/upper) hinge +/- 3.0 hspread
	*/

	NUMsort_d (ndata, data);

	if (ymax <= ymin) {
		ymin = data[1]; ymax = data[ndata];
	}
	if (data[1] > ymax || data[ndata] < ymin) {
		return;
	}

	double mean = 0;
	for (long i = 1; i <= ndata; i++) {
		mean += data[i];
	}
	mean /= ndata;

	double q25 = NUMquantile (ndata, data, 0.25);
	double q50 = NUMquantile (ndata, data, 0.5);
	double q75 = NUMquantile (ndata, data, 0.75);

	double hspread = fabs (q75 - q25);
	double lowerOuterFence = q25 - 3.0 * hspread;
	double lowerInnerFence = q25 - 1.5 * hspread;
	double upperInnerFence = q75 + 1.5 * hspread;
	double upperOuterFence = q75 + 3.0 * hspread;

	/*
		Decide whether there are outliers that have to be drawn.
		First process data from below (data are sorted).
	*/

	long i = 1, ie = ndata;
	while (i <= ie && data[i] < ymin) {
		i++;
	}
	Graphics_setTextAlignment (g, Graphics_CENTRE, Graphics_HALF);
	while (i <= ie && data[i] < lowerOuterFence) {
		Graphics_text (g, x, data[i], L"o"); i++;
	}
	while (i <= ie && data[i] < lowerInnerFence) {
		Graphics_text (g, x, data[i], L"*"); i++;
	}
	double lowerWhisker = data[i] < q25 ? data[i] : lowerInnerFence;
	if (lowerWhisker > ymax) {
		return;
	}

	// Next process data from above.

	i = ndata; ie = i;
	while (i >= ie && data[i] > ymax) {
		i--;
	}
	while (i >= ie && data[i] > upperOuterFence) {
		Graphics_text (g, x, data[i], L"o"); i--;
	}
	while (i >= ie && data[i] > upperInnerFence) {
		Graphics_text (g, x, data[i], L"*"); i--;
	}
	double upperWhisker = data[i] > q75 ? data[i] : upperInnerFence;
	if (upperWhisker < ymin) {
		return;
	}

	/*
		Determine what parts of the "box" have to be drawn within the
		range [ymin, ymax].
		Horizontal lines first.
	*/

	double y1 = lowerWhisker;
	if (ymax > y1 && ymin < y1) {
		Graphics_line (g, x - r, y1, x + r, y1);
	}
	y1 = q25;
	if (ymax > y1 && ymin < y1) {
		Graphics_line (g, x - w, y1, x + w, y1);
	}
	y1 = q50;
	if (ymax > y1 && ymin < y1) {
		Graphics_line (g, x - w, y1, x + w, y1);
	}
	y1 = q75;
	if (ymax > y1 && ymin < y1) {
		Graphics_line (g, x - w, y1, x + w, y1);
	}
	y1 = upperWhisker;
	if (ymax > y1 && ymin < y1) {
		Graphics_line (g, x - r, y1, x + r, y1);
	}

	// Extension: draw the mean too.

	y1 = mean;
	if (ymax > y1 && ymin < y1) {
		Graphics_setLineType (g, Graphics_DOTTED);
		Graphics_line (g, x - w, y1, x + w, y1);
		Graphics_setLineType (g, lineType);
	}

	// Now process the vertical lines.

	y1 = lowerWhisker;
	double y2 = q25;
	if (ymax > y1 && ymin < y2) {
		y1 = y1 > ymin ? y1 : ymin;
		y2 = y2 < ymax ? y2 : ymax;
		Graphics_line (g, x, y1, x, y2);
	}
	y1 = q25; y2 = q75;
	if (ymax > y1 && ymin < y2) {
		y1 = y1 > ymin ? y1 : ymin;
		y2 = y2 < ymax ? y2 : ymax;
		Graphics_line (g, x - w, y1, x - w, y2);
		Graphics_line (g, x + w, y1, x + w, y2);
	}
	y1 = q75; y2 = upperWhisker;
	if (ymax > y1 && ymin < y2) {
		y1 = y1 > ymin ? y1 : ymin;
		y2 = y2 < ymax ? y2 : ymax;
		Graphics_line (g, x, y1, x, y2);
	}
}
コード例 #11
0
int HyperPage_script (I, double width_inches, double height_inches, const wchar_t *script) {
	iam (HyperPage);
	wchar_t *text = Melder_wcsdup_f (script);
	Interpreter interpreter = Interpreter_createFromEnvironment (NULL);
	double topSpacing = 0.1, bottomSpacing = 0.1, minFooterDistance = 0.0;
	kGraphics_font font = my font;
	int size = my fontSize;
	double true_width_inches = width_inches * ( width_inches < 0.0 ? -1.0 : size / 12.0 );
	double true_height_inches = height_inches * ( height_inches < 0.0 ? -1.0 : size / 12.0 );
if (! my printing) {
	my d_y -= ( my previousBottomSpacing > topSpacing ? my previousBottomSpacing : topSpacing ) * size / 12.0;
	if (my d_y > PAGE_HEIGHT + true_height_inches || my d_y < PAGE_HEIGHT - SCREEN_HEIGHT) {
		my d_y -= true_height_inches;
	} else {
		my d_y -= true_height_inches;
		Graphics_setFont (my g, font);
		Graphics_setFontStyle (my g, 0);
		Graphics_setFontSize (my g, size);
		my d_x = true_width_inches > my rightMargin ? 0 : 0.5 * (my rightMargin - true_width_inches);
		Graphics_setWrapWidth (my g, 0);
		long x1DCold, x2DCold, y1DCold, y2DCold;
		Graphics_inqWsViewport (my g, & x1DCold, & x2DCold, & y1DCold, & y2DCold);
		double x1NDCold, x2NDCold, y1NDCold, y2NDCold;
		Graphics_inqWsWindow (my g, & x1NDCold, & x2NDCold, & y1NDCold, & y2NDCold);
		{
			if (my praatApplication == NULL) my praatApplication = Melder_calloc_f (structPraatApplication, 1);
			if (my praatObjects == NULL) my praatObjects = Melder_calloc_f (structPraatObjects, 1);
			if (my praatPicture == NULL) my praatPicture = Melder_calloc_f (structPraatPicture, 1);
			theCurrentPraatApplication = (PraatApplication) my praatApplication;
			theCurrentPraatApplication -> batch = true;   // prevent creation of editor windows
			theCurrentPraatApplication -> topShell = theForegroundPraatApplication. topShell;   // needed for UiForm_create () in dialogs
			theCurrentPraatObjects = (PraatObjects) my praatObjects;
			theCurrentPraatPicture = (PraatPicture) my praatPicture;
			theCurrentPraatPicture -> graphics = my g;   // has to draw into HyperPage rather than Picture window
			theCurrentPraatPicture -> font = font;
			theCurrentPraatPicture -> fontSize = size;
			theCurrentPraatPicture -> lineType = Graphics_DRAWN;
			theCurrentPraatPicture -> colour = Graphics_BLACK;
			theCurrentPraatPicture -> lineWidth = 1.0;
			theCurrentPraatPicture -> arrowSize = 1.0;
			theCurrentPraatPicture -> x1NDC = my d_x;
			theCurrentPraatPicture -> x2NDC = my d_x + true_width_inches;
			theCurrentPraatPicture -> y1NDC = my d_y;
			theCurrentPraatPicture -> y2NDC = my d_y + true_height_inches;

			Graphics_setViewport (my g, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
			Graphics_setWindow (my g, 0.0, 1.0, 0.0, 1.0);
			long x1DC, y1DC, x2DC, y2DC;
			Graphics_WCtoDC (my g, 0.0, 0.0, & x1DC, & y2DC);
			Graphics_WCtoDC (my g, 1.0, 1.0, & x2DC, & y1DC);
			Graphics_resetWsViewport (my g, x1DC, x2DC, y1DC, y2DC);
			Graphics_setWsWindow (my g, 0, width_inches, 0, height_inches);
			theCurrentPraatPicture -> x1NDC = 0;
			theCurrentPraatPicture -> x2NDC = width_inches;
			theCurrentPraatPicture -> y1NDC = 0;
			theCurrentPraatPicture -> y2NDC = height_inches;
			Graphics_setViewport (my g, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);			

			{ // scope
				autoMelderProgressOff progress;
				autoMelderWarningOff warning;
				autoMelderSaveDefaultDir saveDir;
				if (! MelderDir_isNull (& my rootDirectory)) {
					Melder_setDefaultDir (& my rootDirectory);
				}
				try {
					Interpreter_run (interpreter, text);
				} catch (MelderError) {
					if (my scriptErrorHasBeenNotified) {
						Melder_clearError ();
					} else {
						Melder_flushError (NULL);
						my scriptErrorHasBeenNotified = true;
					}
				}
			}
			Graphics_setLineType (my g, Graphics_DRAWN);
			Graphics_setLineWidth (my g, 1.0);
			Graphics_setArrowSize (my g, 1.0);
			Graphics_setColour (my g, Graphics_BLACK);
			/*Graphics_Link *paragraphLinks;
			long numberOfParagraphLinks = Graphics_getLinks (& paragraphLinks);
			if (my links) for (long ilink = 1; ilink <= numberOfParagraphLinks; ilink ++) {
				HyperLink link = HyperLink_create (paragraphLinks [ilink]. name,
					paragraphLinks [ilink]. x1, paragraphLinks [ilink]. x2,
					paragraphLinks [ilink]. y1, paragraphLinks [ilink]. y2);
				Collection_addItem (my links, link);
			}*/
			theCurrentPraatApplication = & theForegroundPraatApplication;
			theCurrentPraatObjects = & theForegroundPraatObjects;
			theCurrentPraatPicture = & theForegroundPraatPicture;
		}
		Graphics_resetWsViewport (my g, x1DCold, x2DCold, y1DCold, y2DCold);
		Graphics_setWsWindow (my g, x1NDCold, x2NDCold, y1NDCold, y2NDCold);
		Graphics_setViewport (my g, 0, 1, 0, 1);
		Graphics_setWindow (my g, 0, 1, 0, 1);
		Graphics_setTextAlignment (my g, Graphics_LEFT, Graphics_BOTTOM);
	}
} else {
	Graphics_setFont (my ps, font);
	Graphics_setFontStyle (my ps, 0);
	Graphics_setFontSize (my ps, size);
	my d_y -= my d_y == PAPER_TOP - TOP_MARGIN ? 0 : ( my previousBottomSpacing > topSpacing ? my previousBottomSpacing : topSpacing ) * size / 12.0;
	my d_y -= true_height_inches;
	if (my d_y < PAPER_BOTTOM + BOTTOM_MARGIN + minFooterDistance) {
		Graphics_nextSheetOfPaper (my ps);
		if (my d_printingPageNumber) my d_printingPageNumber ++;
		HyperPage_initSheetOfPaper (me);
		Graphics_setFont (my ps, font);
		Graphics_setFontSize (my ps, size);
		my d_y -= true_height_inches;
	}
	my d_x = 3.7 - 0.5 * true_width_inches;
	if (my d_x < 0) my d_x = 0;
	Graphics_setWrapWidth (my ps, 0);
	long x1DCold, x2DCold, y1DCold, y2DCold;
	Graphics_inqWsViewport (my ps, & x1DCold, & x2DCold, & y1DCold, & y2DCold);
	double x1NDCold, x2NDCold, y1NDCold, y2NDCold;
	Graphics_inqWsWindow (my ps, & x1NDCold, & x2NDCold, & y1NDCold, & y2NDCold);
	{
		if (my praatApplication == NULL) my praatApplication = Melder_calloc_f (structPraatApplication, 1);
		if (my praatObjects == NULL) my praatObjects = Melder_calloc_f (structPraatObjects, 1);
		if (my praatPicture == NULL) my praatPicture = Melder_calloc_f (structPraatPicture, 1);
		theCurrentPraatApplication = (PraatApplication) my praatApplication;
		theCurrentPraatApplication -> batch = true;
		theCurrentPraatApplication -> topShell = theForegroundPraatApplication. topShell;   // needed for UiForm_create () in dialogs
		theCurrentPraatObjects = (PraatObjects) my praatObjects;
		theCurrentPraatPicture = (PraatPicture) my praatPicture;
		theCurrentPraatPicture -> graphics = my ps;
		theCurrentPraatPicture -> font = font;
		theCurrentPraatPicture -> fontSize = size;
		theCurrentPraatPicture -> lineType = Graphics_DRAWN;
		theCurrentPraatPicture -> colour = Graphics_BLACK;
		theCurrentPraatPicture -> lineWidth = 1.0;
		theCurrentPraatPicture -> arrowSize = 1.0;
		theCurrentPraatPicture -> x1NDC = my d_x;
		theCurrentPraatPicture -> x2NDC = my d_x + true_width_inches;
		theCurrentPraatPicture -> y1NDC = my d_y;
		theCurrentPraatPicture -> y2NDC = my d_y + true_height_inches;

		Graphics_setViewport (my ps, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);
		Graphics_setWindow (my ps, 0.0, 1.0, 0.0, 1.0);
		long x1DC, y1DC, x2DC, y2DC;
		Graphics_WCtoDC (my ps, 0.0, 0.0, & x1DC, & y2DC);
		Graphics_WCtoDC (my ps, 1.0, 1.0, & x2DC, & y1DC);
		long shift = (long) (Graphics_getResolution (my ps) * true_height_inches) + (y1DCold - y2DCold);
		Graphics_resetWsViewport (my ps, x1DC, x2DC, y1DC + shift, y2DC + shift);
		Graphics_setWsWindow (my ps, 0, width_inches, 0, height_inches);
		theCurrentPraatPicture -> x1NDC = 0;
		theCurrentPraatPicture -> x2NDC = width_inches;
		theCurrentPraatPicture -> y1NDC = 0;
		theCurrentPraatPicture -> y2NDC = height_inches;
		Graphics_setViewport (my ps, theCurrentPraatPicture -> x1NDC, theCurrentPraatPicture -> x2NDC, theCurrentPraatPicture -> y1NDC, theCurrentPraatPicture -> y2NDC);

		{ // scope
			autoMelderProgressOff progress;
			autoMelderWarningOff warning;
			autoMelderSaveDefaultDir saveDir;
			if (! MelderDir_isNull (& my rootDirectory)) {
				Melder_setDefaultDir (& my rootDirectory);
			}
			try {
				Interpreter_run (interpreter, text);
			} catch (MelderError) {
				Melder_clearError ();
			}
		}
		Graphics_setLineType (my ps, Graphics_DRAWN);
		Graphics_setLineWidth (my ps, 1.0);
		Graphics_setArrowSize (my ps, 1.0);
		Graphics_setColour (my ps, Graphics_BLACK);
		theCurrentPraatApplication = & theForegroundPraatApplication;
		theCurrentPraatObjects = & theForegroundPraatObjects;
		theCurrentPraatPicture = & theForegroundPraatPicture;
	}
	Graphics_resetWsViewport (my ps, x1DCold, x2DCold, y1DCold, y2DCold);
	Graphics_setWsWindow (my ps, x1NDCold, x2NDCold, y1NDCold, y2NDCold);
	Graphics_setViewport (my ps, 0, 1, 0, 1);
	Graphics_setWindow (my ps, 0, 1, 0, 1);
	Graphics_setTextAlignment (my ps, Graphics_LEFT, Graphics_BOTTOM);
}
	my previousBottomSpacing = bottomSpacing;
	forget (interpreter);
	Melder_free (text);
	return 1;
}
コード例 #12
0
ファイル: TextGrid_Sound.cpp プロジェクト: dellison/APILPraat
void TextGrid_Sound_draw (TextGrid me, Sound sound, Graphics g, double tmin, double tmax,
	int showBoundaries, int useTextStyles, int garnish)   // STEREO BUG
{
	long numberOfTiers = my tiers -> size;

	/*
	 * Automatic windowing:
	 */
	if (tmax <= tmin) tmin = my xmin, tmax = my xmax;

	Graphics_setInner (g);
	Graphics_setWindow (g, tmin, tmax, -1.0 - 0.5 * numberOfTiers, 1.0);

	/*
	 * Draw sound in upper part.
	 */
	long first, last;
	if (sound && Sampled_getWindowSamples (sound, tmin, tmax, & first, & last) > 1) {
		Graphics_setLineType (g, Graphics_DOTTED);
		Graphics_line (g, tmin, 0.0, tmax, 0.0);
		Graphics_setLineType (g, Graphics_DRAWN);      
		Graphics_function (g, sound -> z [1], first, last,
			Sampled_indexToX (sound, first), Sampled_indexToX (sound, last));
	}

	/*
	 * Draw labels in lower part.
	 */
	Graphics_setTextAlignment (g, Graphics_CENTRE, Graphics_HALF);
	Graphics_setPercentSignIsItalic (g, useTextStyles);
	Graphics_setNumberSignIsBold (g, useTextStyles);
	Graphics_setCircumflexIsSuperscript (g, useTextStyles);
	Graphics_setUnderscoreIsSubscript (g, useTextStyles);
	for (long itier = 1; itier <= numberOfTiers; itier ++) {
		Function anyTier = (Function) my tiers -> item [itier];
		double ymin = -1.0 - 0.5 * itier, ymax = ymin + 0.5;
		Graphics_rectangle (g, tmin, tmax, ymin, ymax);
		if (anyTier -> classInfo == classIntervalTier) {
			IntervalTier tier = (IntervalTier) anyTier;
			long ninterval = tier -> intervals -> size;
			for (long iinterval = 1; iinterval <= ninterval; iinterval ++) {
				TextInterval interval = (TextInterval) tier -> intervals -> item [iinterval];
				double intmin = interval -> xmin, intmax = interval -> xmax;
				if (intmin < tmin) intmin = tmin;
				if (intmax > tmax) intmax = tmax;
				if (intmin >= intmax) continue;
				if (showBoundaries && intmin > tmin && intmin < tmax) {
					Graphics_setLineType (g, Graphics_DOTTED);
					Graphics_line (g, intmin, -1.0, intmin, 1.0);   /* In sound part. */
					Graphics_setLineType (g, Graphics_DRAWN);
				}      
				/* Draw left boundary. */
				if (intmin > tmin && intmin < tmax) Graphics_line (g, intmin, ymin, intmin, ymax);
				/* Draw label text. */
				if (interval -> text && intmax >= tmin && intmin <= tmax) {
					double t1 = tmin > intmin ? tmin : intmin;
					double t2 = tmax < intmax ? tmax : intmax;
					Graphics_text (g, 0.5 * (t1 + t2), 0.5 * (ymin + ymax), interval -> text);
				}
			}
		} else {
			TextTier tier = (TextTier) anyTier;
			long numberOfPoints = tier -> points -> size;
			for (long ipoint = 1; ipoint <= numberOfPoints; ipoint ++) {
				TextPoint point = (TextPoint) tier -> points -> item [ipoint];
				double t = point -> number;
				if (t > tmin && t < tmax) {
					if (showBoundaries) {
						Graphics_setLineType (g, Graphics_DOTTED);
						Graphics_line (g, t, -1.0, t, 1.0);   /* In sound part. */
						Graphics_setLineType (g, Graphics_DRAWN);
					}
					Graphics_line (g, t, ymin, t, 0.8 * ymin + 0.2 * ymax);
					Graphics_line (g, t, 0.2 * ymin + 0.8 * ymax, t, ymax);
					if (point -> mark)
						Graphics_text (g, t, 0.5 * (ymin + ymax), point -> mark);
				}
			}
		}
	}
	Graphics_setPercentSignIsItalic (g, TRUE);
	Graphics_setNumberSignIsBold (g, TRUE);
	Graphics_setCircumflexIsSuperscript (g, TRUE);
	Graphics_setUnderscoreIsSubscript (g, TRUE);
	Graphics_unsetInner (g);
	if (garnish) {
		Graphics_drawInnerBox (g);
		Graphics_textBottom (g, 1, L"Time (s)");
		Graphics_marksBottom (g, 2, 1, 1, 1);
	}
}
コード例 #13
0
Sound Artword_Speaker_to_Sound (Artword artword, Speaker speaker,
	double fsamp, int oversampling,
	Sound *out_w1, int iw1, Sound *out_w2, int iw2, Sound *out_w3, int iw3,
	Sound *out_p1, int ip1, Sound *out_p2, int ip2, Sound *out_p3, int ip3,
	Sound *out_v1, int iv1, Sound *out_v2, int iv2, Sound *out_v3, int iv3)
{
	try {
		autoSound result = Sound_createSimple (1, artword -> totalTime, fsamp);
		long numberOfSamples = result -> nx;
		double minTract [1+78], maxTract [1+78];   /* For drawing. */
		double Dt = 1 / fsamp / oversampling,
			rho0 = 1.14,
			c = 353,
			onebyc2 = 1.0 / (c * c),
			rho0c2 = rho0 * c * c,
			halfDt = 0.5 * Dt,
			twoDt = 2 * Dt,
			halfc2Dt = 0.5 * c * c * Dt,
			twoc2Dt = 2 * c * c * Dt,
			onebytworho0 = 1.0 / (2.0 * rho0),
			Dtbytworho0 = Dt / (2.0 * rho0);
		double tension, rrad, onebygrad, totalVolume;
		autoArt art = Art_create ();
		long sample;
		int n, m, M;
		autoDelta delta = Speaker_to_Delta (speaker);
		autoMelderMonitor monitor (U"Articulatory synthesis");
		Artword_intoArt (artword, art.peek(), 0.0);
		Art_Speaker_intoDelta (art.peek(), speaker, delta.peek());
		M = delta -> numberOfTubes;
		autoSound w1, w2, w3, p1, p2, p3, v1, v2, v3;
		if (iw1 > 0 && iw1 <= M) w1.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else iw1 = 0;
		if (iw2 > 0 && iw2 <= M) w2.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else iw2 = 0;
		if (iw3 > 0 && iw3 <= M) w3.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else iw3 = 0;
		if (ip1 > 0 && ip1 <= M) p1.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else ip1 = 0;
		if (ip2 > 0 && ip2 <= M) p2.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else ip2 = 0;
		if (ip3 > 0 && ip3 <= M) p3.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else ip3 = 0;
		if (iv1 > 0 && iv1 <= M) v1.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else iv1 = 0;
		if (iv2 > 0 && iv2 <= M) v2.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else iv2 = 0;
		if (iv3 > 0 && iv3 <= M) v3.reset (Sound_createSimple (1, artword -> totalTime, fsamp)); else iv3 = 0;
		/* Initialize drawing. */
		{ int i; for (i = 1; i <= 78; i ++) { minTract [i] = 100; maxTract [i] = -100; } }
		totalVolume = 0.0;
		for (m = 1; m <= M; m ++) {
			Delta_Tube t = delta->tube + m;
			if (! t -> left1 && ! t -> right1) continue;
			t->Dx = t->Dxeq; t->dDxdt = 0;   /* 5.113 */
			t->Dy = t->Dyeq; t->dDydt = 0;   /* 5.113 */
			t->Dz = t->Dzeq;   /* 5.113 */
			t->A = t->Dz * ( t->Dy >= t->dy ? t->Dy + Dymin :
				t->Dy <= - t->dy ? Dymin :
				(t->dy + t->Dy) * (t->dy + t->Dy) / (4 * t->dy) + Dymin );   /* 4.4, 4.5 */
			#if EQUAL_TUBE_WIDTHS
				t->A = 0.0001;
			#endif
			t->Jleft = t->Jright = 0;   /* 5.113 */
			t->Qleft = t->Qright = rho0c2;   /* 5.113 */
			t->pleft = t->pright = 0;   /* 5.114 */
			t->Kleft = t->Kright = 0;   /* 5.114 */
			t->V = t->A * t->Dx;   /* 5.114 */
			totalVolume += t->V;
		}
		//Melder_casual (U"Starting volume: ", totalVolume * 1000, U" litres.");
		for (sample = 1; sample <= numberOfSamples; sample ++) {
			double time = (sample - 1) / fsamp;
			Artword_intoArt (artword, art.peek(), time);
			Art_Speaker_intoDelta (art.peek(), speaker, delta.peek());
			if (sample % MONITOR_SAMPLES == 0 && monitor.graphics()) {   // because we can be in batch
				Graphics graphics = monitor.graphics();
				double area [1+78];
				Graphics_Viewport vp;
				for (int i = 1; i <= 78; i ++) {
					area [i] = delta -> tube [i]. A;
					if (area [i] < minTract [i]) minTract [i] = area [i];
					if (area [i] > maxTract [i]) maxTract [i] = area [i];
				}
				Graphics_clearWs (graphics);

				vp = Graphics_insetViewport (monitor.graphics(), 0, 0.5, 0.5, 1);
				Graphics_setWindow (graphics, 0, 1, 0, 0.05);
				Graphics_setColour (graphics, Graphics_RED);
				Graphics_function (graphics, minTract, 1, 35, 0, 0.9);
				Graphics_function (graphics, maxTract, 1, 35, 0, 0.9);
				Graphics_setColour (graphics, Graphics_BLACK);
				Graphics_function (graphics, area, 1, 35, 0, 0.9);
				Graphics_setLineType (graphics, Graphics_DOTTED);
				Graphics_line (graphics, 0, 0, 1, 0);
				Graphics_setLineType (graphics, Graphics_DRAWN);
				Graphics_resetViewport (graphics, vp);

				vp = Graphics_insetViewport (graphics, 0, 0.5, 0, 0.5);
				Graphics_setWindow (graphics, 0, 1, -0.000003, 0.00001);
				Graphics_setColour (graphics, Graphics_RED);
				Graphics_function (graphics, minTract, 36, 37, 0.2, 0.8);
				Graphics_function (graphics, maxTract, 36, 37, 0.2, 0.8);
				Graphics_setColour (graphics, Graphics_BLACK);
				Graphics_function (graphics, area, 36, 37, 0.2, 0.8);
				Graphics_setLineType (graphics, Graphics_DOTTED);
				Graphics_line (graphics, 0, 0, 1, 0);
				Graphics_setLineType (graphics, Graphics_DRAWN);
				Graphics_resetViewport (graphics, vp);

				vp = Graphics_insetViewport (graphics, 0.5, 1, 0.5, 1);
				Graphics_setWindow (graphics, 0, 1, 0, 0.001);
				Graphics_setColour (graphics, Graphics_RED);
				Graphics_function (graphics, minTract, 38, 64, 0, 1);
				Graphics_function (graphics, maxTract, 38, 64, 0, 1);
				Graphics_setColour (graphics, Graphics_BLACK);
				Graphics_function (graphics, area, 38, 64, 0, 1);
				Graphics_setLineType (graphics, Graphics_DOTTED);
				Graphics_line (graphics, 0, 0, 1, 0);
				Graphics_setLineType (graphics, Graphics_DRAWN);
				Graphics_resetViewport (graphics, vp);

				vp = Graphics_insetViewport (graphics, 0.5, 1, 0, 0.5);
				Graphics_setWindow (graphics, 0, 1, 0.001, 0);
				Graphics_setColour (graphics, Graphics_RED);
				Graphics_function (graphics, minTract, 65, 78, 0.5, 1);
				Graphics_function (graphics, maxTract, 65, 78, 0.5, 1);
				Graphics_setColour (graphics, Graphics_BLACK);
				Graphics_function (graphics, area, 65, 78, 0.5, 1);
				Graphics_setLineType (graphics, Graphics_DRAWN);
				Graphics_resetViewport (graphics, vp);
				Melder_monitor ((double) sample / numberOfSamples, U"Articulatory synthesis: ", Melder_half (time), U" seconds");
			}
			for (n = 1; n <= oversampling; n ++) {
				for (m = 1; m <= M; m ++) {
					Delta_Tube t = delta -> tube + m;
					if (! t -> left1 && ! t -> right1) continue;

					/* New geometry. */

					#if CONSTANT_TUBE_LENGTHS
						t->Dxnew = t->Dx;
					#else
						t->dDxdtnew = (t->dDxdt + Dt * 10000 * (t->Dxeq - t->Dx)) /
							(1 + 200 * Dt);   /* Critical damping, 10 ms. */
						t->Dxnew = t->Dx + t->dDxdtnew * Dt;
					#endif
					/* 3-way: equal lengths. */
					/* This requires left tubes to be processed before right tubes. */
					if (t->left1 && t->left1->right2) t->Dxnew = t->left1->Dxnew;
					t->Dz = t->Dzeq;   /* immediate... */
					t->eleft = (t->Qleft - t->Kleft) * t->V;   /* 5.115 */
					t->eright = (t->Qright - t->Kright) * t->V;   /* 5.115 */
					t->e = 0.5 * (t->eleft + t->eright);   /* 5.116 */
					t->p = 0.5 * (t->pleft + t->pright);   /* 5.116 */
					t->DeltaP = t->e / t->V - rho0c2;   /* 5.117 */
					t->v = t->p / (rho0 + onebyc2 * t->DeltaP);   /* 5.118 */
					{
						double dDy = t->Dyeq - t->Dy;
						double cubic = t->k3 * dDy * dDy;
						Delta_Tube l1 = t->left1, l2 = t->left2, r1 = t->right1, r2 = t->right2;
						tension = dDy * (t->k1 + cubic);
						t->B = 2 * t->Brel * sqrt (t->mass * (t->k1 + 3 * cubic));
						if (t->k1left1 != 0.0 && l1)
							tension += t->k1left1 * t->k1 * (dDy - (l1->Dyeq - l1->Dy));
						if (t->k1left2 != 0.0 && l2)
							tension += t->k1left2 * t->k1 * (dDy - (l2->Dyeq - l2->Dy));
						if (t->k1right1 != 0.0 && r1)
							tension += t->k1right1 * t->k1 * (dDy - (r1->Dyeq - r1->Dy));
						if (t->k1right2 != 0.0 && r2)
							tension += t->k1right2 * t->k1 * (dDy - (r2->Dyeq - r2->Dy));
					}
					if (t->Dy < t->dy) {
						if (t->Dy >= - t->dy) {
							double dDy = t->dy - t->Dy, dDy2 = dDy * dDy;
							tension += dDy2 / (4 * t->dy) * (t->s1 + 0.5 * t->s3 * dDy2);
							t->B += 2 * dDy / (2 * t->dy) *
								sqrt (t->mass * (t->s1 + t->s3 * dDy2));
						} else {
							tension -= t->Dy * (t->s1 + t->s3 * (t->Dy * t->Dy + t->dy * t->dy));
							t->B += 2 * sqrt (t->mass * (t->s1 + t->s3 * (3 * t->Dy * t->Dy + t->dy * t->dy)));
						}
					}
					t->dDydtnew = (t->dDydt + Dt / t->mass * (tension + 2 * t->DeltaP * t->Dz * t->Dx)) /
						(1 + t->B * Dt / t->mass);   /* 5.119 */
					t->Dynew = t->Dy + t->dDydtnew * Dt;   /* 5.119 */
					#if NO_MOVING_WALLS
						t->Dynew = t->Dy;
					#endif
					t->Anew = t->Dz * ( t->Dynew >= t->dy ? t->Dynew + Dymin :
						t->Dynew <= - t->dy ? Dymin :
						(t->dy + t->Dynew) * (t->dy + t->Dynew) / (4 * t->dy) + Dymin );   /* 4.4, 4.5 */
					#if EQUAL_TUBE_WIDTHS
						t->Anew = 0.0001;
					#endif
					t->Ahalf = 0.5 * (t->A + t->Anew);   /* 5.120 */
					t->Dxhalf = 0.5 * (t->Dxnew + t->Dx);   /* 5.121 */
					t->Vnew = t->Anew * t->Dxnew;   /* 5.128 */
					{ double oneByDyav = t->Dz / t->A;
					/*t->R = 12 * 1.86e-5 * t->parallel * t->parallel * oneByDyav * oneByDyav;*/
					if (t->Dy < 0)
						t->R = 12 * 1.86e-5 / (Dymin * Dymin + t->dy * t->dy);
					else
						t->R = 12 * 1.86e-5 * t->parallel * t->parallel /
							((t->Dy + Dymin) * (t->Dy + Dymin) + t->dy * t->dy);
					t->R += 0.3 * t->parallel * oneByDyav;   /* 5.23 */ }
					t->r = (1 + t->R * Dt / rho0) * t->Dxhalf / t->Anew;   /* 5.122 */
					t->ehalf = t->e + halfc2Dt * (t->Jleft - t->Jright);   /* 5.123 */
					t->phalf = (t->p + halfDt * (t->Qleft - t->Qright) / t->Dx) / (1 + Dtbytworho0 * t->R);   /* 5.123 */
					#if MASS_LEAPFROG
						t->ehalf = t->ehalfold + 2 * halfc2Dt * (t->Jleft - t->Jright);
					#endif
					t->Jhalf = t->phalf * t->Ahalf;   /* 5.124 */
					t->Qhalf = t->ehalf / (t->Ahalf * t->Dxhalf) + onebytworho0 * t->phalf * t->phalf;   /* 5.124 */
					#if NO_BERNOULLI_EFFECT
						t->Qhalf = t->ehalf / (t->Ahalf * t->Dxhalf);
					#endif
				}
				for (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 l1 = l, l2 = r ? r -> left2 : NULL;
					if (l->left1 == NULL) {   /* Closed boundary at the left side (diaphragm)? */
						if (r == NULL) continue;   /* Tube not connected at all. */
						l->Jleftnew = 0;   /* 5.132. */
						l->Qleftnew = (l->eleft - twoc2Dt * l->Jhalf) / l->Vnew;   /* 5.132. */
					}
					else   /* Left boundary open to another tube will be handled... */
						(void) 0;   /* ...together with the right boundary of the tube to the left. */
					if (r == NULL) {   /* Open boundary at the right side (lips, nostrils)? */
						rrad = 1 - c * Dt / 0.02;   /* Radiation resistance, 5.135. */
						onebygrad = 1 / (1 + c * Dt / 0.02);   /* Radiation conductance, 5.135. */
						#if NO_RADIATION_DAMPING
							rrad = 0;
							onebygrad = 0;
						#endif
						l->prightnew = ((l->Dxhalf / Dt + c * onebygrad) * l->pright +
							 2 * ((l->Qhalf - rho0c2) - (l->Qright - rho0c2) * onebygrad)) /
							(l->r * l->Anew / Dt + c * onebygrad);   /* 5.136 */
						l->Jrightnew = l->prightnew * l->Anew;   /* 5.136 */
						l->Qrightnew = (rrad * (l->Qright - rho0c2) +
							c * (l->prightnew - l->pright)) * onebygrad + rho0c2;   /* 5.136 */
					} else if (l2 == NULL && r2 == NULL) {   /* Two-way boundary. */
						if (l->v > criticalVelocity && l->A < r->A) {
							l->Pturbrightnew = -0.5 * rho0 * (l->v - criticalVelocity) *
								(1 - l->A / r->A) * (1 - l->A / r->A) * l->v;
							if (l->Pturbrightnew != 0.0)
								l->Pturbrightnew *= 1 + NUMrandomGauss (0, noiseFactor) /* * l->A */;
						}
						if (r->v < - criticalVelocity && r->A < l->A) {
							l->Pturbrightnew = 0.5 * rho0 * (r->v + criticalVelocity) *
								(1 - r->A / l->A) * (1 - r->A / l->A) * r->v;
							if (l->Pturbrightnew != 0.0)
								l->Pturbrightnew *= 1 + NUMrandomGauss (0, noiseFactor) /* * r->A */;
						}
						#if NO_TURBULENCE
							l->Pturbrightnew = 0;
						#endif
						l->Jrightnew = r->Jleftnew =
							(l->Dxhalf * l->pright + r->Dxhalf * r->pleft +
							 twoDt * (l->Qhalf - r->Qhalf + l->Pturbright)) /
							(l->r + r->r);   /* 5.127 */
						#if B91
							l->Jrightnew = r->Jleftnew =
								(l->pright + r->pleft +
								 2 * twoDt * (l->Qhalf - r->Qhalf + l->Pturbright) / (l->Dxhalf + r->Dxhalf)) /
								(l->r / l->Dxhalf + r->r / r->Dxhalf);
						#endif
						l->prightnew = l->Jrightnew / l->Anew;   /* 5.128 */
						r->pleftnew = r->Jleftnew / r->Anew;   /* 5.128 */
						l->Krightnew = onebytworho0 * l->prightnew * l->prightnew;   /* 5.128 */
						r->Kleftnew = onebytworho0 * r->pleftnew * r->pleftnew;   /* 5.128 */
						#if NO_BERNOULLI_EFFECT
							l->Krightnew = r->Kleftnew = 0;
						#endif
						l->Qrightnew =
							(l->eright + r->eleft + twoc2Dt * (l->Jhalf - r->Jhalf)
							 + l->Krightnew * l->Vnew + (r->Kleftnew - l->Pturbrightnew) * r->Vnew) /
							(l->Vnew + r->Vnew);   /* 5.131 */
						r->Qleftnew = l->Qrightnew + l->Pturbrightnew;   /* 5.131 */
					} else if (r2) {   /* Two adjacent tubes at the right side (velic). */
						r1->Jleftnew =
							(r1->Jleft * r1->Dxhalf * (1 / (l->A + r2->A) + 1 / r1->A) +
							 twoDt * ((l->Ahalf * l->Qhalf + r2->Ahalf * r2->Qhalf ) / (l->Ahalf  + r2->Ahalf) - r1->Qhalf)) /
							(1 / (1 / l->r + 1 / r2->r) + r1->r);   /* 5.138 */
						r2->Jleftnew =
							(r2->Jleft * r2->Dxhalf * (1 / (l->A + r1->A) + 1 / r2->A) +
							 twoDt * ((l->Ahalf * l->Qhalf + r1->Ahalf * r1->Qhalf ) / (l->Ahalf  + r1->Ahalf) - r2->Qhalf)) /
							(1 / (1 / l->r + 1 / r1->r) + r2->r);   /* 5.138 */
						l->Jrightnew = r1->Jleftnew + r2->Jleftnew;   /* 5.139 */
						l->prightnew = l->Jrightnew / l->Anew;   /* 5.128 */
						r1->pleftnew = r1->Jleftnew / r1->Anew;   /* 5.128 */
						r2->pleftnew = r2->Jleftnew / r2->Anew;   /* 5.128 */
						l->Krightnew = onebytworho0 * l->prightnew * l->prightnew;   /* 5.128 */
						r1->Kleftnew = onebytworho0 * r1->pleftnew * r1->pleftnew;   /* 5.128 */
						r2->Kleftnew = onebytworho0 * r2->pleftnew * r2->pleftnew;   /* 5.128 */
						#if NO_BERNOULLI_EFFECT
							l->Krightnew = r1->Kleftnew = r2->Kleftnew = 0;
						#endif
						l->Qrightnew = r1->Qleftnew = r2->Qleftnew =
							(l->eright + r1->eleft + r2->eleft + twoc2Dt * (l->Jhalf - r1->Jhalf - r2->Jhalf) +
							 l->Krightnew * l->Vnew + r1->Kleftnew * r1->Vnew + r2->Kleftnew * r2->Vnew) /
							(l->Vnew + r1->Vnew + r2->Vnew);   /* 5.137 */
					} else {
						Melder_assert (l2 != NULL);
						l1->Jrightnew =
							(l1->Jright * l1->Dxhalf * (1 / (r->A + l2->A) + 1 / l1->A) -
							 twoDt * ((r->Ahalf * r->Qhalf + l2->Ahalf * l2->Qhalf ) / (r->Ahalf  + l2->Ahalf) - l1->Qhalf)) /
							(1 / (1 / r->r + 1 / l2->r) + l1->r);   /* 5.138 */
						l2->Jrightnew =
							(l2->Jright * l2->Dxhalf * (1 / (r->A + l1->A) + 1 / l2->A) -
							 twoDt * ((r->Ahalf * r->Qhalf + l1->Ahalf  * l1->Qhalf ) / (r->Ahalf  + l1->Ahalf) - l2->Qhalf)) /
							(1 / (1 / r->r + 1 / l1->r) + l2->r);   /* 5.138 */
						r->Jleftnew = l1->Jrightnew + l2->Jrightnew;   /* 5.139 */
						r->pleftnew = r->Jleftnew / r->Anew;   /* 5.128 */
						l1->prightnew = l1->Jrightnew / l1->Anew;   /* 5.128 */
						l2->prightnew = l2->Jrightnew / l2->Anew;   /* 5.128 */
						r->Kleftnew = onebytworho0 * r->pleftnew * r->pleftnew;   /* 5.128 */
						l1->Krightnew = onebytworho0 * l1->prightnew * l1->prightnew;   /* 5.128 */
						l2->Krightnew = onebytworho0 * l2->prightnew * l2->prightnew;   /* 5.128 */
						#if NO_BERNOULLI_EFFECT
							r->Kleftnew = l1->Krightnew = l2->Krightnew = 0;
						#endif
						r->Qleftnew = l1->Qrightnew = l2->Qrightnew =
							(r->eleft + l1->eright + l2->eright + twoc2Dt * (l1->Jhalf + l2->Jhalf - r->Jhalf) +
							 r->Kleftnew * r->Vnew + l1->Krightnew * l1->Vnew + l2->Krightnew * l2->Vnew) /
							(r->Vnew + l1->Vnew + l2->Vnew);   /* 5.137 */
					}
				}

				/* Save some results. */

				if (n == (oversampling + 1) / 2) {
					double out = 0.0;
					for (m = 1; m <= M; m ++) {
						Delta_Tube t = delta->tube + m;
						out += rho0 * t->Dx * t->Dz * t->dDydt * Dt * 1000;   /* Radiation of wall movement, 5.140. */
						if (t->right1 == NULL)
							out += t->Jrightnew - t->Jright;   /* Radiation of open tube end. */
					}
					result -> z [1] [sample] = out /= 4 * 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;
				}
				for (m = 1; m <= M; m ++) {
					Delta_Tube t = delta->tube + m;
					t->Jleft = t->Jleftnew;
					t->Jright = t->Jrightnew;
					t->Qleft = t->Qleftnew;
					t->Qright = t->Qrightnew;
					t->Dy = t->Dynew;
					t->dDydt = t->dDydtnew;
					t->A = t->Anew;
					t->Dx = t->Dxnew;
					t->dDxdt = t->dDxdtnew;
					t->eleft = t->eleftnew;
					t->eright = t->erightnew;
					#if MASS_LEAPFROG
						t->ehalfold = t->ehalf;
					#endif
					t->pleft = t->pleftnew;
					t->pright = t->prightnew;
					t->Kleft = t->Kleftnew;
					t->Kright = t->Krightnew;
					t->V = t->Vnew;
					t->Pturbright = t->Pturbrightnew;
				}
			}
		}
		totalVolume = 0.0;
		for (m = 1; m <= M; m ++)
			totalVolume += delta->tube [m]. V;
		//Melder_casual (U"Ending volume: ", totalVolume * 1000, U" litres.");
		if (out_w1) *out_w1 = w1.transfer();
		if (out_w2) *out_w2 = w2.transfer();
		if (out_w3) *out_w3 = w3.transfer();
		if (out_p1) *out_p1 = p1.transfer();
		if (out_p2) *out_p2 = p2.transfer();
		if (out_p3) *out_p3 = p3.transfer();
		if (out_v1) *out_v1 = v1.transfer();
		if (out_v2) *out_v2 = v2.transfer();
		if (out_v3) *out_v3 = v3.transfer();
		return result.transfer();
	} catch (MelderError) {
		Melder_throw (artword, U" & ", speaker, U": articulatory synthesis not performed.");
	}
}