kopia lustrzana https://github.com/backface/turtlestitch
new "getSoundAttribute" reporter primitive
rodzic
4e4d4cb5db
commit
6b874c18f3
|
@ -16,6 +16,7 @@
|
|||
* selectors for changing and querying "draggable" and "rotation style" settings
|
||||
* new sound + music "volume" feature + blocks
|
||||
* new sound + music stereo "panning" feature + blocks
|
||||
* new sound attribute getter reporter
|
||||
* new "play frequency" commands in the Sounds category
|
||||
* added "neg" selector to monadic function reporter in "Operators" category
|
||||
* added "log2" selector to monadic function reporter in "Operators" category
|
||||
|
@ -57,6 +58,9 @@
|
|||
* German
|
||||
* French
|
||||
|
||||
### 2019-04-08
|
||||
* Blocks, Objects, Threads: new "getSoundAttribute" reporter primitive
|
||||
|
||||
### 2019-04-05
|
||||
* Objects: eliminated "clicks" when playing music notes
|
||||
* Objects: eliminated "clicks" when playing a frequency
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
<link rel="shortcut icon" href="src/favicon.ico">
|
||||
<script type="text/javascript" src="src/morphic.js?version=2019-02-07"></script>
|
||||
<script type="text/javascript" src="src/widgets.js?version=2019-04-05"></script>
|
||||
<script type="text/javascript" src="src/blocks.js?version=2019-04-04"></script>
|
||||
<script type="text/javascript" src="src/threads.js?version=2019-04-07"></script>
|
||||
<script type="text/javascript" src="src/objects.js?version=2019-04-05"></script>
|
||||
<script type="text/javascript" src="src/blocks.js?version=2019-04-08"></script>
|
||||
<script type="text/javascript" src="src/threads.js?version=2019-04-08"></script>
|
||||
<script type="text/javascript" src="src/objects.js?version=2019-04-08"></script>
|
||||
<script type="text/javascript" src="src/gui.js?version=2019-03-25"></script>
|
||||
<script type="text/javascript" src="src/paint.js?version=2019-02-22"></script>
|
||||
<script type="text/javascript" src="src/lists.js?version=2019-02-07"></script>
|
||||
|
|
|
@ -148,7 +148,7 @@ CustomCommandBlockMorph, SymbolMorph, ToggleButtonMorph, DialMorph*/
|
|||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.blocks = '2019-April-05';
|
||||
modules.blocks = '2019-April-08';
|
||||
|
||||
var SyntaxElementMorph;
|
||||
var BlockMorph;
|
||||
|
@ -995,6 +995,21 @@ SyntaxElementMorph.prototype.labelPart = function (spec) {
|
|||
true // read-only
|
||||
);
|
||||
break;
|
||||
case '%aa': // audio attributes
|
||||
part = new InputSlotMorph(
|
||||
null, // text
|
||||
false, // numeric?
|
||||
{
|
||||
'name' : ['name'],
|
||||
'duration' : ['duration'],
|
||||
'length' : ['length'],
|
||||
'number of channels' : ['number of channels'],
|
||||
'sample rate' : ['sample rate'],
|
||||
'samples' : ['samples']
|
||||
},
|
||||
true // read-only
|
||||
);
|
||||
break;
|
||||
case '%month':
|
||||
part = new InputSlotMorph(
|
||||
null, // text
|
||||
|
|
|
@ -84,7 +84,7 @@ BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize,
|
|||
TableMorph, TableFrameMorph, normalizeCanvas, BooleanSlotMorph, HandleMorph,
|
||||
AlignmentMorph, Process, XML_Element, VectorPaintEditorMorph*/
|
||||
|
||||
modules.objects = '2019-April-05';
|
||||
modules.objects = '2019-April-08';
|
||||
|
||||
var SpriteMorph;
|
||||
var StageMorph;
|
||||
|
@ -439,6 +439,12 @@ SpriteMorph.prototype.initBlocks = function () {
|
|||
category: 'sound',
|
||||
spec: 'stop all sounds'
|
||||
},
|
||||
reportGetSoundAttribute: {
|
||||
type: 'reporter',
|
||||
category: 'sound',
|
||||
spec: '%aa of sound %snd',
|
||||
defaults: [['duration']]
|
||||
},
|
||||
doRest: {
|
||||
type: 'command',
|
||||
category: 'sound',
|
||||
|
@ -2029,6 +2035,8 @@ SpriteMorph.prototype.blockTemplates = function (category) {
|
|||
blocks.push(block('doPlaySoundUntilDone'));
|
||||
blocks.push(block('doStopAllSounds'));
|
||||
blocks.push('-');
|
||||
blocks.push(block('reportGetSoundAttribute'));
|
||||
blocks.push('-');
|
||||
blocks.push(block('doRest'));
|
||||
blocks.push(block('doPlayNote'));
|
||||
blocks.push(block('doSetInstrument'));
|
||||
|
@ -7509,6 +7517,8 @@ StageMorph.prototype.blockTemplates = function (category) {
|
|||
blocks.push(block('doPlaySoundUntilDone'));
|
||||
blocks.push(block('doStopAllSounds'));
|
||||
blocks.push('-');
|
||||
blocks.push(block('reportGetSoundAttribute'));
|
||||
blocks.push('-');
|
||||
blocks.push(block('doRest'));
|
||||
blocks.push(block('doPlayNote'));
|
||||
blocks.push(block('doSetInstrument'));
|
||||
|
@ -9140,6 +9150,13 @@ CostumeEditorMorph.prototype.mouseMove
|
|||
function Sound(audio, name) {
|
||||
this.audio = audio; // mandatory
|
||||
this.name = name || "Sound";
|
||||
|
||||
// cached samples, don't persist
|
||||
this.cachedSamples = null;
|
||||
|
||||
// internal for decoding, don't persist
|
||||
this.audioBuffer = null; // for decoding ops
|
||||
this.isDecoding = false;
|
||||
}
|
||||
|
||||
Sound.prototype.play = function () {
|
||||
|
|
|
@ -62,7 +62,7 @@ StageMorph, SpriteMorph, StagePrompterMorph, Note, modules, isString, copy,
|
|||
isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph, Color,
|
||||
TableFrameMorph, ColorSlotMorph, isSnapObject, Map*/
|
||||
|
||||
modules.threads = '2019-April-07';
|
||||
modules.threads = '2019-April-08';
|
||||
|
||||
var ThreadManager;
|
||||
var Process;
|
||||
|
@ -2249,6 +2249,86 @@ Process.prototype.doStopAllSounds = function () {
|
|||
}
|
||||
};
|
||||
|
||||
Process.prototype.reportGetSoundAttribute = function (choice, soundName) {
|
||||
var sound = soundName instanceof Sound ? soundName : detect(
|
||||
this.blockReceiver().sounds.asArray(),
|
||||
function (s) {return s.name === soundName.toString(); }
|
||||
),
|
||||
option = this.inputOption(choice);
|
||||
|
||||
if (option === 'name') {
|
||||
return sound.name;
|
||||
}
|
||||
|
||||
if (!sound.audioBuffer) {
|
||||
this.decodeSound(sound);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (option) {
|
||||
case 'samples':
|
||||
if (!sound.cachedSamples) {
|
||||
sound.cachedSamples = function (sound) {
|
||||
var buf = sound.audioBuffer,
|
||||
result, i;
|
||||
if (buf.numberOfChannels > 1) {
|
||||
result = new List();
|
||||
for (i = 0; i < buf.numberOfChannels; i += 1) {
|
||||
result.add(new List(buf.getChannelData(i)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return new List(buf.getChannelData(0));
|
||||
} (sound);
|
||||
}
|
||||
return sound.cachedSamples;
|
||||
case 'sample rate':
|
||||
return sound.audioBuffer.sampleRate;
|
||||
case 'duration':
|
||||
return sound.audioBuffer.duration;
|
||||
case 'length':
|
||||
return sound.audioBuffer.length;
|
||||
case 'number of channels':
|
||||
return sound.audioBuffer.numberOfChannels;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
Process.prototype.decodeSound = function (sound, callback) {
|
||||
// private - callback is optional and invoked with sound as argument
|
||||
var base64, binaryString, len, bytes, i, arrayBuffer, audioCtx,
|
||||
myself = this;
|
||||
if (sound.audioBuffer) {
|
||||
return (callback || nop)(sound);
|
||||
}
|
||||
if (!sound.isDecoding) {
|
||||
base64 = sound.audio.src.split(',')[1];
|
||||
binaryString = window.atob(base64);
|
||||
len = binaryString.length;
|
||||
bytes = new Uint8Array(len);
|
||||
for (i = 0; i < len; i += 1) {
|
||||
bytes[i] = binaryString.charCodeAt(i);
|
||||
}
|
||||
arrayBuffer = bytes.buffer;
|
||||
audioCtx = Note.prototype.getAudioContext();
|
||||
sound.isDecoding = true;
|
||||
audioCtx.decodeAudioData(
|
||||
arrayBuffer,
|
||||
function(buffer) {
|
||||
sound.audioBuffer = buffer;
|
||||
sound.isDecoding = false;
|
||||
},
|
||||
function (err) {
|
||||
sound.isDecoding = false;
|
||||
myself.handleError(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
this.pushContext('doYield');
|
||||
this.pushContext();
|
||||
};
|
||||
|
||||
// Process audio input (interpolated)
|
||||
|
||||
Process.prototype.reportAudio = function (choice) {
|
||||
|
|
Ładowanie…
Reference in New Issue