UNPKG

essentia.js

Version:

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

54 lines (51 loc) 11 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).EssentiaModel={})}(this,(function(e){"use strict"; /*! ***************************************************************************** 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 t=function(e,r){return(t=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])})(e,r)};function r(e,r){function n(){this.constructor=e}t(e,r),e.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}function n(e,t,r,n){return new(r||(r=Promise))((function(o,i){function s(e){try{u(n.next(e))}catch(e){i(e)}}function a(e){try{u(n.throw(e))}catch(e){i(e)}}function u(e){e.done?o(e.value):new r((function(t){t(e.value)})).then(s,a)}u((n=n.apply(e,t||[])).next())}))}function o(e,t){var r,n,o,i,s={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(r)throw new TypeError("Generator is already executing.");for(;s;)try{if(r=1,n&&(o=2&i[0]?n.return:i[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,i[1])).done)return o;switch(n=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return s.label++,{value:i[1],done:!1};case 5:s.label++,n=i[1],i=[0];continue;case 7:i=s.ops.pop(),s.trys.pop();continue;default:if(!(o=s.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){s=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){s.label=i[1];break}if(6===i[0]&&s.label<o[1]){s.label=o[1],o=i;break}if(o&&s.label<o[2]){s.label=o[2],s.ops.push(i);break}o[2]&&s.ops.pop(),s.trys.pop();continue}i=t.call(e,s)}catch(e){i=[6,e],n=0}finally{r=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,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 n(this,void 0,void 0,(function(){var r;return o(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).audio;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),o=[],i=null,s=0;s<n.size();s++)i=this.compute(this.vectorToArray(n.get(s))),o.push(i.melSpectrum);return i.melSpectrum=o,i.frameSize=n.size(),n.delete(),i},e.prototype.delete=function(){this.essentia.delete()},e.prototype.shutdown=function(){this.essentia.shutdown()},e}(),s=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 n(this,void 0,void 0,(function(){var e;return o(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 o,i,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?(i=Math.floor(t[0]/r)+1,o=this.tf.zeros([Math.floor(i*r-e.length),t[1]],"float32"),s=s.concat(o),o.dispose(),s.as3D(i,r,t[1])):(i=Math.floor(t[0]/r),o=this.tf.zeros([Math.floor(i*r-e.length),t[1]],"float32"),s=s.concat(o),o.dispose(),s.as3D(i,r,t[1])):(i=1,o=this.tf.zeros([r-t[0],t[1]]),s=s.concat(o),o.dispose(),s.as3D(i,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}(),a=function(e){function t(t,r,n){var o=e.call(this,t,r)||this;return o.minimumInputFrameSize=3,o}return r(t,e),t.prototype.predict=function(e,t){return void 0===t&&(t=!1),n(this,void 0,void 0,(function(){var r,n,i,s;return o(this,(function(o){switch(o.label){case 0:return r=this.arrayToTensorAsBatches(e.melSpectrum,[e.frameSize,e.melBandsSize],e.patchSize,t),(n=this.disambiguateExtraInputs()).push(r),i=this.model.execute(n),r.dispose(),[4,i.array()];case 1:return s=o.sent(),i.dispose(),[2,s]}}))}))},t}(s),u=function(e){function t(t,r,n){return e.call(this,t,r)||this}return r(t,e),t.prototype.predict=function(e,t){return void 0===t&&(t=!1),n(this,void 0,void 0,(function(){var r,n,i,s;return o(this,(function(o){switch(o.label){case 0:return r=this.arrayToTensorAsBatches(e.melSpectrum,[e.frameSize,e.melBandsSize],e.patchSize,t),(n=this.disambiguateExtraInputs()).push(r),i=this.model.execute(n),r.dispose(),[4,i.array()];case 1:return s=o.sent(),i.dispose(),[2,s]}}))}))},t}(s); /** * @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/ */e.EssentiaTFInputExtractor=i,e.EssentiaTensorflowJSModel=s,e.TensorflowMusiCNN=a,e.TensorflowVGGish=u,Object.defineProperty(e,"__esModule",{value:!0})}));