diff --git a/HISTORY.md b/HISTORY.md index 59fb22ac..bdf8fb5c 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -53,6 +53,7 @@ * ported multiline library to new (custom input slot) format * new "text costumes" library for generating costumes from letters or words of text * took out "b block" costume from catalog +* added microphone "resolution" concept governing "bins" (buffer / bin sizes) ### 2019-03-10 * Objects, Blocks, Threads: added microphone note and pitch detection diff --git a/snap.html b/snap.html index f528fe5f..0981b360 100755 --- a/snap.html +++ b/snap.html @@ -6,9 +6,9 @@ - - - + + + diff --git a/src/blocks.js b/src/blocks.js index 9f122ff6..9b525a3f 100644 --- a/src/blocks.js +++ b/src/blocks.js @@ -148,7 +148,7 @@ CustomCommandBlockMorph, SymbolMorph, ToggleButtonMorph, DialMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.blocks = '2019-March-10'; +modules.blocks = '2019-March-11'; var SyntaxElementMorph; var BlockMorph; @@ -992,7 +992,9 @@ SyntaxElementMorph.prototype.labelPart = function (spec) { 'note' : ['note'], 'pitch' : ['pitch'], 'signals' : ['signals'], - 'frequencies' : ['frequencies'] + 'frequencies' : ['frequencies'], + '~' : null, + 'bins' : ['bins'] }, true // read-only ); diff --git a/src/objects.js b/src/objects.js index 48bfa500..e8081b76 100644 --- a/src/objects.js +++ b/src/objects.js @@ -84,7 +84,7 @@ BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize, TableMorph, TableFrameMorph, normalizeCanvas, BooleanSlotMorph, HandleMorph, AlignmentMorph, Process, XML_Element, VectorPaintEditorMorph*/ -modules.objects = '2019-March-10'; +modules.objects = '2019-March-11'; var SpriteMorph; var StageMorph; @@ -8871,8 +8871,7 @@ function Microphone() { this.analyser = null; // parameters: - this.signalBufferSize = 512; // should probably be 1024 by default - this.fftSize = 1024; // should probably be 2048 by default + this.resolution = 2; this.MIN_SAMPLES = 0; // will be initialized when AudioContext is created. this.GOOD_ENOUGH_CORRELATION = 0.9; @@ -8904,6 +8903,27 @@ Microphone.prototype.isOn = function () { return false; }; +// Microphone shared properties + +Microphone.prototype.binSizes = [256, 512, 1024, 2048, 4096]; + +// Microphone resolution + +Microphone.prototype.binSize = function () { + return this.binSizes[this.resolution - 1]; +}; + +Microphone.prototype.setResolution = function (num) { + if (contains([1, 2, 3, 4], num)) { + if (this.isReady) { + this.stop(); + this.resolution = num; + } + } +}; + +// Microphone ops + Microphone.prototype.start = function () { var AudioContext = window.AudioContext || window.webkitAudioContext, myself = this; @@ -8964,7 +8984,7 @@ Microphone.prototype.setupNodes = function (stream) { Microphone.prototype.createAnalyser = function () { var freqBufLength; this.analyser = this.audioContext.createAnalyser(); - this.analyser.fftSize = this.fftSize; + this.analyser.fftSize = this.binSizes[this.resolution]; freqBufLength = this.analyser.frequencyBinCount; this.freqBuffer = new Uint8Array(freqBufLength); this.pitchBuffer = new Float32Array(freqBufLength); @@ -8973,7 +8993,7 @@ Microphone.prototype.createAnalyser = function () { Microphone.prototype.createProcessor = function () { var myself = this; this.processor = this.audioContext.createScriptProcessor( - this.signalBufferSize + this.binSizes[this.resolution - 1] ); this.processor.onaudioprocess = function (event) { diff --git a/src/threads.js b/src/threads.js index f381c5b1..4e6fd682 100644 --- a/src/threads.js +++ b/src/threads.js @@ -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-March-10'; +modules.threads = '2019-March-11'; var ThreadManager; var Process; @@ -2252,9 +2252,13 @@ Process.prototype.doStopAllSounds = function () { // Process audio input (interpolated) Process.prototype.reportAudio = function (choice) { - var stage = this.blockReceiver().parentThatIsA(StageMorph); + var stage = this.blockReceiver().parentThatIsA(StageMorph), + selection = this.inputOption(choice); + if (selection === 'bins') { + return stage.microphone.binSize(); + } if (stage.microphone.isOn()) { - switch (this.inputOption(choice)) { + switch (selection) { case 'volume': return stage.microphone.volume; case 'pitch':