pxt-core 7.5.8 → 7.5.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/built/pxt.js +1004 -4
  2. package/built/pxtblockly.js +439 -49
  3. package/built/pxtblocks.d.ts +34 -0
  4. package/built/pxtblocks.js +439 -49
  5. package/built/pxtlib.d.ts +20 -2
  6. package/built/pxtlib.js +127 -3
  7. package/built/pxtsim.d.ts +222 -0
  8. package/built/pxtsim.js +877 -1
  9. package/built/target.js +1 -1
  10. package/built/web/icons.css +49 -10
  11. package/built/web/main.js +1 -1
  12. package/built/web/pxtapp.js +1 -1
  13. package/built/web/pxtasseteditor.js +1 -1
  14. package/built/web/pxtblockly.js +1 -1
  15. package/built/web/pxtblocks.js +1 -1
  16. package/built/web/pxtembed.js +2 -2
  17. package/built/web/pxtlib.js +1 -1
  18. package/built/web/pxtsim.js +1 -1
  19. package/built/web/pxtworker.js +1 -1
  20. package/built/web/react-common-authcode.css +130 -1
  21. package/built/web/react-common-skillmap.css +1 -1
  22. package/built/web/rtlreact-common-skillmap.css +1 -1
  23. package/built/web/rtlsemantic.css +2 -2
  24. package/built/web/semantic.css +2 -2
  25. package/built/web/skillmap/js/main.e30f6be4.chunk.js +1 -0
  26. package/docfiles/footer.html +1 -1
  27. package/docfiles/script.html +1 -1
  28. package/docfiles/thin-footer.html +1 -1
  29. package/localtypings/pxtarget.d.ts +1 -0
  30. package/package.json +1 -1
  31. package/react-common/components/controls/Button.tsx +10 -4
  32. package/react-common/components/controls/DraggableGraph.tsx +242 -0
  33. package/react-common/components/controls/Dropdown.tsx +121 -0
  34. package/react-common/components/controls/FocusList.tsx +17 -8
  35. package/react-common/components/controls/Input.tsx +13 -3
  36. package/react-common/components/controls/RadioButtonGroup.tsx +66 -0
  37. package/react-common/components/util.tsx +23 -0
  38. package/react-common/styles/controls/Button.less +21 -0
  39. package/react-common/styles/controls/DraggableGraph.less +13 -0
  40. package/react-common/styles/controls/Dropdown.less +68 -0
  41. package/react-common/styles/controls/RadioButtonGroup.less +36 -0
  42. package/react-common/styles/react-common-variables.less +38 -0
  43. package/react-common/styles/react-common.less +3 -0
  44. package/theme/pxt.less +1 -0
  45. package/theme/soundeffecteditor.less +239 -0
  46. package/webapp/public/skillmap.html +1 -1
  47. package/built/web/skillmap/js/main.2485091f.chunk.js +0 -1
package/built/pxtsim.js CHANGED
@@ -6298,7 +6298,7 @@ var pxsim;
6298
6298
  frame.id = 'sim-frame-' + this.nextId();
6299
6299
  frame.title = pxsim.localization.lf("Simulator");
6300
6300
  frame.allowFullscreen = true;
6301
- frame.setAttribute('allow', 'autoplay');
6301
+ frame.setAttribute('allow', 'autoplay;microphone');
6302
6302
  frame.setAttribute('sandbox', 'allow-same-origin allow-scripts');
6303
6303
  frame.className = 'no-select';
6304
6304
  const furl = (url || this.getSimUrl()) + '#' + frame.id;
@@ -7854,6 +7854,882 @@ var pxsim;
7854
7854
  })(svg = pxsim.svg || (pxsim.svg = {}));
7855
7855
  })(pxsim || (pxsim = {}));
7856
7856
  var pxsim;
7857
+ (function (pxsim) {
7858
+ var codal;
7859
+ (function (codal) {
7860
+ var music;
7861
+ (function (music) {
7862
+ var MusicalIntervals;
7863
+ (function (MusicalIntervals) {
7864
+ // #if CONFIG_ENABLED(JUST_SCALE)
7865
+ // const float MusicalIntervals.chromaticInterval[] = [1.000000, 1.059463, 1.122462, 1.189207, 1.259921, 1.334840, 1.414214, 1.498307, 1.587401, 1.681793, 1.781797, 1.887749];
7866
+ // #else
7867
+ // const float MusicalIntervals.chromaticInterval[] = [1.000000, 1.0417, 1.1250, 1.2000, 1.2500, 1.3333, 1.4063, 1.5000, 1.6000, 1.6667, 1.8000, 1.8750];
7868
+ // #endif
7869
+ MusicalIntervals.chromaticInterval = [1.000000, 1.0417, 1.1250, 1.2000, 1.2500, 1.3333, 1.4063, 1.5000, 1.6000, 1.6667, 1.8000, 1.8750];
7870
+ MusicalIntervals.majorScaleInterval = [MusicalIntervals.chromaticInterval[0], MusicalIntervals.chromaticInterval[2], MusicalIntervals.chromaticInterval[4], MusicalIntervals.chromaticInterval[5], MusicalIntervals.chromaticInterval[7], MusicalIntervals.chromaticInterval[9], MusicalIntervals.chromaticInterval[11]];
7871
+ MusicalIntervals.minorScaleInterval = [MusicalIntervals.chromaticInterval[0], MusicalIntervals.chromaticInterval[2], MusicalIntervals.chromaticInterval[3], MusicalIntervals.chromaticInterval[5], MusicalIntervals.chromaticInterval[7], MusicalIntervals.chromaticInterval[8], MusicalIntervals.chromaticInterval[10]];
7872
+ MusicalIntervals.pentatonicScaleInterval = [MusicalIntervals.chromaticInterval[0], MusicalIntervals.chromaticInterval[2], MusicalIntervals.chromaticInterval[4], MusicalIntervals.chromaticInterval[7], MusicalIntervals.chromaticInterval[9]];
7873
+ MusicalIntervals.majorTriadInterval = [MusicalIntervals.chromaticInterval[0], MusicalIntervals.chromaticInterval[4], MusicalIntervals.chromaticInterval[7]];
7874
+ MusicalIntervals.minorTriadInterval = [MusicalIntervals.chromaticInterval[0], MusicalIntervals.chromaticInterval[3], MusicalIntervals.chromaticInterval[7]];
7875
+ MusicalIntervals.diminishedInterval = [MusicalIntervals.chromaticInterval[0], MusicalIntervals.chromaticInterval[3], MusicalIntervals.chromaticInterval[6], MusicalIntervals.chromaticInterval[9]];
7876
+ MusicalIntervals.wholeToneInterval = [MusicalIntervals.chromaticInterval[0], MusicalIntervals.chromaticInterval[2], MusicalIntervals.chromaticInterval[4], MusicalIntervals.chromaticInterval[6], MusicalIntervals.chromaticInterval[8], MusicalIntervals.chromaticInterval[10]];
7877
+ })(MusicalIntervals = music.MusicalIntervals || (music.MusicalIntervals = {}));
7878
+ })(music = codal.music || (codal.music = {}));
7879
+ })(codal = pxsim.codal || (pxsim.codal = {}));
7880
+ })(pxsim || (pxsim = {}));
7881
+ (function (pxsim) {
7882
+ var codal;
7883
+ (function (codal) {
7884
+ var music;
7885
+ (function (music) {
7886
+ var MusicalProgressions;
7887
+ (function (MusicalProgressions) {
7888
+ MusicalProgressions.chromatic = { interval: music.MusicalIntervals.chromaticInterval, length: 12 };
7889
+ MusicalProgressions.majorScale = { interval: music.MusicalIntervals.majorScaleInterval, length: 7 };
7890
+ MusicalProgressions.minorScale = { interval: music.MusicalIntervals.minorScaleInterval, length: 7 };
7891
+ MusicalProgressions.pentatonicScale = { interval: music.MusicalIntervals.pentatonicScaleInterval, length: 5 };
7892
+ MusicalProgressions.majorTriad = { interval: music.MusicalIntervals.majorTriadInterval, length: 3 };
7893
+ MusicalProgressions.minorTriad = { interval: music.MusicalIntervals.minorTriadInterval, length: 3 };
7894
+ MusicalProgressions.diminished = { interval: music.MusicalIntervals.diminishedInterval, length: 4 };
7895
+ MusicalProgressions.wholeTone = { interval: music.MusicalIntervals.wholeToneInterval, length: 6 };
7896
+ /**
7897
+ * Determine the frequency of a given note in a given progressions
7898
+ *
7899
+ * @param root The root frequency of the progression
7900
+ * @param progression The Progression to use
7901
+ * @param offset The offset (interval) of the note to generate
7902
+ * @return The frequency of the note requested in Hz.
7903
+ */
7904
+ function calculateFrequencyFromProgression(root, progression, offset) {
7905
+ let octave = Math.floor(offset / progression.length);
7906
+ let index = offset % progression.length;
7907
+ return root * Math.pow(2, octave) * progression.interval[index];
7908
+ }
7909
+ MusicalProgressions.calculateFrequencyFromProgression = calculateFrequencyFromProgression;
7910
+ })(MusicalProgressions = music.MusicalProgressions || (music.MusicalProgressions = {}));
7911
+ })(music = codal.music || (codal.music = {}));
7912
+ })(codal = pxsim.codal || (pxsim.codal = {}));
7913
+ })(pxsim || (pxsim = {}));
7914
+ /**
7915
+ * Adapted from lancaster-university/codal-microbit-v2
7916
+ * https://github.com/lancaster-university/codal-microbit-v2/blob/master/source/SoundEmojiSynthesizer.cpp
7917
+ */
7918
+ var pxsim;
7919
+ (function (pxsim) {
7920
+ var codal;
7921
+ (function (codal) {
7922
+ var music;
7923
+ (function (music) {
7924
+ // https://github.com/lancaster-university/codal-microbit-v2/blob/master/inc/SoundEmojiSynthesizer.h#L30
7925
+ music.EMOJI_SYNTHESIZER_SAMPLE_RATE = 44100;
7926
+ music.EMOJI_SYNTHESIZER_TONE_WIDTH_F = 1024;
7927
+ music.EMOJI_SYNTHESIZER_TONE_WIDTH = 1024;
7928
+ music.EMOJI_SYNTHESIZER_BUFFER_SIZE = 512;
7929
+ music.EMOJI_SYNTHESIZER_TONE_EFFECT_PARAMETERS = 2;
7930
+ music.EMOJI_SYNTHESIZER_TONE_EFFECTS = 3;
7931
+ music.EMOJI_SYNTHESIZER_STATUS_ACTIVE = 0x1;
7932
+ music.EMOJI_SYNTHESIZER_STATUS_OUTPUT_SILENCE_AS_EMPTY = 0x2;
7933
+ music.EMOJI_SYNTHESIZER_STATUS_STOPPING = 0x4;
7934
+ class SoundEmojiSynthesizer {
7935
+ constructor(id, sampleRate = music.EMOJI_SYNTHESIZER_SAMPLE_RATE) {
7936
+ this.samplesPerStep = [];
7937
+ this.status = 0;
7938
+ this.effectPointer = 0;
7939
+ this.position = 0;
7940
+ this.bufferSize = music.EMOJI_SYNTHESIZER_BUFFER_SIZE;
7941
+ this.sampleRate = sampleRate;
7942
+ this.samplesToWrite = 0;
7943
+ this.samplesWritten = 0;
7944
+ this.sampleRange = 1023;
7945
+ this.orMask = 0;
7946
+ this.effectPointer = -1;
7947
+ this.volume = 1;
7948
+ }
7949
+ get effect() {
7950
+ return this.effectBuffer[this.effectPointer];
7951
+ }
7952
+ play(sound) {
7953
+ this.effectBuffer = sound;
7954
+ this.effectPointer = -1;
7955
+ this.nextSoundEffect();
7956
+ }
7957
+ nextSoundEffect() {
7958
+ const hadEffect = this.effect != null;
7959
+ if (this.status & music.EMOJI_SYNTHESIZER_STATUS_STOPPING) {
7960
+ this.effectPointer = null;
7961
+ this.effectBuffer = [];
7962
+ }
7963
+ // If a sequence of SoundEffects are being played, attempt to move on to the next.
7964
+ // If not, select the first in the buffer.
7965
+ if (this.effect)
7966
+ this.effectPointer++;
7967
+ else
7968
+ this.effectPointer = 0;
7969
+ // Validate that we have a valid sound effect. If not, record that we have nothing to play.
7970
+ if (this.effectPointer >= this.effectBuffer.length) {
7971
+ // if we have an effect with a negative duration, reset the buffer (unless there is an update pending)
7972
+ this.effectPointer = 0;
7973
+ if (this.effect.duration >= 0) {
7974
+ this.effectPointer = -1;
7975
+ this.effectBuffer = [];
7976
+ this.samplesWritten = 0;
7977
+ this.samplesToWrite = 0;
7978
+ this.position = 0;
7979
+ return hadEffect;
7980
+ }
7981
+ }
7982
+ // We have a valid buffer. Set up our synthesizer to the requested parameters.
7983
+ this.samplesToWrite = this.determineSampleCount(this.effect.duration);
7984
+ this.frequency = this.effect.frequency;
7985
+ this.volume = this.effect.volume;
7986
+ this.samplesWritten = 0;
7987
+ // validate and initialise per effect rendering state.
7988
+ for (let i = 0; i < music.EMOJI_SYNTHESIZER_TONE_EFFECTS; i++) {
7989
+ this.effect.effects[i].step = 0;
7990
+ this.effect.effects[i].steps = Math.max(this.effect.effects[i].steps, 1);
7991
+ this.samplesPerStep[i] = Math.floor(this.samplesToWrite / this.effect.effects[i].steps);
7992
+ }
7993
+ return false;
7994
+ }
7995
+ pull() {
7996
+ let done = false;
7997
+ let sample;
7998
+ let bufferEnd;
7999
+ while (!done) {
8000
+ if (this.samplesWritten == this.samplesToWrite || this.status & music.EMOJI_SYNTHESIZER_STATUS_STOPPING) {
8001
+ let renderComplete = this.nextSoundEffect();
8002
+ // If we have just completed active playout of an effect, and there are no more effects scheduled,
8003
+ // unblock any fibers that may be waiting to play a sound effect.
8004
+ if (this.samplesToWrite == 0 || this.status & music.EMOJI_SYNTHESIZER_STATUS_STOPPING) {
8005
+ done = true;
8006
+ if (renderComplete || this.status & music.EMOJI_SYNTHESIZER_STATUS_STOPPING) {
8007
+ this.status &= ~music.EMOJI_SYNTHESIZER_STATUS_STOPPING;
8008
+ // Event(id, DEVICE_SOUND_EMOJI_SYNTHESIZER_EVT_DONE);
8009
+ // lock.notify();
8010
+ }
8011
+ }
8012
+ }
8013
+ // If we have something to do, ensure our buffers are created.
8014
+ // We defer creation to avoid unnecessary heap allocation when generating silence.
8015
+ if (((this.samplesWritten < this.samplesToWrite) || !(this.status & music.EMOJI_SYNTHESIZER_STATUS_OUTPUT_SILENCE_AS_EMPTY)) && sample == null) {
8016
+ this.buffer = new Array(this.bufferSize);
8017
+ sample = 0;
8018
+ bufferEnd = this.buffer.length;
8019
+ }
8020
+ // Generate some samples with the current this.effect parameters.
8021
+ while (this.samplesWritten < this.samplesToWrite) {
8022
+ let skip = ((music.EMOJI_SYNTHESIZER_TONE_WIDTH_F * this.frequency) / this.sampleRate);
8023
+ let gain = (this.sampleRange * this.volume) / 1024;
8024
+ let offset = 512 - (512 * gain);
8025
+ let effectStepEnd = [];
8026
+ for (let i = 0; i < music.EMOJI_SYNTHESIZER_TONE_EFFECTS; i++) {
8027
+ effectStepEnd[i] = (this.samplesPerStep[i] * (this.effect.effects[i].step));
8028
+ if (this.effect.effects[i].step == this.effect.effects[i].steps - 1)
8029
+ effectStepEnd[i] = this.samplesToWrite;
8030
+ }
8031
+ let stepEndPosition = effectStepEnd[0];
8032
+ for (let i = 1; i < music.EMOJI_SYNTHESIZER_TONE_EFFECTS; i++)
8033
+ stepEndPosition = Math.min(stepEndPosition, effectStepEnd[i]);
8034
+ // Write samples until the end of the next this.effect-step
8035
+ while (this.samplesWritten < stepEndPosition) {
8036
+ // Stop processing when we've filled the requested this.buffer
8037
+ if (sample == bufferEnd) {
8038
+ // downStream.pullRequest();
8039
+ return this.buffer;
8040
+ }
8041
+ // Synthesize a sample
8042
+ let s = this.effect.tone.tonePrint(this.effect.tone.parameter, this.position);
8043
+ // Apply volume scaling and OR mask (if specified).
8044
+ this.buffer[sample] = (((s * gain) + offset)); // | this.orMask;
8045
+ // Move on our pointers.
8046
+ sample++;
8047
+ this.samplesWritten++;
8048
+ this.position += skip;
8049
+ // Keep our toneprint pointer in range
8050
+ while (this.position > music.EMOJI_SYNTHESIZER_TONE_WIDTH_F)
8051
+ this.position -= music.EMOJI_SYNTHESIZER_TONE_WIDTH_F;
8052
+ }
8053
+ // Invoke the this.effect function for any effects that are due.
8054
+ for (let i = 0; i < music.EMOJI_SYNTHESIZER_TONE_EFFECTS; i++) {
8055
+ if (this.samplesWritten == effectStepEnd[i]) {
8056
+ if (this.effect.effects[i].step < this.effect.effects[i].steps) {
8057
+ if (this.effect.effects[i].effect)
8058
+ this.effect.effects[i].effect(this, this.effect.effects[i]);
8059
+ this.effect.effects[i].step++;
8060
+ }
8061
+ }
8062
+ }
8063
+ }
8064
+ }
8065
+ // if we have no data to send, return an empty this.buffer (if requested)
8066
+ if (sample == null) {
8067
+ this.buffer = [];
8068
+ }
8069
+ else {
8070
+ // Pad the output this.buffer with silence if necessary.
8071
+ const silence = (this.sampleRange * 0.5); // | this.orMask;
8072
+ while (sample < bufferEnd) {
8073
+ this.buffer[sample] = silence;
8074
+ sample++;
8075
+ }
8076
+ }
8077
+ // Issue a Pull Request so that we are always receiver driven, and we're done.
8078
+ // downStream.pullRequest();
8079
+ return this.buffer;
8080
+ }
8081
+ determineSampleCount(playoutTime) {
8082
+ if (playoutTime < 0)
8083
+ playoutTime = -playoutTime;
8084
+ const seconds = playoutTime / 1000;
8085
+ return Math.floor(this.sampleRate * seconds);
8086
+ }
8087
+ totalDuration() {
8088
+ let duration = 0;
8089
+ for (const effect of this.effectBuffer)
8090
+ duration += effect.duration;
8091
+ return duration;
8092
+ }
8093
+ }
8094
+ music.SoundEmojiSynthesizer = SoundEmojiSynthesizer;
8095
+ })(music = codal.music || (codal.music = {}));
8096
+ })(codal = pxsim.codal || (pxsim.codal = {}));
8097
+ })(pxsim || (pxsim = {}));
8098
+ /**
8099
+ * Adapted from lancaster-university/codal-core
8100
+ * https://github.com/lancaster-university/codal-core/blob/master/source/streams/Synthesizer.cpp#L54
8101
+ */
8102
+ var pxsim;
8103
+ (function (pxsim) {
8104
+ var codal;
8105
+ (function (codal) {
8106
+ var music;
8107
+ (function (music) {
8108
+ var Synthesizer;
8109
+ (function (Synthesizer) {
8110
+ const sineTone = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 11, 12, 13, 13, 14, 15, 16, 16, 17, 18, 19, 20, 21, 22, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 40, 41, 42, 43, 45, 46, 47, 49, 50, 51, 53, 54, 56, 57, 58, 60, 61, 63, 64, 66, 68, 69, 71, 72, 74, 76, 77, 79, 81, 82, 84, 86, 87, 89, 91, 93, 95, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 141, 143, 145, 147, 149, 152, 154, 156, 158, 161, 163, 165, 167, 170, 172, 175, 177, 179, 182, 184, 187, 189, 191, 194, 196, 199, 201, 204, 206, 209, 211, 214, 216, 219, 222, 224, 227, 229, 232, 235, 237, 240, 243, 245, 248, 251, 253, 256, 259, 262, 264, 267, 270, 273, 275, 278, 281, 284, 287, 289, 292, 295, 298, 301, 304, 307, 309, 312, 315, 318, 321, 324, 327, 330, 333, 336, 339, 342, 345, 348, 351, 354, 357, 360, 363, 366, 369, 372, 375, 378, 381, 384, 387, 390, 393, 396, 399, 402, 405, 408, 411, 414, 417, 420, 424, 427, 430, 433, 436, 439, 442, 445, 448, 452, 455, 458, 461, 464, 467, 470, 473, 477, 480, 483, 486, 489, 492, 495, 498, 502, 505, 508, 511, 514, 517, 520, 524, 527, 530, 533, 536, 539, 542, 545, 549, 552, 555, 558, 561, 564, 567, 570, 574, 577, 580, 583, 586, 589, 592, 595, 598, 602, 605, 608, 611, 614, 617, 620, 623, 626, 629, 632, 635, 638, 641, 644, 647, 650, 653, 656, 659, 662, 665, 668, 671, 674, 677, 680, 683, 686, 689, 692, 695, 698, 701, 704, 707, 710, 713, 715, 718, 721, 724, 727, 730, 733, 735, 738, 741, 744, 747, 749, 752, 755, 758, 760, 763, 766, 769, 771, 774, 777, 779, 782, 785, 787, 790, 793, 795, 798, 800, 803, 806, 808, 811, 813, 816, 818, 821, 823, 826, 828, 831, 833, 835, 838, 840, 843, 845, 847, 850, 852, 855, 857, 859, 861, 864, 866, 868, 870, 873, 875, 877, 879, 881, 884, 886, 888, 890, 892, 894, 896, 898, 900, 902, 904, 906, 908, 910, 912, 914, 916, 918, 920, 922, 924, 926, 927, 929, 931, 933, 935, 936, 938, 940, 941, 943, 945, 946, 948, 950, 951, 953, 954, 956, 958, 959, 961, 962, 964, 965, 966, 968, 969, 971, 972, 973, 975, 976, 977, 979, 980, 981, 982, 984, 985, 986, 987, 988, 989, 990, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1006, 1007, 1008, 1009, 1009, 1010, 1011, 1011, 1012, 1013, 1013, 1014, 1014, 1015, 1015, 1016, 1016, 1017, 1017, 1018, 1018, 1019, 1019, 1019, 1020, 1020, 1020, 1021, 1021, 1021, 1021, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1023, 1022];
8111
+ const TONE_WIDTH = 1024;
8112
+ function SineTone(arg, position) {
8113
+ position |= 0;
8114
+ let off = TONE_WIDTH - position;
8115
+ if (off < TONE_WIDTH / 2)
8116
+ position = off;
8117
+ return sineTone[position];
8118
+ }
8119
+ Synthesizer.SineTone = SineTone;
8120
+ function SawtoothTone(arg, position) {
8121
+ return position;
8122
+ }
8123
+ Synthesizer.SawtoothTone = SawtoothTone;
8124
+ function TriangleTone(arg, position) {
8125
+ return position < 512 ? position * 2 : (1023 - position) * 2;
8126
+ }
8127
+ Synthesizer.TriangleTone = TriangleTone;
8128
+ function NoiseTone(arg, position) {
8129
+ // deterministic, semi-random noise
8130
+ let mult = arg[0];
8131
+ if (mult == 0)
8132
+ mult = 7919;
8133
+ return (position * mult) & 1023;
8134
+ }
8135
+ Synthesizer.NoiseTone = NoiseTone;
8136
+ function SquareWaveTone(arg, position) {
8137
+ return position < 512 ? 1023 : 0;
8138
+ }
8139
+ Synthesizer.SquareWaveTone = SquareWaveTone;
8140
+ })(Synthesizer = music.Synthesizer || (music.Synthesizer = {}));
8141
+ })(music = codal.music || (codal.music = {}));
8142
+ })(codal = pxsim.codal || (pxsim.codal = {}));
8143
+ })(pxsim || (pxsim = {}));
8144
+ /**
8145
+ * Adapted from lancaster-university/codal-microbit-v2
8146
+ * https://github.com/lancaster-university/codal-microbit-v2/blob/master/source/SoundSynthesizerEffects.cpp
8147
+ */
8148
+ var pxsim;
8149
+ (function (pxsim) {
8150
+ var codal;
8151
+ (function (codal) {
8152
+ var music;
8153
+ (function (music) {
8154
+ var SoundSynthesizerEffects;
8155
+ (function (SoundSynthesizerEffects) {
8156
+ /*
8157
+ * Definitions of standard progressions.
8158
+ */
8159
+ /**
8160
+ * Root Frequency Interpolation Effect Functions
8161
+ */
8162
+ function noInterpolation(synth, context) {
8163
+ }
8164
+ SoundSynthesizerEffects.noInterpolation = noInterpolation;
8165
+ // Linear interpolate function.
8166
+ // parameter[0]: end frequency
8167
+ function linearInterpolation(synth, context) {
8168
+ let interval = (context.parameter[0] - synth.effect.frequency) / context.steps;
8169
+ synth.frequency = synth.effect.frequency + interval * context.step;
8170
+ }
8171
+ SoundSynthesizerEffects.linearInterpolation = linearInterpolation;
8172
+ // Linear interpolate function.
8173
+ // parameter[0]: end frequency
8174
+ function logarithmicInterpolation(synth, context) {
8175
+ synth.frequency = synth.effect.frequency + (Math.log10(Math.max(context.step, 0.1)) * (context.parameter[0] - synth.effect.frequency) / 1.95);
8176
+ }
8177
+ SoundSynthesizerEffects.logarithmicInterpolation = logarithmicInterpolation;
8178
+ // Curve interpolate function
8179
+ // parameter[0]: end frequency
8180
+ function curveInterpolation(synth, context) {
8181
+ synth.frequency = (Math.sin(context.step * 3.12159 / 180.0) * (context.parameter[0] - synth.effect.frequency) + synth.effect.frequency);
8182
+ }
8183
+ SoundSynthesizerEffects.curveInterpolation = curveInterpolation;
8184
+ // Cosine interpolate function
8185
+ // parameter[0]: end frequency
8186
+ function slowVibratoInterpolation(synth, context) {
8187
+ synth.frequency = Math.sin(context.step / 10) * context.parameter[0] + synth.effect.frequency;
8188
+ }
8189
+ SoundSynthesizerEffects.slowVibratoInterpolation = slowVibratoInterpolation;
8190
+ //warble function
8191
+ // parameter[0]: end frequency
8192
+ function warbleInterpolation(synth, context) {
8193
+ synth.frequency = (Math.sin(context.step) * (context.parameter[0] - synth.effect.frequency) + synth.effect.frequency);
8194
+ }
8195
+ SoundSynthesizerEffects.warbleInterpolation = warbleInterpolation;
8196
+ // Vibrato function
8197
+ // parameter[0]: end frequency
8198
+ function vibratoInterpolation(synth, context) {
8199
+ synth.frequency = synth.effect.frequency + Math.sin(context.step) * context.parameter[0];
8200
+ }
8201
+ SoundSynthesizerEffects.vibratoInterpolation = vibratoInterpolation;
8202
+ // Exponential rising function
8203
+ // parameter[0]: end frequency
8204
+ function exponentialRisingInterpolation(synth, context) {
8205
+ synth.frequency = synth.effect.frequency + Math.sin(0.01745329 * context.step) * context.parameter[0];
8206
+ }
8207
+ SoundSynthesizerEffects.exponentialRisingInterpolation = exponentialRisingInterpolation;
8208
+ // Exponential falling function
8209
+ function exponentialFallingInterpolation(synth, context) {
8210
+ synth.frequency = synth.effect.frequency + Math.cos(0.01745329 * context.step) * context.parameter[0];
8211
+ }
8212
+ SoundSynthesizerEffects.exponentialFallingInterpolation = exponentialFallingInterpolation;
8213
+ // Argeppio functions
8214
+ function appregrioAscending(synth, context) {
8215
+ synth.frequency = music.MusicalProgressions.calculateFrequencyFromProgression(synth.effect.frequency, context.parameter_p[0], context.step);
8216
+ }
8217
+ SoundSynthesizerEffects.appregrioAscending = appregrioAscending;
8218
+ function appregrioDescending(synth, context) {
8219
+ synth.frequency = music.MusicalProgressions.calculateFrequencyFromProgression(synth.effect.frequency, context.parameter_p[0], context.steps - context.step - 1);
8220
+ }
8221
+ SoundSynthesizerEffects.appregrioDescending = appregrioDescending;
8222
+ /**
8223
+ * Frequency Delta effects
8224
+ */
8225
+ // Frequency vibrato function
8226
+ // parameter[0]: vibrato frequency multiplier
8227
+ function frequencyVibratoEffect(synth, context) {
8228
+ if (context.step == 0)
8229
+ return;
8230
+ if (context.step % 2 == 0)
8231
+ synth.frequency /= context.parameter[0];
8232
+ else
8233
+ synth.frequency *= context.parameter[0];
8234
+ }
8235
+ SoundSynthesizerEffects.frequencyVibratoEffect = frequencyVibratoEffect;
8236
+ // Volume vibrato function
8237
+ // parameter[0]: vibrato volume multiplier
8238
+ function volumeVibratoEffect(synth, context) {
8239
+ if (context.step == 0)
8240
+ return;
8241
+ if (context.step % 2 == 0)
8242
+ synth.volume /= context.parameter[0];
8243
+ else
8244
+ synth.volume *= context.parameter[0];
8245
+ }
8246
+ SoundSynthesizerEffects.volumeVibratoEffect = volumeVibratoEffect;
8247
+ /**
8248
+ * Volume Delta effects
8249
+ */
8250
+ /** Simple ADSR enveleope effect.
8251
+ * parameter[0]: Centre volume
8252
+ * parameter[1]: End volume
8253
+ * effect.volume: start volume
8254
+ */
8255
+ function adsrVolumeEffect(synth, context) {
8256
+ let halfSteps = context.steps * 0.5;
8257
+ if (context.step <= halfSteps) {
8258
+ let delta = (context.parameter[0] - synth.effect.volume) / halfSteps;
8259
+ synth.volume = synth.effect.volume + context.step * delta;
8260
+ }
8261
+ else {
8262
+ let delta = (context.parameter[1] - context.parameter[0]) / halfSteps;
8263
+ synth.volume = context.parameter[0] + (context.step - halfSteps) * delta;
8264
+ }
8265
+ }
8266
+ SoundSynthesizerEffects.adsrVolumeEffect = adsrVolumeEffect;
8267
+ /**
8268
+ * Simple volume ramp effect
8269
+ * parameter[0]: End volume
8270
+ * effect.volume: start volume
8271
+ */
8272
+ function volumeRampEffect(synth, context) {
8273
+ let delta = (context.parameter[0] - synth.effect.volume) / context.steps;
8274
+ synth.volume = synth.effect.volume + context.step * delta;
8275
+ }
8276
+ SoundSynthesizerEffects.volumeRampEffect = volumeRampEffect;
8277
+ })(SoundSynthesizerEffects = music.SoundSynthesizerEffects || (music.SoundSynthesizerEffects = {}));
8278
+ })(music = codal.music || (codal.music = {}));
8279
+ })(codal = pxsim.codal || (pxsim.codal = {}));
8280
+ })(pxsim || (pxsim = {}));
8281
+ var pxsim;
8282
+ (function (pxsim) {
8283
+ var codal;
8284
+ (function (codal) {
8285
+ var music;
8286
+ (function (music) {
8287
+ let WaveShape;
8288
+ (function (WaveShape) {
8289
+ WaveShape[WaveShape["Sine"] = 0] = "Sine";
8290
+ WaveShape[WaveShape["Sawtooth"] = 1] = "Sawtooth";
8291
+ WaveShape[WaveShape["Triangle"] = 2] = "Triangle";
8292
+ WaveShape[WaveShape["Square"] = 3] = "Square";
8293
+ WaveShape[WaveShape["Noise"] = 4] = "Noise";
8294
+ })(WaveShape = music.WaveShape || (music.WaveShape = {}));
8295
+ let InterpolationEffect;
8296
+ (function (InterpolationEffect) {
8297
+ InterpolationEffect[InterpolationEffect["None"] = 0] = "None";
8298
+ InterpolationEffect[InterpolationEffect["Linear"] = 1] = "Linear";
8299
+ InterpolationEffect[InterpolationEffect["Curve"] = 2] = "Curve";
8300
+ InterpolationEffect[InterpolationEffect["ExponentialRising"] = 5] = "ExponentialRising";
8301
+ InterpolationEffect[InterpolationEffect["ExponentialFalling"] = 6] = "ExponentialFalling";
8302
+ InterpolationEffect[InterpolationEffect["ArpeggioRisingMajor"] = 8] = "ArpeggioRisingMajor";
8303
+ InterpolationEffect[InterpolationEffect["ArpeggioRisingMinor"] = 10] = "ArpeggioRisingMinor";
8304
+ InterpolationEffect[InterpolationEffect["ArpeggioRisingDiminished"] = 12] = "ArpeggioRisingDiminished";
8305
+ InterpolationEffect[InterpolationEffect["ArpeggioRisingChromatic"] = 14] = "ArpeggioRisingChromatic";
8306
+ InterpolationEffect[InterpolationEffect["ArpeggioRisingWholeTone"] = 16] = "ArpeggioRisingWholeTone";
8307
+ InterpolationEffect[InterpolationEffect["ArpeggioFallingMajor"] = 9] = "ArpeggioFallingMajor";
8308
+ InterpolationEffect[InterpolationEffect["ArpeggioFallingMinor"] = 11] = "ArpeggioFallingMinor";
8309
+ InterpolationEffect[InterpolationEffect["ArpeggioFallingDiminished"] = 13] = "ArpeggioFallingDiminished";
8310
+ InterpolationEffect[InterpolationEffect["ArpeggioFallingChromatic"] = 15] = "ArpeggioFallingChromatic";
8311
+ InterpolationEffect[InterpolationEffect["ArpeggioFallingWholeTone"] = 17] = "ArpeggioFallingWholeTone";
8312
+ InterpolationEffect[InterpolationEffect["Logarithmic"] = 18] = "Logarithmic";
8313
+ })(InterpolationEffect = music.InterpolationEffect || (music.InterpolationEffect = {}));
8314
+ let Effect;
8315
+ (function (Effect) {
8316
+ Effect[Effect["None"] = 0] = "None";
8317
+ Effect[Effect["Vibrato"] = 1] = "Vibrato";
8318
+ Effect[Effect["Tremolo"] = 2] = "Tremolo";
8319
+ Effect[Effect["Warble"] = 3] = "Warble";
8320
+ })(Effect = music.Effect || (music.Effect = {}));
8321
+ class Sound {
8322
+ constructor() {
8323
+ this.src = "000000000000000000000000000000000000000000000000000000000000000000000000";
8324
+ }
8325
+ get wave() {
8326
+ return this.getValue(0, 1);
8327
+ }
8328
+ set wave(value) {
8329
+ this.setValue(0, constrain(value, 0, 4), 1);
8330
+ }
8331
+ get volume() {
8332
+ return this.getValue(1, 4);
8333
+ }
8334
+ set volume(value) {
8335
+ this.setValue(1, constrain(value, 0, 1023), 4);
8336
+ }
8337
+ get frequency() {
8338
+ return this.getValue(5, 4);
8339
+ }
8340
+ set frequency(value) {
8341
+ this.setValue(5, value, 4);
8342
+ }
8343
+ get duration() {
8344
+ return this.getValue(9, 4);
8345
+ }
8346
+ set duration(value) {
8347
+ this.setValue(9, value, 4);
8348
+ }
8349
+ get shape() {
8350
+ return this.getValue(13, 2);
8351
+ }
8352
+ set shape(value) {
8353
+ this.setValue(13, value, 2);
8354
+ }
8355
+ get endFrequency() {
8356
+ return this.getValue(18, 4);
8357
+ }
8358
+ set endFrequency(value) {
8359
+ this.setValue(18, value, 4);
8360
+ }
8361
+ get endVolume() {
8362
+ return this.getValue(26, 4);
8363
+ }
8364
+ set endVolume(value) {
8365
+ this.setValue(26, constrain(value, 0, 1023), 4);
8366
+ }
8367
+ get steps() {
8368
+ return this.getValue(30, 4);
8369
+ }
8370
+ set steps(value) {
8371
+ this.setValue(30, value, 4);
8372
+ }
8373
+ get fx() {
8374
+ return this.getValue(34, 2);
8375
+ }
8376
+ set fx(value) {
8377
+ this.setValue(34, constrain(value, 0, 3), 2);
8378
+ }
8379
+ get fxParam() {
8380
+ return this.getValue(36, 4);
8381
+ }
8382
+ set fxParam(value) {
8383
+ this.setValue(36, value, 4);
8384
+ }
8385
+ get fxnSteps() {
8386
+ return this.getValue(40, 4);
8387
+ }
8388
+ set fxnSteps(value) {
8389
+ this.setValue(40, value, 4);
8390
+ }
8391
+ get frequencyRandomness() {
8392
+ return this.getValue(44, 4);
8393
+ }
8394
+ set frequencyRandomness(value) {
8395
+ this.setValue(44, value, 4);
8396
+ }
8397
+ get endFrequencyRandomness() {
8398
+ return this.getValue(48, 4);
8399
+ }
8400
+ set endFrequencyRandomness(value) {
8401
+ this.setValue(48, value, 4);
8402
+ }
8403
+ get volumeRandomness() {
8404
+ return this.getValue(52, 4);
8405
+ }
8406
+ set volumeRandomness(value) {
8407
+ this.setValue(52, value, 4);
8408
+ }
8409
+ get endVolumeRandomness() {
8410
+ return this.getValue(56, 4);
8411
+ }
8412
+ set endVolumeRandomness(value) {
8413
+ this.setValue(56, value, 4);
8414
+ }
8415
+ get durationRandomness() {
8416
+ return this.getValue(60, 4);
8417
+ }
8418
+ set durationRandomness(value) {
8419
+ this.setValue(60, value, 4);
8420
+ }
8421
+ get fxParamRandomness() {
8422
+ return this.getValue(64, 4);
8423
+ }
8424
+ set fxParamRandomness(value) {
8425
+ this.setValue(64, value, 4);
8426
+ }
8427
+ get fxnStepsRandomness() {
8428
+ return this.getValue(68, 4);
8429
+ }
8430
+ set fxnStepsRandomness(value) {
8431
+ this.setValue(68, value, 4);
8432
+ }
8433
+ copy() {
8434
+ const result = new Sound();
8435
+ result.src = this.src.slice(0);
8436
+ return result;
8437
+ }
8438
+ setValue(offset, value, length) {
8439
+ value = constrain(value | 0, 0, Math.pow(10, length) - 1);
8440
+ this.src = this.src.substr(0, offset) + formatNumber(value, length) + this.src.substr(offset + length);
8441
+ }
8442
+ getValue(offset, length) {
8443
+ return parseInt(this.src.substr(offset, length));
8444
+ }
8445
+ }
8446
+ music.Sound = Sound;
8447
+ function formatNumber(num, length) {
8448
+ let result = num + "";
8449
+ while (result.length < length)
8450
+ result = "0" + result;
8451
+ return result;
8452
+ }
8453
+ let soundPromise;
8454
+ function __playSoundExpression(notes, waitTillDone) {
8455
+ const cb = pxsim.getResume();
8456
+ if (!soundPromise)
8457
+ soundPromise = Promise.resolve();
8458
+ soundPromise = soundPromise.then(() => playSoundExpressionAsync(notes));
8459
+ if (!waitTillDone)
8460
+ cb();
8461
+ else
8462
+ soundPromise = soundPromise.then(cb);
8463
+ }
8464
+ music.__playSoundExpression = __playSoundExpression;
8465
+ function playSoundExpressionAsync(notes, isCancelled, onPull) {
8466
+ const synth = new music.SoundEmojiSynthesizer(0);
8467
+ const soundEffects = parseSoundEffects(notes);
8468
+ synth.play(soundEffects);
8469
+ let cancelled = false;
8470
+ return Promise.race([
8471
+ delayAsync(synth.totalDuration())
8472
+ .then(() => {
8473
+ // If safari didn't allow the sound to play for some reason,
8474
+ // it will get delayed until the user does something that
8475
+ // unmutes it. make sure we cancel it so that it doesn't
8476
+ // play long after it was supposed to
8477
+ cancelled = true;
8478
+ }),
8479
+ pxsim.AudioContextManager.playPCMBufferStreamAsync(() => {
8480
+ if (!synth.effect)
8481
+ return undefined;
8482
+ const buff = synth.pull();
8483
+ if (onPull)
8484
+ onPull(synth.frequency, synth.volume);
8485
+ const arr = new Float32Array(buff.length);
8486
+ for (let i = 0; i < buff.length; i++) {
8487
+ // Buffer is (0, 1023) we need to map it to (-1, 1)
8488
+ arr[i] = ((buff[i] - 512) / 512);
8489
+ }
8490
+ return arr;
8491
+ }, synth.sampleRate, 0.03, () => cancelled || (isCancelled && isCancelled()))
8492
+ ]);
8493
+ }
8494
+ music.playSoundExpressionAsync = playSoundExpressionAsync;
8495
+ function __stopSoundExpressions() {
8496
+ pxsim.AudioContextManager.stopAll();
8497
+ }
8498
+ music.__stopSoundExpressions = __stopSoundExpressions;
8499
+ /**
8500
+ * Adapted from lancaster-university/codal-microbit-v2
8501
+ * https://github.com/lancaster-university/codal-microbit-v2/blob/master/source/SoundExpressions.cpp
8502
+ */
8503
+ function parseSoundEffects(notes) {
8504
+ // https://github.com/lancaster-university/codal-microbit-v2/blob/master/source/SoundExpressions.cpp#L57
8505
+ // 72 characters of sound data comma separated
8506
+ const charsPerEffect = 72;
8507
+ const effectCount = Math.floor((notes.length + 1) / (charsPerEffect + 1));
8508
+ const expectedLength = effectCount * (charsPerEffect + 1) - 1;
8509
+ if (notes.length != expectedLength) {
8510
+ return [];
8511
+ }
8512
+ const soundEffects = [];
8513
+ for (let i = 0; i < effectCount; ++i) {
8514
+ const start = i * charsPerEffect + i;
8515
+ if (start > 0 && notes[start - 1] != ',') {
8516
+ return [];
8517
+ }
8518
+ const effect = blankSoundEffect();
8519
+ if (!parseSoundExpression(notes.substr(start), effect)) {
8520
+ return [];
8521
+ }
8522
+ soundEffects.push(effect);
8523
+ }
8524
+ return soundEffects;
8525
+ }
8526
+ function parseSoundExpression(soundChars, fx) {
8527
+ // https://github.com/lancaster-university/codal-microbit-v2/blob/master/source/SoundExpressions.cpp#L115
8528
+ // Encoded as a sequence of zero padded decimal strings.
8529
+ // This encoding is worth reconsidering if we can!
8530
+ // The ADSR effect (and perhaps others in future) has two parameters which cannot be expressed.
8531
+ // 72 chars total
8532
+ // [0] 0-4 wave
8533
+ let wave = parseInt(soundChars.substr(0, 1));
8534
+ // [1] 0000-1023 volume
8535
+ let effectVolume = parseInt(soundChars.substr(1, 4));
8536
+ // [5] 0000-9999 frequency
8537
+ let frequency = parseInt(soundChars.substr(5, 4));
8538
+ // [9] 0000-9999 duration
8539
+ let duration = parseInt(soundChars.substr(9, 4));
8540
+ // [13] 00 shape (specific known values)
8541
+ let shape = parseInt(soundChars.substr(13, 2));
8542
+ // [15] XXX unused/bug. This was startFrequency but we use frequency above.
8543
+ // [18] 0000-9999 end frequency
8544
+ let endFrequency = parseInt(soundChars.substr(18, 4));
8545
+ // [22] XXXX unused. This was start volume but we use volume above.
8546
+ // [26] 0000-1023 end volume
8547
+ let endVolume = parseInt(soundChars.substr(26, 4));
8548
+ // [30] 0000-9999 steps
8549
+ let steps = parseInt(soundChars.substr(30, 4));
8550
+ // [34] 00-03 fx choice
8551
+ let fxChoice = parseInt(soundChars.substr(34, 2));
8552
+ // [36] 0000-9999 fxParam
8553
+ let fxParam = parseInt(soundChars.substr(36, 4));
8554
+ // [40] 0000-9999 fxnSteps
8555
+ let fxnSteps = parseInt(soundChars.substr(40, 4));
8556
+ // Details that encoded randomness to be applied when frame is used:
8557
+ // Can the randomness cause any parameters to go out of range?
8558
+ // [44] 0000-9999 frequency random
8559
+ frequency = applyRandom(frequency, parseInt(soundChars.substr(44, 4)));
8560
+ // [48] 0000-9999 end frequency random
8561
+ endFrequency = applyRandom(endFrequency, parseInt(soundChars.substr(48, 4)));
8562
+ // [52] 0000-9999 volume random
8563
+ effectVolume = applyRandom(effectVolume, parseInt(soundChars.substr(52, 4)));
8564
+ // [56] 0000-9999 end volume random
8565
+ endVolume = applyRandom(endVolume, parseInt(soundChars.substr(56, 4)));
8566
+ // [60] 0000-9999 duration random
8567
+ duration = applyRandom(duration, parseInt(soundChars.substr(60, 4)));
8568
+ // [64] 0000-9999 fxParamRandom
8569
+ fxParam = applyRandom(fxParam, parseInt(soundChars.substr(64, 4)));
8570
+ // [68] 0000-9999 fxnStepsRandom
8571
+ fxnSteps = applyRandom(fxnSteps, parseInt(soundChars.substr(68, 4)));
8572
+ if (frequency == -1 || endFrequency == -1 || effectVolume == -1 || endVolume == -1 || duration == -1 || fxParam == -1 || fxnSteps == -1) {
8573
+ return false;
8574
+ }
8575
+ let volumeScaleFactor = 1;
8576
+ switch (wave) {
8577
+ case 0:
8578
+ fx.tone.tonePrint = music.Synthesizer.SineTone;
8579
+ break;
8580
+ case 1:
8581
+ fx.tone.tonePrint = music.Synthesizer.SawtoothTone;
8582
+ break;
8583
+ case 2:
8584
+ fx.tone.tonePrint = music.Synthesizer.TriangleTone;
8585
+ break;
8586
+ case 3:
8587
+ fx.tone.tonePrint = music.Synthesizer.SquareWaveTone;
8588
+ break;
8589
+ case 4:
8590
+ fx.tone.tonePrint = music.Synthesizer.NoiseTone;
8591
+ break;
8592
+ }
8593
+ fx.frequency = frequency;
8594
+ fx.duration = duration;
8595
+ fx.effects[0].steps = steps;
8596
+ switch (shape) {
8597
+ case 0:
8598
+ fx.effects[0].effect = music.SoundSynthesizerEffects.noInterpolation;
8599
+ break;
8600
+ case 1:
8601
+ fx.effects[0].effect = music.SoundSynthesizerEffects.linearInterpolation;
8602
+ fx.effects[0].parameter[0] = endFrequency;
8603
+ break;
8604
+ case 2:
8605
+ fx.effects[0].effect = music.SoundSynthesizerEffects.curveInterpolation;
8606
+ fx.effects[0].parameter[0] = endFrequency;
8607
+ break;
8608
+ case 5:
8609
+ fx.effects[0].effect = music.SoundSynthesizerEffects.exponentialRisingInterpolation;
8610
+ fx.effects[0].parameter[0] = endFrequency;
8611
+ break;
8612
+ case 6:
8613
+ fx.effects[0].effect = music.SoundSynthesizerEffects.exponentialFallingInterpolation;
8614
+ fx.effects[0].parameter[0] = endFrequency;
8615
+ break;
8616
+ case 8: // various ascending scales - see next switch
8617
+ case 10:
8618
+ case 12:
8619
+ case 14:
8620
+ case 16:
8621
+ fx.effects[0].effect = music.SoundSynthesizerEffects.appregrioAscending;
8622
+ break;
8623
+ case 9: // various descending scales - see next switch
8624
+ case 11:
8625
+ case 13:
8626
+ case 15:
8627
+ case 17:
8628
+ fx.effects[0].effect = music.SoundSynthesizerEffects.appregrioDescending;
8629
+ break;
8630
+ case 18:
8631
+ fx.effects[0].effect = music.SoundSynthesizerEffects.logarithmicInterpolation;
8632
+ fx.effects[0].parameter[0] = endFrequency;
8633
+ break;
8634
+ }
8635
+ // Scale
8636
+ switch (shape) {
8637
+ case 8:
8638
+ case 9:
8639
+ fx.effects[0].parameter_p[0] = music.MusicalProgressions.majorScale;
8640
+ break;
8641
+ case 10:
8642
+ case 11:
8643
+ fx.effects[0].parameter_p[0] = music.MusicalProgressions.minorScale;
8644
+ break;
8645
+ case 12:
8646
+ case 13:
8647
+ fx.effects[0].parameter_p[0] = music.MusicalProgressions.diminished;
8648
+ break;
8649
+ case 14:
8650
+ case 15:
8651
+ fx.effects[0].parameter_p[0] = music.MusicalProgressions.chromatic;
8652
+ break;
8653
+ case 16:
8654
+ case 17:
8655
+ fx.effects[0].parameter_p[0] = music.MusicalProgressions.wholeTone;
8656
+ break;
8657
+ }
8658
+ // Volume envelope
8659
+ let effectVolumeFloat = CLAMP(0, effectVolume, 1023) / 1023.0;
8660
+ let endVolumeFloat = CLAMP(0, endVolume, 1023) / 1023.0;
8661
+ fx.volume = volumeScaleFactor * effectVolumeFloat;
8662
+ fx.effects[1].effect = music.SoundSynthesizerEffects.volumeRampEffect;
8663
+ fx.effects[1].steps = 36;
8664
+ fx.effects[1].parameter[0] = volumeScaleFactor * endVolumeFloat;
8665
+ // Vibrato effect
8666
+ // Steps need to be spread across duration evenly.
8667
+ let normalizedFxnSteps = Math.round(fx.duration / 10000 * fxnSteps);
8668
+ switch (fxChoice) {
8669
+ case 1:
8670
+ fx.effects[2].steps = normalizedFxnSteps;
8671
+ fx.effects[2].effect = music.SoundSynthesizerEffects.frequencyVibratoEffect;
8672
+ fx.effects[2].parameter[0] = fxParam;
8673
+ break;
8674
+ case 2:
8675
+ fx.effects[2].steps = normalizedFxnSteps;
8676
+ fx.effects[2].effect = music.SoundSynthesizerEffects.volumeVibratoEffect;
8677
+ fx.effects[2].parameter[0] = fxParam;
8678
+ break;
8679
+ case 3:
8680
+ fx.effects[2].steps = normalizedFxnSteps;
8681
+ fx.effects[2].effect = music.SoundSynthesizerEffects.warbleInterpolation;
8682
+ fx.effects[2].parameter[0] = fxParam;
8683
+ break;
8684
+ }
8685
+ return true;
8686
+ }
8687
+ music.parseSoundExpression = parseSoundExpression;
8688
+ function random(max) {
8689
+ return Math.floor(Math.random() * max);
8690
+ }
8691
+ function CLAMP(min, value, max) {
8692
+ return Math.min(max, Math.max(min, value));
8693
+ }
8694
+ function applyRandom(value, rand) {
8695
+ if (value < 0 || rand < 0) {
8696
+ return -1;
8697
+ }
8698
+ const delta = random(rand * 2 + 1) - rand;
8699
+ return Math.abs(value + delta);
8700
+ }
8701
+ function blankSoundEffect() {
8702
+ const res = {
8703
+ frequency: 0,
8704
+ volume: 1,
8705
+ duration: 0,
8706
+ tone: {
8707
+ tonePrint: undefined,
8708
+ parameter: [0]
8709
+ },
8710
+ effects: []
8711
+ };
8712
+ for (let i = 0; i < music.EMOJI_SYNTHESIZER_TONE_EFFECTS; i++) {
8713
+ res.effects.push({
8714
+ effect: undefined,
8715
+ step: 0,
8716
+ steps: 0,
8717
+ parameter: [],
8718
+ parameter_p: []
8719
+ });
8720
+ }
8721
+ return res;
8722
+ }
8723
+ function delayAsync(millis) {
8724
+ return new Promise(resolve => setTimeout(resolve, millis));
8725
+ }
8726
+ function constrain(val, min, max) {
8727
+ return Math.min(Math.max(val, min), max);
8728
+ }
8729
+ })(music = codal.music || (codal.music = {}));
8730
+ })(codal = pxsim.codal || (pxsim.codal = {}));
8731
+ })(pxsim || (pxsim = {}));
8732
+ var pxsim;
7857
8733
  (function (pxsim) {
7858
8734
  class Button {
7859
8735
  constructor(id) {