UNPKG

essentia.js

Version:

JavaScript library for music/audio analysis and processing, powered by Essentia WebAssembly

54 lines (51 loc) 10.6 kB
/*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ var e=function(t,r){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(t,r)};function t(t,r){function n(){this.constructor=t}e(t,r),t.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}function r(e,t,r,n){return new(r||(r=Promise))((function(i,o){function s(e){try{u(n.next(e))}catch(e){o(e)}}function a(e){try{u(n.throw(e))}catch(e){o(e)}}function u(e){e.done?i(e.value):new r((function(t){t(e.value)})).then(s,a)}u((n=n.apply(e,t||[])).next())}))}function n(e,t){var r,n,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(r)throw new TypeError("Generator is already executing.");for(;s;)try{if(r=1,n&&(i=2&o[0]?n.return:o[0]?n.throw||((i=n.return)&&i.call(n),0):n.next)&&!(i=i.call(n,o[1])).done)return i;switch(n=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,n=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],n=0}finally{r=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}} /** * @license * Copyright (C) 2006-2020 Music Technology Group - Universitat Pompeu Fabra * * This file is part of Essentia * * Essentia is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the Free * Software Foundation (FSF), either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the Affero GNU General Public License * version 3 along with this program. If not, see http://www.gnu.org/licenses/ */var i=function(){function e(e,t,r){if(void 0===t&&(t="musicnn"),void 0===r&&(r=!1),this.essentia=null,this.module=null,this.frameSize=512,this.sampleRate=16e3,this.extractorType=t,"musicnn"===this.extractorType)this.frameSize=512;else if("vggish"===this.extractorType)this.frameSize=400;else{if("tempocnn"!==this.extractorType)throw Error("Invalid 'extractorType' choice! Available types are [musicnn', 'vggish', 'tempocnn']");this.frameSize=1024}this.essentia=new e.EssentiaJS(r),this.module=e}return e.prototype.arrayToVector=function(e){return this.module.arrayToVector(e)},e.prototype.vectorToArray=function(e){return this.module.vectorToArray(e)},e.prototype.getAudioBufferFromURL=function(e,t){return r(this,void 0,void 0,(function(){var r;return n(this,(function(n){switch(n.label){case 0:return[4,fetch(e)];case 1:return[4,n.sent().arrayBuffer()];case 2:return r=n.sent(),[4,t.decodeAudioData(r)];case 3:return[2,n.sent()]}}))}))},e.prototype.audioBufferToMonoSignal=function(e){if(1===e.numberOfChannels)return e.getChannelData(0);if(2===e.numberOfChannels){var t=this.arrayToVector(e.getChannelData(0)),r=this.arrayToVector(e.getChannelData(1)),n=this.essentia.MonoMixer(t,r);return this.vectorToArray(n)}throw new Error("Unexpected number of channels found in audio buffer. Only accepts mono or stereo audio buffers.")},e.prototype.downsampleAudioBuffer=function(e){var t=new OfflineAudioContext(1,e.duration*this.sampleRate,this.sampleRate),r=t.createBuffer(1,e.length,e.sampleRate);r.copyToChannel(this.audioBufferToMonoSignal(e),0);var n=t.createBufferSource();return n.buffer=r,n.connect(t.destination),new Promise((function(e){t.oncomplete=function(t){var r=t.renderedBuffer.getChannelData(0);e(r)},t.startRendering(),n.start(0)}))},e.prototype.compute=function(e){var t;switch(t=e instanceof Float32Array?this.arrayToVector(e):e,this.extractorType){case"musicnn":if(e.length!=this.frameSize)throw new Error("The chosen `extractorType` only works with an audio signal frame size of "+this.frameSize);var r=this.essentia.TensorflowInputMusiCNN(t);return{melSpectrum:this.vectorToArray(r.bands),frameSize:1,patchSize:187,melBandsSize:96};case"vggish":if(e.length!=this.frameSize)throw new Error("The chosen `extractorType` only works with an audio signal frame size of 400 "+this.frameSize);r=this.essentia.TensorflowInputVGGish(t);return{melSpectrum:this.vectorToArray(r.bands),frameSize:1,patchSize:96,melBandsSize:64};case"tempocnn":if(e.length!=this.frameSize)throw Error("The chosen `extractorType` only works with an audio signal frame size of "+this.frameSize);r=this.essentia.TensorflowInputTempoCNN(t);return{melSpectrum:this.vectorToArray(r.bands),frameSize:1,patchSize:256,melBandsSize:40};default:throw Error("Invalid 'extractorType' choice! Available types are [musicnn', 'vggish', 'tempocnn']")}},e.prototype.computeFrameWise=function(e,t){var r;r=t||this.frameSize;for(var n=this.essentia.FrameGenerator(e,this.frameSize,r),i=[],o=null,s=0;s<n.size();s++)o=this.compute(this.vectorToArray(n.get(s))),i.push(o.melSpectrum);return o.melSpectrum=i,o.frameSize=n.size(),n.delete(),o},e.prototype.delete=function(){this.essentia.delete()},e.prototype.shutdown=function(){this.essentia.shutdown()},e}(),o=function(){function e(e,t,r){this.model=null,this.audioSampleRate=16e3,this.tf=null,this.isReady=!1,this.modelPath="",this.IS_TRAIN=null,this.randomTensorInput=null,this.minimumInputFrameSize=null,this.tf=e,this.IS_TRAIN=this.tf.tensor([0],[1],"bool"),this.modelPath=t,this.isReady=!!this.model}return e.prototype.initialize=function(){return r(this,void 0,void 0,(function(){var e;return n(this,(function(t){switch(t.label){case 0:return e=this,[4,this.tf.loadGraphModel(this.modelPath)];case 1:return e.model=t.sent(),this.isReady=!0,[2]}}))}))},e.prototype.arrayToTensorAsBatches=function(e,t,r,n){void 0===n&&(n=!1);var i,o,s=this.tf.tensor(e,t,"float32");return n?t[0]===r?s.as3D(1,r,t[1]):t[0]>r?t[0]%r!=0?(o=Math.floor(t[0]/r)+1,i=this.tf.zeros([Math.floor(o*r-e.length),t[1]],"float32"),s=s.concat(i),i.dispose(),s.as3D(o,r,t[1])):(o=Math.floor(t[0]/r),i=this.tf.zeros([Math.floor(o*r-e.length),t[1]],"float32"),s=s.concat(i),i.dispose(),s.as3D(o,r,t[1])):(o=1,i=this.tf.zeros([r-t[0],t[1]]),s=s.concat(i),i.dispose(),s.as3D(o,r,t[1])):(this.assertMinimumFeatureInputSize({melSpectrum:e,frameSize:t[0],melBandsSize:t[1],patchSize:r}),s.as3D(1,r,t[1]))},e.prototype.dispose=function(){this.model.dispose()},e.prototype.assertMinimumFeatureInputSize=function(e){if(this.minimumInputFrameSize=e.patchSize,e.melSpectrum.length!=this.minimumInputFrameSize)throw Error("When `padding=false` in `predict` method, the model expect audio feature for a minimum frame size of "+this.minimumInputFrameSize+". Was given "+e.melSpectrum.length+" melband frames")},e.prototype.disambiguateExtraInputs=function(){if(!this.isReady)throw Error("No loaded tfjs model found! Make sure to call `initialize` method and resolve the promise before calling `predict` method.");var e=this.model.executor.inputs.length;if(1===e)return[];if(2===e)return[this.IS_TRAIN.clone()];if(3===e)return this.randomTensorInput||(this.randomTensorInput=this.tf.zeros([1,this.model.executor.inputs[0].shape[1]])),[this.randomTensorInput.clone(),this.IS_TRAIN.clone()];throw Error("Found unsupported number of input requirements for the model. Expects the following inputs -> "+this.model.executor.inputs)},e}(),s=function(e){function i(t,r,n){var i=e.call(this,t,r)||this;return i.minimumInputFrameSize=3,i}return t(i,e),i.prototype.predict=function(e,t){return void 0===t&&(t=!1),r(this,void 0,void 0,(function(){var r,i,o,s;return n(this,(function(n){switch(n.label){case 0:return r=this.arrayToTensorAsBatches(e.melSpectrum,[e.frameSize,e.melBandsSize],e.patchSize,t),(i=this.disambiguateExtraInputs()).push(r),o=this.model.execute(i),r.dispose(),[4,o.array()];case 1:return s=n.sent(),o.dispose(),[2,s]}}))}))},i}(o),a=function(e){function i(t,r,n){return e.call(this,t,r)||this}return t(i,e),i.prototype.predict=function(e,t){return void 0===t&&(t=!1),r(this,void 0,void 0,(function(){var r,i,o,s;return n(this,(function(n){switch(n.label){case 0:return r=this.arrayToTensorAsBatches(e.melSpectrum,[e.frameSize,e.melBandsSize],e.patchSize,t),(i=this.disambiguateExtraInputs()).push(r),o=this.model.execute(i),r.dispose(),[4,o.array()];case 1:return s=n.sent(),o.dispose(),[2,s]}}))}))},i}(o); /** * @license * Copyright (C) 2006-2020 Music Technology Group - Universitat Pompeu Fabra * * This file is part of Essentia * * Essentia is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the Free * Software Foundation (FSF), either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the Affero GNU General Public License * version 3 along with this program. If not, see http://www.gnu.org/licenses/ */export{i as EssentiaTFInputExtractor,o as EssentiaTensorflowJSModel,s as TensorflowMusiCNN,a as TensorflowVGGish};