PointEditor.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /* PointEditor.cpp
  2. *
  3. * Copyright (C) 1992-2011,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. #include "PointEditor.h"
  19. #include "PointProcess_and_Sound.h"
  20. #include "EditorM.h"
  21. #include "VoiceAnalysis.h"
  22. Thing_implement (PointEditor, TimeSoundEditor, 0);
  23. /********** DESTRUCTION **********/
  24. void structPointEditor :: v_destroy () noexcept {
  25. PointEditor_Parent :: v_destroy ();
  26. }
  27. /********** MENU COMMANDS **********/
  28. static void menu_cb_getJitter_local (PointEditor me, EDITOR_ARGS_DIRECT) {
  29. if (my startSelection == my endSelection) Melder_throw (U"To measure jitter, make a selection first.");
  30. Melder_informationReal (PointProcess_getJitter_local ((PointProcess) my data, my startSelection, my endSelection, 1e-4, 0.02, 1.3), nullptr);
  31. }
  32. static void menu_cb_getJitter_local_absolute (PointEditor me, EDITOR_ARGS_DIRECT) {
  33. if (my startSelection == my endSelection) Melder_throw (U"To measure jitter, make a selection first.");
  34. Melder_informationReal (PointProcess_getJitter_local_absolute ((PointProcess) my data, my startSelection, my endSelection, 1e-4, 0.02, 1.3), U"seconds");
  35. }
  36. static void menu_cb_getJitter_rap (PointEditor me, EDITOR_ARGS_DIRECT) {
  37. if (my startSelection == my endSelection) Melder_throw (U"To measure jitter, make a selection first.");
  38. Melder_informationReal (PointProcess_getJitter_rap ((PointProcess) my data, my startSelection, my endSelection, 1e-4, 0.02, 1.3), nullptr);
  39. }
  40. static void menu_cb_getJitter_ppq5 (PointEditor me, EDITOR_ARGS_DIRECT) {
  41. if (my startSelection == my endSelection) Melder_throw (U"To measure jitter, make a selection first.");
  42. Melder_informationReal (PointProcess_getJitter_ppq5 ((PointProcess) my data, my startSelection, my endSelection, 1e-4, 0.02, 1.3), nullptr);
  43. }
  44. static void menu_cb_getJitter_ddp (PointEditor me, EDITOR_ARGS_DIRECT) {
  45. if (my startSelection == my endSelection) Melder_throw (U"To measure jitter, make a selection first.");
  46. Melder_informationReal (PointProcess_getJitter_ddp ((PointProcess) my data, my startSelection, my endSelection, 1e-4, 0.02, 1.3), nullptr);
  47. }
  48. static void menu_cb_getShimmer_local (PointEditor me, EDITOR_ARGS_DIRECT) {
  49. if (my startSelection == my endSelection) Melder_throw (U"To measure shimmer, make a selection first.");
  50. Melder_informationReal (PointProcess_Sound_getShimmer_local ((PointProcess) my data, my d_sound.data, my startSelection, my endSelection, 1e-4, 0.02, 1.3, 1.6), nullptr);
  51. }
  52. static void menu_cb_getShimmer_local_dB (PointEditor me, EDITOR_ARGS_DIRECT) {
  53. if (my startSelection == my endSelection) Melder_throw (U"To measure shimmer, make a selection first.");
  54. Melder_informationReal (PointProcess_Sound_getShimmer_local_dB ((PointProcess) my data, my d_sound.data, my startSelection, my endSelection, 1e-4, 0.02, 1.3, 1.6), nullptr);
  55. }
  56. static void menu_cb_getShimmer_apq3 (PointEditor me, EDITOR_ARGS_DIRECT) {
  57. if (my startSelection == my endSelection) Melder_throw (U"To measure shimmer, make a selection first.");
  58. Melder_informationReal (PointProcess_Sound_getShimmer_apq3 ((PointProcess) my data, my d_sound.data, my startSelection, my endSelection, 1e-4, 0.02, 1.3, 1.6), nullptr);
  59. }
  60. static void menu_cb_getShimmer_apq5 (PointEditor me, EDITOR_ARGS_DIRECT) {
  61. if (my startSelection == my endSelection) Melder_throw (U"To measure shimmer, make a selection first.");
  62. Melder_informationReal (PointProcess_Sound_getShimmer_apq5 ((PointProcess) my data, my d_sound.data, my startSelection, my endSelection, 1e-4, 0.02, 1.3, 1.6), nullptr);
  63. }
  64. static void menu_cb_getShimmer_apq11 (PointEditor me, EDITOR_ARGS_DIRECT) {
  65. if (my startSelection == my endSelection) Melder_throw (U"To measure shimmer, make a selection first.");
  66. Melder_informationReal (PointProcess_Sound_getShimmer_apq11 ((PointProcess) my data, my d_sound.data, my startSelection, my endSelection, 1e-4, 0.02, 1.3, 1.6), nullptr);
  67. }
  68. static void menu_cb_getShimmer_dda (PointEditor me, EDITOR_ARGS_DIRECT) {
  69. if (my startSelection == my endSelection) Melder_throw (U"To measure shimmer, make a selection first.");
  70. Melder_informationReal (PointProcess_Sound_getShimmer_dda ((PointProcess) my data, my d_sound.data, my startSelection, my endSelection, 1e-4, 0.02, 1.3, 1.6), nullptr);
  71. }
  72. static void menu_cb_removePoints (PointEditor me, EDITOR_ARGS_DIRECT) {
  73. Editor_save (me, U"Remove point(s)");
  74. if (my startSelection == my endSelection)
  75. PointProcess_removePointNear ((PointProcess) my data, my startSelection);
  76. else
  77. PointProcess_removePointsBetween ((PointProcess) my data, my startSelection, my endSelection);
  78. FunctionEditor_redraw (me);
  79. Editor_broadcastDataChanged (me);
  80. }
  81. static void menu_cb_addPointAtCursor (PointEditor me, EDITOR_ARGS_DIRECT) {
  82. Editor_save (me, U"Add point");
  83. PointProcess_addPoint ((PointProcess) my data, 0.5 * (my startSelection + my endSelection));
  84. FunctionEditor_redraw (me);
  85. Editor_broadcastDataChanged (me);
  86. }
  87. static void menu_cb_addPointAt (PointEditor me, EDITOR_ARGS_FORM) {
  88. EDITOR_FORM (U"Add point", nullptr)
  89. REAL (position, U"Position", U"0.0");
  90. EDITOR_OK
  91. SET_REAL (position, 0.5 * (my startSelection + my endSelection));
  92. EDITOR_DO
  93. Editor_save (me, U"Add point");
  94. PointProcess_addPoint ((PointProcess) my data, position);
  95. FunctionEditor_redraw (me);
  96. Editor_broadcastDataChanged (me);
  97. EDITOR_END
  98. }
  99. static void menu_cb_PointEditorHelp (PointEditor, EDITOR_ARGS_DIRECT) { Melder_help (U"PointEditor"); }
  100. void structPointEditor :: v_createMenus () {
  101. PointEditor_Parent :: v_createMenus ();
  102. Editor_addCommand (this, U"Query", U"-- query jitter --", 0, nullptr);
  103. Editor_addCommand (this, U"Query", U"Get jitter (local)", 0, menu_cb_getJitter_local);
  104. Editor_addCommand (this, U"Query", U"Get jitter (local, absolute)", 0, menu_cb_getJitter_local_absolute);
  105. Editor_addCommand (this, U"Query", U"Get jitter (rap)", 0, menu_cb_getJitter_rap);
  106. Editor_addCommand (this, U"Query", U"Get jitter (ppq5)", 0, menu_cb_getJitter_ppq5);
  107. Editor_addCommand (this, U"Query", U"Get jitter (ddp)", 0, menu_cb_getJitter_ddp);
  108. if (d_sound.data) {
  109. Editor_addCommand (this, U"Query", U"-- query shimmer --", 0, nullptr);
  110. Editor_addCommand (this, U"Query", U"Get shimmer (local)", 0, menu_cb_getShimmer_local);
  111. Editor_addCommand (this, U"Query", U"Get shimmer (local, dB)", 0, menu_cb_getShimmer_local_dB);
  112. Editor_addCommand (this, U"Query", U"Get shimmer (apq3)", 0, menu_cb_getShimmer_apq3);
  113. Editor_addCommand (this, U"Query", U"Get shimmer (apq5)", 0, menu_cb_getShimmer_apq5);
  114. Editor_addCommand (this, U"Query", U"Get shimmer (apq11)", 0, menu_cb_getShimmer_apq11);
  115. Editor_addCommand (this, U"Query", U"Get shimmer (dda)", 0, menu_cb_getShimmer_dda);
  116. }
  117. Editor_addMenu (this, U"Point", 0);
  118. Editor_addCommand (this, U"Point", U"Add point at cursor", 'P', menu_cb_addPointAtCursor);
  119. Editor_addCommand (this, U"Point", U"Add point at...", 0, menu_cb_addPointAt);
  120. Editor_addCommand (this, U"Point", U"-- remove point --", 0, nullptr);
  121. Editor_addCommand (this, U"Point", U"Remove point(s)", GuiMenu_OPTION | 'P', menu_cb_removePoints);
  122. }
  123. void structPointEditor :: v_createHelpMenuItems (EditorMenu menu) {
  124. PointEditor_Parent :: v_createHelpMenuItems (menu);
  125. EditorMenu_addCommand (menu, U"PointEditor help", '?', menu_cb_PointEditorHelp);
  126. }
  127. /********** DRAWING AREA **********/
  128. void structPointEditor :: v_draw () {
  129. PointProcess point = static_cast <PointProcess> (our data);
  130. Sound sound = d_sound.data;
  131. Graphics_setColour (our graphics.get(), Graphics_WHITE);
  132. Graphics_setWindow (our graphics.get(), 0.0, 1.0, 0.0, 1.0);
  133. Graphics_fillRectangle (our graphics.get(), 0.0, 1.0, 0.0, 1.0);
  134. double minimum = -1.0, maximum = +1.0;
  135. if (sound && (p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy::BY_WINDOW || p_sound_scalingStrategy == kTimeSoundEditor_scalingStrategy::BY_WINDOW_AND_CHANNEL)) {
  136. integer first, last;
  137. if (Sampled_getWindowSamples (sound, our startWindow, our endWindow, & first, & last) >= 1) {
  138. Matrix_getWindowExtrema (sound, first, last, 1, 1, & minimum, & maximum);
  139. if (minimum == maximum) {
  140. minimum -= 1.0;
  141. maximum += 1.0;
  142. }
  143. }
  144. }
  145. Graphics_setWindow (our graphics.get(), our startWindow, our endWindow, minimum, maximum);
  146. Graphics_setColour (our graphics.get(), Graphics_BLACK);
  147. if (sound) {
  148. integer first, last;
  149. if (Sampled_getWindowSamples (sound, our startWindow, our endWindow, & first, & last) > 1) {
  150. Graphics_setLineType (our graphics.get(), Graphics_DOTTED);
  151. Graphics_line (our graphics.get(), our startWindow, 0.0, our endWindow, 0.0);
  152. Graphics_setLineType (our graphics.get(), Graphics_DRAWN);
  153. Graphics_function (our graphics.get(), & sound -> z [1] [0], first, last,
  154. Sampled_indexToX (sound, first), Sampled_indexToX (sound, last));
  155. }
  156. }
  157. Graphics_setColour (our graphics.get(), Graphics_BLUE);
  158. Graphics_setWindow (our graphics.get(), our startWindow, our endWindow, -1.0, +1.0);
  159. for (integer i = 1; i <= point -> nt; i ++) {
  160. double t = point -> t [i];
  161. if (t >= our startWindow && t <= our endWindow)
  162. Graphics_line (our graphics.get(), t, -0.9, t, +0.9);
  163. }
  164. Graphics_setColour (our graphics.get(), Graphics_BLACK);
  165. v_updateMenuItems_file ();
  166. }
  167. void structPointEditor :: v_play (double a_tmin, double a_tmax) {
  168. if (d_sound.data) {
  169. Sound_playPart (d_sound.data, a_tmin, a_tmax, theFunctionEditor_playCallback, this);
  170. } else {
  171. PointProcess_playPart ((PointProcess) data, a_tmin, a_tmax);
  172. }
  173. }
  174. autoPointEditor PointEditor_create (conststring32 title, PointProcess point, Sound sound) {
  175. try {
  176. autoPointEditor me = Thing_new (PointEditor);
  177. if (sound) {
  178. my monoSound = Sound_convertToMono (sound);
  179. }
  180. TimeSoundEditor_init (me.get(), title, point, my monoSound.get(), false);
  181. return me;
  182. } catch (MelderError) {
  183. Melder_throw (U"PointProcess window not created.");
  184. }
  185. }
  186. /* End of file PointEditor.cpp */