Skip to content

Commit

Permalink
reflect chosen freesound id and analysis parameters on URL search par…
Browse files Browse the repository at this point in the history
…ams for easy sharing of results
  • Loading branch information
jmarcosfer committed Feb 2, 2022
1 parent 9a3a499 commit 7a51d90
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 81 deletions.
75 changes: 66 additions & 9 deletions examples/demos/onsets/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div id="app">
<div id="instructions" v-if="!instructionsClosed">
<div id="instructions" v-show="!instructionsClosed">
<!-- using placeholder GIFs -->
<instructions-modal :img-link="instructionsGifs"
@closed="instructionsClosed=true">
Expand All @@ -9,11 +9,11 @@
<template slot="dismiss">Got it!</template>
</instructions-modal>
</div>
<main v-if="instructionsClosed" class="d-flex flex-column justify-content-between align-items-center">
<main v-show="instructionsClosed" class="d-flex flex-column justify-content-between align-items-center">
<demos-header></demos-header>
<section id="middle-screen" class="d-flex flex-column justify-content-around align-items-center container-fluid">
<browse-display></browse-display>
<algorithm-controls></algorithm-controls>
<algorithm-controls :init="algorithmParameters"></algorithm-controls>
</section>
<demos-footer></demos-footer>
</main>
Expand All @@ -29,6 +29,7 @@ import DemosHeader from './components/DemosHeader.vue';
import BrowseDisplay from './components/BrowseDisplayPanel.vue';
import AlgorithmControls from './components/AlgorithmControls.vue';
import audioURL from './assets/acoustic-drums.wav';
import gif1 from './assets/onset-instructions-1.gif';
import gif2 from './assets/onset-instructions-2.gif';
import gif3 from './assets/onset-instructions-3.gif';
Expand All @@ -41,11 +42,71 @@ export default {
return {
instructionsClosed: false,
audioUploaded: false,
instructionsGifs: [gif1, gif2, gif3, gif4]
instructionsGifs: [gif1, gif2, gif3, gif4],
url: new URL(window.location),
algorithmParameters: {}
}
},
created () {
// EventBus.$on()
EventBus.$on('sound-selected', sound => {
if (sound.id !== '') {
this.url.searchParams.set('id', sound.id);
window.history.pushState({}, '', this.url);
}
})
EventBus.$on('algo-params-updated', params => {
let searchParams = new URLSearchParams(params);
for (let p of searchParams) {
this.url.searchParams.set(p[0], p[1]);
}
window.history.pushState({}, '', this.url);
})
this.initAlgoParams();
},
mounted () {
function loadSound () {
// initialize sound
if (this.url.searchParams.has('id')) {
// grab from URL params (Freesound-hosted)
console.log("grab from URL params (Freesound-hosted)")
const id = this.url.searchParams.get('id');
EventBus.$emit('sound-selected', {name: '', url: '', id: id, user: '', fsLink: '', license: ''});
} else {
// load self-hosted file
console.log("load self-hosted file")
EventBus.$emit("sound-selected", {name: 'acoustic-drums', url: audioURL, id: '', user: '', fsLink: '', license: ''});
}
}
this.$nextTick(loadSound);
},
methods: {
initAlgoParams () {
let algoParams = {
frameSize: 1024,
hopSize: 512,
odfs: ["hfc","complex"],
odfsWeights: [0.5,0.5],
sensitivity: 0.65
};
if (this.url.searchParams.has('frameSize')) {
for (let p of this.url.searchParams) {
if (p[0] === 'id') continue;
let paramVal = p[1].split(',').map( v => p[0] === 'odfs' ? v : Number(v))
if (p[0] === 'odfs' || p[0] === 'odfsWeights') {
algoParams[p[0]] = paramVal;
continue;
}
algoParams[p[0]] = paramVal[0];
}
console.info('found algo params in URL!', algoParams);
}
this.algorithmParameters = algoParams;
EventBus.$emit('algo-params-init', algoParams);
}
}
}
</script>
Expand All @@ -58,8 +119,4 @@ export default {
#middle-screen {
flex-grow: 1;
}
// #algo-controls {
// height: 200px;
// }
</style>
16 changes: 10 additions & 6 deletions examples/demos/onsets/src/components/AlgorithmControls.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,23 +55,27 @@ const quickhelpContents = {
"Complex Phase": "Similar to 'Complex' but considers only phase changes, weighted by magnitude. Good for tonal sounds such as bowed string, but tends to over-detect percussive events.",
none: "Hover over any of the controls for more info."
};
const odfsNames = ['hfc', 'complex', 'flux', 'complex_phase'];
export default {
components: { ExpSlider, LinearSlider, ProportionSlider },
props: {
init: Object
},
data () {
return {
frameSize: 1024,
hopSizePercentage: 50,
frameSize: this.init.frameSize,
hopSizePercentage: this.init.hopSize * 100 / this.init.frameSize,
odfs: {
on: {
names: ["hfc", "complex"],
values: [0.5, 0.5]
names: this.init.odfs,
values: this.init.odfsWeights
},
off: {
names: ["flux", "complex_phase"]
names: odfsNames.filter( odf => !this.init.odfs.includes(odf) )
}
},
sensitivity: 0.3,
sensitivity: this.init.sensitivity,
paramsChanged: false,
currentlyHovered: "none"
}
Expand Down
9 changes: 3 additions & 6 deletions examples/demos/onsets/src/components/AudioDisplay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ import MarkersPlugin from 'wavesurfer.js/dist/plugin/wavesurfer.markers';
import RegionsPlugin from 'wavesurfer.js/dist/plugin/wavesurfer.regions';
import LicenseLogo from './LicenseLogo.vue';
import audioURL from '../assets/acoustic-drums.wav';
export default {
components: {LicenseLogo},
data () {
Expand Down Expand Up @@ -148,7 +146,9 @@ export default {
}
},
created () {
window.addEventListener('resize', this.redraw);
window.addEventListener('resize', () => {
if (this.wavesurfer) this.redraw()
});
},
mounted () {
this.height = this.$el.querySelector("#audio-display").clientHeight;
Expand Down Expand Up @@ -206,9 +206,6 @@ export default {
this.waitingOnsetsMsg = "Recalculating...";
this.waitingOnsets = true;
})
// initialize sound
EventBus.$emit("sound-selected", {name: 'acoustic-drums', url: audioURL, id: '', user: '', fsLink: '', license: ''});
}
}
</script>
Expand Down
4 changes: 3 additions & 1 deletion examples/demos/onsets/src/components/BrowseDisplayPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
Sorry, no results were found for "{{searchTerm}}" on Freesound. Try something different or upload your own.
</b-alert>
<b-alert id="search-failure" show dismissible v-show="showSearchFailureBanner" @dismissed="showSearchFailureBanner = false; searchTerm=''">
Sorry, Freesound search is currently not available. Try uploading a sound instead.
Sorry, Freesound search failed. Try another search term or sound ID, or upload your own sound instead.
</b-alert>
<freesound-results :class="[{ 'd-flex': showFreesoundResults }, { 'd-none': !showFreesoundResults }]"></freesound-results>
<audio-display v-show="!showFreesoundResults"></audio-display>
Expand Down Expand Up @@ -124,6 +124,8 @@ export default {
this.showFreesoundResults = false;
this.searchTerm = "";
})
EventBus.$on('fs-search-failed', err => this.handleSearchFailure(err));
},
mounted () {
this.uploadLabel = document.querySelector("#file-upload-label");
Expand Down
82 changes: 49 additions & 33 deletions examples/demos/onsets/src/core/audio-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,8 @@ log("Imports went OK");
self.essentia = null;

self.allowedParams = ['sampleRate', 'frameSize', 'hopSize', 'odfs', 'odfsWeights', 'sensitivity'];
self.params = {
sampleRate: 44100,
frameSize: 1024,
hopSize: 512,
odfs: ['hfc', 'complex'], // Onset Detection Function(s) list
odfsWeights: [1, 1], // per ODF weights list
sensitivity: 0.3
}; // changing odfs should require changing odfsWeights (at least length), and viceversa
self.params = {}; // changing odfs should require changing odfsWeights (at least length), and viceversa
self.fftRecomputeNeeded = true;

// global storage for slicing
self.signal = null;
Expand All @@ -39,32 +33,30 @@ try {
// COMMS
onmessage = function listenToMainThread(msg) {
switch (msg.data.request) {
case 'analyse':
case 'analyse': {
log('received analyse cmd')
// const signal = new Float32Array(msg.data.audio);
self.signal = msg.data.audio;
computeFFT();

if (self.fftRecomputeNeeded) {
computeFFT()
}
self.onsetPositions = computeOnsets();

postMessage(self.onsetPositions);
break;
case 'updateParams':
// guard: check for empty params obj
if (!msg.data.params) {
error('missing `params` object in the `updateParams` command');
return;
}
let suppliedParamList = Object.keys(msg.data.params);

// guard: check obj properties for forbidden params
if (!paramsAreAllowed(suppliedParamList)) {
error(`illegal parameter(s) in 'updateParams' command \n - ${getUnsupportedParams(suppliedParamList).join('\n - ')}`);
return;
}

let newParams = msg.data.params;
}
case 'initParams': {
let [suppliedParamList, newParams] = checkParams(msg.data.params);
self.params = {...self.params, ...newParams}; // update existing params obj
log(`updated the following params: ${suppliedParamList.join(',')}`);
log('current params are: ');
console.info(self.params);

odfParamsAreOkay(suppliedParamList, newParams);
break;
}
case 'updateParams': {
let [suppliedParamList, newParams] = checkParams(msg.data.params);

self.params = {...self.params, ...newParams}; // update existing params obj
log(`updated the following params: ${suppliedParamList.join(',')}`);
Expand All @@ -78,20 +70,21 @@ onmessage = function listenToMainThread(msg) {

if (self.polarFrames === null || self.polarFrames.length === 0) {
// file hasn't been uploaded and analysed for 1st time, or it has been cleared
error("Audio file has NOT been provided yet. Please upload an audio file and send it to the worker.")
break;
self.fftRecomputeNeeded = true;
}

if (suppliedParamList.includes('frameSize') || suppliedParamList.includes('hopSize')) {
// re-compute FFT analysis if updated params affect it (frame or hop size changed)
computeFFT();
self.fftRecomputeNeeded = true;
}

if (self.fftRecomputeNeeded) {
computeFFT()
}
// always re-compute onset positions after params update
self.onsetPositions = computeOnsets();
postMessage(self.onsetPositions);

break;
case 'slice':
}
case 'slice': {
if (!self.signal) {
error('no audio signal available for slicing');
break;
Expand All @@ -105,6 +98,7 @@ onmessage = function listenToMainThread(msg) {
// log(slices);
postMessage(slices);
break;
}
case 'clear':
// audio worker state and saved analysis should be cleared
break;
Expand Down Expand Up @@ -139,6 +133,7 @@ function computeFFT () {

frames.delete();
PolarFFT.shutdown();
self.fftRecomputeNeeded = false;
}

function computeOnsets () {
Expand Down Expand Up @@ -174,6 +169,27 @@ function sliceAudio () {

// UTILS

function checkParams (params) {
// guard: check for empty params obj
if (!params) {
error('missing `params` object in the `updateParams` command');
return;
}
let suppliedParamList = Object.keys(params);

// guard: check obj properties for forbidden params
if (!paramsAreAllowed(suppliedParamList)) {
error(`illegal parameter(s) in 'updateParams' command \n - ${getUnsupportedParams(suppliedParamList).join('\n - ')}`);
return;
}

let newParams = params;

odfParamsAreOkay(suppliedParamList, newParams);

return [suppliedParamList, newParams];
}

function paramsAreAllowed (paramsList) {
return paramsList.every( (p) => self.allowedParams.includes(p) );
}
Expand Down
Loading

0 comments on commit 7a51d90

Please sign in to comment.