AmplitudeTier.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /* AmplitudeTier.cpp
  2. *
  3. * Copyright (C) 2003-2011,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. #include "AmplitudeTier.h"
  19. Thing_implement (AmplitudeTier, RealTier, 0);
  20. autoAmplitudeTier AmplitudeTier_create (double tmin, double tmax) {
  21. try {
  22. autoAmplitudeTier me = Thing_new (AmplitudeTier);
  23. RealTier_init (me.get(), tmin, tmax);
  24. return me;
  25. } catch (MelderError) {
  26. Melder_throw (U"AmplitudeTier not created.");
  27. }
  28. }
  29. void AmplitudeTier_draw (AmplitudeTier me, Graphics g, double tmin, double tmax,
  30. double ymin, double ymax, conststring32 method, bool garnish)
  31. {
  32. RealTier_draw (me, g, tmin, tmax, ymin, ymax, garnish, method, U"Sound pressure (Pa)");
  33. }
  34. autoAmplitudeTier PointProcess_upto_AmplitudeTier (PointProcess me, double soundPressure) {
  35. try {
  36. autoAmplitudeTier thee = PointProcess_upto_RealTier (me, soundPressure, classAmplitudeTier).static_cast_move<structAmplitudeTier>();
  37. return thee;
  38. } catch (MelderError) {
  39. Melder_throw (me, U": not converted to AmplitudeTier.");
  40. }
  41. }
  42. autoAmplitudeTier IntensityTier_to_AmplitudeTier (IntensityTier me) {
  43. try {
  44. autoAmplitudeTier thee = Thing_new (AmplitudeTier);
  45. my structRealTier :: v_copy (thee.get());
  46. for (integer i = 1; i <= thy points.size; i ++) {
  47. RealPoint point = thy points.at [i];
  48. point -> value = pow (10.0, point -> value / 20.0) * 2.0e-5;
  49. }
  50. return thee;
  51. } catch (MelderError) {
  52. Melder_throw (me, U": not converted to AmplitudeTier.");
  53. }
  54. }
  55. autoIntensityTier AmplitudeTier_to_IntensityTier (AmplitudeTier me, double threshold_dB) {
  56. try {
  57. double threshold_Pa = pow (10.0, threshold_dB / 20.0) * 2.0e-5; // often zero!
  58. autoIntensityTier thee = Thing_new (IntensityTier);
  59. my structRealTier :: v_copy (thee.get());
  60. for (integer i = 1; i <= thy points.size; i ++) {
  61. RealPoint point = thy points.at [i];
  62. double absoluteValue = fabs (point -> value);
  63. point -> value = absoluteValue <= threshold_Pa ? threshold_dB : 20.0 * log10 (absoluteValue / 2.0e-5);
  64. }
  65. return thee;
  66. } catch (MelderError) {
  67. Melder_throw (me, U": not converted to IntensityTier.");
  68. }
  69. }
  70. autoTableOfReal AmplitudeTier_downto_TableOfReal (AmplitudeTier me) {
  71. return RealTier_downto_TableOfReal (me, U"Time (s)", U"Sound pressure (Pa)");
  72. }
  73. void Sound_AmplitudeTier_multiply_inplace (Sound me, AmplitudeTier amplitude) {
  74. if (amplitude -> points.size == 0) return;
  75. for (integer isamp = 1; isamp <= my nx; isamp ++) {
  76. double t = my x1 + (isamp - 1) * my dx;
  77. double factor = RealTier_getValueAtTime (amplitude, t);
  78. for (integer channel = 1; channel <= my ny; channel ++) {
  79. my z [channel] [isamp] *= factor;
  80. }
  81. }
  82. }
  83. autoSound Sound_AmplitudeTier_multiply (Sound me, AmplitudeTier amplitude) {
  84. try {
  85. autoSound thee = Data_copy (me);
  86. Sound_AmplitudeTier_multiply_inplace (thee.get(), amplitude);
  87. Vector_scale (thee.get(), 0.9);
  88. return thee;
  89. } catch (MelderError) {
  90. Melder_throw (me, U": not multiplied by ", amplitude, U".");
  91. }
  92. }
  93. autoAmplitudeTier PointProcess_Sound_to_AmplitudeTier_point (PointProcess me, Sound you) {
  94. try {
  95. integer imin, imax, numberOfPeaks = PointProcess_getWindowPoints (me, my xmin, my xmax, & imin, & imax);
  96. if (numberOfPeaks < 3) return autoAmplitudeTier();
  97. autoAmplitudeTier him = AmplitudeTier_create (my xmin, my xmax);
  98. for (integer i = imin; i <= imax; i ++) {
  99. double value = Vector_getValueAtX (you, my t [i], Vector_CHANNEL_AVERAGE, Vector_VALUE_INTERPOLATION_SINC700);
  100. if (isdefined (value)) RealTier_addPoint (him.get(), my t [i], value);
  101. }
  102. return him;
  103. } catch (MelderError) {
  104. Melder_throw (me, U" & ", you, U": not converted to AmplitudeTier.");
  105. }
  106. }
  107. /*
  108. static double Sound_getPeak (Sound me, double tmin, double tmax, integer channel) {
  109. double *y = my z [channel];
  110. integer imin, imax;
  111. if (Sampled_getWindowSamples (me, tmin, tmax, & imin, & imax) < 3) return undefined;
  112. double minimum = y [imin];
  113. double maximum = y [imin];
  114. integer sampleOfMinimum = imin;
  115. integer sampleOfMaximum = imin;
  116. for (integer i = imin + 1; i <= imax; i ++) {
  117. if (y [i] < minimum) { minimum = y [i]; sampleOfMinimum = i; }
  118. if (y [i] > maximum) { maximum = y [i]; sampleOfMaximum = i; }
  119. }
  120. double timeOfMinimum = my x1 + (sampleOfMinimum - 1) * my dx;
  121. double timeOfMaximum = my x1 + (sampleOfMaximum - 1) * my dx;
  122. Vector_getMinimumAndX (me, timeOfMinimum - my dx, timeOfMinimum + my dx, NUM_PEAK_INTERPOLATE_SINC70, & minimum, & timeOfMinimum);
  123. Vector_getMaximumAndX (me, timeOfMaximum - my dx, timeOfMaximum + my dx, NUM_PEAK_INTERPOLATE_SINC70, & maximum, & timeOfMaximum);
  124. return maximum - minimum;
  125. }
  126. */
  127. static double Sound_getHannWindowedRms (Sound me, double tmid, double widthLeft, double widthRight) {
  128. integer imin, imax;
  129. if (Sampled_getWindowSamples (me, tmid - widthLeft, tmid + widthRight, & imin, & imax) < 3) return undefined;
  130. longdouble sumOfSquares = 0.0, windowSumOfSquares = 0.0;
  131. for (integer i = imin; i <= imax; i ++) {
  132. double t = my x1 + (i - 1) * my dx;
  133. double width = t < tmid ? widthLeft : widthRight;
  134. double windowPhase = (t - tmid) / width; /* in [-1 .. 1] */
  135. double window = 0.5 + 0.5 * cos (NUMpi * windowPhase); /* Hann */
  136. double windowedValue = ( my ny == 1 ? my z [1] [i] : 0.5 * (my z [1] [i] + my z [2] [i]) ) * window;
  137. sumOfSquares += windowedValue * windowedValue;
  138. windowSumOfSquares += window * window;
  139. }
  140. return sqrt (double (sumOfSquares / windowSumOfSquares));
  141. }
  142. autoAmplitudeTier PointProcess_Sound_to_AmplitudeTier_period (PointProcess me, Sound you, double tmin, double tmax,
  143. double pmin, double pmax, double maximumPeriodFactor)
  144. {
  145. try {
  146. if (tmax <= tmin) tmin = my xmin, tmax = my xmax;
  147. integer imin, imax;
  148. integer numberOfPeaks = PointProcess_getWindowPoints (me, tmin, tmax, & imin, & imax);
  149. if (numberOfPeaks < 3) Melder_throw (U"Too few pulses between ", tmin, U" and ", tmax, U" seconds.");
  150. autoAmplitudeTier him = AmplitudeTier_create (tmin, tmax);
  151. for (integer i = imin + 1; i < imax; i ++) {
  152. double p1 = my t [i] - my t [i - 1], p2 = my t [i + 1] - my t [i];
  153. double intervalFactor = p1 > p2 ? p1 / p2 : p2 / p1;
  154. if (pmin == pmax || (p1 >= pmin && p1 <= pmax && p2 >= pmin && p2 <= pmax && intervalFactor <= maximumPeriodFactor)) {
  155. double peak = Sound_getHannWindowedRms (you, my t [i], 0.2 * p1, 0.2 * p2);
  156. if (isdefined (peak) && peak > 0.0)
  157. RealTier_addPoint (him.get(), my t [i], peak);
  158. }
  159. }
  160. return him;
  161. } catch (MelderError) {
  162. Melder_throw (me, U" & ", you, U": not converted to AmplitudeTier.");
  163. }
  164. }
  165. double AmplitudeTier_getShimmer_local (AmplitudeTier me, double pmin, double pmax, double maximumAmplitudeFactor) {
  166. integer numberOfPeaks = 0;
  167. longdouble numerator = 0.0, denominator = 0.0;
  168. RealPoint *points = & my points.at [0];
  169. for (integer i = 2; i <= my points.size; i ++) {
  170. double p = points [i] -> number - points [i - 1] -> number;
  171. if (pmin == pmax || (p >= pmin && p <= pmax)) {
  172. double a1 = points [i - 1] -> value, a2 = points [i] -> value;
  173. double amplitudeFactor = a1 > a2 ? a1 / a2 : a2 / a1;
  174. if (amplitudeFactor <= maximumAmplitudeFactor) {
  175. numerator += fabs (a1 - a2);
  176. numberOfPeaks ++;
  177. }
  178. }
  179. }
  180. if (numberOfPeaks < 1) return undefined;
  181. numerator /= numberOfPeaks;
  182. numberOfPeaks = 0;
  183. for (integer i = 1; i < my points.size; i ++) {
  184. denominator += points [i] -> value;
  185. numberOfPeaks ++;
  186. }
  187. denominator /= numberOfPeaks;
  188. if (denominator == 0.0) return undefined;
  189. return double (numerator / denominator);
  190. }
  191. double AmplitudeTier_getShimmer_local_dB (AmplitudeTier me, double pmin, double pmax, double maximumAmplitudeFactor) {
  192. integer numberOfPeaks = 0;
  193. longdouble result = 0.0;
  194. RealPoint *points = & my points.at [0];
  195. for (integer i = 2; i <= my points.size; i ++) {
  196. double p = points [i] -> number - points [i - 1] -> number;
  197. if (pmin == pmax || (p >= pmin && p <= pmax)) {
  198. double a1 = points [i - 1] -> value, a2 = points [i] -> value;
  199. double amplitudeFactor = a1 > a2 ? a1 / a2 : a2 / a1;
  200. if (amplitudeFactor <= maximumAmplitudeFactor) {
  201. result += fabs (log10 (a1 / a2));
  202. numberOfPeaks ++;
  203. }
  204. }
  205. }
  206. if (numberOfPeaks < 1) return undefined;
  207. result /= numberOfPeaks;
  208. return double (20.0 * result);
  209. }
  210. double AmplitudeTier_getShimmer_apq3 (AmplitudeTier me, double pmin, double pmax, double maximumAmplitudeFactor) {
  211. integer numberOfPeaks = 0;
  212. longdouble numerator = 0.0, denominator = 0.0;
  213. RealPoint *points = & my points.at [0];
  214. for (integer i = 2; i <= my points.size - 1; i ++) {
  215. double
  216. p1 = points [i] -> number - points [i - 1] -> number,
  217. p2 = points [i + 1] -> number - points [i] -> number;
  218. if (pmin == pmax || (p1 >= pmin && p1 <= pmax && p2 >= pmin && p2 <= pmax)) {
  219. double a1 = points [i - 1] -> value, a2 = points [i] -> value, a3 = points [i + 1] -> value;
  220. double f1 = a1 > a2 ? a1 / a2 : a2 / a1, f2 = a2 > a3 ? a2 / a3 : a3 / a2;
  221. if (f1 <= maximumAmplitudeFactor && f2 <= maximumAmplitudeFactor) {
  222. double threePointAverage = (a1 + a2 + a3) / 3.0;
  223. numerator += fabs (a2 - threePointAverage);
  224. numberOfPeaks ++;
  225. }
  226. }
  227. }
  228. if (numberOfPeaks < 1) return undefined;
  229. numerator /= numberOfPeaks;
  230. numberOfPeaks = 0;
  231. for (integer i = 1; i < my points.size; i ++) {
  232. denominator += points [i] -> value;
  233. numberOfPeaks ++;
  234. }
  235. denominator /= numberOfPeaks;
  236. if (denominator == 0.0) return undefined;
  237. return double (numerator / denominator);
  238. }
  239. double AmplitudeTier_getShimmer_apq5 (AmplitudeTier me, double pmin, double pmax, double maximumAmplitudeFactor) {
  240. integer numberOfPeaks = 0;
  241. longdouble numerator = 0.0, denominator = 0.0;
  242. RealPoint *points = & my points.at [0];
  243. for (integer i = 3; i <= my points.size - 2; i ++) {
  244. double
  245. p1 = points [i - 1] -> number - points [i - 2] -> number,
  246. p2 = points [i] -> number - points [i - 1] -> number,
  247. p3 = points [i + 1] -> number - points [i] -> number,
  248. p4 = points [i + 2] -> number - points [i + 1] -> number;
  249. if (pmin == pmax || (p1 >= pmin && p1 <= pmax && p2 >= pmin && p2 <= pmax
  250. && p3 >= pmin && p3 <= pmax && p4 >= pmin && p4 <= pmax))
  251. {
  252. double a1 = points [i - 2] -> value, a2 = points [i - 1] -> value, a3 = points [i] -> value,
  253. a4 = points [i + 1] -> value, a5 = points [i + 2] -> value;
  254. double f1 = a1 > a2 ? a1 / a2 : a2 / a1, f2 = a2 > a3 ? a2 / a3 : a3 / a2,
  255. f3 = a3 > a4 ? a3 / a4 : a4 / a3, f4 = a4 > a5 ? a4 / a5 : a5 / a4;
  256. if (f1 <= maximumAmplitudeFactor && f2 <= maximumAmplitudeFactor &&
  257. f3 <= maximumAmplitudeFactor && f4 <= maximumAmplitudeFactor)
  258. {
  259. double fivePointAverage = ((a1 + a2 + a3) + (a4 + a5)) / 5.0;
  260. numerator += fabs (a3 - fivePointAverage);
  261. numberOfPeaks ++;
  262. }
  263. }
  264. }
  265. if (numberOfPeaks < 1) return undefined;
  266. numerator /= numberOfPeaks;
  267. numberOfPeaks = 0;
  268. for (integer i = 1; i < my points.size; i ++) {
  269. denominator += points [i] -> value;
  270. numberOfPeaks ++;
  271. }
  272. denominator /= numberOfPeaks;
  273. if (denominator == 0.0) return undefined;
  274. return double (numerator / denominator);
  275. }
  276. double AmplitudeTier_getShimmer_apq11 (AmplitudeTier me, double pmin, double pmax, double maximumAmplitudeFactor) {
  277. integer numberOfPeaks = 0;
  278. longdouble numerator = 0.0, denominator = 0.0;
  279. RealPoint *points = & my points.at [0];
  280. for (integer i = 6; i <= my points.size - 5; i ++) {
  281. double
  282. p1 = points [i - 4] -> number - points [i - 5] -> number,
  283. p2 = points [i - 3] -> number - points [i - 4] -> number,
  284. p3 = points [i - 2] -> number - points [i - 3] -> number,
  285. p4 = points [i - 1] -> number - points [i - 2] -> number,
  286. p5 = points [i] -> number - points [i - 1] -> number,
  287. p6 = points [i + 1] -> number - points [i] -> number,
  288. p7 = points [i + 2] -> number - points [i + 1] -> number,
  289. p8 = points [i + 3] -> number - points [i + 2] -> number,
  290. p9 = points [i + 4] -> number - points [i + 3] -> number,
  291. p10 = points [i + 5] -> number - points [i + 4] -> number;
  292. if (pmin == pmax || (p1 >= pmin && p1 <= pmax && p2 >= pmin && p2 <= pmax
  293. && p3 >= pmin && p3 <= pmax && p4 >= pmin && p4 <= pmax && p5 >= pmin && p5 <= pmax
  294. && p6 >= pmin && p6 <= pmax && p7 >= pmin && p7 <= pmax && p8 >= pmin && p8 <= pmax
  295. && p9 >= pmin && p9 <= pmax && p10 >= pmin && p10 <= pmax))
  296. {
  297. double a1 = points [i - 5] -> value, a2 = points [i - 4] -> value, a3 = points [i - 3] -> value,
  298. a4 = points [i - 2] -> value, a5 = points [i - 1] -> value, a6 = points [i] -> value,
  299. a7 = points [i + 1] -> value, a8 = points [i + 2] -> value, a9 = points [i + 3] -> value,
  300. a10 = points [i + 4] -> value, a11 = points [i + 5] -> value;
  301. double f1 = a1 > a2 ? a1 / a2 : a2 / a1, f2 = a2 > a3 ? a2 / a3 : a3 / a2,
  302. f3 = a3 > a4 ? a3 / a4 : a4 / a3, f4 = a4 > a5 ? a4 / a5 : a5 / a4,
  303. f5 = a5 > a6 ? a5 / a6 : a6 / a5, f6 = a6 > a7 ? a6 / a7 : a7 / a6,
  304. f7 = a7 > a8 ? a7 / a8 : a8 / a7, f8 = a8 > a9 ? a8 / a9 : a9 / a8,
  305. f9 = a9 > a10 ? a9 / a10 : a10 / a9, f10 = a10 > a11 ? a10 / a11 : a11 / a10;
  306. if (f1 <= maximumAmplitudeFactor && f2 <= maximumAmplitudeFactor &&
  307. f3 <= maximumAmplitudeFactor && f4 <= maximumAmplitudeFactor &&
  308. f5 <= maximumAmplitudeFactor && f6 <= maximumAmplitudeFactor &&
  309. f7 <= maximumAmplitudeFactor && f8 <= maximumAmplitudeFactor &&
  310. f9 <= maximumAmplitudeFactor && f10 <= maximumAmplitudeFactor)
  311. {
  312. double elevenPointAverage = (((a1 + a2 + a3) + (a4 + a5 + a6)) + ((a7 + a8 + a9) + (a10 + a11))) / 11.0;
  313. numerator += fabs (a6 - elevenPointAverage);
  314. numberOfPeaks ++;
  315. }
  316. }
  317. }
  318. if (numberOfPeaks < 1) return undefined;
  319. numerator /= numberOfPeaks;
  320. numberOfPeaks = 0;
  321. for (integer i = 1; i < my points.size; i ++) {
  322. denominator += points [i] -> value;
  323. numberOfPeaks ++;
  324. }
  325. denominator /= numberOfPeaks;
  326. if (denominator == 0.0) return undefined;
  327. return double (numerator / denominator);
  328. }
  329. double AmplitudeTier_getShimmer_dda (AmplitudeTier me, double pmin, double pmax, double maximumAmplitudeFactor) {
  330. double apq3 = AmplitudeTier_getShimmer_apq3 (me, pmin, pmax, maximumAmplitudeFactor);
  331. return ( isdefined (apq3) ? 3.0 * apq3 : undefined );
  332. }
  333. autoSound AmplitudeTier_to_Sound (AmplitudeTier me, double samplingFrequency, integer interpolationDepth) {
  334. try {
  335. integer sound_nt = 1 + Melder_ifloor ((my xmax - my xmin) * samplingFrequency); // >= 1
  336. double dt = 1.0 / samplingFrequency;
  337. double tmid = (my xmin + my xmax) / 2;
  338. double t1 = tmid - 0.5 * (sound_nt - 1) * dt;
  339. double *sound;
  340. autoSound you = Sound_create (1, my xmin, my xmax, sound_nt, dt, t1);
  341. sound = your z [1];
  342. for (integer it = 1; it <= my points.size; it ++) {
  343. RealPoint point = my points.at [it];
  344. double t = point -> number, amplitude = point -> value, angle, halfampsinangle;
  345. integer mid = Sampled_xToNearestIndex (you.get(), t), j;
  346. integer begin = mid - interpolationDepth, end = mid + interpolationDepth;
  347. if (begin < 1) begin = 1;
  348. if (end > your nx) end = your nx;
  349. angle = NUMpi * (Sampled_indexToX (you.get(), begin) - t) / your dx;
  350. halfampsinangle = 0.5 * amplitude * sin (angle);
  351. for (j = begin; j <= end; j ++) {
  352. if (fabs (angle) < 1e-6)
  353. sound [j] += amplitude;
  354. else if (angle < 0.0)
  355. sound [j] += halfampsinangle *
  356. (1.0 + cos (angle / (mid - begin + 1))) / angle;
  357. else
  358. sound [j] += halfampsinangle *
  359. (1.0 + cos (angle / (end - mid + 1))) / angle;
  360. angle += NUMpi;
  361. halfampsinangle = - halfampsinangle;
  362. }
  363. }
  364. return you;
  365. } catch (MelderError) {
  366. Melder_throw (me, U": not converted to Sound.");
  367. }
  368. }
  369. /* End of file AmplitudeTier.cpp */