Skip to content

Commit

Permalink
Next: Ports from master and bugfixes (#1035)
Browse files Browse the repository at this point in the history
* added contributing info (#1006)

* Readded global audio context singleton, functionally equal to PR #1021

* Cleanup npm package (#995)

* ignore eclipse project files

* exclude everything except dist, plugin and src directories in npm package

* only include minified plugins in npm package

* updated .npmignore to exclude everything except dist and src directories and subdirectories

* Add support for forceDecode (#1009)

* Add support for forceDecode

Adds the `forceDecode` option to force client side decoding of the audio after download regardless if pre-decoded peaks are passed to the `.load/2` method. This is primarily for use with `.zoom/1` to enable high fidelity rendering on zoom. Without local decoding, the zoom on pre-decoded peaks is very low fidelity.

* Update conditional brackets for failing test

* nullify this.arraybuffer when destroying to prevent memory leak

* removed <<<< HEAD

* return array when using getImage() (#1027)

* return array when using getImage()

* return one canvas image data if not multiple canvases

* Update drawer.multicanvas.js

* updated getImage()

* add comments fir getImage()

* updated comments

* updated getImage to es6 syntax and applied jsdoc formatting

* create new labels feature for spectrogram plugin (#984)

* create new labels feature for spectrogram plugin

- create labels parameter (true|false)
- create labels element and canvas
- create labels frequency method loadLabels();
- update createWrapper() method and apply labels feature parameter.

* create new labels feature for spectrogram plugin

create new labels feature for spectrogram plugin

- create labels parameter (true|false)
- create labels element and canvas
- create labels frequency method loadLabels();
- update createWrapper() method and apply labels feature parameter.

* remove extra spaces

* removed one more extra white space :)

* update css formatting

* remove extra space

* remove extra space

* Updated spectrogram labels to es6

* add getFilters method (#982)

* add getFilters method

* add getFilters() method

add 'Filters must be set with setFilters method first' note.

* return empty array if no filters are set

* change to `return this.backend.filters || [];`

* add debounce to resize/orientationchange event for minimap plugin (#987)

* add debounce to resize event
* add orientationchange event

* getVolume method (#978)

* getVolume method

returns the current gainNode volume.

* added getVolume method

* added getVolume method

* updated getVolume to es6 syntax

* avoid error when calling pause before play (#977)

This prevents a `Failed to execute 'stop' on 'AudioBufferSourceNode'` when stop() is called before play().

* fix getDuration() return value when using MediaElement (#941)

* fix getDuration() return value for MediaElement

change getDuration function in mediaelement.js to return the correct duration length same as WebAudio.

from
        var duration = this.media.duration; // incorrect duration value returned
        console.log preview:
        https://cloud.githubusercontent.com/assets/5193884/22399178/6d26c1fe-e565-11e6-9b13-e6107641666a.png
to
        var duration = this.buffer.duration; // correct duration value returned same as WebAudio
        console.log preview:
        https://cloud.githubusercontent.com/assets/5193884/22393549/7b130096-e4d6-11e6-83ff-4ebb78b9e42f.png

* Update mediaelement.js

* add wavesurfer.getPlaybackRate() (#939)

add getPlaybackRate method and return playback rate.
  • Loading branch information
mspae authored Mar 8, 2017
1 parent ea5b15f commit bbfa222
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 20 deletions.
26 changes: 26 additions & 0 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Hey, thank you for testing and contributing to wavesurfer.js!

## Please make sure you can check all of these points below before opening an issue:

(You don't have to post this section)

- [ ] I have checked [the FAQ](https://wavesurfer-js.org/faq/) and it doesn't solve my problem.
- [ ] I have checked [the documentation](https://wavesurfer-js.org/docs/) and it doesn't solve my problem
- [ ] I have searched for [already open issues](https://github.com/katspaugh/wavesurfer.js/issues) which desribe my problem.
- [ ] The issue I'm having is related to and caused by wavesurfer.js, not by other software (which maybe packages and uses wavesurfer incorrectly) – In that case you should open the issue on the respective project pages.

## Please make sure you provide the following information (if applicable):

### Wavesurfer.js version(s):


### Browser version(s):


### Code needed to reproduce the issue:

(Please reduce your code as much as possible and only post the minimum code needed to reproduce the issue. [A Code pen](http://codepen.io/) is an excellent way to share such code)


### Use behaviour needed to reproduce the issue:

21 changes: 21 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Hey, thank you for contributing to wavesurfer.js!

To review/merge open PRs it is very helpful to know as much as possible about the changes which are being introduced. Reviewing PRs is very time consuming, please be patient, it can take some time to do properly.

**Title:** Please make sure the name of your PR is as descriptive as possible (Describe the feature that is introduced or the bug that is being fixed).

## Please make sure you provide the information below:

### Short description of changes:


### Breaking in the external API:


### Breaking changes in the internal API:


### Todos/Notes:


### Related Issues and other PRs:
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ dist/plugin/*.js
/_SpecRunner.html
.DS_Store
.idea
.project
7 changes: 4 additions & 3 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/dist/wavesurfer.min.js.map
/dist/wavesurfer.amd.js
/dist/wavesurfer.min.js
# exclude everything except dist and src
**/*
!dist/**
!src/**
12 changes: 12 additions & 0 deletions src/drawer.multicanvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,18 @@ export default class MultiCanvas extends Drawer {
}
}

/**
* Return image data of the waveform
*
* @param {string} type='image/png' An optional value of a format type.
* @param {number} quality=0.92 An optional value between 0 and 1.
* @return {string|string[]} images A data URL or an array of data URLs
*/
getImage(type, quality) {
const images = this.canvases.map(entry => entry.wave.toDataURL(type, quality));
return images.length > 1 ? images : images[0];
}

/**
* Render the new progress
*
Expand Down
2 changes: 1 addition & 1 deletion src/mediaelement.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export default class MediaElement extends WebAudio {
* @return {number}
*/
getDuration() {
let duration = this.media.duration;
var duration = (this.buffer || this.media).duration;
if (duration >= Infinity) { // streaming audio
duration = this.media.seekable.end(0);
}
Expand Down
6 changes: 4 additions & 2 deletions src/plugin/minimap.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,13 @@ export default function(params = {}) {
}
};
let prevWidth = 0;
this._onResize = () => {
this._onResize = wavesurfer.util.debounce(() => {
if (prevWidth != this.wrapper.clientWidth) {
prevWidth = this.wrapper.clientWidth;
this.render();
this.progress(this.wavesurfer.backend.getPlayedPercents());
}
};
});
}

init() {
Expand All @@ -103,6 +103,7 @@ export default function(params = {}) {

destroy() {
window.removeEventListener('resize', this._onResize, true);
window.removeEventListener('orientationchange', this._onResize, true);
this.wavesurfer.drawer.wrapper.removeEventListener('mouseover', this._onMouseover);
this.wavesurfer.un('ready', this._onReady);
this.wavesurfer.un('seek', this._onSeek);
Expand Down Expand Up @@ -177,6 +178,7 @@ export default function(params = {}) {

bindWaveSurferEvents() {
window.addEventListener('resize', this._onResize, true);
window.addEventListener('orientationchange', this._onResize, true);
this.wavesurfer.on('audioprocess', this._onAudioprocess);
this.wavesurfer.on('seek', this._onSeek);
if (this.params.showOverview) {
Expand Down
82 changes: 78 additions & 4 deletions src/plugin/spectrogram.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,22 @@ export default function spectrogram(params = {}) {
if (prevSpectrogram) {
this.container.removeChild(prevSpectrogram);
}

const wsParams = this.wavesurfer.params;
this.wrapper = document.createElement('spectrogram');
// if labels are active
if (this.params.labels) {
const labelsEl = this.labelsEl = document.createElement('canvas');
labelsEl.classList.add('spec-labels');
this.drawer.style(labelsEl, {
left: 0,
position: 'absolute',
zIndex: 9
});
this.wrapper.appendChild(labelsEl);
// can be customized in next version
this.loadLabels('rgba(68,68,68,0.5)', '12px', '10px', '', '#fff', '#f7f7f7', 'center', '#specLabels');
}

this.wrapper = this.container.appendChild(
document.createElement('spectrogram')
);
this.drawer.style(this.wrapper, {
display: 'block',
position: 'relative',
Expand All @@ -292,6 +302,7 @@ export default function spectrogram(params = {}) {
overflowY: 'hidden'
});
}
this.container.appendChild(this.wrapper);

this.wrapper.addEventListener('click', e => {
e.preventDefault();
Expand Down Expand Up @@ -394,6 +405,69 @@ export default function spectrogram(params = {}) {
return ajax;
}

freqType(freq) {
return (freq >= 1000 ? (freq / 1000).toFixed(1) : Math.round(freq));
}

unitType(freq) {
return (freq >= 1000 ? 'KHz' : 'Hz');
}

loadLabels(bgFill, fontSizeFreq, fontSizeUnit, fontType, textColorFreq, textColorUnit, textAlign, container) {
const frequenciesHeight = this.height;
bgFill = bgFill || 'rgba(68,68,68,0)';
fontSizeFreq = fontSizeFreq || '12px';
fontSizeUnit = fontSizeUnit || '10px';
fontType = fontType || 'Helvetica';
textColorFreq = textColorFreq || '#fff';
textColorUnit = textColorUnit || '#fff';
textAlign = textAlign || 'center';
container = container || '#specLabels';
const getMaxY = frequenciesHeight || 512;
const labelIndex = 5 * (getMaxY / 256);
const freqStart = 0;
const step = ((this.wavesurfer.backend.ac.sampleRate / 2) - freqStart) / labelIndex;

const ctx = this.labelsEl.getContext('2d');
this.labelsEl.height = this.height / this.pixelRatio;
this.labelsEl.width = 55;

ctx.fillStyle = bgFill;
ctx.fillRect(0, 0, 55, getMaxY);
ctx.fill();
let i;

for (i = 0; i <= labelIndex; i++) {
ctx.textAlign = textAlign;
ctx.textBaseline = 'middle';

const freq = freqStart + (step * i);
const index = Math.round(freq / (this.sampleRate / 2) * this.fftSamples);
const percent = index / this.fftSamples / 2;
const y = (1 - percent) * this.height;
const label = this.freqType(freq);
const units = this.unitType(freq);
const x = 16;
const yLabelOffset = 2;

if (i == 0) {
ctx.fillStyle = textColorUnit;
ctx.font = fontSizeUnit + ' ' + fontType;
ctx.fillText(units, x + 24, getMaxY + i - 10);
ctx.fillStyle = textColorFreq;
ctx.font = fontSizeFreq + ' ' + fontType;
ctx.fillText(label, x, getMaxY + i - 10);
} else {
ctx.fillStyle = textColorUnit;
ctx.font = fontSizeUnit + ' ' + fontType;
ctx.fillText(units, x + 24, getMaxY - i * 50 + yLabelOffset);
ctx.fillStyle = textColorFreq;
ctx.font = fontSizeFreq + ' ' + fontType;
ctx.fillText(label, x, getMaxY - i * 50 + yLabelOffset);
}
}
}

updateScroll(e) {
this.wrapper.scrollLeft = e.target.scrollLeft;
}
Expand Down
47 changes: 43 additions & 4 deletions src/wavesurfer.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,17 @@ import PeakCache from './peakcache';
* @property {string} backend='WebAudio' `'WebAudio'|'MediaElement'` In most cases
* you don't have to set this manually. MediaElement is a fallback for
* unsupported browsers.
* @property {boolean} closeAudioContext=false Close and nullify all audio
* contexts when the destroy method is called.
* @property {!string|HTMLElement} container CSS selector or HTML element where
* the waveform should be drawn. This is the only required parameter.
* @property {string} cursorColor='#333' The fill color of the cursor indicating
* the playhead position.
* @property {number} cursorWidth=1 Measured in pixels.
* @property {boolean} fillParent=true Whether to fill the entire container or
* draw only according to `minPxPerSec`.
* @property {boolean} forceDecode=false Force decoding of audio using web audio
* when zooming to get a more detailed waveform.
* @property {number} height=128 The height of the waveform. Measured in
* pixels.
* @property {boolean} hideScrollbar=false Whether to hide the horizontal
Expand Down Expand Up @@ -131,6 +135,7 @@ export default class WaveSurfer extends util.Observer {
cursorWidth : 1,
dragSelection : true,
fillParent : true,
forceDecode : true,
height : 128,
hideScrollbar : false,
interact : true,
Expand Down Expand Up @@ -585,7 +590,7 @@ export default class WaveSurfer extends util.Observer {
* @example wavesurfer.pause();
*/
pause() {
this.backend.pause();
this.backend.isPaused() || this.backend.pause();
}

/**
Expand Down Expand Up @@ -710,6 +715,16 @@ export default class WaveSurfer extends util.Observer {
this.backend.setVolume(newVolume);
}

/**
* Get the playback volume.
*
* @return {number} A value between 0 and 1, 0 being no
* volume and 1 being full volume.
*/
getVolume () {
return this.backend.getVolume();
}

/**
* Set the playback rate.
*
Expand All @@ -721,6 +736,15 @@ export default class WaveSurfer extends util.Observer {
this.backend.setPlaybackRate(rate);
}

/**
* Get the playback rate.
*
* @return {number}
*/
getPlaybackRate() {
return this.backend.getPlaybackRate();
}

/**
* Toggle the volume on and off. It not currenly muted it will save the
* current volume value and turn the volume off. If currently muted then it
Expand Down Expand Up @@ -761,6 +785,16 @@ export default class WaveSurfer extends util.Observer {
}
}

/**
* Get the current mute status.
*
* @example const isMuted = wavesurfer.getMute();
* @return {boolean}
*/
getMute() {
return this.isMuted;
}

/**
* Toggles `scrollParent` and redraws
*
Expand Down Expand Up @@ -970,14 +1004,18 @@ export default class WaveSurfer extends util.Observer {
this.backend.once('error', err => this.fireEvent('error', err))
);

// If no pre-decoded peaks provided, attempt to download the audio file
// and decode it with Web Audio.
// If no pre-decoded peaks provided or pre-decoded peaks are
// provided with forceDecode flag, attempt to download the
// audio file and decode it with Web Audio.
if (peaks) {
this.backend.setPeaks(peaks);
} else if (this.backend.supportsWebAudio()) {
}

if ((!peaks || this.params.forceDecode) && this.backend.supportsWebAudio()) {
this.getArrayBuffer(url, arraybuffer => {
this.decodeArrayBuffer(arraybuffer, buffer => {
this.backend.buffer = buffer;
this.backend.setPeaks(null);
this.drawBuffer();
this.fireEvent('waveform-ready');
});
Expand Down Expand Up @@ -1154,5 +1192,6 @@ export default class WaveSurfer extends util.Observer {
this.backend.destroy();
this.drawer.destroy();
this.isDestroyed = true;
this.arraybuffer = null;
}
}
31 changes: 25 additions & 6 deletions src/webaudio.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ export default class WebAudio extends util.Observer {
* @return {AudioContext}
*/
getAudioContext() {
if (!this.audioContext) {
this.audioContext = new (
if (!window.WaveSurferAudioContext) {
window.WaveSurferAudioContext = new (
window.AudioContext || window.webkitAudioContext
);
}
return this.audioContext;
return window.WaveSurferAudioContext;
}

/**
Expand All @@ -87,12 +87,12 @@ export default class WebAudio extends util.Observer {
* @return {OfflineAudioContext}
*/
getOfflineAudioContext(sampleRate) {
if (!this.offlineAudioContext) {
this.offlineAudioContext = new (
if (!window.WaveSurferOfflineAudioContext) {
window.WaveSurferOfflineAudioContext = new (
window.OfflineAudioContext || window.webkitOfflineAudioContext
)(1, 2, sampleRate);
}
return this.offlineAudioContext;
return window.WaveSurferOfflineAudioContext;
}

/**
Expand Down Expand Up @@ -420,6 +420,25 @@ export default class WebAudio extends util.Observer {
this.gainNode.disconnect();
this.scriptNode.disconnect();
this.analyser.disconnect();

// close the audioContext if closeAudioContext option is set to true
if (this.params.closeAudioContext) {
// check if browser supports AudioContext.close()
if (typeof this.ac.close === 'function') {
this.ac.close();
}
// clear the reference to the audiocontext
this.ac = null;
// clear the actual audiocontext, either passed as param or the
// global singleton
if (!this.params.audioContext) {
window.WaveSurferAudioContext = null;
} else {
this.params.audioContext = null;
}
// clear the offlineAudioContext
window.WaveSurferOfflineAudioContext = null;
}
}

/**
Expand Down

0 comments on commit bbfa222

Please sign in to comment.