audio_util.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.mergePause = mergePause;
  4. exports.mergeMarkup = mergeMarkup;
  5. exports.sortClose = sortClose;
  6. exports.personalityMarkup = personalityMarkup;
  7. exports.isMarkupElement = isMarkupElement;
  8. exports.isPauseElement = isPauseElement;
  9. const base_util_js_1 = require("../common/base_util.js");
  10. const EngineConst = require("../common/engine_const.js");
  11. const engine_js_1 = require("../common/engine.js");
  12. const span_js_1 = require("./span.js");
  13. function mergePause(oldPause, newPause, opt_merge) {
  14. if (!oldPause) {
  15. return newPause;
  16. }
  17. return { pause: mergePause_(oldPause.pause, newPause.pause, opt_merge) };
  18. }
  19. function mergePause_(oldPause, newPause, opt_merge) {
  20. const merge = opt_merge ||
  21. function (x, y) {
  22. if (typeof x === 'number' && typeof y === 'number') {
  23. return x + y;
  24. }
  25. if (typeof x === 'number') {
  26. return y;
  27. }
  28. if (typeof y === 'number') {
  29. return x;
  30. }
  31. return [oldPause, newPause].sort()[0];
  32. };
  33. return merge.call(null, oldPause, newPause);
  34. }
  35. function mergeMarkup(oldPers, newPers) {
  36. delete oldPers.open;
  37. newPers.close.forEach((x) => delete oldPers[x]);
  38. newPers.open.forEach((x) => (oldPers[x] = newPers[x]));
  39. const keys = Object.keys(oldPers);
  40. oldPers.open = keys;
  41. }
  42. function sortClose(open, descrs) {
  43. if (open.length <= 1) {
  44. return open;
  45. }
  46. const result = [];
  47. for (let i = 0, descr; (descr = descrs[i]), open.length; i++) {
  48. if (!descr.close || !descr.close.length) {
  49. continue;
  50. }
  51. descr.close.forEach(function (x) {
  52. const index = open.indexOf(x);
  53. if (index !== -1) {
  54. result.unshift(x);
  55. open.splice(index, 1);
  56. }
  57. });
  58. }
  59. return result;
  60. }
  61. let PersonalityRanges_ = {};
  62. let LastOpen_ = [];
  63. function personalityMarkup(descrs) {
  64. PersonalityRanges_ = {};
  65. LastOpen_ = [];
  66. let result = [];
  67. const currentPers = {};
  68. for (let i = 0, descr; (descr = descrs[i]); i++) {
  69. let pause = null;
  70. const span = descr.descriptionSpan();
  71. const pers = descr.personality;
  72. const join = pers[EngineConst.personalityProps.JOIN];
  73. delete pers[EngineConst.personalityProps.JOIN];
  74. if (typeof pers[EngineConst.personalityProps.PAUSE] !== 'undefined') {
  75. pause = {
  76. [EngineConst.personalityProps.PAUSE]: pers[EngineConst.personalityProps.PAUSE]
  77. };
  78. delete pers[EngineConst.personalityProps.PAUSE];
  79. }
  80. const diff = personalityDiff_(pers, currentPers);
  81. appendMarkup_(result, span, diff, join, pause, true);
  82. }
  83. result = result.concat(finaliseMarkup_());
  84. result = simplifyMarkup_(result);
  85. result = engine_js_1.Engine.getInstance().cleanpause ? cleanPause(result) : result;
  86. return result;
  87. }
  88. function cleanPause(markup) {
  89. while (isPauseElement(markup[0])) {
  90. markup.shift();
  91. }
  92. while (isPauseElement(markup[markup.length - 1])) {
  93. markup.pop();
  94. }
  95. return markup;
  96. }
  97. function appendElement_(markup, element) {
  98. const last = markup[markup.length - 1];
  99. if (!last) {
  100. markup.push(element);
  101. return;
  102. }
  103. if (isSpanElement(element) && isSpanElement(last)) {
  104. if (typeof last.join === 'undefined') {
  105. last.span = last.span.concat(element.span);
  106. return;
  107. }
  108. const lstr = last['span'].pop();
  109. const fstr = element['span'].shift();
  110. last['span'].push(lstr + last.join + fstr);
  111. last['span'] = last['span'].concat(element.span);
  112. last.join = element.join;
  113. return;
  114. }
  115. if (isPauseElement(element) && isPauseElement(last)) {
  116. last.pause = mergePause_(last.pause, element.pause);
  117. return;
  118. }
  119. markup.push(element);
  120. }
  121. function simplifyMarkup_(markup) {
  122. const lastPers = {};
  123. const result = [];
  124. for (let i = 0, element; (element = markup[i]); i++) {
  125. if (!isMarkupElement(element)) {
  126. appendElement_(result, element);
  127. continue;
  128. }
  129. if (!element.close || element.close.length !== 1 || element.open.length) {
  130. copyValues_(element, lastPers);
  131. result.push(element);
  132. continue;
  133. }
  134. let nextElement = markup[i + 1];
  135. if (!nextElement || isSpanElement(nextElement)) {
  136. copyValues_(element, lastPers);
  137. result.push(element);
  138. continue;
  139. }
  140. const pauseElement = isPauseElement(nextElement) ? nextElement : null;
  141. if (pauseElement) {
  142. nextElement = markup[i + 2];
  143. }
  144. if (nextElement &&
  145. isMarkupElement(nextElement) &&
  146. nextElement.open[0] === element.close[0] &&
  147. !nextElement.close.length &&
  148. nextElement[nextElement.open[0]] === lastPers[nextElement.open[0]]) {
  149. if (pauseElement) {
  150. appendElement_(result, pauseElement);
  151. i = i + 2;
  152. }
  153. else {
  154. i = i + 1;
  155. }
  156. }
  157. else {
  158. copyValues_(element, lastPers);
  159. result.push(element);
  160. }
  161. }
  162. return result;
  163. }
  164. function copyValues_(from, to) {
  165. if (from['rate']) {
  166. to['rate'] = from['rate'];
  167. }
  168. if (from['pitch']) {
  169. to['pitch'] = from['pitch'];
  170. }
  171. if (from['volume']) {
  172. to['volume'] = from['volume'];
  173. }
  174. }
  175. function finaliseMarkup_() {
  176. const final = [];
  177. for (let i = LastOpen_.length - 1; i >= 0; i--) {
  178. const pers = LastOpen_[i];
  179. if (pers.length) {
  180. const markup = { open: [], close: [] };
  181. for (let j = 0; j < pers.length; j++) {
  182. const per = pers[j];
  183. markup.close.push(per);
  184. markup[per] = 0;
  185. }
  186. final.push(markup);
  187. }
  188. }
  189. return final;
  190. }
  191. function isMarkupElement(element) {
  192. return typeof element === 'object' && element.open;
  193. }
  194. function isPauseElement(element) {
  195. return (typeof element === 'object' &&
  196. Object.keys(element).length === 1 &&
  197. Object.keys(element)[0] === EngineConst.personalityProps.PAUSE);
  198. }
  199. function isSpanElement(element) {
  200. const keys = Object.keys(element);
  201. return (typeof element === 'object' &&
  202. ((keys.length === 1 && keys[0] === 'span') ||
  203. (keys.length === 2 &&
  204. ((keys[0] === 'span' && keys[1] === 'join') ||
  205. (keys[1] === 'span' && keys[0] === 'join')))));
  206. }
  207. function appendMarkup_(markup, span, pers, join, pause, merge = false) {
  208. if (merge) {
  209. const last = markup[markup.length - 1];
  210. let oldJoin;
  211. if (last) {
  212. oldJoin = last[EngineConst.personalityProps.JOIN];
  213. }
  214. if (last && !span.speech && pause && isPauseElement(last)) {
  215. const pauseProp = EngineConst.personalityProps.PAUSE;
  216. last[pauseProp] = mergePause_(last[pauseProp], pause[pauseProp]);
  217. pause = null;
  218. }
  219. if (last &&
  220. span.speech &&
  221. Object.keys(pers).length === 0 &&
  222. isSpanElement(last)) {
  223. if (typeof oldJoin !== 'undefined') {
  224. const lastSpan = last['span'].pop();
  225. span = span_js_1.Span.stringAttr(lastSpan.speech + oldJoin + span.speech, lastSpan.attributes);
  226. }
  227. last['span'].push(span);
  228. span = span_js_1.Span.empty();
  229. last[EngineConst.personalityProps.JOIN] = join;
  230. }
  231. }
  232. if (Object.keys(pers).length !== 0) {
  233. markup.push(pers);
  234. }
  235. if (span.speech) {
  236. markup.push({ span: [span], join: join });
  237. }
  238. if (pause) {
  239. markup.push(pause);
  240. }
  241. }
  242. function personalityDiff_(current, old) {
  243. if (!old) {
  244. return current;
  245. }
  246. const result = {};
  247. for (const prop of EngineConst.personalityPropList) {
  248. const currentValue = current[prop];
  249. const oldValue = old[prop];
  250. if ((!currentValue && !oldValue) ||
  251. (currentValue && oldValue && currentValue === oldValue)) {
  252. continue;
  253. }
  254. const value = currentValue || 0;
  255. if (!isMarkupElement(result)) {
  256. result.open = [];
  257. result.close = [];
  258. }
  259. if (!currentValue) {
  260. result.close.push(prop);
  261. }
  262. if (!oldValue) {
  263. result.open.push(prop);
  264. }
  265. if (oldValue && currentValue) {
  266. result.close.push(prop);
  267. result.open.push(prop);
  268. }
  269. old[prop] = value;
  270. result[prop] = value;
  271. PersonalityRanges_[prop]
  272. ? PersonalityRanges_[prop].push(value)
  273. : (PersonalityRanges_[prop] = [value]);
  274. }
  275. if (isMarkupElement(result)) {
  276. let c = result.close.slice();
  277. while (c.length > 0) {
  278. let lo = LastOpen_.pop();
  279. const loNew = (0, base_util_js_1.setdifference)(lo, c);
  280. c = (0, base_util_js_1.setdifference)(c, lo);
  281. lo = loNew;
  282. if (c.length === 0) {
  283. if (lo.length !== 0) {
  284. LastOpen_.push(lo);
  285. }
  286. continue;
  287. }
  288. if (lo.length === 0) {
  289. continue;
  290. }
  291. result.close = result.close.concat(lo);
  292. result.open = result.open.concat(lo);
  293. for (let i = 0, open; (open = lo[i]); i++) {
  294. result[open] = old[open];
  295. }
  296. }
  297. LastOpen_.push(result.open);
  298. }
  299. return result;
  300. }