pxt-core 8.2.3 → 8.2.4

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.
@@ -689,7 +689,7 @@ var pxt;
689
689
  docs.prepTemplate = prepTemplate;
690
690
  function setupRenderer(renderer) {
691
691
  renderer.image = function (href, title, text) {
692
- const endpointName = "makecode-lucas-testing-makecodetempmediaservice-usea";
692
+ const endpointName = "makecodeprodmediaeastus-usea";
693
693
  if (href.startsWith("youtube:")) {
694
694
  let out = '<div class="tutorial-video-embed"><iframe class="yt-embed" src="https://www.youtube.com/embed/' + href.split(":").pop()
695
695
  + '" title="' + text + '" frameborder="0" ' + 'allowFullScreen ' + 'allow="autoplay; picture-in-picture"></iframe></div>';
package/built/gdb.js CHANGED
@@ -38,16 +38,16 @@ function getBMPSerialPortsAsync() {
38
38
  });
39
39
  }
40
40
  else if (process.platform == "darwin") {
41
- return cpExecAsync("ioreg -p IOUSB -l -w 0")
41
+ return cpExecAsync("system_profiler SPUSBDataType")
42
42
  .then(({ stdout, stderr }) => {
43
43
  let res = [];
44
44
  let inBMP = false;
45
45
  stdout.split(/\n/).forEach(ln => {
46
- if (ln.indexOf("+-o Black Magic Probe") >= 0)
46
+ if (ln.indexOf(" Black Magic Probe") >= 0)
47
47
  inBMP = true;
48
48
  if (!inBMP)
49
49
  return;
50
- let m = /"USB Serial Number" = "(\w+)"/.exec(ln);
50
+ let m = / Serial Number: (\w+)/.exec(ln);
51
51
  if (m) {
52
52
  inBMP = false;
53
53
  res.push("/dev/cu.usbmodem" + m[1] + "1");
package/built/pxt.js CHANGED
@@ -106399,7 +106399,7 @@ var pxt;
106399
106399
  docs.prepTemplate = prepTemplate;
106400
106400
  function setupRenderer(renderer) {
106401
106401
  renderer.image = function (href, title, text) {
106402
- const endpointName = "makecode-lucas-testing-makecodetempmediaservice-usea";
106402
+ const endpointName = "makecodeprodmediaeastus-usea";
106403
106403
  if (href.startsWith("youtube:")) {
106404
106404
  let out = '<div class="tutorial-video-embed"><iframe class="yt-embed" src="https://www.youtube.com/embed/' + href.split(":").pop()
106405
106405
  + '" title="' + text + '" frameborder="0" ' + 'allowFullScreen ' + 'allow="autoplay; picture-in-picture"></iframe></div>';
@@ -108186,14 +108186,17 @@ var pxt;
108186
108186
  return false;
108187
108187
  }
108188
108188
  function isRepoBanned(repo, config) {
108189
+ var _a, _b;
108189
108190
  if (isOrgBanned(repo, config))
108190
108191
  return true;
108191
108192
  if (!config)
108192
108193
  return false; // don't know
108193
- if (!repo || !repo.fullName)
108194
+ if (!repo)
108194
108195
  return true;
108196
+ const repoFull = (_a = repo.fullName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
108197
+ const repoSlug = (_b = repo.slug) === null || _b === void 0 ? void 0 : _b.toLowerCase();
108195
108198
  if (config.bannedRepos
108196
- && config.bannedRepos.some(fn => fn.toLowerCase() == repo.fullName.toLowerCase()))
108199
+ && config.bannedRepos.some(fn => fn && (fn.toLowerCase() == repoFull || fn.toLowerCase() == repoSlug)))
108197
108200
  return true;
108198
108201
  return false;
108199
108202
  }
@@ -108207,13 +108210,15 @@ var pxt;
108207
108210
  return false;
108208
108211
  }
108209
108212
  function isRepoApproved(repo, config) {
108210
- var _a;
108213
+ var _a, _b;
108211
108214
  if (isOrgApproved(repo, config))
108212
108215
  return true;
108213
- if (!repo || !config)
108216
+ const repoFull = (_a = repo === null || repo === void 0 ? void 0 : repo.fullName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
108217
+ const repoSlug = (_b = repo === null || repo === void 0 ? void 0 : repo.slug) === null || _b === void 0 ? void 0 : _b.toLowerCase();
108218
+ if (!(config === null || config === void 0 ? void 0 : config.approvedRepoLib) || !(repoFull || repoSlug))
108214
108219
  return false;
108215
- if (repo.fullName
108216
- && ((_a = config.approvedRepoLib) === null || _a === void 0 ? void 0 : _a[repo.fullName.toLowerCase()]))
108220
+ if (config.approvedRepoLib[repoFull]
108221
+ || config.approvedRepoLib[repoSlug])
108217
108222
  return true;
108218
108223
  return false;
108219
108224
  }
@@ -114591,6 +114596,97 @@ var pxt;
114591
114596
  return outParts.join(" ");
114592
114597
  }
114593
114598
  }
114599
+ function soundToInstructionBuffer(sound, fxSteps, fxRange) {
114600
+ const { startFrequency, endFrequency, startVolume, endVolume, interpolation, duration } = sound;
114601
+ const steps = [];
114602
+ // Optimize the simple case
114603
+ if (sound.interpolation === "linear" && sound.effect === "none") {
114604
+ steps.push({
114605
+ frequency: startFrequency,
114606
+ volume: (startVolume / assets.MAX_VOLUME) * 1024,
114607
+ });
114608
+ steps.push({
114609
+ frequency: endFrequency,
114610
+ volume: (endVolume / assets.MAX_VOLUME) * 1024,
114611
+ });
114612
+ }
114613
+ else {
114614
+ fxSteps = Math.min(fxSteps, Math.floor(duration / 5));
114615
+ const getVolumeAt = (t) => ((startVolume + t * (endVolume - startVolume) / duration) / assets.MAX_VOLUME) * 1024;
114616
+ let getFrequencyAt;
114617
+ switch (interpolation) {
114618
+ case "linear":
114619
+ getFrequencyAt = t => startFrequency + t * (endFrequency - startFrequency) / duration;
114620
+ break;
114621
+ case "curve":
114622
+ getFrequencyAt = t => startFrequency + (endFrequency - startFrequency) * Math.sin(t / duration * (Math.PI / 2));
114623
+ break;
114624
+ case "logarithmic":
114625
+ getFrequencyAt = t => startFrequency + Math.log10(1 + 9 * (t / duration)) * (endFrequency - startFrequency);
114626
+ break;
114627
+ }
114628
+ const timeSlice = duration / fxSteps;
114629
+ for (let i = 0; i < fxSteps; i++) {
114630
+ const newStep = {
114631
+ frequency: Math.max(getFrequencyAt(i * timeSlice), 1),
114632
+ volume: getVolumeAt(i * timeSlice)
114633
+ };
114634
+ if (sound.effect === "tremolo") {
114635
+ if (i % 2 === 0) {
114636
+ newStep.volume = Math.max(newStep.volume - fxRange * 500, 0);
114637
+ }
114638
+ else {
114639
+ newStep.volume = Math.min(newStep.volume + fxRange * 500, 1023);
114640
+ }
114641
+ }
114642
+ else if (sound.effect === "vibrato") {
114643
+ if (i % 2 === 0) {
114644
+ newStep.frequency = Math.max(newStep.frequency - fxRange * 100, 1);
114645
+ }
114646
+ else {
114647
+ newStep.frequency = newStep.frequency + fxRange * 100;
114648
+ }
114649
+ }
114650
+ else if (sound.effect === "warble") {
114651
+ if (i % 2 === 0) {
114652
+ newStep.frequency = Math.max(newStep.frequency - fxRange * 1000, 1);
114653
+ }
114654
+ else {
114655
+ newStep.frequency = newStep.frequency + fxRange * 1000;
114656
+ }
114657
+ }
114658
+ steps.push(newStep);
114659
+ }
114660
+ }
114661
+ const out = new Uint8Array(12 * (steps.length - 1));
114662
+ const stepDuration = Math.floor(duration / (steps.length - 1));
114663
+ for (let i = 0; i < steps.length - 1; i++) {
114664
+ const offset = i * 12;
114665
+ out[offset] = waveToValue(sound.wave);
114666
+ set16BitNumber(out, offset + 2, steps[i].frequency);
114667
+ set16BitNumber(out, offset + 4, stepDuration);
114668
+ set16BitNumber(out, offset + 6, steps[i].volume);
114669
+ set16BitNumber(out, offset + 8, steps[i + 1].volume);
114670
+ set16BitNumber(out, offset + 10, steps[i + 1].frequency);
114671
+ }
114672
+ return out;
114673
+ }
114674
+ assets.soundToInstructionBuffer = soundToInstructionBuffer;
114675
+ function waveToValue(wave) {
114676
+ switch (wave) {
114677
+ case "square": return 15;
114678
+ case "sine": return 3;
114679
+ case "triangle": return 1;
114680
+ case "noise": return 18;
114681
+ case "sawtooth": return 2;
114682
+ }
114683
+ }
114684
+ function set16BitNumber(buf, offset, value) {
114685
+ const temp = new Uint8Array(2);
114686
+ new Uint16Array(temp.buffer)[0] = value | 0;
114687
+ buf[offset] = temp[0];
114688
+ buf[offset + 1] = temp[1];
114689
+ }
114594
114690
  })(assets = pxt.assets || (pxt.assets = {}));
114595
114691
  })(pxt || (pxt = {}));
114596
114692
  // See https://github.com/microsoft/TouchDevelop-backend/blob/master/docs/streams.md
@@ -154227,92 +154323,10 @@ var pxsim;
154227
154323
  .then(() => {
154228
154324
  if (prevStop != instrStopId)
154229
154325
  return Promise.resolve();
154230
- return playInstructionsAsync(b);
154326
+ return playInstructionsAsync(b.data);
154231
154327
  });
154232
154328
  }
154233
154329
  AudioContextManager.queuePlayInstructions = queuePlayInstructions;
154234
- function playInstructionsAsync(b) {
154235
- const prevStop = instrStopId;
154236
- let ctx = context();
154237
- let idx = 0;
154238
- let ch = new Channel();
154239
- let currWave = -1;
154240
- let currFreq = -1;
154241
- let timeOff = 0;
154242
- if (channels.length > 5)
154243
- channels[0].remove();
154244
- channels.push(ch);
154245
- /** Square waves are perceved as much louder than other sounds, so scale it down a bit to make it less jarring **/
154246
- const scaleVol = (n, isSqWave) => (n / 1024) / 4 * (isSqWave ? .5 : 1);
154247
- const finish = () => {
154248
- ch.disconnectNodes();
154249
- timeOff = 0;
154250
- currWave = -1;
154251
- currFreq = -1;
154252
- };
154253
- const loopAsync = () => {
154254
- if (idx >= b.data.length || !b.data[idx])
154255
- return pxsim.U.delay(timeOff).then(finish);
154256
- const soundWaveIdx = b.data[idx];
154257
- const freq = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 2);
154258
- const duration = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 4);
154259
- const startVol = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 6);
154260
- const endVol = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 8);
154261
- const endFreq = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 10);
154262
- const isSquareWave = 11 <= soundWaveIdx && soundWaveIdx <= 15;
154263
- const isFilteredNoise = soundWaveIdx == 4 || (16 <= soundWaveIdx && soundWaveIdx <= 18);
154264
- const scaledStart = scaleVol(startVol, isSquareWave);
154265
- const scaledEnd = scaleVol(endVol, isSquareWave);
154266
- if (!ctx || prevStop != instrStopId)
154267
- return pxsim.U.delay(duration);
154268
- if (currWave != soundWaveIdx || currFreq != freq || freq != endFreq) {
154269
- if (ch.generator) {
154270
- return pxsim.U.delay(timeOff)
154271
- .then(() => {
154272
- finish();
154273
- return loopAsync();
154274
- });
154275
- }
154276
- ch.generator = getGenerator(soundWaveIdx, freq);
154277
- if (!ch.generator)
154278
- return pxsim.U.delay(duration);
154279
- currWave = soundWaveIdx;
154280
- currFreq = freq;
154281
- ch.gain = ctx.createGain();
154282
- ch.gain.gain.value = 0;
154283
- ch.gain.gain.setTargetAtTime(scaledStart, _context.currentTime, 0.015);
154284
- if (endFreq != freq) {
154285
- if (ch.generator.frequency != undefined) {
154286
- // If generator is an OscillatorNode
154287
- const param = ch.generator.frequency;
154288
- param.linearRampToValueAtTime(endFreq, ctx.currentTime + ((timeOff + duration) / 1000));
154289
- }
154290
- else if (ch.generator.playbackRate != undefined) {
154291
- // If generator is an AudioBufferSourceNode
154292
- const param = ch.generator.playbackRate;
154293
- const bufferSamplesPerWave = isFilteredNoise ? 4 : 1024;
154294
- param.linearRampToValueAtTime(endFreq / (context().sampleRate / bufferSamplesPerWave), ctx.currentTime + ((timeOff + duration) / 1000));
154295
- }
154296
- }
154297
- ch.generator.connect(ch.gain);
154298
- ch.gain.connect(destination);
154299
- ch.generator.start();
154300
- }
154301
- idx += 12;
154302
- ch.gain.gain.setValueAtTime(scaledStart, ctx.currentTime + (timeOff / 1000));
154303
- timeOff += duration;
154304
- // To prevent clipping, we ramp to this value slightly earlier than intended. This is so that we
154305
- // can go for a smooth ramp to 0 in ch.mute() without this operation interrupting it. If we had
154306
- // more accurate timing this would not be necessary, but we'd probably have to do something like
154307
- // running a metronome in a webworker to get the level of precision we need
154308
- const endTime = scaledEnd !== 0 && duration > 50 ? ((timeOff - 50) / 1000) : ((timeOff - 10) / 1000);
154309
- ch.gain.gain.linearRampToValueAtTime(scaledEnd, ctx.currentTime + endTime);
154310
- return loopAsync();
154311
- };
154312
- return loopAsync()
154313
- .then(() => ch.remove());
154314
- }
154315
- AudioContextManager.playInstructionsAsync = playInstructionsAsync;
154316
154330
  function tone(frequency, gain) {
154317
154331
  if (frequency < 0)
154318
154332
  return;
@@ -154451,6 +154465,126 @@ var pxsim;
154451
154465
  function frequencyFromMidiNoteNumber(note) {
154452
154466
  return 440 * Math.pow(2, (note - 69) / 12);
154453
154467
  }
154468
+ function playInstructionsAsync(instructions, isCancelled, onPull) {
154469
+ return new Promise(async (resolve) => {
154470
+ let resolved = false;
154471
+ let ctx = context();
154472
+ let channel = new Channel();
154473
+ if (channels.length > 5)
154474
+ channels[0].remove();
154475
+ channels.push(channel);
154476
+ channel.gain = ctx.createGain();
154477
+ channel.gain.gain.value = 1;
154478
+ channel.gain.connect(destination);
154479
+ const oscillators = {};
154480
+ const gains = {};
154481
+ let startTime = ctx.currentTime;
154482
+ let currentTime = startTime;
154483
+ let currentWave = 0;
154484
+ let totalDuration = 0;
154485
+ /** Square waves are perceved as much louder than other sounds, so scale it down a bit to make it less jarring **/
154486
+ const scaleVol = (n, isSqWave) => (n / 1024) / 4 * (isSqWave ? .5 : 1);
154487
+ const disconnectNodes = () => {
154488
+ if (resolved)
154489
+ return;
154490
+ resolved = true;
154491
+ channel.disconnectNodes();
154492
+ for (const wave of Object.keys(oscillators)) {
154493
+ oscillators[wave].stop();
154494
+ oscillators[wave].disconnect();
154495
+ gains[wave].disconnect();
154496
+ }
154497
+ resolve();
154498
+ };
154499
+ for (let i = 0; i < instructions.length; i += 12) {
154500
+ const wave = instructions[i];
154501
+ const startFrequency = readUint16(instructions, i + 2);
154502
+ const duration = readUint16(instructions, i + 4) / 1000;
154503
+ const startVolume = readUint16(instructions, i + 6);
154504
+ const endVolume = readUint16(instructions, i + 8);
154505
+ const endFrequency = readUint16(instructions, i + 10);
154506
+ totalDuration += duration;
154507
+ const isSquareWave = 11 <= wave && wave <= 15;
154508
+ if (!oscillators[wave]) {
154509
+ oscillators[wave] = getGenerator(wave, startFrequency);
154510
+ gains[wave] = ctx.createGain();
154511
+ gains[wave].gain.value = 0;
154512
+ gains[wave].connect(channel.gain);
154513
+ oscillators[wave].connect(gains[wave]);
154514
+ oscillators[wave].start();
154515
+ }
154516
+ if (currentWave && wave !== currentWave) {
154517
+ gains[currentWave].gain.setTargetAtTime(0, currentTime, 0.015);
154518
+ }
154519
+ const osc = oscillators[wave];
154520
+ const gain = gains[wave];
154521
+ if (osc instanceof OscillatorNode) {
154522
+ osc.frequency.setValueAtTime(startFrequency, currentTime);
154523
+ osc.frequency.linearRampToValueAtTime(endFrequency, currentTime + duration);
154524
+ }
154525
+ else {
154526
+ const isFilteredNoise = wave == 4 || (16 <= wave && wave <= 18);
154527
+ if (isFilteredNoise)
154528
+ osc.playbackRate.linearRampToValueAtTime(endFrequency / (ctx.sampleRate / 4), currentTime + duration);
154529
+ else if (wave != 5)
154530
+ osc.playbackRate.linearRampToValueAtTime(endFrequency / (ctx.sampleRate / 1024), currentTime + duration);
154531
+ }
154532
+ gain.gain.setValueAtTime(scaleVol(startVolume, isSquareWave), currentTime);
154533
+ gain.gain.linearRampToValueAtTime(scaleVol(endVolume, isSquareWave), currentTime + duration);
154534
+ currentWave = wave;
154535
+ currentTime += duration;
154536
+ }
154537
+ channel.gain.gain.setTargetAtTime(0, currentTime, 0.015);
154538
+ if (isCancelled || onPull) {
154539
+ const handleAnimationFrame = () => {
154540
+ const time = ctx.currentTime;
154541
+ if (time > startTime + totalDuration) {
154542
+ return;
154543
+ }
154544
+ if (isCancelled && isCancelled()) {
154545
+ disconnectNodes();
154546
+ return;
154547
+ }
154548
+ const { frequency, volume } = findFrequencyAndVolumeAtTime((time - startTime) * 1000, instructions);
154549
+ onPull(frequency, volume / 1024);
154550
+ requestAnimationFrame(handleAnimationFrame);
154551
+ };
154552
+ requestAnimationFrame(handleAnimationFrame);
154553
+ }
154554
+ await pxsim.U.delay(totalDuration * 1000);
154555
+ disconnectNodes();
154556
+ });
154557
+ }
154558
+ AudioContextManager.playInstructionsAsync = playInstructionsAsync;
154559
+ function readUint16(buf, offset) {
154560
+ const temp = new Uint8Array(2);
154561
+ temp[0] = buf[offset];
154562
+ temp[1] = buf[offset + 1];
154563
+ return new Uint16Array(temp.buffer)[0];
154564
+ }
154565
+ function findFrequencyAndVolumeAtTime(millis, instructions) {
154566
+ let currentTime = 0;
154567
+ for (let i = 0; i < instructions.length; i += 12) {
154568
+ const startFrequency = readUint16(instructions, i + 2);
154569
+ const duration = readUint16(instructions, i + 4);
154570
+ const startVolume = readUint16(instructions, i + 6);
154571
+ const endVolume = readUint16(instructions, i + 8);
154572
+ const endFrequency = readUint16(instructions, i + 10);
154573
+ if (currentTime + duration < millis) {
154574
+ currentTime += duration;
154575
+ continue;
154576
+ }
154577
+ const offset = (millis - currentTime) / duration;
154578
+ return {
154579
+ frequency: startFrequency + (endFrequency - startFrequency) * offset,
154580
+ volume: startVolume + (endVolume - startVolume) * offset,
154581
+ };
154582
+ }
154583
+ return {
154584
+ frequency: -1,
154585
+ volume: -1
154586
+ };
154587
+ }
154454
154588
  function sendMidiMessage(buf) {
154455
154589
  const data = buf.data;
154456
154590
  if (!data.length) // garbage.
@@ -15424,6 +15424,8 @@ var pxtblockly;
15424
15424
  this.options.interpolationFieldName = "interpolation";
15425
15425
  if (!this.options.effectFieldName)
15426
15426
  this.options.effectFieldName = "effect";
15427
+ if (!this.options.useMixerSynthesizer)
15428
+ this.options.useMixerSynthesizer = false;
15427
15429
  this.redrawPreview();
15428
15430
  if (this.sourceBlock_.workspace) {
15429
15431
  this.workspace = this.sourceBlock_.workspace;
@@ -15540,7 +15542,8 @@ var pxtblockly;
15540
15542
  this.updateSiblingBlocks(newSound);
15541
15543
  this.redrawPreview();
15542
15544
  },
15543
- initialSound: initialSound
15545
+ initialSound: initialSound,
15546
+ useMixerSynthesizer: isTrue(this.options.useMixerSynthesizer)
15544
15547
  };
15545
15548
  const fv = pxt.react.getFieldEditorView("soundeffect-editor", initialSound, opts, widgetDiv);
15546
15549
  const block = this.sourceBlock_;
@@ -15734,6 +15737,23 @@ var pxtblockly;
15734
15737
  function reverseLookup(map, value) {
15735
15738
  return Object.keys(map).find(k => map[k] === value);
15736
15739
  }
15740
+ function isTrue(value) {
15741
+ if (!value)
15742
+ return false;
15743
+ if (typeof value === "string") {
15744
+ switch (value.toLowerCase().trim()) {
15745
+ case "1":
15746
+ case "yes":
15747
+ case "y":
15748
+ case "on":
15749
+ case "true":
15750
+ return true;
15751
+ default:
15752
+ return false;
15753
+ }
15754
+ }
15755
+ return !!value;
15756
+ }
15737
15757
  })(pxtblockly || (pxtblockly = {}));
15738
15758
  /// <reference path="../../localtypings/blockly.d.ts"/>
15739
15759
  /// <reference path="../../built/pxtsim.d.ts"/>
@@ -1187,6 +1187,7 @@ declare namespace pxtblockly {
1187
1187
  waveFieldName: string;
1188
1188
  interpolationFieldName: string;
1189
1189
  effectFieldName: string;
1190
+ useMixerSynthesizer: any;
1190
1191
  }
1191
1192
  class FieldSoundEffect extends FieldBase<FieldSoundEffectParams> {
1192
1193
  protected mostRecentValue: pxt.assets.Sound;
@@ -11862,6 +11862,8 @@ var pxtblockly;
11862
11862
  this.options.interpolationFieldName = "interpolation";
11863
11863
  if (!this.options.effectFieldName)
11864
11864
  this.options.effectFieldName = "effect";
11865
+ if (!this.options.useMixerSynthesizer)
11866
+ this.options.useMixerSynthesizer = false;
11865
11867
  this.redrawPreview();
11866
11868
  if (this.sourceBlock_.workspace) {
11867
11869
  this.workspace = this.sourceBlock_.workspace;
@@ -11978,7 +11980,8 @@ var pxtblockly;
11978
11980
  this.updateSiblingBlocks(newSound);
11979
11981
  this.redrawPreview();
11980
11982
  },
11981
- initialSound: initialSound
11983
+ initialSound: initialSound,
11984
+ useMixerSynthesizer: isTrue(this.options.useMixerSynthesizer)
11982
11985
  };
11983
11986
  const fv = pxt.react.getFieldEditorView("soundeffect-editor", initialSound, opts, widgetDiv);
11984
11987
  const block = this.sourceBlock_;
@@ -12172,6 +12175,23 @@ var pxtblockly;
12172
12175
  function reverseLookup(map, value) {
12173
12176
  return Object.keys(map).find(k => map[k] === value);
12174
12177
  }
12178
+ function isTrue(value) {
12179
+ if (!value)
12180
+ return false;
12181
+ if (typeof value === "string") {
12182
+ switch (value.toLowerCase().trim()) {
12183
+ case "1":
12184
+ case "yes":
12185
+ case "y":
12186
+ case "on":
12187
+ case "true":
12188
+ return true;
12189
+ default:
12190
+ return false;
12191
+ }
12192
+ }
12193
+ return !!value;
12194
+ }
12175
12195
  })(pxtblockly || (pxtblockly = {}));
12176
12196
  /// <reference path="../../localtypings/blockly.d.ts"/>
12177
12197
  /// <reference path="../../built/pxtsim.d.ts"/>
@@ -1055,7 +1055,8 @@ var pxt;
1055
1055
  onClose: () => this.fv.hide(),
1056
1056
  onSoundChange: (newValue) => this.value = newValue,
1057
1057
  initialSound: this.value,
1058
- useFlex: true
1058
+ useFlex: true,
1059
+ useMixerSynthesizer: pxt.appTarget.id !== "microbit" // FIXME
1059
1060
  };
1060
1061
  }
1061
1062
  }
package/built/pxtlib.d.ts CHANGED
@@ -2333,6 +2333,7 @@ declare namespace pxt.assets {
2333
2333
  const MAX_VOLUME = 255;
2334
2334
  function renderSoundPath(sound: pxt.assets.Sound, width: number, height: number): string;
2335
2335
  function renderWaveSnapshot(frequency: number, volume: number, wave: SoundWaveForm, width: number, height: number, timeBase: number): string;
2336
+ function soundToInstructionBuffer(sound: Sound, fxSteps: number, fxRange: number): Uint8Array;
2336
2337
  }
2337
2338
  declare namespace pxt.streams {
2338
2339
  interface JsonStreamField {
package/built/pxtlib.js CHANGED
@@ -8713,7 +8713,7 @@ var pxt;
8713
8713
  docs.prepTemplate = prepTemplate;
8714
8714
  function setupRenderer(renderer) {
8715
8715
  renderer.image = function (href, title, text) {
8716
- const endpointName = "makecode-lucas-testing-makecodetempmediaservice-usea";
8716
+ const endpointName = "makecodeprodmediaeastus-usea";
8717
8717
  if (href.startsWith("youtube:")) {
8718
8718
  let out = '<div class="tutorial-video-embed"><iframe class="yt-embed" src="https://www.youtube.com/embed/' + href.split(":").pop()
8719
8719
  + '" title="' + text + '" frameborder="0" ' + 'allowFullScreen ' + 'allow="autoplay; picture-in-picture"></iframe></div>';
@@ -10500,14 +10500,17 @@ var pxt;
10500
10500
  return false;
10501
10501
  }
10502
10502
  function isRepoBanned(repo, config) {
10503
+ var _a, _b;
10503
10504
  if (isOrgBanned(repo, config))
10504
10505
  return true;
10505
10506
  if (!config)
10506
10507
  return false; // don't know
10507
- if (!repo || !repo.fullName)
10508
+ if (!repo)
10508
10509
  return true;
10510
+ const repoFull = (_a = repo.fullName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
10511
+ const repoSlug = (_b = repo.slug) === null || _b === void 0 ? void 0 : _b.toLowerCase();
10509
10512
  if (config.bannedRepos
10510
- && config.bannedRepos.some(fn => fn.toLowerCase() == repo.fullName.toLowerCase()))
10513
+ && config.bannedRepos.some(fn => fn && (fn.toLowerCase() == repoFull || fn.toLowerCase() == repoSlug)))
10511
10514
  return true;
10512
10515
  return false;
10513
10516
  }
@@ -10521,13 +10524,15 @@ var pxt;
10521
10524
  return false;
10522
10525
  }
10523
10526
  function isRepoApproved(repo, config) {
10524
- var _a;
10527
+ var _a, _b;
10525
10528
  if (isOrgApproved(repo, config))
10526
10529
  return true;
10527
- if (!repo || !config)
10530
+ const repoFull = (_a = repo === null || repo === void 0 ? void 0 : repo.fullName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
10531
+ const repoSlug = (_b = repo === null || repo === void 0 ? void 0 : repo.slug) === null || _b === void 0 ? void 0 : _b.toLowerCase();
10532
+ if (!(config === null || config === void 0 ? void 0 : config.approvedRepoLib) || !(repoFull || repoSlug))
10528
10533
  return false;
10529
- if (repo.fullName
10530
- && ((_a = config.approvedRepoLib) === null || _a === void 0 ? void 0 : _a[repo.fullName.toLowerCase()]))
10534
+ if (config.approvedRepoLib[repoFull]
10535
+ || config.approvedRepoLib[repoSlug])
10531
10536
  return true;
10532
10537
  return false;
10533
10538
  }
@@ -16905,6 +16910,97 @@ var pxt;
16905
16910
  return outParts.join(" ");
16906
16911
  }
16907
16912
  }
16913
+ function soundToInstructionBuffer(sound, fxSteps, fxRange) {
16914
+ const { startFrequency, endFrequency, startVolume, endVolume, interpolation, duration } = sound;
16915
+ const steps = [];
16916
+ // Optimize the simple case
16917
+ if (sound.interpolation === "linear" && sound.effect === "none") {
16918
+ steps.push({
16919
+ frequency: startFrequency,
16920
+ volume: (startVolume / assets.MAX_VOLUME) * 1024,
16921
+ });
16922
+ steps.push({
16923
+ frequency: endFrequency,
16924
+ volume: (endVolume / assets.MAX_VOLUME) * 1024,
16925
+ });
16926
+ }
16927
+ else {
16928
+ fxSteps = Math.min(fxSteps, Math.floor(duration / 5));
16929
+ const getVolumeAt = (t) => ((startVolume + t * (endVolume - startVolume) / duration) / assets.MAX_VOLUME) * 1024;
16930
+ let getFrequencyAt;
16931
+ switch (interpolation) {
16932
+ case "linear":
16933
+ getFrequencyAt = t => startFrequency + t * (endFrequency - startFrequency) / duration;
16934
+ break;
16935
+ case "curve":
16936
+ getFrequencyAt = t => startFrequency + (endFrequency - startFrequency) * Math.sin(t / duration * (Math.PI / 2));
16937
+ break;
16938
+ case "logarithmic":
16939
+ getFrequencyAt = t => startFrequency + Math.log10(1 + 9 * (t / duration)) * (endFrequency - startFrequency);
16940
+ break;
16941
+ }
16942
+ const timeSlice = duration / fxSteps;
16943
+ for (let i = 0; i < fxSteps; i++) {
16944
+ const newStep = {
16945
+ frequency: Math.max(getFrequencyAt(i * timeSlice), 1),
16946
+ volume: getVolumeAt(i * timeSlice)
16947
+ };
16948
+ if (sound.effect === "tremolo") {
16949
+ if (i % 2 === 0) {
16950
+ newStep.volume = Math.max(newStep.volume - fxRange * 500, 0);
16951
+ }
16952
+ else {
16953
+ newStep.volume = Math.min(newStep.volume + fxRange * 500, 1023);
16954
+ }
16955
+ }
16956
+ else if (sound.effect === "vibrato") {
16957
+ if (i % 2 === 0) {
16958
+ newStep.frequency = Math.max(newStep.frequency - fxRange * 100, 1);
16959
+ }
16960
+ else {
16961
+ newStep.frequency = newStep.frequency + fxRange * 100;
16962
+ }
16963
+ }
16964
+ else if (sound.effect === "warble") {
16965
+ if (i % 2 === 0) {
16966
+ newStep.frequency = Math.max(newStep.frequency - fxRange * 1000, 1);
16967
+ }
16968
+ else {
16969
+ newStep.frequency = newStep.frequency + fxRange * 1000;
16970
+ }
16971
+ }
16972
+ steps.push(newStep);
16973
+ }
16974
+ }
16975
+ const out = new Uint8Array(12 * (steps.length - 1));
16976
+ const stepDuration = Math.floor(duration / (steps.length - 1));
16977
+ for (let i = 0; i < steps.length - 1; i++) {
16978
+ const offset = i * 12;
16979
+ out[offset] = waveToValue(sound.wave);
16980
+ set16BitNumber(out, offset + 2, steps[i].frequency);
16981
+ set16BitNumber(out, offset + 4, stepDuration);
16982
+ set16BitNumber(out, offset + 6, steps[i].volume);
16983
+ set16BitNumber(out, offset + 8, steps[i + 1].volume);
16984
+ set16BitNumber(out, offset + 10, steps[i + 1].frequency);
16985
+ }
16986
+ return out;
16987
+ }
16988
+ assets.soundToInstructionBuffer = soundToInstructionBuffer;
16989
+ function waveToValue(wave) {
16990
+ switch (wave) {
16991
+ case "square": return 15;
16992
+ case "sine": return 3;
16993
+ case "triangle": return 1;
16994
+ case "noise": return 18;
16995
+ case "sawtooth": return 2;
16996
+ }
16997
+ }
16998
+ function set16BitNumber(buf, offset, value) {
16999
+ const temp = new Uint8Array(2);
17000
+ new Uint16Array(temp.buffer)[0] = value | 0;
17001
+ buf[offset] = temp[0];
17002
+ buf[offset + 1] = temp[1];
17003
+ }
16908
17004
  })(assets = pxt.assets || (pxt.assets = {}));
16909
17005
  })(pxt || (pxt = {}));
16910
17006
  // See https://github.com/microsoft/TouchDevelop-backend/blob/master/docs/streams.md