node-web-audio-api 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,7 +11,7 @@ npm install [--save] node-web-audio-api
11
11
  ## Example
12
12
 
13
13
  ```js
14
- import { AudioContext, OscillatorNode, GainNode } from 'node-web-audio-api';
14
+ const { AudioContext, OscillatorNode, GainNode } = require('node-web-audio-api');
15
15
 
16
16
  const audioContext = new AudioContext();
17
17
 
@@ -33,34 +33,81 @@ setInterval(() => {
33
33
  }, 50);
34
34
  ```
35
35
 
36
+ or using with EcmaScript module syntax
36
37
 
38
+ ```js
39
+ import wabaudioapi from 'node-web-audio-api';
40
+ const { AudioContext, OscillatorNode, GainNode } = webaudioapi;
41
+
42
+ const audioContext = new AudioContext();
43
+ //...
44
+ ```
37
45
 
38
- ## Build manually
46
+ ## Caveats
39
47
 
40
- If prebuilt binaries are not shippped for your platform, you will need to install
41
- the rust toolchain and install and build the package from github.
48
+ - Currently the library does not provide any way of chosing the output interface, system default interface will be used. As the spec and web-audio-api evolve evolve, thus should change in the future see [https://github.com/orottier/web-audio-api-rs/issues/216](https://github.com/orottier/web-audio-api-rs/issues/216)
49
+ - On Linux systems, the audio backend is Alsa, this is subject to change in the future.
42
50
 
43
- 1. Install rust toolchain
51
+ ### Raspberry Pi
52
+
53
+ On Raspberry Pi, the default render quantum size (128) is too small and underruns
54
+ occurs frequently. To prevent that you should provide a latency hint when building
55
+ an audio context:
44
56
 
57
+ ```js
58
+ const audioContext = new AudioContext({ latencyHint: 'playback' });
45
59
  ```
60
+
61
+ The 'playback' latency hint, 1024 samples / ~21ms at 48000Hz, has been found
62
+ a good value.
63
+
64
+ ## Supported Platforms
65
+
66
+ | | binaries | tested |
67
+ | ---------------------------| ------ | ------ |
68
+ | Windows x64 | ✓ | |
69
+ | Windows arm64 | ✓ | |
70
+ | macOS x64 | ✓ | ✓ |
71
+ | macOS aarch64 | ✓ | |
72
+ | Linux x64 gnu | ✓ | |
73
+ | Linux arm gnueabihf (RPi) | ✓ | ✓ |
74
+
75
+
76
+ ### Manual Build
77
+
78
+ If prebuilt binaries are not shippped for your platform, you will need to:
79
+
80
+ 1. Install rust toolchain
81
+
82
+ ```sh
46
83
  curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
47
84
  ```
48
85
 
49
- 2. Install from github
86
+ 2. Install and build from github
50
87
 
51
- ```
88
+ ```sh
52
89
  npm install --save git+https://github.com/b-ma/node-web-audio-api.git
90
+ cd node_modules/node-web-audio-api
91
+ npm run build
53
92
  ```
54
93
 
55
- Note that the package will be built on your machine, so the install process might be a bit long
94
+ The package will then be built on your machine, which might take some time
56
95
 
57
- ## Roadmap
96
+ ## Known limitation / caveats
58
97
 
59
- - Make a few nodes work properly with clean and predictable code
60
- - Generate bindings from IDL [https://webaudio.github.io/web-audio-api/#idl-index](https://webaudio.github.io/web-audio-api/#idl-index)
61
- - Publish on `npm` with binaries
62
- - Implement prototype chain (?)
63
- - Follow developments of `web-audio-api-rs`
98
+ - async function are not trully async but only monkey patched on the JS side, this will
99
+ be updated once `web-audio-api-rs` provide async version of the methods.
100
+ - see `web-audio-api-rs`
101
+
102
+ ## Development notes
103
+
104
+ The npm script rely on [`cargo-bump`](https://crates.io/crates/cargo-bump) to maintain version synced between
105
+ the `package.json` and the `Cargo.toml` files. Therefore, you will need to install
106
+ `cargo-bump` on your machine
107
+
108
+ ```
109
+ cargo install cargo-bump
110
+ ```
64
111
 
65
112
  ## License
66
113
 
package/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  const { existsSync, readFileSync } = require('fs');
2
2
  const { join } = require('path');
3
- const { patchAudioContext } = require('./monkey-patch.js');
4
3
 
5
4
  const { platform, arch } = process;
6
5
 
@@ -87,7 +86,10 @@ if (!nativeBinding) {
87
86
  throw new Error(`Failed to load native binding for OS: ${platform}, architecture: ${arch}`);
88
87
  }
89
88
 
89
+ const { patchAudioContext, load } = require('./monkey-patch.js');
90
+
90
91
  nativeBinding.AudioContext = patchAudioContext(nativeBinding.AudioContext);
92
+ nativeBinding.load = load;
91
93
 
92
94
  module.exports = nativeBinding;
93
95
 
package/monkey-patch.js CHANGED
@@ -1,6 +1,11 @@
1
+ const fs = require('fs');
1
2
 
2
3
  let contextId = 0;
3
4
 
5
+ const isPlainObject = function(obj) {
6
+ return Object.prototype.toString.call(obj) === '[object Object]';
7
+ };
8
+
4
9
  module.exports.patchAudioContext = function(NativeAudioContext) {
5
10
  class AudioContext extends NativeAudioContext {
6
11
  constructor(...args) {
@@ -8,31 +13,65 @@ module.exports.patchAudioContext = function(NativeAudioContext) {
8
13
  // prevent garbage collection
9
14
  const processId = `__AudioContext_${contextId}`;
10
15
  process[processId] = this;
11
- this.__processId = processId;
16
+
17
+ Object.defineProperty(this, '__processId', {
18
+ value: processId,
19
+ enumerable: false,
20
+ writable: false,
21
+ configurable: false,
22
+ });
12
23
 
13
24
  contextId += 1;
14
25
  // keep process awake
15
- this.__keepAwakeId = setInterval(() => {}, 10000);
26
+ const keepAwakeId = setInterval(() => {}, 10000);
27
+ Object.defineProperty(this, '__keepAwakeId', {
28
+ value: keepAwakeId,
29
+ enumerable: false,
30
+ writable: true,
31
+ configurable: false,
32
+ });
33
+ }
34
+
35
+ // promisify sync APIs
36
+ resume() {
37
+ clearTimeout(this.__keepAwakeId);
38
+ this.__keepAwakeId = setInterval(() => {}, 2000);
39
+ return Promise.resolve(super.resume());
40
+ }
41
+
42
+ suspend() {
43
+ return Promise.resolve(super.suspend());
44
+ }
45
+
46
+ close() {
47
+ delete process[this.__processId];
48
+ clearTimeout(this.__keepAwakeId);
49
+ return Promise.resolve(super.close());
16
50
  }
17
51
 
18
- // @todo
19
- // resume() {
20
- // this.__keepAwakeId = setInterval(() => {}, 2000);
21
- // return super.resume();
22
- // }
23
-
24
- // suspend() {
25
- // // not sure to be confirmed
26
- // clearTimeout(this.__keepAwakeId);
27
- // return super.suspend();
28
- // }
29
-
30
- // close() {
31
- // delete process[this.__processId];
32
- // clearTimeout(this.__keepAwakeId);
33
- // return super.close();
34
- // }
52
+ decodeAudioData(audioData) {
53
+ if (!isPlainObject(audioData) || !('path' in audioData)) {
54
+ throw new Error(`Invalid argument, please consider using the load helper`);
55
+ }
56
+
57
+ try {
58
+ const audioBuffer = super.decodeAudioData(audioData);
59
+ return Promise.resolve(audioBuffer);
60
+ } catch (err) {
61
+ return Promise.reject(err);
62
+ }
63
+ }
35
64
  }
36
65
 
37
66
  return AudioContext;
38
67
  }
68
+
69
+ // dumb method provided to mock an xhr call and mimick browser's API
70
+ // see also `AudioContext.decodeAudioData`
71
+ module.exports.load = function(path) {
72
+ if (!fs.existsSync(path)) {
73
+ throw new Error(`File not found: "${path}"`);
74
+ }
75
+
76
+ return { path };
77
+ }
Binary file
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "node-web-audio-api",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "author": "Benjamin Matuszewski",
5
5
  "description": "Node.js bindings for web-audio-api-rs using napi-rs",
6
6
  "main": "index.js",
7
- "repository": "git@github.com:b-ma/node-web-audio-api.git",
7
+ "repository": "https://github.com/ircam-ismm/node-web-audio-api",
8
8
  "license": "BSD-3-Clause",
9
9
  "keywords": [
10
10
  "audio",
@@ -24,18 +24,24 @@
24
24
  },
25
25
  "scripts": {
26
26
  "artifacts": "napi artifacts",
27
- "build": "napi build --platform --release",
28
- "build:debug": "napi build --platform",
27
+ "build": "npm run generate && napi build --platform --release",
28
+ "build:debug": "npm run generate && napi build --platform",
29
29
  "check": "cargo fmt && cargo clippy",
30
- "generate": "node generator/index.js",
31
- "preversion": "npm run generate"
30
+ "generate": "node generator/index.mjs && cargo fmt",
31
+ "preversion": "yarn install && npm run generate",
32
+ "postversion": "cargo bump $npm_package_version && git commit -am \"v$npm_package_version\""
32
33
  },
33
34
  "devDependencies": {
35
+ "@sindresorhus/slugify": "^2.1.0",
34
36
  "chalk": "^5.0.1",
37
+ "camelcase": "^6.3.0",
35
38
  "dotenv": "^16.0.2",
36
39
  "node-ssh": "^13.0.0",
37
40
  "octokit": "^2.0.7",
38
- "ping": "^0.4.2"
41
+ "ping": "^0.4.2",
42
+ "template-literal": "^1.0.4",
43
+ "waves-masters": "^2.3.1",
44
+ "webidl2": "^24.2.0"
39
45
  },
40
46
  "dependencies": {
41
47
  "@napi-rs/cli": "^2.10.0",