Skip to content

Commit

Permalink
bundle a fftw-js compiled with latest emscripten for any files length…
Browse files Browse the repository at this point in the history
… analysis

due to the latest emscripten the library interface was slightly updated with promise based initialization
  • Loading branch information
grz0zrg committed Jul 12, 2020
1 parent f36e623 commit d5dc1e7
Show file tree
Hide file tree
Showing 7 changed files with 1,443 additions and 1,293 deletions.
40 changes: 33 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ Run the demo in default browser (which will use `http-server` to avoid CORS issu
`npm install ccwt.js --save`

```js
let CCWT = require('ccwt.js')
const CCWT = require('ccwt.js')

CCWT.onReady = function () {
// CCWT.frequencyBand
// CCWT.fft1d
// CCWT.numericOutput
CCWT.then((ccwt_lib) => {
// ccwt_lib.frequencyBand
// ccwt_lib.fft1d
// ccwt_lib.numericOutput
// see demo/index.html :)
}
});
```

## Browser
Expand All @@ -54,7 +54,7 @@ See `demo/index.html`

## Documentation

First register a ready callback to `CCWT.onReady`, it will fire once the library is initialized
Include the library file `ccwt.js`, the web version define a `CCWT` symbol globally which is a promise (which load the FFTW .wasm file) which when resolved return the CCWT library object where all functions are defined.

Then there is only 3 functions needed :

Expand All @@ -71,3 +71,29 @@ The provided example `demo/index.html` has everything needed to generate a linea
All usable CCWT functions in `src/ccwt.js` are documented using JSDoc

The [original tutorial](https://github.com/Lichtso/CCWT/wiki/Tutorial) can also help (note : functions name are the same but arguments orders aren't)

## fftw-js

This library use a modified [fftw-js](https://github.com/dean-shaff/fftw-js) library which is a Javascript port via Emscripten of the FFTW library.

The modifications include :

* compiled with Emscripten 1.39.17 (latest right now)
* compiled with `-s ALLOW_MEMORY_GROWTH=1` to allow arbitrary files length analysis

There is also a small modification of the glue code to silence warnings related to errno.

Note : The original `Makefile.emscripten` of the fftw-js library had to be modified a bit to produce a correct build, here are the options used :

```bash
OPTIONS=--memory-init-file 0 \
-s FILESYSTEM=0 \
-s PRECISE_F32=1 \
-s MODULARIZE=1 \
-s WASM=1 \
-s ALLOW_MEMORY_GROWTH=1 \
-s EXPORT_NAME="'FFTWModule'" \
-s EXPORTED_FUNCTIONS=$(EXPORTED_FUNCTIONS) \
-s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap']"

```
Binary file modified demo/dist/FFTW.wasm
Binary file not shown.
2 changes: 1 addition & 1 deletion demo/dist/ccwt.js

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
canvas_ctx.fillStyle = "#000000"
canvas_ctx.fillRect(0, 0, canvas.width, canvas.height)

CCWT.onReady = function () {
CCWT.then((ccwt_lib) => {
// load audio
const audio_context = new window.AudioContext({
sampleRate: 44100
Expand Down Expand Up @@ -56,15 +56,15 @@
const frequency_offset_log = minimum_octave

// linear
//CCWT.frequencyBand(frequencies, height, frequency_range_linear, frequency_offset_linear, frequency_basis_linear, deviation)
//ccwt_lib.frequencyBand(frequencies, height, frequency_range_linear, frequency_offset_linear, frequency_basis_linear, deviation)

// logarithmic
const frequencies = CCWT.frequencyBand(height, frequency_range_log, frequency_offset_log, frequency_basis_log, deviation)
const frequencies = ccwt_lib.frequencyBand(height, frequency_range_log, frequency_offset_log, frequency_basis_log, deviation)

// add some padding to avoid start / end oddities (when there is data at one/both end of the signal)
const padding = 0
const gain_factor = 30
const fourier_transformed_signal = CCWT.fft1d(pcmf32_buffer, padding, gain_factor)
const fourier_transformed_signal = ccwt_lib.fft1d(pcmf32_buffer, padding, gain_factor)

const pixels_per_second = 60
const output_width = Math.floor(length_in_seconds * pixels_per_second)
Expand Down Expand Up @@ -116,14 +116,14 @@
canvas.width = output_width
canvas.height = height

CCWT.numericOutput(fourier_transformed_signal, padding, frequencies, 0, frequencies.length / 2, output_width, row_callback)
ccwt_lib.numericOutput(fourier_transformed_signal, padding, frequencies, 0, frequencies.length / 2, output_width, row_callback)
}, function () {
window.alert('Could not load audio file.')
})

}
request.send()
}
})
}
</script>
</body>
Expand Down
23 changes: 11 additions & 12 deletions src/ccwt.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ const FFTW_BACKWARD = 1
const FFTW_MEASURE = 0
const FFTW_ESTIMATE = (1 << 6)

const CCWT = {
onReady: null
}
const CCWT_obj = fftw_runtime.then((fftw_runtime) => {
const CCWT = {

};

fftw_runtime.onRuntimeInitialized = () => {
// initialize fftw functions
const fftwf_plan_dft_r2c_1d = fftw_runtime.cwrap('fftwf_plan_dft_r2c_1d', 'number', ['number', 'number', 'number', 'number'])

Expand Down Expand Up @@ -74,7 +74,10 @@ fftw_runtime.onRuntimeInitialized = () => {
fftwf_free(input_ptr)
fftwf_free(output_ptr)

return output.slice()
// due to memory growth build a new buffer view
const output_data = new Float32Array(fftw_runtime.HEAPU8.buffer, output_ptr, input_sample_count * 2)

return output_data
}

/**
Expand Down Expand Up @@ -243,11 +246,7 @@ fftw_runtime.onRuntimeInitialized = () => {
return 0
}

if (CCWT.onReady !== null) {
CCWT.onReady()
} else {
console.log("ccwt.js : unregistered onReady callback")
}
}
return CCWT;
});

module.exports = CCWT
module.exports = CCWT_obj
Loading

0 comments on commit d5dc1e7

Please sign in to comment.