@plotdb/sfx 0.0.0-stage → 0.0.2
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/CHANGELOG.md +28 -0
- package/LICENSE +21 -0
- package/README.md +175 -2
- package/index.js +2677 -0
- package/index.min.js +1 -0
- package/package.json +1 -6
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Change Logs
|
|
2
|
+
|
|
3
|
+
## v0.0.2
|
|
4
|
+
|
|
5
|
+
- feature: 新增合成聲
|
|
6
|
+
- 動作:`slide` `rise` `fall` `count` `snap` `draw` `glitch`,以及通用的 `sweep`
|
|
7
|
+
- 敘事:`reveal` `error` `tension` `heartbeat` `clock`
|
|
8
|
+
- 擬音:`paper` `water` `fire` `steps` `bell` `thunder`
|
|
9
|
+
- 樂器:`marimba` `xylophone` `vibraphone` `glockenspiel` ( 模態合成 )、`guitar` ( 單音或刷和弦 )
|
|
10
|
+
- 人聲與人體:`fingersnap` ( 打響指 ) `huh` ( 蛤? ) `yay` ( 耶! ),人聲以共振峰合成
|
|
11
|
+
- 答題:`correct` ( 叮咚 / 琶音 ) `wrong` ( 噗噗 / 悲傷長號 )
|
|
12
|
+
- 鼓組:`kick` `snare` `hihat` `tom` `clap` `crash` `ride`,以及節奏器 `beat`
|
|
13
|
+
- 擬音與鈸 ( `crash` `ride` `thunder` `steps` `paper` `water` ) 依真實錄音的頻譜與衰減分析調整;`steps` 有 `gait: run`
|
|
14
|
+
- feature: 全部合成聲都可以加 `reverb` / `room` 殘響;另有 `S.reverb(buffer, {mix, room})`
|
|
15
|
+
- feature: `synth.melody` 新增 `instrument`,可以換成任一有 `note` 參數的聲音 ( 預設仍是 `pluck` )
|
|
16
|
+
- tweak: `whoosh` 與 `swell` 改用連續的時變濾波,去掉分段濾波造成的接縫雜音 ( 質感會略有不同 )
|
|
17
|
+
- feature: demo 網站改用專案慣例 ( `web/src/pug` 經 `@zbryikt/template` 建置到 `web/static` ),取代手寫的 `web/index.html`
|
|
18
|
+
- 合成聲:每種聲音以滑桿 / 欄位調參數、範例標籤、波形與播放進度、可複製的程式碼
|
|
19
|
+
- 時間軸:可編輯的場景 ( JSON )、播放 / 暫停 / 拖曳 / 倍速、各項的檔案範圍與擊點、離線混成 wav
|
|
20
|
+
- bus 音量 ( master / music / sfx / voice )
|
|
21
|
+
- bug fix: `synth.pluck` ( 與 `synth.melody` ) 的 `slide: 0` 被當成預設值 0.6,現在可以關掉滑音
|
|
22
|
+
- bug fix: `synth.pluck` 給了 `bright` 時 `slide` 沒有設定,整段變成 NaN ( 無聲 );同一行 `if ... else x; y = ...` 會把後面的設定吞進 else
|
|
23
|
+
- tweak: `./build` 改把 `dist/` 複製到 `web/static/assets/lib/@plotdb/sfx/dev/`
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## v0.0.1
|
|
27
|
+
|
|
28
|
+
- 從 Shelf 的 shelfSound 抽出的音訊 runtime 與程序化合成
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 zbryikt
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,176 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @plotdb/sfx
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
給確定性動畫 ( 例如 [lotion](https://github.com/plotdb/lotion) ) 用的音訊 runtime:
|
|
4
|
+
|
|
5
|
+
- 時間軸:聲音綁在動畫時間上,播放、暫停、拖曳、倍速都會同步。
|
|
6
|
+
- 指令式播放:互動用,與時間軸無關。
|
|
7
|
+
- 程序化合成:在瀏覽器裡算出 UI 音效、撥弦、環境聲,免費、可重現 ( 同樣的參數永遠是同樣的聲音 )。
|
|
8
|
+
- 離線混音:把時間軸混成一段音訊 ( 輸出影片配音用 )。
|
|
9
|
+
|
|
10
|
+
試玩:`npm install`、`npx fedep`、`npm run build` 後 `npm start` ( 即 `npx server -r web -o true` )。
|
|
11
|
+
頁面原始碼在 `web/src/pug`,建置到 `web/static`:每種合成聲都可以調參數試聽,也可以編輯一段時間軸播放、拖曳、倍速並混成 wav。
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## 安裝與載入
|
|
15
|
+
|
|
16
|
+
npm install github:plotdb/sfx
|
|
17
|
+
|
|
18
|
+
頁面裡在 lotion 之後載入 `dist/index.min.js`,全域變數 `window.sfx`:
|
|
19
|
+
|
|
20
|
+
<script src="/assets/lib/@plotdb/lotion/main/index.min.js"></script>
|
|
21
|
+
<script src="/assets/lib/@plotdb/sfx/main/index.min.js"></script>
|
|
22
|
+
<script>
|
|
23
|
+
const S = window.sfx;
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
頁面上有 `lotion.player` 時會自動攔截它的 play / pause / seek,不用另外接。
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## 載入聲音
|
|
30
|
+
|
|
31
|
+
S.load({bgm: 'assets/bgm.mp3', pop: S.synth.pop()}).then(() => { ... })
|
|
32
|
+
|
|
33
|
+
- 值可以是網址、`AudioBuffer` ( 例如合成的聲音 ) 或回傳 `AudioBuffer` 的 Promise。
|
|
34
|
+
- 載完再設時間軸,並在 `player.start()` 之前完成。
|
|
35
|
+
- `S.pending`:載入中的數量。`S.errors`:載入或播放的錯誤訊息。
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## 時間軸
|
|
39
|
+
|
|
40
|
+
S.timeline([
|
|
41
|
+
{t: 0, sound: 'bgm', bus: 'music', gain: 0.35, fadeIn: 1, fadeOut: 2},
|
|
42
|
+
{t: 5.2, sound: 'pop', gain: 0.8}
|
|
43
|
+
])
|
|
44
|
+
|
|
45
|
+
每一項:
|
|
46
|
+
|
|
47
|
+
- `t`:動畫時間 ( 秒 )。
|
|
48
|
+
- `sound`:`S.load` 的名稱。
|
|
49
|
+
- `bus`:`music` | `sfx` ( 預設 ) | `voice`。
|
|
50
|
+
- `gain`、`rate` ( 播放速率 )、`offset` ( 從檔案的第幾秒開始 )、`duration`。
|
|
51
|
+
- `fadeIn`、`fadeOut`:秒。
|
|
52
|
+
- `loop: true` 搭配 `until`:循環到某個時間。
|
|
53
|
+
- `align`:`peak` ( `sfx` 預設,讓聲音的起音點落在 `t` 上 ) | `start` ( 其他 bus 預設,從 `t` 開始播 )。
|
|
54
|
+
|
|
55
|
+
`S.cues(cues)`:把 lotion 的 cues `[{t, sfx, gain}]` 轉成時間軸。
|
|
56
|
+
|
|
57
|
+
### 外部時鐘
|
|
58
|
+
|
|
59
|
+
動畫由外層控制 ( 例如外層頁面經 postMessage 控制 iframe 裡的動畫 ) 時,由外層告知播放狀態:
|
|
60
|
+
|
|
61
|
+
S.transport({playing: true, t: 12.3, rate: 1.5, from: 'host'})
|
|
62
|
+
|
|
63
|
+
- 帶 `from` 之後不再跟隨頁面上的 player。
|
|
64
|
+
- `rate`:倍速。旁白 ( `voice` ) 與配樂 ( `music` ) 用網址載入的會保持音高;合成的聲音與短音效直接變速。
|
|
65
|
+
- 非連續的時間 ( 拖曳 ) 或 `force: true` 時重新排程。
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
## 指令式播放
|
|
69
|
+
|
|
70
|
+
h = S.play('pop', {gain: 0.8, loop: false, fadeIn: 0})
|
|
71
|
+
h.fade(0.2, 0.5) // 0.5 秒內淡到 0.2
|
|
72
|
+
h.stop(0.1) // 0.1 秒淡出後停止
|
|
73
|
+
S.stop('pop') // 停止這個名稱的指令式聲音 ( 不給名稱全停 )
|
|
74
|
+
S.music('bgm', {fade: 1}) // 背景音樂槽: 同時一首, 換曲時交叉淡入淡出; S.music(null) 淡出
|
|
75
|
+
S.volume('music', 0.5) // bus 音量: music | sfx | voice | master
|
|
76
|
+
|
|
77
|
+
瀏覽器的自動播放限制:要在使用者操作後呼叫 `S.resume()` ( `S.play` 會自己呼叫 )。
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
## 合成
|
|
81
|
+
|
|
82
|
+
全部回傳 `AudioBuffer` ( 48kHz 雙聲道 ),可直接 `S.load`。音高參數可以給 Hz 或音名 ( `'A4'`、`'C#5'` )。
|
|
83
|
+
|
|
84
|
+
- `seed`:用到雜訊的聲音 ( click、type、thump、whoosh、swell、pluck、wind、rain ) 換一組雜訊,同樣參數、不同質感。
|
|
85
|
+
- `pan`:-1 左 ~ 1 右,單點的聲音 ( click、tick、pop、toggle、thump、chime、success、notify、pluck、buzz ) 才有;
|
|
86
|
+
whoosh、wind、rain 本身就有左右移動或去相關。
|
|
87
|
+
|
|
88
|
+
| 聲音 | 長度 | 參數 | 用途 |
|
|
89
|
+
| --- | --- | --- | --- |
|
|
90
|
+
| `click` | 0.05s | `freq` | 點擊 |
|
|
91
|
+
| `tick` | 0.06s | `note` / `freq` | 刻度、計數 |
|
|
92
|
+
| `pop` | 0.15s | `from`、`to` ( Hz,音高滑動 ) | 元素出現 |
|
|
93
|
+
| `toggle` | 0.12s | | 開關 |
|
|
94
|
+
| `type` | 0.05s | | 打字 ( 每次 seed 不同較自然 ) |
|
|
95
|
+
| `thump` | 0.35s | | 落地、蓋章 |
|
|
96
|
+
| `snap` | 0.1s | | 吸附、到位 |
|
|
97
|
+
| `chime` | `dur` ( 1.4 ) | `note` ( E6 ) | 鈴聲、完成一步 |
|
|
98
|
+
| `success` | 0.9s | | 成功 ( C-E-G 琶音 ) |
|
|
99
|
+
| `notify` | 0.7s | | 通知 |
|
|
100
|
+
| `error` | 0.5s | `from` ( B3 )、`to` ( F3 ) | 錯誤 |
|
|
101
|
+
| `reveal` | 1.6s | `notes` ( [C6, E6, G6, C7, E7] )、`gap` ( 0.06 ) | 揭曉 ( 預設 `reverb: 0.35` ) |
|
|
102
|
+
| `correct` | 自動 | `style` ( pingpong「叮咚」\| arp 琶音 )、`notes`、`gap` | 答對 |
|
|
103
|
+
| `wrong` | 自動 | `style` ( buzzer「噗噗」\| trombone 悲傷長號 )、`pitch` ( 140 ) | 答錯 |
|
|
104
|
+
| `whoosh` | `dur` ( 0.7 ) | `from` ( 400 )、`peak` ( 2600 )、`to` ( 600 )、`at` ( 0.45 )、`q` ( 1.2 ) | 轉場 |
|
|
105
|
+
| `swell` | `dur` ( 2 ) | | 段落前的醞釀 |
|
|
106
|
+
| `slide` | `dur` ( 0.3 ) | `from` ( 900 )、`to` ( 2600 )、`q` ( 0.9 )、`dir` ( 1 往右,-1 往左 ) | 滑入、滑出 |
|
|
107
|
+
| `rise` / `fall` | `dur` ( 0.6 ) | `from`、`to` ( Hz 或音名;300→900 / 900→250 ) | 數值上升 / 下降 |
|
|
108
|
+
| `count` | `dur` + 0.2 | `n` ( 12 )、`dur` ( 1.2 )、`ease` ( out \| in \| linear )、`climb` ( 7 半音 )、`note` ( C6 ) | 數字滾動 |
|
|
109
|
+
| `draw` | `dur` ( 1 ) | `rough` ( 0~1 )、`pitch` ( 2500 ) | 筆畫 |
|
|
110
|
+
| `glitch` | `dur` ( 0.5 ) | | 故障 |
|
|
111
|
+
| `sweep` | `dur` ( 1 ) | `wave` ( sine \| triangle \| square \| saw \| noise )、`from` ( 200 )、`to` ( 2000 )、`curve` ( exp \| lin )、`q`、`attack`、`release` | 通用掃頻 |
|
|
112
|
+
| `tension` | `dur` ( 6 ) | `note` ( A2 ) | 緊張 |
|
|
113
|
+
| `heartbeat` | `dur` ( 4 ) | `bpm` ( 70 ) | 心跳 |
|
|
114
|
+
| `clock` | `dur` ( 4 ) | `bpm` ( 60 ) | 時鐘 |
|
|
115
|
+
| `fingersnap` | 0.12s | `tone` ( 手掌共鳴 3200Hz ) | 打響指 |
|
|
116
|
+
| `huh` | `dur` ( 0.45 ) | `pitch` ( 200 )、`rise` ( 上揚倍數 1.9 )、`size` | 蛤? |
|
|
117
|
+
| `yay` | `dur` ( 0.5 ) | `pitch` ( 300 )、`size` | 耶! |
|
|
118
|
+
| `paper` | `dur` ( 1.2 ) | `crisp` ( 劈啪聲,0 軟紙 ~ 3 硬紙 )、`flutter` ( 紙張抖動 0~1 ) | 翻頁 |
|
|
119
|
+
| `water` | 自動 | `n` ( 氣泡數,1 為水滴 )、`size` ( 平均半徑 mm,越大越低 )、`rise` ( 音高上升 ) | 水滴、冒泡、溪流 |
|
|
120
|
+
| `fire` | `dur` ( 6 ) | `density` ( 1 ) | 火 |
|
|
121
|
+
| `steps` | 自動 | `surface` ( wood \| concrete \| gravel \| snow \| grass )、`gait` ( walk \| run )、`n` ( 4 )、`pace` ( 走 0.5 / 跑 0.3 ) | 腳步 |
|
|
122
|
+
| `bell` | `dur` ( 5 ) | `note` ( C5 ) | 教堂鐘、管鐘 ( 預設 `reverb: 0.2` ) |
|
|
123
|
+
| `thunder` | `dur` ( 6 ) | `dist` ( 0 近 ~ 1 遠 ) | 雷 |
|
|
124
|
+
| `wind` | `dur` ( 6 ) | `cutoff` ( 900 ) | 風 |
|
|
125
|
+
| `rain` | `dur` ( 6 ) | `density` ( 0.02 ) | 雨 |
|
|
126
|
+
| `buzz` | `dur` ( 1.5 ) | `freq` ( 220 ) | 昆蟲振翅 |
|
|
127
|
+
| `pluck` | `dur` ( 2.5 ) | `note` ( A3 )、`bright` ( 0~1 )、`slide` ( 半音 ) | 撥弦 ( 類古箏 ) |
|
|
128
|
+
| `guitar` | `dur` ( 3 ) | `note` ( E3 ) 或 `chord` ( C D Dm E Em F G A Am ) 或 `notes`、`strum` ( 0.03 )、`dir` ( down \| up )、`bright`、`pos` ( 撥弦位置 0.2 )、`mute` ( 0~1 ) | 吉他 |
|
|
129
|
+
| `marimba` | `dur` ( 1.5 ) | `note` ( C4 )、`hard` ( 槌子硬度 0~1 ) | 馬林巴 |
|
|
130
|
+
| `xylophone` | `dur` ( 0.8 ) | `note` ( C5 )、`hard` | 木琴 |
|
|
131
|
+
| `vibraphone` | `dur` ( 3 ) | `note` ( F4 )、`hard`、`trem` ( 顫音深度 0.35 ) | 鐵琴 |
|
|
132
|
+
| `glockenspiel` | `dur` ( 2 ) | `note` ( C6 )、`hard` | 鐘琴 |
|
|
133
|
+
| `melody` | 自動 | `notes: [[t, note, dur, vel], ...]`、`instrument` ( pluck )、`bright`、`slide` | 旋律 |
|
|
134
|
+
| `drone` | `dur` ( 8 ) | `notes` ( [A1, E2, A2] )、`attack`、`release` | 持續低音 |
|
|
135
|
+
| `kick` | 自動 | `tune` ( 50 Hz )、`decay` ( 0.3 )、`punch` ( 0~1 ) | 大鼓 |
|
|
136
|
+
| `snare` | 自動 | `tune` ( 180 Hz )、`decay` ( 0.15 )、`snappy` ( 0~1 ) | 小鼓 |
|
|
137
|
+
| `hihat` | 自動 | `open` ( 0 閉 ~ 1 開 )、`tune` ( 1 ) | hi-hat |
|
|
138
|
+
| `tom` | 自動 | `note` ( A2 )、`decay` ( 0.35 ) | 中鼓 / 落地鼓 |
|
|
139
|
+
| `clap` | 自動 | `decay` ( 0.12 ) | 拍手 |
|
|
140
|
+
| `crash` | 自動 | `decay` ( 尾音倍數,1 約 2 秒 )、`tune` ( 1 ) | 碎音鈸 |
|
|
141
|
+
| `ride` | 自動 | `decay` ( 尾音倍數,1 約 3 秒 )、`bell` ( 0~1,越大越靠近鈸心 )、`tune` ( 1 ) | 疊音鈸 |
|
|
142
|
+
| `beat` | 自動 | `pattern`、`bpm` ( 100 )、`bars` ( 1 )、`swing` ( 0~1 ) | 節奏 |
|
|
143
|
+
|
|
144
|
+
擬音、鈸與人聲 ( `crash` `ride` `thunder` `steps` `paper` `water` `fingersnap` `huh` `yay` ) 依 Wikimedia Commons 上的錄音分析調整過頻譜分布、衰減曲線、音高與共振峰。
|
|
145
|
+
|
|
146
|
+
人聲 ( `huh` `yay` ) 以共振峰合成:聲帶脈衝與氣音經過 4 個會移動的共振峰。`size` 是聲道大小 ( 小孩約 1.15,大人男聲約 0.9 )。聽得出是人聲,但偏卡通,不像真人錄音。
|
|
147
|
+
|
|
148
|
+
全部的合成聲都可以加 `reverb` ( 0~1,濕聲比例 ) 與 `room` ( 0~1,空間大小 ),聲音會多出殘響的尾巴。
|
|
149
|
+
已經有的 `AudioBuffer` 也可以用 `S.reverb(buffer, {mix, room})` 加殘響。
|
|
150
|
+
|
|
151
|
+
`melody` 的 `instrument` 可以是任何有 `note` 參數的聲音:`pluck` ( 預設 )、`guitar`、`marimba`、`xylophone`、`vibraphone`、`glockenspiel`、`chime`、`bell`。
|
|
152
|
+
|
|
153
|
+
`beat` 的 `pattern` 一個字元是一格十六分音符:`X` 重音、`x` 一般、`o` 輕,其他字元 ( `.`、`-` ) 是休止,空白與 `|` 忽略。
|
|
154
|
+
|
|
155
|
+
S.synth.beat({bpm: 96, bars: 2, swing: 0.3, pattern: {
|
|
156
|
+
kick: 'x.......x.x.....',
|
|
157
|
+
snare: '....x.......x..o',
|
|
158
|
+
hihat: 'x.x.x.x.x.x.x.x.',
|
|
159
|
+
tom: ['..............x.', {note: 'D3'}] // 也可以給 [pattern, 參數]
|
|
160
|
+
}})
|
|
161
|
+
|
|
162
|
+
名稱可以是 `kick` `snare` `hihat` `ohat` ( 開 hi-hat ) `tom` `ltom` `htom` `clap` `crash` `ride`,或任何合成聲的名稱。
|
|
163
|
+
|
|
164
|
+
`whoosh` 是帶通濾波的雜訊,中心頻率依 `from` → `peak` → `to` 走,在 `at` ( 0~1 ) 處最亮最響:
|
|
165
|
+
|
|
166
|
+
- 短促的掃過:`{dur: 0.35}`;更短更乾淨:`{dur: 0.25, q: 2}`。
|
|
167
|
+
- 往上衝:`{from: 300, peak: 3500, to: 3000, at: 0.8}`;往下沉:`{from: 3000, peak: 3000, to: 300, at: 0.1}`。
|
|
168
|
+
- `q` 小 ( 0.5 ) 像風,大 ( 3 ) 像哨音。
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
## 混音與檢查
|
|
172
|
+
|
|
173
|
+
- 建議音量:配樂 0.3~0.4、音效 0.6~1、旁白 1。
|
|
174
|
+
- `S.report()`:載入的聲音 ( 長度、起音點 )、時間軸數量、播放狀態、AudioContext 狀態、最近的錯誤。
|
|
175
|
+
- `S.peak(buffer)`:起音點 ( 秒 )。
|
|
176
|
+
- `S.render(duration)`:離線混音,回傳 Promise<AudioBuffer>。`S.wav(buffer)`:轉成 16-bit wav Blob。
|