diff --git a/cypress/e2e/spectrogram.cy.js b/cypress/e2e/spectrogram.cy.js index fcaa80f96..89938c72e 100644 --- a/cypress/e2e/spectrogram.cy.js +++ b/cypress/e2e/spectrogram.cy.js @@ -1,4 +1,5 @@ const id = '#waveform' +const scales = ['linear', 'mel', 'log', 'bark', 'erb'] xdescribe('WaveSurfer Spectrogram plugin tests', () => { it('should render a spectrogram', () => { @@ -81,4 +82,34 @@ xdescribe('WaveSurfer Spectrogram plugin tests', () => { }) }) }) + + scales.forEach(scale => { + it(`should display correct frequency labels with 1kHz tone (${scale})`, () => { + cy.visit('cypress/e2e/index.html') + cy.window().then((win) => { + return new Promise((resolve) => { + win.wavesurfer = win.WaveSurfer.create({ + container: id, + height: 200, + url: '../../examples/audio/1khz.mp3', + plugins: [ + win.Spectrogram.create({ + height: 200, + labels: true, + scale: scale, + frequencyMin: 0, + frequencyMax: 4000, + splitChannels: false + }), + ], + }) + + win.wavesurfer.once('ready', () => { + cy.get(id).matchImageSnapshot(`spectrogram-1khz-${scale}`) + resolve() + }) + }) + }) + }) + }) }) diff --git a/examples/audio/1khz.mp3 b/examples/audio/1khz.mp3 new file mode 100644 index 000000000..6269ad508 Binary files /dev/null and b/examples/audio/1khz.mp3 differ diff --git a/src/plugins/spectrogram.ts b/src/plugins/spectrogram.ts index 8d234c975..46658fb35 100644 --- a/src/plugins/spectrogram.ts +++ b/src/plugins/spectrogram.ts @@ -255,7 +255,7 @@ export type SpectrogramPluginOptions = { alpha?: number /** Min frequency to scale spectrogram. */ frequencyMin?: number - /** Max frequency to scale spectrogram. Set this to samplerate/4 to draw whole range of spectrogram. */ + /** Max frequency to scale spectrogram. Set this to samplerate/2 to draw whole range of spectrogram. */ frequencyMax?: number /** * Based on: https://manual.audacityteam.org/man/spectrogram_settings.html @@ -384,10 +384,12 @@ class SpectrogramPlugin extends BasePlugin freqFrom) { + // Draw background since spectrogram will not fill the entire canvas + const bgColor = this.colorMap[this.colorMap.length - 1] + spectrCc.fillStyle = `rgba(${bgColor[0]}, ${bgColor[1]}, ${bgColor[2]}, ${bgColor[3]})` + spectrCc.fillRect(0, 0, width, height * frequenciesData.length) + } + for (let c = 0; c < frequenciesData.length; c++) { // for each channel const pixels = this.resample(frequenciesData[c]) @@ -521,7 +534,7 @@ class SpectrogramPlugin extends BasePlugin freqFrom` + const rMax1 = Math.min(1, rMax) + + // Crop, scale and stack spectrograms createImageBitmap( imageData, 0, - Math.round(bitmapHeight - bitmapHeight * (freqMax / freqFrom)) / 2, + Math.round(bitmapHeight * (1 - rMax1)), width, - Math.round(bitmapHeight * ((freqMax - freqMin) / freqFrom)), + Math.round(bitmapHeight * (rMax1 - rMin)), ).then((bitmap) => { - spectrCc.drawImage(bitmap, 0, height * c, width, height * 2) + spectrCc.drawImage( + bitmap, + 0, + height * (c + 1 - rMax1 / rMax), + width, + height * rMax1 / rMax, + ) }) } @@ -637,6 +663,34 @@ class SpectrogramPlugin extends BasePlugin 0) @@ -656,7 +710,7 @@ class SpectrogramPlugin extends BasePlugin number, - scaleToHz: (scale: number) => number, ) { - const scaleMin = hzToScale(0) - const scaleMax = hzToScale(this.frequencyMax) - return scaleToHz(scaleMin + (index / labelIndex) * (scaleMax - scaleMin)) + const scaleMin = this.hzToScale(this.frequencyMin) + const scaleMax = this.hzToScale(this.frequencyMax) + return this.scaleToHz(scaleMin + (index / labelIndex) * (scaleMax - scaleMin)) } private loadLabels( @@ -796,25 +848,7 @@ class SpectrogramPlugin extends BasePlugin