| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 | /** * Create a WaveSurfer instance. */var wavesurfer;/** * Init & load. */document.addEventListener('DOMContentLoaded', function () {    // Init wavesurfer    wavesurfer = WaveSurfer.create({        container: '#waveform',        height: 100,        pixelRatio: 1,        scrollParent: true,        normalize: true,        minimap: true,        backend: 'MediaElement',        plugins: [            WaveSurfer.regions.create(),            WaveSurfer.minimap.create({                height: 30,                waveColor: '#ddd',                progressColor: '#999',                cursorColor: '#999'            }),            WaveSurfer.timeline.create({                container: "#wave-timeline"            })        ]    });    wavesurfer.util.ajax({        responseType: 'json',        url: 'rashomon.json'    }).on('success', function (data) {        wavesurfer.load(            'http://www.archive.org/download/mshortworks_001_1202_librivox/msw001_03_rashomon_akutagawa_mt_64kb.mp3',            data        );    });    /* Regions */    wavesurfer.on('ready', function () {        wavesurfer.enableDragSelection({            color: randomColor(0.1)        });        if (localStorage.regions) {            loadRegions(JSON.parse(localStorage.regions));        } else {            // loadRegions(            //     extractRegions(            //         wavesurfer.backend.getPeaks(512),            //         wavesurfer.getDuration()            //     )            // );            wavesurfer.util.ajax({                responseType: 'json',                url: 'annotations.json'            }).on('success', function (data) {                loadRegions(data);                saveRegions();            });        }    });    wavesurfer.on('region-click', function (region, e) {        e.stopPropagation();        // Play on click, loop on shift click        e.shiftKey ? region.playLoop() : region.play();    });    wavesurfer.on('region-click', editAnnotation);    wavesurfer.on('region-updated', saveRegions);    wavesurfer.on('region-removed', saveRegions);    wavesurfer.on('region-in', showNote);    wavesurfer.on('region-play', function (region) {        region.once('out', function () {            wavesurfer.play(region.start);            wavesurfer.pause();        });    });    /* Toggle play/pause buttons. */    var playButton = document.querySelector('#play');    var pauseButton = document.querySelector('#pause');    wavesurfer.on('play', function () {        playButton.style.display = 'none';        pauseButton.style.display = '';    });    wavesurfer.on('pause', function () {        playButton.style.display = '';        pauseButton.style.display = 'none';    });});/** * Save annotations to localStorage. */function saveRegions() {    localStorage.regions = JSON.stringify(        Object.keys(wavesurfer.regions.list).map(function (id) {            var region = wavesurfer.regions.list[id];            return {                start: region.start,                end: region.end,                attributes: region.attributes,                data: region.data            };        })    );}/** * Load regions from localStorage. */function loadRegions(regions) {    regions.forEach(function (region) {        region.color = randomColor(0.1);        wavesurfer.addRegion(region);    });}/** * Extract regions separated by silence. */function extractRegions(peaks, duration) {    // Silence params    var minValue = 0.0015;    var minSeconds = 0.25;    var length = peaks.length;    var coef = duration / length;    var minLen = minSeconds / coef;    // Gather silence indeces    var silences = [];    Array.prototype.forEach.call(peaks, function (val, index) {        if (Math.abs(val) <= minValue) {            silences.push(index);        }    });    // Cluster silence values    var clusters = [];    silences.forEach(function (val, index) {        if (clusters.length && val == silences[index - 1] + 1) {            clusters[clusters.length - 1].push(val);        } else {            clusters.push([ val ]);        }    });    // Filter silence clusters by minimum length    var fClusters = clusters.filter(function (cluster) {        return cluster.length >= minLen;    });    // Create regions on the edges of silences    var regions = fClusters.map(function (cluster, index) {        var next = fClusters[index + 1];        return {            start: cluster[cluster.length - 1],            end: (next ? next[0] : length - 1)        };    });    // Add an initial region if the audio doesn't start with silence    var firstCluster = fClusters[0];    if (firstCluster && firstCluster[0] != 0) {        regions.unshift({            start: 0,            end: firstCluster[firstCluster.length - 1]        });    }    // Filter regions by minimum length    var fRegions = regions.filter(function (reg) {        return reg.end - reg.start >= minLen;    });    // Return time-based regions    return fRegions.map(function (reg) {        return {            start: Math.round(reg.start * coef * 10) / 10,            end: Math.round(reg.end * coef * 10) / 10        };    });}/** * Random RGBA color. */function randomColor(alpha) {    return 'rgba(' + [        ~~(Math.random() * 255),        ~~(Math.random() * 255),        ~~(Math.random() * 255),        alpha || 1    ] + ')';}/** * Edit annotation for a region. */function editAnnotation (region) {    var form = document.forms.edit;    form.style.opacity = 1;    form.elements.start.value = Math.round(region.start * 10) / 10,    form.elements.end.value = Math.round(region.end * 10) / 10;    form.elements.note.value = region.data.note || '';    form.onsubmit = function (e) {        e.preventDefault();        region.update({            start: form.elements.start.value,            end: form.elements.end.value,            data: {                note: form.elements.note.value            }        });        form.style.opacity = 0;    };    form.onreset = function () {        form.style.opacity = 0;        form.dataset.region = null;    };    form.dataset.region = region.id;}/** * Display annotation. */function showNote (region) {    if (!showNote.el) {        showNote.el = document.querySelector('#subtitle');    }    showNote.el.textContent = region.data.note || '–';}/** * Bind controls. */GLOBAL_ACTIONS['delete-region'] = function () {    var form = document.forms.edit;    var regionId = form.dataset.region;    if (regionId) {        wavesurfer.regions.list[regionId].remove();        form.reset();    }};GLOBAL_ACTIONS['export'] = function () {    window.open('data:application/json;charset=utf-8,' +        encodeURIComponent(localStorage.regions));};
 |