├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── addons └── my_example_plugin │ ├── my_example_dock.tscn │ ├── my_example_plugin.ts │ └── plugin.cfg ├── audio_generator ├── fft.ts ├── generator.tscn └── generator_demo.ts ├── experimental └── static_binding_generator.ts ├── icon.svg ├── icon.svg.import ├── icon ├── affiliate.svg ├── affiliate.svg.import ├── filetype-js.svg └── filetype-js.svg.import ├── jumpybird ├── bird.png ├── bird.png.import ├── bird.tscn ├── cloud.png ├── cloud.png.import ├── jumpybird_main.ts ├── jumpybird_main.tscn ├── jumpybird_pipe.ts ├── offset.gdshader ├── pipe.tscn ├── pipe_body.png ├── pipe_body.png.import ├── pipe_head.png ├── pipe_head.png.import ├── sky.png ├── sky.png.import ├── skyline.png └── skyline.png.import ├── libs ├── zzfxm.js └── zzfxm_gn.js ├── main.tscn ├── package-lock.json ├── package.json ├── piggy ├── arrow.png ├── arrow.png.import ├── arrow.ts ├── arrow.tscn ├── background.png ├── background.png.import ├── piggy_main.ts ├── piggy_main.tscn ├── piggy_ui.ts ├── raw │ ├── .gdignore │ ├── arrow.aseprite │ ├── background.aseprite │ ├── ladder.aseprite │ ├── rope.aseprite │ ├── shooter.aseprite │ └── wolf.aseprite ├── rope.png ├── rope.png.import ├── shooter.png ├── shooter.png.import ├── shooter.ts ├── tiling.gdshader ├── wolf.png ├── wolf.png.import ├── wolf.ts └── wolf.tscn ├── project.godot ├── raw ├── .gdignore └── screenshots │ ├── .gdignore │ ├── audio_generator.gif │ ├── jumpybird.gif │ ├── piggy.gif │ └── snake_01.gif ├── simple_js_node.js ├── snake ├── block.png ├── block.png.import ├── body.png ├── body.png.import ├── coin.png ├── coin.png.import ├── coin.ts ├── coin.tscn ├── constants.ts ├── head.png ├── head.png.import ├── map.ts ├── raw │ ├── .gdignore │ ├── block.aseprite │ ├── body.aseprite │ ├── coin.aseprite │ └── head.aseprite ├── snake.ts ├── snake_body.ts ├── snake_body.tscn └── snake_main.tscn ├── test.xlsx ├── test_button.ts ├── tests ├── bot_stats.tres ├── bot_stats.ts ├── bot_stats_base.ts ├── cyclic_import_1.ts ├── cyclic_import_2.ts ├── my_editor_script_1.ts ├── my_editor_sprite.ts ├── read_xlsx.ts ├── test_01.ts ├── test_01.tscn ├── test_01_inspector.ts ├── test_dictionary.ts ├── unused_script_003.ts └── worker.ts ├── tsconfig.json ├── typings ├── .gdignore ├── godot.minimal.d.ts ├── godot.mix.d.ts ├── godot.worker.d.ts ├── godot0.gen.d.ts ├── godot1.gen.d.ts ├── godot2.gen.d.ts ├── godot3.gen.d.ts ├── godot4.gen.d.ts ├── godot5.gen.d.ts ├── godot6.gen.d.ts ├── godot7.gen.d.ts ├── jsb.editor.bundle.d.ts └── jsb.runtime.bundle.d.ts └── ui ├── foo.ts ├── foo_base.ts ├── foo_test.tscn └── main_ui.ts /.gitattributes: -------------------------------------------------------------------------------- 1 | # Normalize EOL for all files that Git considers text files. 2 | * text=auto eol=lf 3 | *.ts text eol=crlf 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | **/.DS_Store 4 | 5 | # include generated d.ts for convenience to checking the example project without any changes 6 | # you could ignore these files in your project if you decide to always generate them locally 7 | !typescripts/typings/godot*.gen.d.ts 8 | 9 | node_modules/ 10 | android/ 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 huliangjie 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GodotJSExample 2 | This project includes examples at different complexity levels, incrementally introducing and utilizing more engine features. 3 | 4 | A prebuilt version of `Godot Editor` can be downloaded from [GodotJS-Build](https://github.com/ialex32x/GodotJS-Build/releases). 5 | 6 | > [!NOTE] 7 | > Run `npm i` in the project folder before opening it in godot editor. 8 | > 9 | > And, so far, `npx tsc` (or `npx tsc -w`) must be run on your side to make the changes to the scripts take effect, since all `.js` files are not included in this git repository. 10 | 11 | ## Snake 12 | A simple snake game. 13 | In this example, only a limited subset of Godot's features is utilized: 14 | * script lifetime callbacks (_ready, _process etc.) 15 | * resource loader 16 | * using primitive types (float, bool, string, StringName) 17 | * export variables 18 | 19 | [![Snake](./raw/screenshots/snake_01.gif)](./snake/snake.ts) 20 | 21 | 22 | ## JumpyBird 23 | 24 | Additional features used: 25 | * Signals (connect `area_shape_entered` signal with js class member function) 26 | 27 | [![JumpyBird](./raw/screenshots/jumpybird.gif)](./jumpybird/jumpybird_main.ts) 28 | 29 | ## Piggy 30 | 31 | Additional features used: 32 | * `signal_` annotation 33 | * `onready_` annotation 34 | * `export_` annotation 35 | 36 | [![Piggy](./raw/screenshots/piggy.gif)](./piggy/piggy_main.ts) 37 | 38 | ## Audio Generator 39 | 40 | This is an example originally from https://godotengine.org/asset-library/asset/526 41 | 42 | It utilizes [ZzFXM](https://keithclark.github.io/ZzFXM/) which is written in pure javascript to play a 8bit-ish sound without audio media files. 43 | 44 | [![AudioGenerator](./raw/screenshots/audio_generator.gif)](./jumpybaudio_generatorird/generator_demo.ts) 45 | -------------------------------------------------------------------------------- /addons/my_example_plugin/my_example_dock.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene format=3 uid="uid://yjkqax0se70r"] 2 | 3 | [node name="MyExampleDock" type="Control"] 4 | layout_mode = 3 5 | anchors_preset = 15 6 | anchor_right = 1.0 7 | anchor_bottom = 1.0 8 | grow_horizontal = 2 9 | grow_vertical = 2 10 | 11 | [node name="Label" type="Label" parent="."] 12 | layout_mode = 1 13 | anchors_preset = 8 14 | anchor_left = 0.5 15 | anchor_top = 0.5 16 | anchor_right = 0.5 17 | anchor_bottom = 0.5 18 | offset_left = -20.0 19 | offset_top = -11.5 20 | offset_right = 20.0 21 | offset_bottom = 11.5 22 | grow_horizontal = 2 23 | grow_vertical = 2 24 | text = "Hello, TypeScript!" 25 | -------------------------------------------------------------------------------- /addons/my_example_plugin/my_example_plugin.ts: -------------------------------------------------------------------------------- 1 | import { Control, EditorPlugin, is_instance_valid, Node, PackedScene, ResourceLoader } from "godot"; 2 | import { tool } from "godot.annotations"; 3 | 4 | @tool() 5 | export default class MyExamplePlugin extends EditorPlugin { 6 | private dock!: Control; 7 | 8 | _enter_tree(): void { 9 | console.log("MyExamplePlugin enter_tree"); 10 | let scene = ResourceLoader.load("res://addons/my_example_plugin/my_example_dock.tscn"); 11 | this.dock = scene.instantiate(); 12 | this.add_control_to_bottom_panel(this.dock, "My Example Plugin (TS)"); 13 | } 14 | 15 | _exit_tree(): void { 16 | console.log("MyExamplePlugin exit_tree"); 17 | this.remove_control_from_bottom_panel(this.dock); 18 | this.dock.free(); 19 | console.assert(!is_instance_valid(this.dock)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /addons/my_example_plugin/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="MyExamplePlugin" 4 | description="example" 5 | author="ialex32x" 6 | version="1.0" 7 | script="my_example_plugin.ts" 8 | -------------------------------------------------------------------------------- /audio_generator/fft.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Free FFT and convolution (TypeScript) 3 | * 4 | * Copyright (c) 2022 Project Nayuki. (MIT License) 5 | * https://www.nayuki.io/page/free-small-fft-in-multiple-languages 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * - The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 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. 22 | */ 23 | 24 | 25 | /* 26 | * Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result back into the vector. 27 | * The vector can have any length. This is a wrapper function. 28 | */ 29 | export function transform(real: Array | Float64Array, imag: Array | Float64Array): void { 30 | const n: number = real.length; 31 | // if (n != imag.length) 32 | // throw new RangeError("Mismatched lengths"); 33 | if (n == 0) 34 | return; 35 | else if ((n & (n - 1)) == 0) // Is power of 2 36 | transformRadix2(real, imag); 37 | else // More complicated algorithm for arbitrary sizes 38 | transformBluestein(real, imag); 39 | } 40 | 41 | 42 | /* 43 | * Computes the inverse discrete Fourier transform (IDFT) of the given complex vector, storing the result back into the vector. 44 | * The vector can have any length. This is a wrapper function. This transform does not perform scaling, so the inverse is not a true inverse. 45 | */ 46 | export function inverseTransform(real: Array | Float64Array, imag: Array | Float64Array): void { 47 | transform(imag, real); 48 | } 49 | 50 | 51 | /* 52 | * Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result back into the vector. 53 | * The vector's length must be a power of 2. Uses the Cooley-Tukey decimation-in-time radix-2 algorithm. 54 | */ 55 | function transformRadix2(real: Array | Float64Array, imag: Array | Float64Array): void { 56 | // Length variables 57 | const n: number = real.length; 58 | // if (n != imag.length) 59 | // throw new RangeError("Mismatched lengths"); 60 | if (n == 1) // Trivial transform 61 | return; 62 | let levels: number = -1; 63 | for (let i = 0; i < 32; i++) { 64 | if (1 << i == n) 65 | levels = i; // Equal to log2(n) 66 | } 67 | if (levels == -1) 68 | throw new RangeError("Length is not a power of 2"); 69 | 70 | // Trigonometric tables 71 | let cosTable = new Array(n / 2); 72 | let sinTable = new Array(n / 2); 73 | for (let i = 0; i < n / 2; i++) { 74 | cosTable[i] = Math.cos(2 * Math.PI * i / n); 75 | sinTable[i] = Math.sin(2 * Math.PI * i / n); 76 | } 77 | 78 | // Bit-reversed addressing permutation 79 | for (let i = 0; i < n; i++) { 80 | const j: number = reverseBits(i, levels); 81 | if (j > i) { 82 | let temp: number = real[i]; 83 | real[i] = real[j]; 84 | real[j] = temp; 85 | temp = imag[i]; 86 | imag[i] = imag[j]; 87 | imag[j] = temp; 88 | } 89 | } 90 | 91 | // Cooley-Tukey decimation-in-time radix-2 FFT 92 | for (let size = 2; size <= n; size *= 2) { 93 | const halfsize: number = size / 2; 94 | const tablestep: number = n / size; 95 | for (let i = 0; i < n; i += size) { 96 | for (let j = i, k = 0; j < i + halfsize; j++, k += tablestep) { 97 | const l: number = j + halfsize; 98 | const tpre: number = real[l] * cosTable[k] + imag[l] * sinTable[k]; 99 | const tpim: number = -real[l] * sinTable[k] + imag[l] * cosTable[k]; 100 | real[l] = real[j] - tpre; 101 | imag[l] = imag[j] - tpim; 102 | real[j] += tpre; 103 | imag[j] += tpim; 104 | } 105 | } 106 | } 107 | 108 | // Returns the integer whose value is the reverse of the lowest 'width' bits of the integer 'val'. 109 | function reverseBits(val: number, width: number): number { 110 | let result: number = 0; 111 | for (let i = 0; i < width; i++) { 112 | result = (result << 1) | (val & 1); 113 | val >>>= 1; 114 | } 115 | return result; 116 | } 117 | } 118 | 119 | 120 | /* 121 | * Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result back into the vector. 122 | * The vector can have any length. This requires the convolution function, which in turn requires the radix-2 FFT function. 123 | * Uses Bluestein's chirp z-transform algorithm. 124 | */ 125 | function transformBluestein(real: Array | Float64Array, imag: Array | Float64Array): void { 126 | // Find a power-of-2 convolution length m such that m >= n * 2 + 1 127 | const n: number = real.length; 128 | // if (n != imag.length) 129 | // throw new RangeError("Mismatched lengths"); 130 | let m: number = 1; 131 | while (m < n * 2 + 1) 132 | m *= 2; 133 | 134 | // Trigonometric tables 135 | let cosTable = new Array(n); 136 | let sinTable = new Array(n); 137 | for (let i = 0; i < n; i++) { 138 | const j: number = i * i % (n * 2); // This is more accurate than j = i * i 139 | cosTable[i] = Math.cos(Math.PI * j / n); 140 | sinTable[i] = Math.sin(Math.PI * j / n); 141 | } 142 | 143 | // Temporary vectors and preprocessing 144 | let areal: Array = newArrayOfZeros(m); 145 | let aimag: Array = newArrayOfZeros(m); 146 | for (let i = 0; i < n; i++) { 147 | areal[i] = real[i] * cosTable[i] + imag[i] * sinTable[i]; 148 | aimag[i] = -real[i] * sinTable[i] + imag[i] * cosTable[i]; 149 | } 150 | let breal: Array = newArrayOfZeros(m); 151 | let bimag: Array = newArrayOfZeros(m); 152 | breal[0] = cosTable[0]; 153 | bimag[0] = sinTable[0]; 154 | for (let i = 1; i < n; i++) { 155 | breal[i] = breal[m - i] = cosTable[i]; 156 | bimag[i] = bimag[m - i] = sinTable[i]; 157 | } 158 | 159 | // Convolution 160 | let creal = new Array(m); 161 | let cimag = new Array(m); 162 | convolveComplex(areal, aimag, breal, bimag, creal, cimag); 163 | 164 | // Postprocessing 165 | for (let i = 0; i < n; i++) { 166 | real[i] = creal[i] * cosTable[i] + cimag[i] * sinTable[i]; 167 | imag[i] = -creal[i] * sinTable[i] + cimag[i] * cosTable[i]; 168 | } 169 | } 170 | 171 | 172 | // /* 173 | // * Computes the circular convolution of the given real vectors. Each vector's length must be the same. 174 | // */ 175 | // function convolveReal(xvec: Array | Float64Array, yvec: Array | Float64Array, outvec: Array | Float64Array): void { 176 | // const n: number = xvec.length; 177 | // if (n != yvec.length || n != outvec.length) 178 | // throw new RangeError("Mismatched lengths"); 179 | // convolveComplex(xvec, newArrayOfZeros(n), yvec, newArrayOfZeros(n), outvec, newArrayOfZeros(n)); 180 | // } 181 | 182 | 183 | /* 184 | * Computes the circular convolution of the given complex vectors. Each vector's length must be the same. 185 | */ 186 | function convolveComplex( 187 | xreal: Array | Float64Array, ximag: Array | Float64Array, 188 | yreal: Array | Float64Array, yimag: Array | Float64Array, 189 | outreal: Array | Float64Array, outimag: Array | Float64Array): void { 190 | 191 | const n: number = xreal.length; 192 | // if (n != ximag.length || n != yreal.length || n != yimag.length 193 | // || n != outreal.length || n != outimag.length) 194 | // throw new RangeError("Mismatched lengths"); 195 | 196 | xreal = xreal.slice(); 197 | ximag = ximag.slice(); 198 | yreal = yreal.slice(); 199 | yimag = yimag.slice(); 200 | transform(xreal, ximag); 201 | transform(yreal, yimag); 202 | 203 | for (let i = 0; i < n; i++) { 204 | const temp: number = xreal[i] * yreal[i] - ximag[i] * yimag[i]; 205 | ximag[i] = ximag[i] * yreal[i] + xreal[i] * yimag[i]; 206 | xreal[i] = temp; 207 | } 208 | inverseTransform(xreal, ximag); 209 | 210 | for (let i = 0; i < n; i++) { // Scaling (because this FFT implementation omits it) 211 | outreal[i] = xreal[i] / n; 212 | outimag[i] = ximag[i] / n; 213 | } 214 | } 215 | 216 | 217 | function newArrayOfZeros(n: number): Array { 218 | let result: Array = []; 219 | for (let i = 0; i < n; i++) 220 | result.push(0); 221 | return result; 222 | } 223 | -------------------------------------------------------------------------------- /audio_generator/generator.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://de6cyyjnvj3lh"] 2 | 3 | [ext_resource type="Script" path="res://audio_generator/generator_demo.ts" id="1_6f8oh"] 4 | 5 | [sub_resource type="AudioStreamGenerator" id="1"] 6 | mix_rate = 22050.0 7 | 8 | [node name="Generator" type="Node"] 9 | script = ExtResource("1_6f8oh") 10 | 11 | [node name="Player" type="AudioStreamPlayer" parent="."] 12 | stream = SubResource("1") 13 | 14 | [node name="Left" type="Control" parent="."] 15 | layout_mode = 3 16 | anchors_preset = 8 17 | anchor_left = 0.5 18 | anchor_top = 0.5 19 | anchor_right = 0.5 20 | anchor_bottom = 0.5 21 | offset_left = -163.0 22 | offset_top = -86.0 23 | offset_right = -13.0 24 | offset_bottom = 30.0 25 | grow_horizontal = 2 26 | grow_vertical = 2 27 | size_flags_horizontal = 4 28 | size_flags_vertical = 4 29 | metadata/_edit_use_anchors_ = true 30 | 31 | [node name="Line2D" type="Line2D" parent="Left"] 32 | points = PackedVector2Array(0, 14.525, 0, 100) 33 | width = 8.0 34 | default_color = Color(1, 0, 0, 1) 35 | 36 | [node name="Line2D2" type="Line2D" parent="Left"] 37 | position = Vector2(10, 0) 38 | points = PackedVector2Array(0, 0, 0, 100) 39 | width = 8.0 40 | 41 | [node name="Line2D3" type="Line2D" parent="Left"] 42 | position = Vector2(20, 0) 43 | points = PackedVector2Array(0, 0, 0, 100) 44 | width = 8.0 45 | 46 | [node name="Line2D4" type="Line2D" parent="Left"] 47 | position = Vector2(30, 0) 48 | points = PackedVector2Array(0, 0, 0, 100) 49 | width = 8.0 50 | 51 | [node name="Line2D5" type="Line2D" parent="Left"] 52 | position = Vector2(40, 0) 53 | points = PackedVector2Array(0, 0, 0, 100) 54 | width = 8.0 55 | 56 | [node name="Line2D6" type="Line2D" parent="Left"] 57 | position = Vector2(50, 0) 58 | points = PackedVector2Array(0, 0, 0, 100) 59 | width = 8.0 60 | 61 | [node name="Line2D7" type="Line2D" parent="Left"] 62 | position = Vector2(60, 0) 63 | points = PackedVector2Array(0, 0, 0, 100) 64 | width = 8.0 65 | 66 | [node name="Line2D8" type="Line2D" parent="Left"] 67 | position = Vector2(70, 0) 68 | points = PackedVector2Array(0, 0, 0, 100) 69 | width = 8.0 70 | 71 | [node name="Line2D9" type="Line2D" parent="Left"] 72 | position = Vector2(80, 0) 73 | points = PackedVector2Array(0, 0, 0, 100) 74 | width = 8.0 75 | 76 | [node name="Line2D10" type="Line2D" parent="Left"] 77 | position = Vector2(90, 0) 78 | points = PackedVector2Array(0, 0, 0, 100) 79 | width = 8.0 80 | 81 | [node name="Line2D11" type="Line2D" parent="Left"] 82 | position = Vector2(100, 0) 83 | points = PackedVector2Array(0, 0, 0, 100) 84 | width = 8.0 85 | 86 | [node name="Line2D12" type="Line2D" parent="Left"] 87 | position = Vector2(110, 0) 88 | points = PackedVector2Array(0, 0, 0, 100) 89 | width = 8.0 90 | 91 | [node name="Line2D13" type="Line2D" parent="Left"] 92 | position = Vector2(120, 0) 93 | points = PackedVector2Array(0, 0, 0, 100) 94 | width = 8.0 95 | 96 | [node name="Line2D14" type="Line2D" parent="Left"] 97 | position = Vector2(130, 0) 98 | points = PackedVector2Array(0, 0, 0, 100) 99 | width = 8.0 100 | 101 | [node name="Line2D15" type="Line2D" parent="Left"] 102 | position = Vector2(140, 0) 103 | points = PackedVector2Array(0, 0, 0, 100) 104 | width = 8.0 105 | 106 | [node name="Line2D16" type="Line2D" parent="Left"] 107 | position = Vector2(150, 0) 108 | points = PackedVector2Array(0, 0, 0, 100) 109 | width = 8.0 110 | 111 | [node name="Line2D17" type="Line2D" parent="Left"] 112 | position = Vector2(160, 0) 113 | points = PackedVector2Array(0, 14.525, 0, 100) 114 | width = 8.0 115 | default_color = Color(1, 0, 0, 1) 116 | 117 | [node name="Line2D18" type="Line2D" parent="Left"] 118 | position = Vector2(170, 0) 119 | points = PackedVector2Array(0, 0, 0, 100) 120 | width = 8.0 121 | 122 | [node name="Line2D19" type="Line2D" parent="Left"] 123 | position = Vector2(180, 0) 124 | points = PackedVector2Array(0, 0, 0, 100) 125 | width = 8.0 126 | 127 | [node name="Line2D20" type="Line2D" parent="Left"] 128 | position = Vector2(190, 0) 129 | points = PackedVector2Array(0, 0, 0, 100) 130 | width = 8.0 131 | 132 | [node name="Line2D21" type="Line2D" parent="Left"] 133 | position = Vector2(200, 0) 134 | points = PackedVector2Array(0, 0, 0, 100) 135 | width = 8.0 136 | 137 | [node name="Line2D22" type="Line2D" parent="Left"] 138 | position = Vector2(210, 0) 139 | points = PackedVector2Array(0, 0, 0, 100) 140 | width = 8.0 141 | 142 | [node name="Line2D23" type="Line2D" parent="Left"] 143 | position = Vector2(220, 0) 144 | points = PackedVector2Array(0, 0, 0, 100) 145 | width = 8.0 146 | 147 | [node name="Line2D24" type="Line2D" parent="Left"] 148 | position = Vector2(230, 0) 149 | points = PackedVector2Array(0, 0, 0, 100) 150 | width = 8.0 151 | 152 | [node name="Line2D25" type="Line2D" parent="Left"] 153 | position = Vector2(240, 0) 154 | points = PackedVector2Array(0, 0, 0, 100) 155 | width = 8.0 156 | 157 | [node name="Line2D26" type="Line2D" parent="Left"] 158 | position = Vector2(250, 0) 159 | points = PackedVector2Array(0, 0, 0, 100) 160 | width = 8.0 161 | 162 | [node name="Line2D27" type="Line2D" parent="Left"] 163 | position = Vector2(260, 0) 164 | points = PackedVector2Array(0, 0, 0, 100) 165 | width = 8.0 166 | 167 | [node name="Line2D28" type="Line2D" parent="Left"] 168 | position = Vector2(270, 0) 169 | points = PackedVector2Array(0, 0, 0, 100) 170 | width = 8.0 171 | 172 | [node name="Line2D29" type="Line2D" parent="Left"] 173 | position = Vector2(280, 0) 174 | points = PackedVector2Array(0, 0, 0, 100) 175 | width = 8.0 176 | 177 | [node name="Line2D30" type="Line2D" parent="Left"] 178 | position = Vector2(290, 0) 179 | points = PackedVector2Array(0, 0, 0, 100) 180 | width = 8.0 181 | 182 | [node name="Line2D31" type="Line2D" parent="Left"] 183 | position = Vector2(300, 0) 184 | points = PackedVector2Array(0, 0, 0, 100) 185 | width = 8.0 186 | 187 | [node name="Line2D32" type="Line2D" parent="Left"] 188 | position = Vector2(310, 0) 189 | points = PackedVector2Array(0, 0, 0, 100) 190 | width = 8.0 191 | 192 | [node name="Right" type="Control" parent="."] 193 | layout_mode = 3 194 | anchors_preset = 8 195 | anchor_left = 0.5 196 | anchor_top = 0.5 197 | anchor_right = 0.5 198 | anchor_bottom = 0.5 199 | offset_left = -163.0 200 | offset_top = 116.0 201 | offset_right = -13.0 202 | offset_bottom = 232.0 203 | grow_horizontal = 2 204 | grow_vertical = 2 205 | scale = Vector2(1, -1) 206 | size_flags_horizontal = 4 207 | size_flags_vertical = 4 208 | metadata/_edit_use_anchors_ = true 209 | 210 | [node name="Line2D" type="Line2D" parent="Right"] 211 | points = PackedVector2Array(0, 14.525, 0, 100) 212 | width = 8.0 213 | default_color = Color(0, 0, 0.976471, 1) 214 | 215 | [node name="Line2D2" type="Line2D" parent="Right"] 216 | position = Vector2(10, 0) 217 | points = PackedVector2Array(0, 0, 0, 100) 218 | width = 8.0 219 | 220 | [node name="Line2D3" type="Line2D" parent="Right"] 221 | position = Vector2(20, 0) 222 | points = PackedVector2Array(0, 0, 0, 100) 223 | width = 8.0 224 | 225 | [node name="Line2D4" type="Line2D" parent="Right"] 226 | position = Vector2(30, 0) 227 | points = PackedVector2Array(0, 0, 0, 100) 228 | width = 8.0 229 | 230 | [node name="Line2D5" type="Line2D" parent="Right"] 231 | position = Vector2(40, 0) 232 | points = PackedVector2Array(0, 0, 0, 100) 233 | width = 8.0 234 | 235 | [node name="Line2D6" type="Line2D" parent="Right"] 236 | position = Vector2(50, 0) 237 | points = PackedVector2Array(0, 0, 0, 100) 238 | width = 8.0 239 | 240 | [node name="Line2D7" type="Line2D" parent="Right"] 241 | position = Vector2(60, 0) 242 | points = PackedVector2Array(0, 0, 0, 100) 243 | width = 8.0 244 | 245 | [node name="Line2D8" type="Line2D" parent="Right"] 246 | position = Vector2(70, 0) 247 | points = PackedVector2Array(0, 0, 0, 100) 248 | width = 8.0 249 | 250 | [node name="Line2D9" type="Line2D" parent="Right"] 251 | position = Vector2(80, 0) 252 | points = PackedVector2Array(0, 0, 0, 100) 253 | width = 8.0 254 | 255 | [node name="Line2D10" type="Line2D" parent="Right"] 256 | position = Vector2(90, 0) 257 | points = PackedVector2Array(0, 0, 0, 100) 258 | width = 8.0 259 | 260 | [node name="Line2D11" type="Line2D" parent="Right"] 261 | position = Vector2(100, 0) 262 | points = PackedVector2Array(0, 0, 0, 100) 263 | width = 8.0 264 | 265 | [node name="Line2D12" type="Line2D" parent="Right"] 266 | position = Vector2(110, 0) 267 | points = PackedVector2Array(0, 0, 0, 100) 268 | width = 8.0 269 | 270 | [node name="Line2D13" type="Line2D" parent="Right"] 271 | position = Vector2(120, 0) 272 | points = PackedVector2Array(0, 0, 0, 100) 273 | width = 8.0 274 | 275 | [node name="Line2D14" type="Line2D" parent="Right"] 276 | position = Vector2(130, 0) 277 | points = PackedVector2Array(0, 0, 0, 100) 278 | width = 8.0 279 | 280 | [node name="Line2D15" type="Line2D" parent="Right"] 281 | position = Vector2(140, 0) 282 | points = PackedVector2Array(0, 0, 0, 100) 283 | width = 8.0 284 | 285 | [node name="Line2D16" type="Line2D" parent="Right"] 286 | position = Vector2(150, 0) 287 | points = PackedVector2Array(0, 0, 0, 100) 288 | width = 8.0 289 | 290 | [node name="Line2D17" type="Line2D" parent="Right"] 291 | position = Vector2(160, 0) 292 | points = PackedVector2Array(0, 14.525, 0, 100) 293 | width = 8.0 294 | default_color = Color(0, 0, 0.976471, 1) 295 | 296 | [node name="Line2D18" type="Line2D" parent="Right"] 297 | position = Vector2(170, 0) 298 | points = PackedVector2Array(0, 0, 0, 100) 299 | width = 8.0 300 | 301 | [node name="Line2D19" type="Line2D" parent="Right"] 302 | position = Vector2(180, 0) 303 | points = PackedVector2Array(0, 0, 0, 100) 304 | width = 8.0 305 | 306 | [node name="Line2D20" type="Line2D" parent="Right"] 307 | position = Vector2(190, 0) 308 | points = PackedVector2Array(0, 0, 0, 100) 309 | width = 8.0 310 | 311 | [node name="Line2D21" type="Line2D" parent="Right"] 312 | position = Vector2(200, 0) 313 | points = PackedVector2Array(0, 0, 0, 100) 314 | width = 8.0 315 | 316 | [node name="Line2D22" type="Line2D" parent="Right"] 317 | position = Vector2(210, 0) 318 | points = PackedVector2Array(0, 0, 0, 100) 319 | width = 8.0 320 | 321 | [node name="Line2D23" type="Line2D" parent="Right"] 322 | position = Vector2(220, 0) 323 | points = PackedVector2Array(0, 0, 0, 100) 324 | width = 8.0 325 | 326 | [node name="Line2D24" type="Line2D" parent="Right"] 327 | position = Vector2(230, 0) 328 | points = PackedVector2Array(0, 0, 0, 100) 329 | width = 8.0 330 | 331 | [node name="Line2D25" type="Line2D" parent="Right"] 332 | position = Vector2(240, 0) 333 | points = PackedVector2Array(0, 0, 0, 100) 334 | width = 8.0 335 | 336 | [node name="Line2D26" type="Line2D" parent="Right"] 337 | position = Vector2(250, 0) 338 | points = PackedVector2Array(0, 0, 0, 100) 339 | width = 8.0 340 | 341 | [node name="Line2D27" type="Line2D" parent="Right"] 342 | position = Vector2(260, 0) 343 | points = PackedVector2Array(0, 0, 0, 100) 344 | width = 8.0 345 | 346 | [node name="Line2D28" type="Line2D" parent="Right"] 347 | position = Vector2(270, 0) 348 | points = PackedVector2Array(0, 0, 0, 100) 349 | width = 8.0 350 | 351 | [node name="Line2D29" type="Line2D" parent="Right"] 352 | position = Vector2(280, 0) 353 | points = PackedVector2Array(0, 0, 0, 100) 354 | width = 8.0 355 | 356 | [node name="Line2D30" type="Line2D" parent="Right"] 357 | position = Vector2(290, 0) 358 | points = PackedVector2Array(0, 0, 0, 100) 359 | width = 8.0 360 | 361 | [node name="Line2D31" type="Line2D" parent="Right"] 362 | position = Vector2(300, 0) 363 | points = PackedVector2Array(0, 0, 0, 100) 364 | width = 8.0 365 | 366 | [node name="Line2D32" type="Line2D" parent="Right"] 367 | position = Vector2(310, 0) 368 | points = PackedVector2Array(0, 0, 0, 100) 369 | width = 8.0 370 | 371 | [node name="Button1" type="Button" parent="."] 372 | offset_right = 8.0 373 | offset_bottom = 8.0 374 | text = "Play Song 1" 375 | 376 | [node name="Button2" type="Button" parent="."] 377 | offset_left = 105.0 378 | offset_top = 2.0 379 | offset_right = 201.0 380 | offset_bottom = 33.0 381 | text = "Play Song 2" 382 | 383 | [node name="SongName" type="Label" parent="."] 384 | offset_top = 45.0 385 | offset_right = 40.0 386 | offset_bottom = 68.0 387 | 388 | [connection signal="pressed" from="Button1" to="." method="on_play_first_song"] 389 | [connection signal="pressed" from="Button2" to="." method="on_play_second_song"] 390 | -------------------------------------------------------------------------------- /audio_generator/generator_demo.ts: -------------------------------------------------------------------------------- 1 | import { AudioEffectSpectrumAnalyzer, AudioServer, AudioStreamGenerator, AudioStreamGeneratorPlayback, AudioStreamPlayer, Color, Label, Line2D, Node, Vector2 } from "godot"; 2 | import { onready } from "godot.annotations"; 3 | import { transform as fft } from "./fft"; 4 | 5 | const zzfxm = require("libs/zzfxm_gn"); 6 | 7 | // https://keithclark.github.io/ZzFXM/ 8 | class SongData { 9 | private _songs: any[] = []; 10 | 11 | access(index: number) { 12 | if (typeof this._songs[index] === "undefined") { 13 | if (typeof this._songs[index] === "undefined") { 14 | this._songs[index] = index == 0 ? { 15 | // Song data for "I am back". Original song by Sky. 16 | "name": "I am back", 17 | "samples": [[[1.8, 0, 72, , , .2, , 4, -2, 6, 50, .15, , 6], [, 0, 655, , , .09, 3, 1.65, , , , , .02, 3.8, -.1, , .2], [1.2, 0, 23, , , .2, 3, 4, , , 3, .9, .05], [1.5, 0, 740, , , .15, 2, .2, -.1, -.15, 9, .02, , .1, .12, , .06]], [[[3, -1, 13, 13, 13, 8, 13, , , , , , , , , , , , 11, 11, 11, 6, 11, , , , , , , , , , , , 10, 10, 10, 6, 10, , , , , , , , , 6, 8, 10, 8, 8, 8, 5, 13, , 8, 8, 8, 5, 13, , , , , ,], [, 1, 25, , 25, , , , , , , , , , , , , 25, 25, , 25, , , , , , , 25, , , 25, , 25, 25, 25, , 25, , , , , , , , , , , 25, 25, 25, 25, , 25, , , , , , , , , , , , , ,], [2, -1, 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, 25, , 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, , , 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, 25, , 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, 25, ,]], [[3, -1, 13, 13, 13, 8, 13, , , , , , , , , , , , 11, 11, 11, 6, 11, , , , , , , , , , , , 10, 10, 10, 6, 10, , , , , , , , , 6, 8, 10, 8, 8, 8, 5, 13, , 8, 8, 8, 5, 13, 8, 8, 8, 5, 13], [2, -1, 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, 25, 27, 11, , 23, , 11, 11, 23, 11, , 11, 23, 11, 11, 11, 23, 22, 18, , 30, , 18, 18, 30, 18, , 18, 30, 18, 18, 18, 30, 22, 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, 25, ,], [, 1, 25, , 25, , , , , , , , , , , , , 25, 25, , 25, , , , , , , , , , , , , , 25, , 25, , , , , , , , , , , 25, 25, 25, 25, , 25, , , , , , , , , , , , , ,], [1, 1, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , 13, 13, 13, 13, 13, 13, 13, 13]], [[3, -1, 13, 13, 13, 8, 13, , 13, 15, 17, 17, 15, 13, 20, 20, 18, 17, 18, , , , 17, , 15, , , , 17, , 18, , 22, 22, 22, , 18, , , , 25, 25, 25, , 22, , , 18, 20, 22, 20, , , , , , , , , , , , , , , ,], 18 | [2, -1, 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, 25, 27, 11, , 23, , 11, 11, 23, 11, , 11, 23, 11, 11, 11, 23, 22, 18, , 30, , 18, 18, 30, 18, , 18, 30, 18, 18, 18, 30, 22, 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, 25, ,], [, 1, 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , ,], [1, 1, , , , , 13, , , , , , , , 13, , , , , , , , 13, , , , , , , , 13, , 13, , , , , , 13, , , , , , , , 13, , , , , , , , 13, , , , , , , , 13, 13, , 13]], [[3, -1, 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, 25, , 11, , 23, , 11, 11, 23, 11, , 11, 23, 11, 11, 11, 23, , 10, , 22, , 10, 10, 22, 10, , 10, 22, 10, 10, 6, 8, 10, 20, 25, 20, 20, 25, 20, , 20, 25, 20, 20, 20, 25, , 20, ,], [2, -1, 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, 25, , 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, 25, , 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, 25, , 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, 25, ,], 19 | [, 1, 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , ,], [1, 1, , , , , 13, , , , , , , , 13, , , , , , , , 13, , , , , , , , 13, , 13, , , , , , 13, , , , , , , , 13, , , , , , , , 13, , , , , , , , 13, 13, , 13]], [[3, -1, 13, , , , , , 8, , 17, 15, 13, , 17, 15, 13, , 15, , , , 10, 13, 15, 10, 13, 15, 10, 13, 15, 10, 13, 15, 12, , , , , , 8, 15, , , , , 17, 15, 13, 8, 13, , , , , , 10, 8, , 20, 20, 20, 20, 20, 20, 20], [2, -1, 13, , 25, , 13, 13, 25, 13, , 13, 25, 13, 13, 13, 25, , 15, , 27, , 15, 15, 27, 15, , 15, 27, 15, 15, 15, 27, 32, 20, , 32, , 20, 20, 32, 20, , 20, 32, 20, 20, 20, 32, , 13, , 25, , 13, 13, 25, 20, , 20, 32, 20, 20, 20, 32, ,], [, 1, 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , ,], [1, 1, , , , , 13, , , , , , , , 13, , , , , , , , 13, , , , , , , , 13, , 13, , , , , , 13, , , , , , , , 13, , , , , , , , 13, , , , , , , , 13, 13, , 13]], [[3, -1, 13, , , , , , 8, , 17, , , , 18, 17, 15, , 18, , , , 13, , , , 10, , , , 6, , , , 8, 12, 15, 12, 20, , 8, 12, 15, 12, 20, , 22, 20, 15, , 13, , , , , , 10, , 8, , , , , 8, 20, 8], [2, -1, 13, , 25, 25, 13, , 25, 25, 13, , 25, 25, 13, , 25, 25, 15, , 27, 27, 15, , 27, 27, 15, , 27, 27, 15, , 27, 27, 20, , 32, 32, 20, , 32, 32, 20, , 32, 32, 20, , 32, 32, 13, , 25, 25, 13, , 25, 25, 20, , 32, 32, 20, , 32, 34], [, 1, 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , ,], [1, 1, , , , , 13, , , , , , , , 13, , , , , , , , 13, , , , , , , , 13, , 13, , , , , , 13, , , , , , , , 13, , , , , , , , 13, , , , , , , , 13, 13, , 13]], [[3, -1, 13, , , , , , 8, , 17, , , , 18, 17, 15, , 18, , , , 13, , , , 10, , , , 6, , , , 8, 12, 15, 12, 20, , 8, 12, 15, 12, 20, , 22, 20, 15, , 13, , , , , , 10, , 8, , , , , 8, 20, 8], 20 | [, 1, 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , ,], [1, 1, , , , , 13, , , , , , , , 13, , , , , , , , 13, , , , , , , , 13, , 13, , , , , , 13, , , , , , , , 13, , , , , , , , 13, , , , , , , , 13, 13, , 13]], [[, 1, 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , , , 25, 25, , 25, 25, , , , , , 25, , , , 25, , , 25, , , , 25, 25, 25, 25, 25], [1, 1, , , , , 13, , , , , , , , 13, , , , , , , , 13, , , , , , , , 13, , 13, , , , , , 13, , , , , , , , 13, , , , , , , , 13, 13, , 13, , 13, 13, 13, 13, 13, 13, 13]]], [0, 1, 2, 2, 3, 3, 2, 2, 4, 4, 5, 6, 6, 7, 2, 2, 3]], 21 | } : { 22 | // Song data for "Sanxion (Loader)". Original song by Rob Hubbard. 23 | "name": "Sanxion", 24 | "samples": [[[.4, 0, 1e4, , , , , , , , , , .01, 6.8, -.2], [1.4, 0, 84, , , , , .7, , , , .5, , 6.7, 1, .01], [, 0, 60, , .1, , 2], [2, 0, 360, , , .12, 2, 2, , , , , , 9, , .1], [.75, 0, 586, , , .25, 6], [2, 0, 360, , , .375, 2, 3.5], [1.2, 0, 490, , .25, .45, , , , , , , .2, , , , , , , .1], [.75, 0, 386, , , .25, 6]], [[[, -1, 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, ,], [2, -1, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 20, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 8, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 8, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 20], [, 1, 32, 22, 22, 32, 32, 22, 32, 27, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 27, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 27, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.5, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.5, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.5, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [4, 1, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , 24.75, 20.75, , , , , , , 24.75, 20.75, , , , 21.75, 20.75, , 24.75, 20.75, , , , , , , 24.75, 20.75, , , , 21.75, 20.75]], [[, -1, 8, , , , , , 8, , 8, , , , , , 8, , 6, , , , , , 6, , 6, , , , , , 6, , 13, , , , , , 13, , 13, , , , , , 13, , 8, , , , , , 8, , 8, , , , , , 8, ,], [2, -1, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 20, , 18, 6, 6, 18, 6, , 18, , 18, , 6, 18, 6, , 6, , 25, 13, 13, 25, 13, , 13, , 25, 13.75, 13, 25, 13, , 25, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 20], [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [5, 1, 20, 20, 15, , 18, , 13, 15, , 11, , 6, 8, , 18, 20, 11, 11, 13, , 10, , 13, 18, 23, 23, 22, , 18, , 13, , 11, 11, 13, , 25, , 11, 13, 25, 25, 11, , 13, , 6, , 8, , , , , , , , , , , , , , , ,]], 25 | [[, -1, 6, , , , , , 6, , 6, , , , , , 6, , 11, , , , , , 11, , 11, , , , , , 11, , 13, , , , , , 13, , 13, , , , , , 13, , 8, , , , , , 8, , 8, , , , , , 8, ,], [2, -1, , 18, 6, 6, 18, 6, , 6, , 18, , 6, 18, 6, , 6, , 23, 11, 11, 23, 11, , 23, , 23, , 11, 23, 11, , 11, , 25, 13, 13, 25, 13, , 13, , 25, 13.75, 13, 25, 13, , 25, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 20], [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [5, 1, 18, 18, 13, , 11, , 10, 11, , 11, , 13, 10, , 11, 13, 23, 23, 22, , 18, , 13, , 11, 10, , 18, 11, , 11, 18, 11, 11, 13, , 25, , 18, 23, 25, 23, 18, , 23, 23, 18, , 20, , 20, 18, 11, , 6, 8, , , , , , , , ,]], [[, -1, 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, ,], [2, -1, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 20, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 8], [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.5, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.5], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,]], [[, -1, 11, , , , , , 11, , 11, , , , , , 11, , 11, , , , , , 11, , 11, , , , , , 11, , 16, , , , , , 16, , 16, , , , , , 16, , 16, , , , , , 16, , 16, , , , , , 16, ,], [2, -1, , 23, 11, 11, 23, 11, , 11, , 23, , 11, 23, 11, , 23, , 23, 11, 11, 23, 11, , 11, , 23, , 11, 23, 11, , 11, , 28, 16, 16, 28, 16, , 16, , 28, , 16, 28, 16, , 16, , 28, 16, 16, 28, 16, , 16, , 28, , 16, 28, 16, , 16], [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], 26 | [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [6, 1, 15, , , , , , , , , , , , , , , , 18, , , , , , , , , , , , 15, 18, 15, 18, 18, , , , 20, , , , , , , , , , , , 23, , , , , , , , , , , , 20, 23, 20, 23]], [[, -1, 13, , , , , , 13, , 13, , , , , , 13, , 13, , , , , , 13, , 13, , , , , , 13, , 15, , , , , , 15, , 15, , , , , , 15, , 15, , , , , , 15, , 15, , , , , , 15, ,], [2, -1, , 25, 13, 13, 25, 13, , 25, , 25, , 13, 25, 13, , 13, , 25, 13, 13, 25, 13, , 25, , 25, , 13, 25, 13, , 25, , 27, 15, 15, 27, 15, , 27, , 27, , 15, 27, 15, , 15, , 27, 15, 15, 27, 15, , 27, , 27, , 15, 27, 15, , 15], [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [6, 1, 25, , , , , , , , , , , , , , , , , , , , , , , , , , , , 20, 23, 25, , 27, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,]], [[2, -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [4, 1, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, , , , , , , , ,], [7, 1, , , , , , , , , , , , , , , , , , , , , , , , , 18, 18, , 18, 13, 13, 10, 10]], [[, -1, 4, , , , , , 4, , 4, , , , , , 4, , 4, , , , , , 4, , 4, , , , , , 4, , 13, , , , , , 13, , 13, , , , , , 13, , 13, , , , , , 13, , 13, , , , , , 13, ,], [2, -1, , 16, 4, 4, 16, 4, , 16, , 16, , 4, 16, 4, , 16, , 16, 4, 4, 16, 4, , 4, , 16, , 4, 16, 4, , 4, , 25, 13, 13, 25, 13, , 13, , 25, , 13, 25, 13, , 13, , 25, 13, 13, 25, 13, , 25, , 25, , 13, 25, 13, , 13], [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], 27 | [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [6, 1, 4, , , , , , 11, , , , , , 16, , , , 21, , , , , , 20, , , , , , 20, , , , 11, , , , , , 13, , , , , , 13, , , , 11, , , , , , 13, , , 13, , , 11, 11, 13, 13]], [[, -1, 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 6, , , , , , 6, , 6, , , , , , 6, , 6, , , , , , 6, , 6, , , , , , 6, ,], [2, -1, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 20, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 8, , 18, 6, 6, 18, 6, , 18, , 18, , 6, 18, 6, , 18, , 18, 6, 6, 18, 6, , 18, , 18, , 6, 18, 6, , 18], [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [6, 1, 8, , , , , , 18, , , , , , , , , , 11, , , , , , 22, , , , , , , , , , , , , , 18, , , , , , , , , , , , 18, 18, 18, 18, 18, 18, 18, 18, 20, 20, 20, 20, 18, 18, 18, 18]], [[, -1, 4, , , , , , 4, , 4, , , , , , 4, , 4, , , , , , 4, , 4, , , , , , 4, , 13, , , , , , 13, , 13, , , , , , 13, , 13, , , , , , 13, , 13, , , , , , 13, ,], [2, -1, , 16, 4, 4, 16, 4, , 16, , 16, , 4, 16, 4, , 16, , 16, 4, 4, 16, 4, , 4, , 16, , 4, 16, 4, , 4, , 25, 13, 13, 25, 13, , 13, , 25, , 13, 25, 13, , 13, , 25, 13, 13, 25, 13, , 25, , 25, , 13, 25, 13, , 13], [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], 28 | [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [6, 1, 4.25, , , , 16, , 16, , , , , , , , 16, , , , 18, , 15, , , , 13, , 11, , , , , , 1, , , , 16, , 16, , , , , , , , 21, , , , 23, , 20, , , , 18, , 16, , 11, , 9, ,]], [[, -1, 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 6, , , , , , 6, , 6, , , , , , 6, , 6, , , , , , 6, , 6, , , , , , 6, ,], [2, -1, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 20, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 8, , 18, 6, 6, 18, 6, , 18, , 18, , 6, 18, 6, , 18, , 18, 6, 6, 18, 6, , 18, , 18, , 6, 18, 6, , 18], [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [6, 1, 11, , , , , , 9, , , , , , 8, , , , 16, , , , , , 15, , , , , , 15, , , , 6, , , , , , 13, , , , , , 18, , , , 23, 22.5, 22.5, 22.37, 22.37, 22.5, 22.5, 22.37, 22.37, 22.5, 22.5, 22.37, 22.37, 22.5, 22.5, 22.37]], [[, -1, 4, , , , , , 4, , 4, , , , , , 4, , 4, , , , , , 4, , 4, , , , , , 4, , 13, , , , , , 13, , 13, , , , , , 13, , 13, , , , , , 13, , 13, , , , , , 13, ,], [2, -1, , 16, 4, 4, 16, 4, , 16, , 16, , 4, 16, 4, , 16, , 16, 4, 4, 16, 4, , 4, , 16, , 4, 16, 4, , 4, , 25, 13, 13, 25, 13, , 13, , 25, , 13, 25, 13, , 13, , 25, 13, 13, 25, 13, , 25, , 25, , 13, 25, 13, , 13], [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [6, 1, 4, , , , , , , , , , , , , , , , , 16, 16, 16, 15, 16, 16, 16, 15, 16, 16, 16, 4, , 6, , 8, , , , , , , , , , , , , , , , , 20, 20, 20, 19, 20, 20, 20, 19, 20, 20, 20, 8, , 9, ,]], 29 | [[, -1, 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 6, , , , , , 6, , 6, , , , , , 6, , 6, , , , , , 6, , 6, , , , , , 6, ,], [2, -1, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 20, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 8, , 18, 6, 6, 18, 6, , 18, , 18, , 6, 18, 6, , 18, , 18, 6, 6, 18, 6, , 18, , 18, , 6, 18, 6, , 18], [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [6, 1, 20, , , , , , 21, , , , , , 20, , , , 16, , , , 15, , 11, , , , 8, , , , , , 6, , , , , , 13, , , , , , 18, , , , 30, , , , , , 25, , 23, , 22, , 18, , 13, ,]], [[, -1, 4, , , , , , 4, , 4, , , , , , 4, , 4, , , , , , 4, , 4, , , , , , 4, , 13, , , , , , 13, , 13, , , , , , 13, , 13, , , , , , 13, , 13, , , , , , 13, ,], [2, -1, , 16, 4, 4, 16, 4, , 16, , 16, , 4, 16, 4, , 16, , 16, 4, 4, 16, 4, , 4, , 16, , 4, 16, 4, , 4, , 25, 13, 13, 25, 13, , 13, , 25, , 13, 25, 13, , 13, , 25, 13, 13, 25, 13, , 25, , 25, , 13, 25, 13, , 13], [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [6, 1, 4.25, , 3, , 4, , 11, , 16, , , , 23, , 20, , 8, , 8.25, , 20, , , , 21, , , , 23, , , , , , , , 23, , , , 21, , , , 20, , 8, 8, 8, 1, 3, , 4, , 8, , 13, , 16, , 20, , 21, ,]], [[, -1, 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 8, , , , , , 8, , 6, , , , , , 6, , 6, , , , , , 6, , 6, , , , , , 6, , 6, , , , , , 6, ,], [2, -1, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 20, , 20, 8, 8, 20, 8, , 8, , 20, , 8, 20, 8, , 8, , 18, 6, 6, 18, 6, , 18, , 18, , 6, 18, 6, , 18, , 18, 6, 6, 18, 6, , 18, , 18, , 6, 18, 6, , 18], 30 | [, 1, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32, 32, 22, 22, 32, 32, 22, 32, 22, 32, 22, 22, 32, 32, 22, 32, 32], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,], [6, 1, 11, , , , , , , , , , , , , , , , , 23, 23, 23, 22, 23, 21, , 20, , 15, , 11, , 8, , 6, , , , , , 8, , , , , , 10, , , , 11, , , , , , 13, , , , , , 16, , , ,]], [[4, -1, 15, 15, 15, , 15, , 15, 15, , 15, , 15, 15, , 15, 15, 15, 15, 15, , 15, , 15, 15, 27, 15, , 15, 15, , 15, 15, 15, 15, 15, , 15, , 15, 15, 15, 15, 15, , 15, 15, 15, , 15, , 15, 15, 15, , 15, 15, , , , , , , , ,], [1, -1, 20, , , 20, , , 20, 22.5, 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25, 20, , , 20, , , 20, , 20, , , 20, , , 20, 20.25], [, -1, , 22, 22, , , 22, , , , 22, 22, , , 22, , , , 22, 22, , , 22, , 22, , 22, 22, , , 22, , , , 22, 22, , , 22, , 22, , 22, 22, , , 22, , , , 22, 22, , , 22, , 22, , 22, 22, , , 22, , ,], [3, -1, , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , , , , , , 32, , , ,]]], [0, 1, 2, 3, 2, 4, 5, 6, 1, 2, 3, 7, 10, 9, 8, 13, 12, 11, 14, 4, 5, 15, 6]] 31 | }; 32 | } else if (index == 1) { 33 | 34 | } 35 | } 36 | return this._songs[index]; 37 | } 38 | } 39 | 40 | const FFT_SIZE = 1024; 41 | 42 | class Visualizer { 43 | private resolution = 32; 44 | private real: Array = []; 45 | private imag: Array = []; 46 | private cache: Array = []; 47 | private dirty = false; 48 | 49 | private get_level(index: number, rf: number) { 50 | let value = 0; 51 | for (let i = 0; i < rf; ++i) { 52 | let e = index * rf + i; 53 | if (e >= this.real.length) break; 54 | value += Math.sqrt(this.real[e] * this.real[e] + this.imag[e] * this.imag[e]); 55 | } 56 | // return Math.max(0, Math.min(20, (value / rf) / 20)); 57 | return Math.max(0, Math.min(2, (value / rf) / 6)); // scale and trunc 58 | } 59 | 60 | setup(samples: Array) { 61 | this.real = samples; 62 | this.dirty = true; 63 | } 64 | 65 | get results(): Array { 66 | if (this.dirty) { 67 | this.dirty = false; 68 | this.imag.fill(0); 69 | fft(this.real, this.imag); 70 | 71 | const rf = Math.floor(this.real.length / this.resolution); 72 | for (let i = 0; i < this.resolution; ++i) { 73 | this.cache[i] = this.get_level(i, rf); 74 | } 75 | } 76 | 77 | return this.cache; 78 | } 79 | } 80 | 81 | /** 82 | * Audio Generator Demo (TypeScript version) 83 | * This is a demo showing how one can generate and play audio samples from TypeScript. 84 | * 85 | * @link https://godotengine.org/asset-library/asset/526 86 | */ 87 | export default class AudioGeneratorDemo extends Node { 88 | @onready("Player") 89 | player!: AudioStreamPlayer; 90 | 91 | private left = new Visualizer(); 92 | private right = new Visualizer(); 93 | private playback!: AudioStreamGeneratorPlayback; 94 | private current_song = -1; 95 | private loading_tag = 0; 96 | private loading = false; 97 | 98 | // use cached Vector2 to avoid unnecessary garbages 99 | private cached_frame = new Vector2(); 100 | private frame_index = 0; 101 | 102 | private data = new SongData(); 103 | private timer?: NodeJS.Timeout; 104 | 105 | _ready(): void { 106 | // this.buffer = zzfx.generate(1.74,.05,598,.09,.26,.41,0,.24,0,0,-46,.07,.17,0,0,0,.09,.42,.28,.06); 107 | (this.player.stream).mix_rate = zzfxm.zzfxR; 108 | this.player.play(); 109 | this.playback = this.player.get_stream_playback(); 110 | this.timer = setInterval(() => { 111 | this.draw("Left", this.left, Color.RED); 112 | this.draw("Right", this.right, Color.BLUE); 113 | }, 100); 114 | this.load_song(0); 115 | } 116 | 117 | on_play_first_song() { 118 | this.load_song(0); 119 | } 120 | 121 | on_play_second_song() { 122 | this.load_song(1); 123 | } 124 | 125 | private async load_song(index: number) { 126 | if (this.current_song === index) { 127 | return; 128 | } 129 | 130 | this.current_song = index; 131 | 132 | const tag = ++this.loading_tag; 133 | const info = this.data.access(this.current_song); 134 | if (typeof info.fully_loaded === "undefined") { 135 | this.loading = true; 136 | this.on_song_changed(); 137 | 138 | const galop = 10_000; 139 | const gen = zzfxm.default(...info.samples); 140 | info.cache = gen.next().value; 141 | for (let i = 0; ; ++i) { 142 | let res = gen.next(); 143 | 144 | if (res.done) { 145 | console.log("song generation done:", info.name); 146 | info.fully_loaded = true; 147 | if (tag === this.loading_tag) { 148 | this.loading = false; 149 | this.on_song_changed(); 150 | } 151 | break; 152 | } 153 | if (tag !== this.loading_tag) { 154 | console.log("song generation cancelled:", info.name); 155 | return; 156 | } 157 | if (!(i % galop)) { 158 | const label =