├── .github
└── dependabot.yml
├── .gitignore
├── LICENSE.md
├── app
├── css
│ ├── fonts
│ │ └── Roboto_Mono
│ │ │ ├── LICENSE.txt
│ │ │ ├── README.txt
│ │ │ ├── RobotoMono-Italic-VariableFont_wght.ttf
│ │ │ ├── RobotoMono-VariableFont_wght.ttf
│ │ │ └── static
│ │ │ ├── RobotoMono-Bold.ttf
│ │ │ ├── RobotoMono-BoldItalic.ttf
│ │ │ ├── RobotoMono-ExtraLight.ttf
│ │ │ ├── RobotoMono-ExtraLightItalic.ttf
│ │ │ ├── RobotoMono-Italic.ttf
│ │ │ ├── RobotoMono-Light.ttf
│ │ │ ├── RobotoMono-LightItalic.ttf
│ │ │ ├── RobotoMono-Medium.ttf
│ │ │ ├── RobotoMono-MediumItalic.ttf
│ │ │ ├── RobotoMono-Regular.ttf
│ │ │ ├── RobotoMono-SemiBold.ttf
│ │ │ ├── RobotoMono-SemiBoldItalic.ttf
│ │ │ ├── RobotoMono-Thin.ttf
│ │ │ └── RobotoMono-ThinItalic.ttf
│ └── styles.css
├── forge.config.js
├── html
│ ├── gui.html
│ ├── readme.html
│ └── render.html
├── icon.icns
├── icon.ico
├── icon.png
├── index.html
├── js
│ ├── acid.js
│ ├── acidgui.js
│ ├── acidrender.js
│ ├── gif.js
│ ├── gif.js.map
│ ├── gif.worker.js
│ ├── gif.worker.js.map
│ ├── guirenderer.js
│ ├── helpers.js
│ ├── renderer.js
│ ├── renderrenderer.js
│ └── wavetables.js
├── main.js
├── package-lock.json
├── package.json
└── preload.js
├── ideas.txt
├── img
├── animated_cover.gif
├── banner.gif
├── banner_logo.gif
├── cover.gif
├── example.gif
├── screenshot-1.jpg
├── screenshot-1.png
├── screenshot-2.jpg
├── screenshot-2.png
├── screenshot-3.jpg
└── screenshot-3.png
└── readme.md
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: npm
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | time: "13:00"
8 | open-pull-requests-limit: 99
9 | versioning-strategy: increase
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | app/node_modules
2 | ideas.txt
3 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | CC0 1.0 Universal
2 | ==================
3 |
4 | Statement of Purpose
5 | ---------------------
6 |
7 | The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
8 |
9 | Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
10 |
11 | For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
12 |
13 | 1. Copyright and Related Rights.
14 | --------------------------------
15 | A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
16 |
17 | i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
18 | ii. moral rights retained by the original author(s) and/or performer(s);
19 | iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
20 | iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
21 | v. rights protecting the extraction, dissemination, use and reuse of data in a Work;
22 | vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
23 | vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
24 |
25 | 2. Waiver.
26 | -----------
27 | To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
28 |
29 | 3. Public License Fallback.
30 | ----------------------------
31 | Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
32 |
33 | 4. Limitations and Disclaimers.
34 | --------------------------------
35 |
36 | a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
37 | b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
38 | c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
39 | d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
40 |
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/README.txt:
--------------------------------------------------------------------------------
1 | Roboto Mono Variable Font
2 | =========================
3 |
4 | This download contains Roboto Mono as both variable fonts and static fonts.
5 |
6 | Roboto Mono is a variable font with this axis:
7 | wght
8 |
9 | This means all the styles are contained in these files:
10 | Roboto_Mono/RobotoMono-VariableFont_wght.ttf
11 | Roboto_Mono/RobotoMono-Italic-VariableFont_wght.ttf
12 |
13 | If your app fully supports variable fonts, you can now pick intermediate styles
14 | that aren’t available as static fonts. Not all apps support variable fonts, and
15 | in those cases you can use the static font files for Roboto Mono:
16 | Roboto_Mono/static/RobotoMono-Thin.ttf
17 | Roboto_Mono/static/RobotoMono-ExtraLight.ttf
18 | Roboto_Mono/static/RobotoMono-Light.ttf
19 | Roboto_Mono/static/RobotoMono-Regular.ttf
20 | Roboto_Mono/static/RobotoMono-Medium.ttf
21 | Roboto_Mono/static/RobotoMono-SemiBold.ttf
22 | Roboto_Mono/static/RobotoMono-Bold.ttf
23 | Roboto_Mono/static/RobotoMono-ThinItalic.ttf
24 | Roboto_Mono/static/RobotoMono-ExtraLightItalic.ttf
25 | Roboto_Mono/static/RobotoMono-LightItalic.ttf
26 | Roboto_Mono/static/RobotoMono-Italic.ttf
27 | Roboto_Mono/static/RobotoMono-MediumItalic.ttf
28 | Roboto_Mono/static/RobotoMono-SemiBoldItalic.ttf
29 | Roboto_Mono/static/RobotoMono-BoldItalic.ttf
30 |
31 | Get started
32 | -----------
33 |
34 | 1. Install the font files you want to use
35 |
36 | 2. Use your app's font picker to view the font family and all the
37 | available styles
38 |
39 | Learn more about variable fonts
40 | -------------------------------
41 |
42 | https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts
43 | https://variablefonts.typenetwork.com
44 | https://medium.com/variable-fonts
45 |
46 | In desktop apps
47 |
48 | https://theblog.adobe.com/can-variable-fonts-illustrator-cc
49 | https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts
50 |
51 | Online
52 |
53 | https://developers.google.com/fonts/docs/getting_started
54 | https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
55 | https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts
56 |
57 | Installing fonts
58 |
59 | MacOS: https://support.apple.com/en-us/HT201749
60 | Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux
61 | Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows
62 |
63 | Android Apps
64 |
65 | https://developers.google.com/fonts/docs/android
66 | https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts
67 |
68 | License
69 | -------
70 | Please read the full license text (LICENSE.txt) to understand the permissions,
71 | restrictions and requirements for usage, redistribution, and modification.
72 |
73 | You can use them freely in your products & projects - print or digital,
74 | commercial or otherwise. However, you can't sell the fonts on their own.
75 |
76 | This isn't legal advice, please consider consulting a lawyer and see the full
77 | license for all details.
78 |
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/RobotoMono-Italic-VariableFont_wght.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/RobotoMono-Italic-VariableFont_wght.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/RobotoMono-VariableFont_wght.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/RobotoMono-VariableFont_wght.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-Bold.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-BoldItalic.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-ExtraLight.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-ExtraLight.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-ExtraLightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-ExtraLightItalic.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-Italic.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-Light.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-LightItalic.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-Medium.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-MediumItalic.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-Regular.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-SemiBold.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-SemiBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-SemiBoldItalic.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-Thin.ttf
--------------------------------------------------------------------------------
/app/css/fonts/Roboto_Mono/static/RobotoMono-ThinItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/app/css/fonts/Roboto_Mono/static/RobotoMono-ThinItalic.ttf
--------------------------------------------------------------------------------
/app/css/styles.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "Monospace";
3 | font-weight: 400;
4 | src: url("./fonts/Roboto_Mono/static/RobotoMono-Regular.ttf");
5 | }
6 | @font-face {
7 | font-family: "Monospace";
8 | font-weight: 700;
9 | src: url("./fonts/Roboto_Mono/static/RobotoMono-Bold.ttf");
10 | }
11 | #readme{
12 | background: black;
13 | color: white;
14 | padding: 24px;
15 | font-size: 16px;
16 | line-height: 1.5em;
17 | }
18 | #readme a{
19 | color: white;
20 | }
21 | b,strong{
22 | font-weight: 700;
23 | }
24 | em,i{
25 | font-style: italic;
26 | }
27 | #canvas{
28 | position: absolute;
29 | top: 0;
30 | left: 0;
31 | }
32 | *{
33 | font-family: "Monospace",monospace;
34 | font-weight: 400;
35 | }
36 | .recording-marker{
37 | position: fixed;
38 | top: 24px;
39 | left: 24px;
40 | height: 24px;
41 | width: 24px;
42 | border-radius: 50%;
43 | background: red;
44 | animation: recording 1s ease-in-out infinite;
45 | z-index: 2;
46 | display: none;
47 | }
48 | .recorder-active .recording-marker{
49 | display: block;
50 | }
51 | .exporting-marker {
52 | position: fixed;
53 | display: none;
54 | top: 24px;
55 | left: 24px;
56 | z-index: 2;
57 | font-size: 2px;
58 | text-indent: -9999em;
59 | width: 11em;
60 | height: 11em;
61 | border-radius: 50%;
62 | background: #ff0000;
63 | background: -moz-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
64 | background: -webkit-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
65 | background: -o-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
66 | background: -ms-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
67 | background: linear-gradient(to right, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
68 | -webkit-animation: load3 1.4s infinite linear;
69 | animation: load3 1.4s infinite linear;
70 | -webkit-transform: translateZ(0);
71 | -ms-transform: translateZ(0);
72 | transform: translateZ(0);
73 | }
74 | .exporting-marker:before {
75 | width: 50%;
76 | height: 50%;
77 | background: #ffffff;
78 | border-radius: 100% 0 0 0;
79 | position: absolute;
80 | top: 0;
81 | left: 0;
82 | content: '';
83 | }
84 | .exporting-marker:after {
85 | background: #ff0000;
86 | width: 75%;
87 | height: 75%;
88 | border-radius: 50%;
89 | content: '';
90 | margin: auto;
91 | position: absolute;
92 | top: 0;
93 | left: 0;
94 | bottom: 0;
95 | right: 0;
96 | }
97 | .export-active .exporting-marker{
98 | display: block;
99 | }
100 | @-webkit-keyframes load3 {
101 | 0% {
102 | -webkit-transform: rotate(0deg);
103 | transform: rotate(0deg);
104 | }
105 | 100% {
106 | -webkit-transform: rotate(360deg);
107 | transform: rotate(360deg);
108 | }
109 | }
110 | @keyframes load3 {
111 | 0% {
112 | -webkit-transform: rotate(0deg);
113 | transform: rotate(0deg);
114 | }
115 | 100% {
116 | -webkit-transform: rotate(360deg);
117 | transform: rotate(360deg);
118 | }
119 | }
120 |
121 | @keyframes recording {
122 | 0%,100%{
123 | opacity: 1;
124 | }
125 | 50%{
126 | opacity: 0;
127 | }
128 | }
129 | #previewWindow{
130 | top: 24px;
131 | left: 24px;
132 | width: calc(50% - 44px);
133 | height: calc(100% - 48px);
134 | position: fixed;
135 | overflow: hidden;
136 | border: 2px solid white;
137 | }
138 | #gui{
139 | position: fixed;
140 | border-top: 2px solid white;
141 | border-bottom: 2px solid white;
142 | top: 24px;
143 | right: 24px;
144 | width: calc(50% - 40px);
145 | height: calc(100% - 48px);
146 | }
147 | @media (max-aspect-ratio: 1/1){
148 | #previewWindow{
149 | top: 24px;
150 | left: 24px;
151 | width: calc(100% - 52px);
152 | height: calc(50% - 40px);
153 | position: fixed;
154 | overflow: hidden;
155 | border: 2px solid white;
156 | }
157 | #gui{
158 | position: fixed;
159 | border-top: 2px solid white;
160 | border-bottom: 2px solid white;
161 | top: auto;
162 | right: auto;
163 | bottom: 24px;
164 | left: 24px;
165 | width: calc(100% - 48px);
166 | height: calc(50% - 40px);
167 | }
168 | }
169 |
170 | #gui{
171 | overflow: auto;
172 | white-space: nowrap;
173 | background: black;
174 | user-select: none;
175 | transition: all 0.2s ease-in-out;
176 | color: #cccccc;
177 | display: grid;
178 | overflow-y: auto;
179 | }
180 | /* .ui-active #gui{
181 | bottom: 0;
182 | } */
183 | /* .gui-window #gui{
184 | left: 0;
185 | top: 0;
186 | bottom: auto;
187 | max-width: none;
188 | max-height: none;
189 | width: calc(100% - 5em);
190 | height: calc(100% - 4em);
191 | padding: 2em;
192 | padding-left: 3em;
193 | background: rgb(16,16,16) !important;
194 | } */
195 | #gui::selection,
196 | #gui::-moz-selection{
197 | background: white;
198 | color: black;
199 | }
200 | #gui table{
201 | font-size: 1em;
202 | padding: 2em;
203 | padding-top: 4em;
204 | width: 100%;
205 | /* padding-top: 2em; */
206 | /* white-space: pre; */
207 | /* padding-left: 2em;
208 | padding-right: 2em; */
209 | /* padding-bottom: 1em; */
210 | position: relative;
211 | display: inline-block;
212 | margin-right: 1em;
213 | margin-bottom: 0.5em;
214 | /* border-spacing: 0.5em 0; */
215 | /* position: absolute;
216 | top: 0;
217 | left: 0; */
218 | border: 2px solid white;
219 | background: black;
220 | box-shadow: 1em 1em rgba(0,0,0,0.5);
221 | height: auto;
222 | /* text-transform: uppercase; */
223 | }
224 | #gui table:not(.table-hidden){
225 | height: 8em;
226 | }
227 | /* #gui table:before{
228 | content: "";
229 | background: #cccccc;
230 | position: absolute;
231 | top: 0;
232 | left: -1em;
233 | width: 2px;
234 | height: 100%;
235 | border-radius: 1px;
236 | transition: all 0.2s ease-in-out;
237 | }
238 | #gui table:after{
239 | content: "";
240 | background: #cccccc;
241 | position: absolute;
242 | top: 0;
243 | left: -1em;
244 | height: 2px;
245 | width: 100%;
246 | border-radius: 1px;
247 | transition: all 0.2s ease-in-out;
248 | } */
249 | #gui tbody{
250 | display: table-row-group;
251 | }
252 | #gui .table-toggle{
253 | position: absolute;
254 | top: 0;
255 | left: 0;
256 | width: 100%;
257 | height: 2em;
258 | cursor: pointer;
259 | /* border-bottom: 2px solid white; */
260 | background: white;
261 | }
262 | #gui .table-toggle:after{
263 | content: "";
264 | background: black;
265 | position: absolute;
266 | top: calc(1em - 1px);
267 | left: 1em;
268 | width: 3ch;
269 | height: 2px;
270 | border-radius: 1px;
271 | transition: all 0.2s ease-in-out;
272 | }
273 |
274 | #gui .table-toggle:hover:after{
275 | width: 4ch;
276 | }
277 | #gui .table-hidden .table-toggle:hover:after{
278 | width: 2ch;
279 | }
280 | #gui .table-hidden .table-toggle{
281 | display: block;
282 | }
283 | #gui .table-hidden .table-toggle:after{
284 | width: 1ch;
285 | }
286 | #gui table:not(.table-hidden) th:not(.table-name),
287 | #gui table:not(.table-hidden) td,
288 | #gui table:not(.table-hidden) span
289 | {
290 |
291 | display: none;
292 | }
293 | #gui table{
294 | border-spacing: 0.5em;
295 | }
296 | #gui th{
297 | color: #ffffff;
298 | text-align: left;
299 | }
300 | #gui td{
301 | /* overflow: hidden; */
302 | height: 1ch;
303 | /* max-width: 3ch; */
304 | }
305 | #gui input{
306 | width: 3ch;
307 | padding: 0;
308 | background: transparent;
309 | border: 0;
310 | outline: none;
311 | text-align: left;
312 | color: inherit;
313 | color: #cccccc;
314 | font-size: 1em;
315 | }
316 | #gui input:hover,
317 | #gui span:hover,
318 | #gui .list-action:hover,
319 | #gui .toggle-action:hover{
320 | font-weight: bold;
321 | color: #ffffff;
322 | }
323 | #gui .toggle-action{
324 | color: #aaaaaa;
325 | font-style: italic;
326 | font-weight: bold;
327 | /* border-bottom: 1px solid white;
328 | */
329 | /* background: white;
330 | color: black !important; */
331 | }
332 | #gui .toggle-action.toggle-active{
333 | color: #ffffff;
334 | }
335 |
336 | #gui span,
337 | #gui .list-action,
338 | #gui .toggle-action{
339 | cursor: pointer;
340 | }
341 | #gui .list-item{
342 | margin-right: 1ch;
343 | }
344 | input[type=number]::-webkit-inner-spin-button {
345 | -webkit-appearance: none;
346 | }
347 |
348 | .for-engine{
349 | display: none;
350 | }
351 | .engine-c2d .for-engine-c2d{
352 | display: table-row;
353 | }
354 | .for-colormode{
355 | display: none;
356 | }
357 | .colormode-ndx tr.for-colormode-ndx{
358 | display: table-row;
359 | }
360 | .colormode-grd tr.for-colormode-grd{
361 | display: table-row;
362 | }
363 | .colormode-rgb tr.for-colormode-rgb{
364 | display: table-row;
365 | }
366 | .colormode-hsl tr.for-colormode-hsl{
367 | display: table-row;
368 | }
369 | .for-sec-colormode,
370 | .engine-c2d .for-sec-colormode{
371 | display: none;
372 | }
373 | .engine-c2d.sec-colormode-ndx tr.for-sec-colormode-ndx{
374 | display: table-row;
375 | }
376 | .engine-c2d.sec-colormode-grd tr.for-sec-colormode-grd{
377 | display: table-row;
378 | }
379 | .engine-c2d.sec-colormode-rgb tr.for-sec-colormode-rgb{
380 | display: table-row;
381 | }
382 | .engine-c2d.sec-colormode-hsl tr.for-sec-colormode-hsl{
383 | display: table-row;
384 | }
385 | .for-osc0-type{
386 | display: none;
387 | }
388 | .osc0-type-osc tr.for-osc0-type-osc,
389 | .osc0-type-sqr tr.for-osc0-type-sqr,
390 | .osc0-type-saw tr.for-osc0-type-saw,
391 | .osc0-type-tri tr.for-osc0-type-tri,
392 | .osc0-type-sin tr.for-osc0-type-sin,
393 | .osc0-type-prl tr.for-osc0-type-prl,
394 | .osc0-type-plx tr.for-osc0-type-plx,
395 | .osc0-type-pwm tr.for-osc0-type-pwm,
396 | .osc0-type-org tr.for-osc0-type-org{
397 | display: table-row;
398 | }
399 | .osc0-type-osc th.for-osc0-type-osc,
400 | .osc0-type-sqr th.for-osc0-type-sqr,
401 | .osc0-type-saw th.for-osc0-type-saw,
402 | .osc0-type-tri th.for-osc0-type-tri,
403 | .osc0-type-sin th.for-osc0-type-sin,
404 | .osc0-type-prl th.for-osc0-type-prl,
405 | .osc0-type-plx th.for-osc0-type-plx,
406 | .osc0-type-pwm th.for-osc0-type-pwm,
407 | .osc0-type-org th.for-osc0-type-org{
408 | display: table-cell;
409 | }
410 | .for-osc1-type{
411 | display: none;
412 | }
413 | .osc1-type-osc tr.for-osc1-type-osc,
414 | .osc1-type-sqr tr.for-osc1-type-sqr,
415 | .osc1-type-saw tr.for-osc1-type-saw,
416 | .osc1-type-tri tr.for-osc1-type-tri,
417 | .osc1-type-sin tr.for-osc1-type-sin,
418 | .osc1-type-prl tr.for-osc1-type-prl,
419 | .osc1-type-plx tr.for-osc1-type-plx,
420 | .osc1-type-pwm tr.for-osc1-type-pwm,
421 | .osc1-type-org tr.for-osc1-type-org{
422 | display: table-row;
423 | }
424 | .osc1-type-osc th.for-osc1-type-osc,
425 | .osc1-type-sqr th.for-osc1-type-sqr,
426 | .osc1-type-saw th.for-osc1-type-saw,
427 | .osc1-type-tri th.for-osc1-type-tri,
428 | .osc1-type-sin th.for-osc1-type-sin,
429 | .osc1-type-prl th.for-osc1-type-prl,
430 | .osc1-type-plx th.for-osc1-type-plx,
431 | .osc1-type-pwm th.for-osc1-type-pwm,
432 | .osc1-type-org th.for-osc1-type-org{
433 | display: table-cell;
434 | }
435 | .for-osc2-type{
436 | display: none;
437 | }
438 | .osc2-type-osc tr.for-osc2-type-osc,
439 | .osc2-type-sqr tr.for-osc2-type-sqr,
440 | .osc2-type-saw tr.for-osc2-type-saw,
441 | .osc2-type-tri tr.for-osc2-type-tri,
442 | .osc2-type-sin tr.for-osc2-type-sin,
443 | .osc2-type-prl tr.for-osc2-type-prl,
444 | .osc2-type-plx tr.for-osc2-type-plx,
445 | .osc2-type-pwm tr.for-osc2-type-pwm,
446 | .osc2-type-org tr.for-osc2-type-org{
447 | display: table-row;
448 | }
449 | .osc2-type-osc th.for-osc2-type-osc,
450 | .osc2-type-sqr th.for-osc2-type-sqr,
451 | .osc2-type-saw th.for-osc2-type-saw,
452 | .osc2-type-tri th.for-osc2-type-tri,
453 | .osc2-type-sin th.for-osc2-type-sin,
454 | .osc2-type-prl th.for-osc2-type-prl,
455 | .osc2-type-plx th.for-osc2-type-plx,
456 | .osc2-type-pwm th.for-osc2-type-pwm,
457 | .osc2-type-org th.for-osc2-type-org{
458 | display: table-cell;
459 | }
460 | .for-osc3-type{
461 | display: none;
462 | }
463 | .osc3-type-osc tr.for-osc3-type-osc,
464 | .osc3-type-sqr tr.for-osc3-type-sqr,
465 | .osc3-type-saw tr.for-osc3-type-saw,
466 | .osc3-type-tri tr.for-osc3-type-tri,
467 | .osc3-type-sin tr.for-osc3-type-sin,
468 | .osc3-type-prl tr.for-osc3-type-prl,
469 | .osc3-type-plx tr.for-osc3-type-plx,
470 | .osc3-type-pwm tr.for-osc3-type-pwm,
471 | .osc3-type-org tr.for-osc3-type-org{
472 | display: table-row;
473 | }
474 | .osc3-type-osc th.for-osc3-type-osc,
475 | .osc3-type-sqr th.for-osc3-type-sqr,
476 | .osc3-type-saw th.for-osc3-type-saw,
477 | .osc3-type-tri th.for-osc3-type-tri,
478 | .osc3-type-sin th.for-osc3-type-sin,
479 | .osc3-type-prl th.for-osc3-type-prl,
480 | .osc3-type-plx th.for-osc3-type-plx,
481 | .osc3-type-pwm th.for-osc3-type-pwm,
482 | .osc3-type-org th.for-osc3-type-org{
483 | display: table-cell;
484 | }
485 | .for-osc4-type{
486 | display: none;
487 | }
488 | .osc4-type-osc tr.for-osc4-type-osc,
489 | .osc4-type-sqr tr.for-osc4-type-sqr,
490 | .osc4-type-saw tr.for-osc4-type-saw,
491 | .osc4-type-tri tr.for-osc4-type-tri,
492 | .osc4-type-sin tr.for-osc4-type-sin,
493 | .osc4-type-prl tr.for-osc4-type-prl,
494 | .osc4-type-plx tr.for-osc4-type-plx,
495 | .osc4-type-pwm tr.for-osc4-type-pwm,
496 | .osc4-type-org tr.for-osc4-type-org{
497 | display: table-row;
498 | }
499 | .osc4-type-osc th.for-osc4-type-osc,
500 | .osc4-type-sqr th.for-osc4-type-sqr,
501 | .osc4-type-saw th.for-osc4-type-saw,
502 | .osc4-type-tri th.for-osc4-type-tri,
503 | .osc4-type-sin th.for-osc4-type-sin,
504 | .osc4-type-prl th.for-osc4-type-prl,
505 | .osc4-type-plx th.for-osc4-type-plx,
506 | .osc4-type-pwm th.for-osc4-type-pwm,
507 | .osc4-type-org th.for-osc4-type-org{
508 | display: table-cell;
509 | }
510 | input[type=range] {
511 | -webkit-appearance: none; /* Hides the slider so that custom slider can be made */
512 | width: calc(100% - 1ch) !important; /* Specific width is required for Firefox. */
513 | background: transparent; /* Otherwise white in Chrome */
514 | transform: translateY(-0.4ch)
515 | }
516 | .text-input{
517 | width: 100% !important; /* Specific width is required for Firefox. */
518 | }
519 | input[type=range]::-webkit-slider-thumb {
520 | -webkit-appearance: none;
521 | }
522 |
523 | input[type=range]:focus {
524 | outline: none; /* Removes the blue border. You should probably do some kind of focus styling for accessibility reasons though. */
525 | }
526 |
527 | input[type=range]::-ms-track {
528 | width: 100%;
529 | cursor: pointer;
530 |
531 | /* Hides the slider so custom styles can be added */
532 | background: transparent;
533 | border-color: transparent;
534 | color: transparent;
535 | }
536 | /* Special styling for WebKit/Blink */
537 | input[type=range]::-webkit-slider-thumb {
538 | -webkit-appearance: none;
539 | height: 0.5em;
540 | width: 0.5em;
541 | border: none;
542 | border-radius: 50%;
543 | background: #ffffff;
544 | cursor: pointer;
545 | margin-top: -0.125em;
546 | }
547 |
548 | input[type=range]::-webkit-slider-runnable-track {
549 | width: 100%;
550 | height: 0.25em;
551 | cursor: pointer;
552 | background: #cccccc;
553 | border-radius: 0.125em;
554 | border: none;
555 | }
556 | .ui-buttons-flag-off .for-ui-buttons{
557 | display: none;
558 | }
559 | .ui-labels-flag-off .for-ui-labels{
560 | display: none;
561 | }
562 | #tooltip{
563 | background: rgba(240,240,240,0.9);
564 | border-radius: 6px;
565 | font-size: 0.8em;
566 | padding: 2em;
567 | color: rgb(16,16,16);
568 | position: fixed;
569 | top: 0;
570 | left: 0;
571 | z-index: 2;
572 | opacity: 0;
573 | user-select: none;
574 | pointer-events: none;
575 | transition: opacity 0.2s ease-in-out;
576 | max-width: 30vw;
577 | white-space: normal;
578 | }
579 | #tooltip b{
580 | font-weight: bold;
581 | text-transform: uppercase;
582 | }
583 | .tooltip-is-active #tooltip{
584 | opacity: 1;
585 | }
586 | .fx-flag-off .for-fx-active{
587 | display: none;
588 | }
589 | #ascii{
590 | position: absolute;
591 | top: 50%;
592 | left: 50%;
593 | transform: translate(-50%,-50%);
594 | color: white;
595 | white-space: nowrap;
596 | font-size: 12px;
597 | line-height: 1em;
598 | letter-spacing: calc(1em - 1ch);
599 | /* mix-blend-mode: difference; */
600 | }
601 | #ascii div{
602 | display: inline-block;
603 | }
604 |
--------------------------------------------------------------------------------
/app/forge.config.js:
--------------------------------------------------------------------------------
1 | // config.forge.js
2 | const path = require('path');
3 |
4 | module.exports = {
5 | packagerConfig: {
6 | icon: path.resolve(__dirname, "icons/logo.icns")
7 | },
8 | makers: [
9 | {
10 | name: '@electron-forge/maker-squirrel',
11 | config: {
12 | // name: "ACID",
13 | // version: "0.1.0",
14 | // author: "Johannes Hassenstein",
15 | // description: "ACID is a general purpose video synthesizer.",
16 | // iconUrl: path.resolve(__dirname, "icons/logo.ico")
17 | }
18 | },
19 | {
20 | name: "@electron-forge/maker-zip",
21 | config: {
22 | icon: path.resolve(__dirname, "icons/logo.icns")
23 | },
24 | platforms: [
25 | "darwin"
26 | ]
27 | },
28 | {
29 | name: '@electron-forge/maker-dmg',
30 | config: {
31 | name: "ACID",
32 | icon: path.resolve(__dirname, "icons/logo.icns"),
33 | }
34 | },
35 | {
36 | name: "@electron-forge/maker-deb",
37 | config: {
38 | options: {
39 | name: "ACID",
40 | maintainer: 'Johannes Hassenstein',
41 | homepage: 'https://johassenstein.de',
42 | categories: ["AudioVideo","Video","Graphics"],
43 | description: "ACID is a general purpose video synthesizer.",
44 | icon: path.resolve(__dirname, "icons/logo_512.png")
45 | }
46 | }
47 | }
48 | ]
49 | }
50 |
--------------------------------------------------------------------------------
/app/html/readme.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ACID:101
6 |
7 |
8 |
9 |
ACID
10 |
Documentation
11 |
All values in the GUI range between 0 and 999, where 0 is the minimum value and 999 is the maximum. The GUI can be toggled either with the space bar or using the options in Menubar > Window. The GUI can also be opened in a second window.
12 |
The labels next to the sliders can be used to set a slider to specific value. The buttons next to the labels can be used to minimize, center, maximize or randomize the slider value. Both can be disabled from the set part of the GUI.
13 |
Oscilators
14 |
An oscilator is either a cyclic transfer function or a noise based algorithm. A cyclic transfer function takes a value between 0 and infinity and returns a value between 0 and 1, the exact distribution of the values inbetween is determined by the oscilators waveform. The amount of values after which the oscilator repeats is determined by its frequency.
15 |
You can use oscilators as fixed filters by setting the spd parameter to 0. This will stop the oscilator from moving entirely. You can then control the exact character of the filter with the frq, off and rot parameters.
16 |
If you need a constant fixed value from an oscilator, you can use a sqr oscilator, with a spd of 0 and a low frq. You can then control the exact value using the min or max parameter.
17 |
If you need a completely random texture, create an oscilator with a medium value and apply a high rnd effect on it.
18 |
All oscilators have an additional "run" property, which can be set to quickly mute an oscilator. You can toggle it by clicking on "osx" (where x is the oscilator number) in the GUI. The run property behaves identical to the off type, but doesnt change the type of the oscilator.
19 |
Channels
20 |
All oscilators can send to 3 different channels independently. They send the same basic value to each channel but you can attenuate the value for each channel individually. You can do so from the rgb section using the inputs for r,g and b.
21 |
Cyclical oscilators
22 |
These are the available cyclical oscilators:
23 |
24 |
sqr (Square) - will create a squarewave, that is either high or low, but has no inbetween states
25 |
pwm (Pulse) - will create a pulse oscilator (and Pulse Width Modulation will be available in the near future)
26 |
saw (Sawtooth) - will create a sawtooth wave, that starts high and falls to low in a linear fashion
27 |
tri (Triangle) - will create a triangle wave, that switches between high and low in linear fashion
28 |
sin (Sine) - will create a sine wave, that switches between high and low in non linear fashion
29 |
osc (Oscilator) - will create a flexible oscilator, which can take any shape between a pure triangle over a pure sine to pure square. The pulse width can be modified, which can turn a triangle into a ramp or saw, or change the width of a squarewave. But it can also do any shape inbetween.
30 |
31 |
32 |
For each oscilator these are the important parameters:
33 |
34 |
typ (Type) - will determine the type of oscilator to use
35 |
36 |
min (Minimum) - sets the minimum amplitude (normally 0)
37 |
38 |
max (Maximum) - sets the maximum amplitude (normally 999)
39 |
40 |
lpf (Low Pass Filter) - Values above this threshold will be cut. The filter behaves relative to min and max
41 |
42 |
hpf (High Pass Filter) - Values below this treshold will be cut. The filter behaves relative to min and max
43 |
44 |
mix (Mixing) - The way this oscilator should be mixed with other oscilators
45 |
46 |
ADD (Additive) - Add the value to the mix
47 |
SUB (Subtractive) - Removes the value from the mix
48 |
MLT (Multiply) - Multiplies the mix with the value
49 |
DIV (Divide) - Divides the mix by the value
50 |
51 |
52 |
53 |
rot (Oscilator Rotation) - Will rotate the oscilator in 2D space
54 |
55 |
frq (Oscilator Frequency) - Determines the frequency of the oscilation
56 |
57 |
spd (Oscilator Speed) - Determines how fast the oscilator moves through 2D space in the direction set by rot
58 |
59 |
off (Oscilator Offset) - Will change the phase of the oscilation, which us really only useful when speed is at 0
60 |
61 |
62 |
63 |
The osc oscilator has these additional parameters:
64 |
65 |
cen (Oscilator Center) - sets the high point of the oscilation relative to the wavelength. 0 means right at the start (which would make a triangle wave a saw wave), 999 means right at the end (which would make a triangle wave a ramp wave)
66 |
shp (Oscilator Shape) - determines the general shape of the oscilator. It does so by fading between pure triangle wave (0), pure sine wave (499) and pure squarewave (999)
67 |
68 |
69 |
Noncyclical oscilators
70 |
These are the available, noncyclical oscilators:
71 |
72 |
plx (Simplex Noise) - An advanced correlating noise algorithm
73 |
prl (Perlin Noise) - A less advanced correlating noise algorithm
74 |
org (Organic) - A noise algorithm that creates "organic" shapes like water ripples or woodgrain (it is simplex noise passed through a seeded random number generator)
75 |
off (Off) - turns the oscilator off
76 |
77 |
78 |
The noncyclical oscilators use some of the cyclical oscilator settings, however they are used somewhat different:
79 |
80 |
frq (Oscilator Frequency) - Determines the frequency of the noise plane, which will feel more like its resolution or graininess maybe
81 |
off (Oscilator Offset) - Will move to a fixed value on the plane of the noise
82 |
83 |
84 |
The organic oscilator also uses the two additional settings from the osc oscilator
85 |
86 |
cen (Oscilator Center) - determines how many different steps or layers are generated
87 |
shp (Oscilator Shape) - blends between quantised and unquantised noise
88 |
89 |
90 |
There are also a couple of additional settings for the two noise algorithms, as they are 3 dimensional. The oscilator settings control the z axis, the other two axis are controlled by their respective parameters. All axis have the same set of parameters.
91 |
The noise algorithms are seedable, which means same values in, same values out. You can reseed the noise algorithms from Menubar > Render > Reseed.
92 |
Effects
93 |
All oscilators can have any number of effects applied to them. Which effects are applied is set by the effects chain ("--- + " in the GUI). Clicking on "+" will add a new effect to the chain, clicking on an effect will flip through the different effect types, clicking on "---" (which will then show "clr") will clear the effect chain. Effects are passed through from left to right.
94 |
95 |
--- (List) - marks the presence of a list. Clicking will clear the list
96 |
+ (Add) - can be clicked to add new entrys to the list.
97 |
98 |
99 |
The settings for all effects in the chain are the same. However you can use the chain to apply effects in different order or multiple times. The settings are set in the fx part of the respective GUI section:
100 |
101 |
bit (Bitreduction) - Will reduce the number of possible values down to only a single one. 0 means no reduction, 999 means maximum reduction.
102 |
cmp (Compression) - Will make lower values higher while influencing higher values less.
103 |
exp (Expansion) - Will make lower values even lower while influencing higher values less. Works somewhat in reverse to compression.
104 |
rnd (Randomization) - Will randomly change values. A low setting will result in a more "analog" look, while a high setting will make things very glitchy
105 |
drv (Drive) - Will amplify all values equally. Can be used as a preamp or overdrive.
106 |
107 |
108 |
Render
109 |
The parameters for the render process can be found under "img". The render process determines how the values generated by ACID and the configuration set in the GUI are used to generate images. Not all settings are available at all times, some may only be visible when a certain color mode or render engine is active.
110 |
111 |
frm (Framerate) - the desired framerate for the undocked render window. To not display visible jumbs between frames the render process will render frame after frame and not skip frames. This can result in exported GIFs looking faster. You can see the true FPS in the settings tab
112 |
113 |
res (Resolution) - resolution for the undocked render window
114 |
115 |
pre
116 |
117 |
res (Preview Resolution) - resolution for the main window
118 |
frm (Preview Framerate) - framerate for the main window
119 |
120 |
121 |
122 |
bw (Black and White) - blends between color and black and white
123 |
124 |
brn (Burn) - can be used to lighten the image when subpixels are enabled
125 |
126 |
drv (Drivetype) - this is the clipping stage of the master amplifier, there are 3 settings available:
127 |
128 |
clp (Clip) - Will simply clip all values over 1 and make them 1
129 |
mod (Modify) - Will wrap all values over 1 until they are below 1. 1.5 would become 0.5, 2.3 would become 0.3 and so on.
130 |
dyn (Dynamic) - Will redistribute all values on a range between the frames lowest and highest value, making it impossible to clip the amp (however you can use a compressor or drive and a low pass filter to achieve the effect on an oscilator level)
131 |
132 |
133 |
134 |
clr (Colormode) - Changes the colormode. You can click on the GUI label to activate a fixed HSL based color mode, which can be helpfull to see how the oscilators effect each other.
135 |
136 |
rgb (Linear RGB) - ACID can effect a linear RGB space
137 |
grd (Gradient) - ACID can effect the value on a range between any amount of colors. The colors are determined by the values in the color list. The black and white values between 0 and 1 are used to determine the position on the gradient.
138 |
ndx (Indexed) - works just like gradient. Except its not a gradient but a stepped gradient with no mix between the steps.
139 |
140 |
141 |
142 |
143 |
144 |
Feedback
145 |
The virtual feedback engine simulates true feedback when using a camera that is pointed on a screen that displays the camera image. Simulates, not duplicates. It is different. But based around the same idea. As ACID is deterministic we can now the value of each pixel at any point in time. And that is exactly how the feedback works. We simply don't show all pixels at the same point in time at the same time.
146 |
147 |
int (Feedback Intensity) - Intensity of the feedback, basically how far into the future we go at max
148 |
edg (Feedback Quantization) - How much the feedback is quantized. This will lead to visible jumps/edges
149 |
x (Feedback Center X) - relative x position of the center of the feedback
150 |
y (Feedback Center Y) - relative y position of the center of the feedback
151 |
mix (Feedback Mix) - mixes between horizontal and vertical feedback
152 |
bnd (Feedback Bend) - mixes between linear and feedbacked feedback (you read that right, the feedback can feedback on it self). This will lead to more bended lines then straight lines
153 |
skw (Feedback Skew) - mixes between horizontal and vertical bend
154 |
sqr (Feedback Squaring/Linearity) - mixes between a linear and a stepped version of the feedback. Linear look like a triangle, stepped like a square (so like classic tv feedback)
155 |
drk (Feedback Darken) - makes the feedback darker the further back it is in time (like classic tv feedbacks)
156 |
157 |
158 |
Settings
159 |
The settings part of the GUI can be found under "set". Here you can change default values, GUI styles and some global settings for the render engine.
160 |
161 |
fps (True FPS) - display the true FPS
162 |
wid (Width) - displays the width of the main window in pixels
163 |
hei (Height) - displays the height of the main window in pixels
164 |
dcl (Default Color) - Sets the default color when adding a new color in indexed color mode
165 |
dfx (Default Effect) - Sets the default effect when adding a new effect to an effects chain
166 |
fx (Toggle Effects) - Toggles the usage of effects
167 |
sub (Toggle Subpixels) - Toggles the render of subpixels
168 |
fdb (Toggle Feedbacl) - Toggles the virtual feedback engine
169 |
col (Toggle Colormodes) - Toggles the availability of color modes
170 |
zom (Zoom) - Sets the size of the GUI
171 |
trn (Transparency) - Sets the transpareny of the GUI in the main window
172 |
tip (Tooltips) - Toggles the display of tooltip boxes when hovering over a parameter name
173 |
lab (Labels) - Toggles the display of labels next to sliders
174 |
btn (Buttons) - Toggles the display of buttons next to sliders
175 |
176 |
177 |
Menubar
178 |
You can access some actions and all import and export dutys from the menubar of the application.
179 |
File
180 |
181 |
Save - Save the current patch as a .txt file
182 |
Open - Open a saved patch
183 |
Exports As > JPG - Export the current frame as a JPG of the render (GUI will not be visible)
184 |
Exports As > PNG - Export the current frame as a PNG of the render (GUI will not be visible)
185 |
Record GIF > Start - starts the recording of a GIF of the render (GUI will not be visible). A flashing red dot will appear (the dot is not visible in the GIF).
186 |
Record GIF > Stop - ends the recording of a GIF, creates a .gif file and opens a save dialog
187 |
Record WEBM > Start - recording of a WEBM video of the render (GUI will not be visible). A flashing red dot will appear (the dot is not visible in the WEBM)
188 |
Record WEBM > Stop - ends the recording of a WEBM video, creates a .webm file and opens a save dialog
189 |
Reset Patch - Clears the internal storage and loads the default patch
190 |
191 |
192 |
Render
193 |
194 |
Play - Start the clock for the renderprocess
195 |
Pause - Pauses the clock for the renderprocess
196 |
Stop - Turns the renderprocess off until play is clicked
197 |
Jump 1 Frame - Increments the clock for the render process once and renders once. Useful when trying to get to specific look when having the render paused or stopped.
198 |
Jump 10 Framse - Increments the clock for the render process by 10 and renders once. Useful when trying to get to specific look when having the render paused or stopped.
199 |
Refresh - Simply renders again when the render is stopped manually. Normally any parameter change will trigger a refresh as well
200 |
Reseed - Reseed all noise oscilators and the SRNG for the global effects
201 |
202 |
203 |
Window
204 |
205 |
Open GUI - Opens the GUI in the main window
206 |
Close GUI - Closes the GUI in the main window
207 |
Undock GUI - Creates a new window with the GUI in it, so you can control the render from a seperate window, optimal for VJing
208 |
Destroy GUI - Destroys a created GUI window
209 |
Undock Render - Creates a new window with the render in it, so you can display it in a seperate window, optimal for VJing
210 |
Destroy Render - Destroys a created render window
211 |
212 |
213 |
Help
214 |
215 |
Open Documentation - Opens a new window containing the full documentation (this document)
"
248 | }
249 | x += clipBackground ? fontWidth : res
250 | }
251 | x = 0
252 | y += clipBackground ? fontHeight : res
253 | if(writeLine){
254 | asciiString += " "
255 | }
256 | }
257 | //WEBGL RENDER
258 | let colorBuffer = gl.createBuffer();
259 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
260 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
261 | let aColor = gl.getAttribLocation(this.shaderProgram, 'aColor');
262 | gl.vertexAttribPointer(aColor, 3 , gl.FLOAT, false, 0, 0);
263 | gl.enableVertexAttribArray(aColor);
264 | let vertex_buffer = gl.createBuffer();
265 | gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
266 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
267 | let coord = gl.getAttribLocation(this.shaderProgram, "coord");
268 | gl.vertexAttribPointer(coord, 2 , gl.FLOAT, false, 0, 0);
269 | gl.enableVertexAttribArray(coord);
270 | gl.clear(gl.COLOR_BUFFER_BIT);
271 | gl.drawArrays(gl.POINTS, 0, verticeN)
272 | //ASCII RENDER
273 | if(asciiFlag){
274 | this.ascii.style.fontSize = this.config.render.ascii.fontsize + "px"
275 | this.ascii.style.lineHeight = this.config.render.ascii.fontsize + "px"
276 | this.ascii.style.opacity = this.config.render.ascii.opacity
277 | this.ascii.style.mixBlendMode = this.config.render.ascii.mix
278 | this.ascii.innerHTML = asciiString
279 | }
280 | else{
281 | this.ascii.innerHTML = ""
282 | }
283 | //UPCOUNT
284 | if(this.running){
285 | this.upCount()
286 | this.mothership.canvasCapturerer.requestGifFrame(60000 / (this.config.settings.framerate * 60))
287 | }
288 | }
289 | this.init = function(){
290 | let gl = this.gl
291 | gl.clearColor(0,0,0,1);
292 |
293 | let vertCode =
294 | 'attribute vec4 coord;'+
295 | 'attribute vec4 aColor;'+
296 | 'varying vec4 vColor;'+
297 | 'uniform float resolution;'+
298 |
299 |
300 | 'void main(void) {'+
301 | 'gl_Position = coord;'+
302 | 'gl_PointSize = resolution;'+
303 | 'vColor = aColor;'+
304 | '}'
305 | let vertShader = gl.createShader(gl.VERTEX_SHADER);
306 | gl.shaderSource(vertShader, vertCode);
307 | gl.compileShader(vertShader);
308 | let fragCode =
309 | 'precision mediump float;'+
310 |
311 | 'varying vec4 vColor;'+
312 |
313 | 'void main() {'+
314 | 'gl_FragColor = vColor;'+
315 | '}'
316 | let fragShader = gl.createShader(gl.FRAGMENT_SHADER);
317 | gl.shaderSource(fragShader, fragCode);
318 | gl.compileShader(fragShader);
319 | let shaderProgram = gl.createProgram();
320 | gl.attachShader(shaderProgram, vertShader);
321 | gl.attachShader(shaderProgram, fragShader);
322 | gl.linkProgram(shaderProgram);
323 | gl.useProgram(shaderProgram);
324 | this.shaderProgram = shaderProgram
325 | this.resolutionLocation = gl.getUniformLocation(shaderProgram, "resolution");
326 | this.ipc.on("requireUpdate", function () {
327 | this.update()
328 | }.bind(this));
329 | this.ipc.on("requirePause", function () {
330 | this.pause()
331 | }.bind(this));
332 | this.ipc.on("requirePlay", function () {
333 | this.play()
334 | }.bind(this));
335 | this.ipc.on("requireStop", function () {
336 | this.stop()
337 | }.bind(this));
338 | this.ipc.on("requireOneFramejump", function () {
339 | this.jump(1)
340 | }.bind(this));
341 | this.ipc.on("requireRefresh", function () {
342 | this.refresh()
343 | }.bind(this));
344 | this.ipc.on("requireTenFramesjump", function () {
345 | this.jump(10)
346 | }.bind(this));
347 | window.addEventListener("resize",function(){
348 | this.resize()
349 | }.bind(this))
350 | this.resize()
351 | this.update()
352 | }
353 | this.init()
354 | }
355 |
--------------------------------------------------------------------------------
/app/js/gif.js:
--------------------------------------------------------------------------------
1 | // gif.js 0.2.0 - https://github.com/jnordberg/gif.js
2 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.GIF=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o0&&this._events[type].length>m){this._events[type].warned=true;console.error("(node) warning: possible EventEmitter memory "+"leak detected. %d listeners added. "+"Use emitter.setMaxListeners() to increase limit.",this._events[type].length);if(typeof console.trace==="function"){console.trace()}}}return this};EventEmitter.prototype.on=EventEmitter.prototype.addListener;EventEmitter.prototype.once=function(type,listener){if(!isFunction(listener))throw TypeError("listener must be a function");var fired=false;function g(){this.removeListener(type,g);if(!fired){fired=true;listener.apply(this,arguments)}}g.listener=listener;this.on(type,g);return this};EventEmitter.prototype.removeListener=function(type,listener){var list,position,length,i;if(!isFunction(listener))throw TypeError("listener must be a function");if(!this._events||!this._events[type])return this;list=this._events[type];length=list.length;position=-1;if(list===listener||isFunction(list.listener)&&list.listener===listener){delete this._events[type];if(this._events.removeListener)this.emit("removeListener",type,listener)}else if(isObject(list)){for(i=length;i-- >0;){if(list[i]===listener||list[i].listener&&list[i].listener===listener){position=i;break}}if(position<0)return this;if(list.length===1){list.length=0;delete this._events[type]}else{list.splice(position,1)}if(this._events.removeListener)this.emit("removeListener",type,listener)}return this};EventEmitter.prototype.removeAllListeners=function(type){var key,listeners;if(!this._events)return this;if(!this._events.removeListener){if(arguments.length===0)this._events={};else if(this._events[type])delete this._events[type];return this}if(arguments.length===0){for(key in this._events){if(key==="removeListener")continue;this.removeAllListeners(key)}this.removeAllListeners("removeListener");this._events={};return this}listeners=this._events[type];if(isFunction(listeners)){this.removeListener(type,listeners)}else if(listeners){while(listeners.length)this.removeListener(type,listeners[listeners.length-1])}delete this._events[type];return this};EventEmitter.prototype.listeners=function(type){var ret;if(!this._events||!this._events[type])ret=[];else if(isFunction(this._events[type]))ret=[this._events[type]];else ret=this._events[type].slice();return ret};EventEmitter.prototype.listenerCount=function(type){if(this._events){var evlistener=this._events[type];if(isFunction(evlistener))return 1;else if(evlistener)return evlistener.length}return 0};EventEmitter.listenerCount=function(emitter,type){return emitter.listenerCount(type)};function isFunction(arg){return typeof arg==="function"}function isNumber(arg){return typeof arg==="number"}function isObject(arg){return typeof arg==="object"&&arg!==null}function isUndefined(arg){return arg===void 0}},{}],2:[function(require,module,exports){var UA,browser,mode,platform,ua;ua=navigator.userAgent.toLowerCase();platform=navigator.platform.toLowerCase();UA=ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/)||[null,"unknown",0];mode=UA[1]==="ie"&&document.documentMode;browser={name:UA[1]==="version"?UA[3]:UA[1],version:mode||parseFloat(UA[1]==="opera"&&UA[4]?UA[4]:UA[2]),platform:{name:ua.match(/ip(?:ad|od|hone)/)?"ios":(ua.match(/(?:webos|android)/)||platform.match(/mac|win|linux/)||["other"])[0]}};browser[browser.name]=true;browser[browser.name+parseInt(browser.version,10)]=true;browser.platform[browser.platform.name]=true;module.exports=browser},{}],3:[function(require,module,exports){var EventEmitter,GIF,browser,extend=function(child,parent){for(var key in parent){if(hasProp.call(parent,key))child[key]=parent[key]}function ctor(){this.constructor=child}ctor.prototype=parent.prototype;child.prototype=new ctor;child.__super__=parent.prototype;return child},hasProp={}.hasOwnProperty,indexOf=[].indexOf||function(item){for(var i=0,l=this.length;iref;i=0<=ref?++j:--j){results.push(null)}return results}.call(this);numWorkers=this.spawnWorkers();if(this.options.globalPalette===true){this.renderNextFrame()}else{for(i=j=0,ref=numWorkers;0<=ref?jref;i=0<=ref?++j:--j){this.renderNextFrame()}}this.emit("start");return this.emit("progress",0)};GIF.prototype.abort=function(){var worker;while(true){worker=this.activeWorkers.shift();if(worker==null){break}this.log("killing active worker");worker.terminate()}this.running=false;return this.emit("abort")};GIF.prototype.spawnWorkers=function(){var j,numWorkers,ref,results;numWorkers=Math.min(this.options.workers,this.frames.length);(function(){results=[];for(var j=ref=this.freeWorkers.length;ref<=numWorkers?jnumWorkers;ref<=numWorkers?j++:j--){results.push(j)}return results}).apply(this).forEach(function(_this){return function(i){var worker;_this.log("spawning worker "+i);worker=new Worker(_this.options.workerScript);worker.onmessage=function(event){_this.activeWorkers.splice(_this.activeWorkers.indexOf(worker),1);_this.freeWorkers.push(worker);return _this.frameFinished(event.data)};return _this.freeWorkers.push(worker)}}(this));return numWorkers};GIF.prototype.frameFinished=function(frame){var i,j,ref;this.log("frame "+frame.index+" finished - "+this.activeWorkers.length+" active");this.finishedFrames++;this.emit("progress",this.finishedFrames/this.frames.length);this.imageParts[frame.index]=frame;if(this.options.globalPalette===true){this.options.globalPalette=frame.globalPalette;this.log("global palette analyzed");if(this.frames.length>2){for(i=j=1,ref=this.freeWorkers.length;1<=ref?jref;i=1<=ref?++j:--j){this.renderNextFrame()}}}if(indexOf.call(this.imageParts,null)>=0){return this.renderNextFrame()}else{return this.finishRendering()}};GIF.prototype.finishRendering=function(){var data,frame,i,image,j,k,l,len,len1,len2,len3,offset,page,ref,ref1,ref2;len=0;ref=this.imageParts;for(j=0,len1=ref.length;j=this.frames.length){return}frame=this.frames[this.nextFrame++];worker=this.freeWorkers.shift();task=this.getTask(frame);this.log("starting frame "+(task.index+1)+" of "+this.frames.length);this.activeWorkers.push(worker);return worker.postMessage(task)};GIF.prototype.getContextData=function(ctx){return ctx.getImageData(0,0,this.options.width,this.options.height).data};GIF.prototype.getImageData=function(image){var ctx;if(this._canvas==null){this._canvas=document.createElement("canvas");this._canvas.width=this.options.width;this._canvas.height=this.options.height}ctx=this._canvas.getContext("2d");ctx.setFill=this.options.background;ctx.fillRect(0,0,this.options.width,this.options.height);ctx.drawImage(image,0,0);return this.getContextData(ctx)};GIF.prototype.getTask=function(frame){var index,task;index=this.frames.indexOf(frame);task={index:index,last:index===this.frames.length-1,delay:frame.delay,transparent:frame.transparent,width:this.options.width,height:this.options.height,quality:this.options.quality,dither:this.options.dither,globalPalette:this.options.globalPalette,repeat:this.options.repeat,canTransfer:browser.name==="chrome"};if(frame.data!=null){task.data=frame.data}else if(frame.context!=null){task.data=this.getContextData(frame.context)}else if(frame.image!=null){task.data=this.getImageData(frame.image)}else{throw new Error("Invalid frame")}return task};GIF.prototype.log=function(){var args;args=1<=arguments.length?slice.call(arguments,0):[];if(!this.options.debug){return}return console.log.apply(console,args)};return GIF}(EventEmitter);module.exports=GIF},{"./browser.coffee":2,events:1}]},{},[3])(3)});
3 | //# sourceMappingURL=gif.js.map
4 |
--------------------------------------------------------------------------------
/app/js/gif.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["node_modules/browser-pack/_prelude.js","node_modules/events/events.js","src/browser.coffee","src/gif.coffee"],"names":["f","exports","module","define","amd","g","window","global","self","this","GIF","e","t","n","r","s","o","u","a","require","i","Error","code","l","call","length","1","EventEmitter","_events","_maxListeners","undefined","prototype","defaultMaxListeners","setMaxListeners","isNumber","isNaN","TypeError","emit","type","er","handler","len","args","listeners","error","isObject","arguments","err","context","isUndefined","isFunction","Array","slice","apply","addListener","listener","m","newListener","push","warned","console","trace","on","once","fired","removeListener","list","position","splice","removeAllListeners","key","ret","listenerCount","evlistener","emitter","arg","UA","browser","mode","platform","ua","navigator","userAgent","toLowerCase","match","document","documentMode","name","version","parseFloat","parseInt","extend","child","parent","hasProp","ctor","constructor","__super__","superClass","defaults","frameDefaults","workerScript","workers","repeat","background","quality","width","height","transparent","debug","dither","delay","copy","options","base","value","running","frames","freeWorkers","activeWorkers","setOptions","setOption","_canvas","results","addFrame","image","frame","ImageData","data","CanvasRenderingContext2D","WebGLRenderingContext","getContextData","childNodes","getImageData","render","j","numWorkers","ref","nextFrame","finishedFrames","imageParts","spawnWorkers","globalPalette","renderNextFrame","abort","worker","shift","log","terminate","Math","min","forEach","_this","Worker","onmessage","event","indexOf","frameFinished","index","finishRendering","k","len1","len2","len3","offset","page","ref1","ref2","pageSize","cursor","round","Uint8Array","set","Blob","task","getTask","postMessage","ctx","createElement","getContext","setFill","fillRect","drawImage","last","canTransfer"],"mappings":"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","sourceRoot":"","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o 0 && this._events[type].length > m) {\n this._events[type].warned = true;\n console.error('(node) warning: possible EventEmitter memory ' +\n 'leak detected. %d listeners added. ' +\n 'Use emitter.setMaxListeners() to increase limit.',\n this._events[type].length);\n if (typeof console.trace === 'function') {\n // not supported in IE 10\n console.trace();\n }\n }\n }\n\n return this;\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.once = function(type, listener) {\n if (!isFunction(listener))\n throw TypeError('listener must be a function');\n\n var fired = false;\n\n function g() {\n this.removeListener(type, g);\n\n if (!fired) {\n fired = true;\n listener.apply(this, arguments);\n }\n }\n\n g.listener = listener;\n this.on(type, g);\n\n return this;\n};\n\n// emits a 'removeListener' event iff the listener was removed\nEventEmitter.prototype.removeListener = function(type, listener) {\n var list, position, length, i;\n\n if (!isFunction(listener))\n throw TypeError('listener must be a function');\n\n if (!this._events || !this._events[type])\n return this;\n\n list = this._events[type];\n length = list.length;\n position = -1;\n\n if (list === listener ||\n (isFunction(list.listener) && list.listener === listener)) {\n delete this._events[type];\n if (this._events.removeListener)\n this.emit('removeListener', type, listener);\n\n } else if (isObject(list)) {\n for (i = length; i-- > 0;) {\n if (list[i] === listener ||\n (list[i].listener && list[i].listener === listener)) {\n position = i;\n break;\n }\n }\n\n if (position < 0)\n return this;\n\n if (list.length === 1) {\n list.length = 0;\n delete this._events[type];\n } else {\n list.splice(position, 1);\n }\n\n if (this._events.removeListener)\n this.emit('removeListener', type, listener);\n }\n\n return this;\n};\n\nEventEmitter.prototype.removeAllListeners = function(type) {\n var key, listeners;\n\n if (!this._events)\n return this;\n\n // not listening for removeListener, no need to emit\n if (!this._events.removeListener) {\n if (arguments.length === 0)\n this._events = {};\n else if (this._events[type])\n delete this._events[type];\n return this;\n }\n\n // emit removeListener for all listeners on all events\n if (arguments.length === 0) {\n for (key in this._events) {\n if (key === 'removeListener') continue;\n this.removeAllListeners(key);\n }\n this.removeAllListeners('removeListener');\n this._events = {};\n return this;\n }\n\n listeners = this._events[type];\n\n if (isFunction(listeners)) {\n this.removeListener(type, listeners);\n } else if (listeners) {\n // LIFO order\n while (listeners.length)\n this.removeListener(type, listeners[listeners.length - 1]);\n }\n delete this._events[type];\n\n return this;\n};\n\nEventEmitter.prototype.listeners = function(type) {\n var ret;\n if (!this._events || !this._events[type])\n ret = [];\n else if (isFunction(this._events[type]))\n ret = [this._events[type]];\n else\n ret = this._events[type].slice();\n return ret;\n};\n\nEventEmitter.prototype.listenerCount = function(type) {\n if (this._events) {\n var evlistener = this._events[type];\n\n if (isFunction(evlistener))\n return 1;\n else if (evlistener)\n return evlistener.length;\n }\n return 0;\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n return emitter.listenerCount(type);\n};\n\nfunction isFunction(arg) {\n return typeof arg === 'function';\n}\n\nfunction isNumber(arg) {\n return typeof arg === 'number';\n}\n\nfunction isObject(arg) {\n return typeof arg === 'object' && arg !== null;\n}\n\nfunction isUndefined(arg) {\n return arg === void 0;\n}\n","### CoffeeScript version of the browser detection from MooTools ###\n\nua = navigator.userAgent.toLowerCase()\nplatform = navigator.platform.toLowerCase()\nUA = ua.match(/(opera|ie|firefox|chrome|version)[\\s\\/:]([\\w\\d\\.]+)?.*?(safari|version[\\s\\/:]([\\w\\d\\.]+)|$)/) or [null, 'unknown', 0]\nmode = UA[1] == 'ie' && document.documentMode\n\nbrowser =\n name: if UA[1] is 'version' then UA[3] else UA[1]\n version: mode or parseFloat(if UA[1] is 'opera' && UA[4] then UA[4] else UA[2])\n\n platform:\n name: if ua.match(/ip(?:ad|od|hone)/) then 'ios' else (ua.match(/(?:webos|android)/) or platform.match(/mac|win|linux/) or ['other'])[0]\n\nbrowser[browser.name] = true\nbrowser[browser.name + parseInt(browser.version, 10)] = true\nbrowser.platform[browser.platform.name] = true\n\nmodule.exports = browser\n","{EventEmitter} = require 'events'\nbrowser = require './browser.coffee'\n\nclass GIF extends EventEmitter\n\n defaults =\n workerScript: 'gif.worker.js'\n workers: 2\n repeat: 0 # repeat forever, -1 = repeat once\n background: '#fff'\n quality: 10 # pixel sample interval, lower is better\n width: null # size derermined from first frame if possible\n height: null\n transparent: null\n debug: false\n dither: false # see GIFEncoder.js for dithering options\n\n frameDefaults =\n delay: 500 # ms\n copy: false\n\n constructor: (options) ->\n @running = false\n\n @options = {}\n @frames = []\n\n @freeWorkers = []\n @activeWorkers = []\n\n @setOptions options\n for key, value of defaults\n @options[key] ?= value\n\n setOption: (key, value) ->\n @options[key] = value\n if @_canvas? and key in ['width', 'height']\n @_canvas[key] = value\n\n setOptions: (options) ->\n @setOption key, value for own key, value of options\n\n addFrame: (image, options={}) ->\n frame = {}\n frame.transparent = @options.transparent\n for key of frameDefaults\n frame[key] = options[key] or frameDefaults[key]\n\n # use the images width and height for options unless already set\n @setOption 'width', image.width unless @options.width?\n @setOption 'height', image.height unless @options.height?\n\n if ImageData? and image instanceof ImageData\n frame.data = image.data\n else if (CanvasRenderingContext2D? and image instanceof CanvasRenderingContext2D) or (WebGLRenderingContext? and image instanceof WebGLRenderingContext)\n if options.copy\n frame.data = @getContextData image\n else\n frame.context = image\n else if image.childNodes?\n if options.copy\n frame.data = @getImageData image\n else\n frame.image = image\n else\n throw new Error 'Invalid image'\n\n @frames.push frame\n\n render: ->\n throw new Error 'Already running' if @running\n\n if not @options.width? or not @options.height?\n throw new Error 'Width and height must be set prior to rendering'\n\n @running = true\n @nextFrame = 0\n @finishedFrames = 0\n\n @imageParts = (null for i in [0...@frames.length])\n numWorkers = @spawnWorkers()\n # we need to wait for the palette\n if @options.globalPalette == true\n @renderNextFrame()\n else\n @renderNextFrame() for i in [0...numWorkers]\n\n @emit 'start'\n @emit 'progress', 0\n\n abort: ->\n loop\n worker = @activeWorkers.shift()\n break unless worker?\n @log 'killing active worker'\n worker.terminate()\n @running = false\n @emit 'abort'\n\n # private\n\n spawnWorkers: ->\n numWorkers = Math.min(@options.workers, @frames.length)\n [@freeWorkers.length...numWorkers].forEach (i) =>\n @log \"spawning worker #{ i }\"\n worker = new Worker @options.workerScript\n worker.onmessage = (event) =>\n @activeWorkers.splice @activeWorkers.indexOf(worker), 1\n @freeWorkers.push worker\n @frameFinished event.data\n @freeWorkers.push worker\n return numWorkers\n\n frameFinished: (frame) ->\n @log \"frame #{ frame.index } finished - #{ @activeWorkers.length } active\"\n @finishedFrames++\n @emit 'progress', @finishedFrames / @frames.length\n @imageParts[frame.index] = frame\n # remember calculated palette, spawn the rest of the workers\n if @options.globalPalette == true\n @options.globalPalette = frame.globalPalette\n @log 'global palette analyzed'\n @renderNextFrame() for i in [1...@freeWorkers.length] if @frames.length > 2\n if null in @imageParts\n @renderNextFrame()\n else\n @finishRendering()\n\n finishRendering: ->\n len = 0\n for frame in @imageParts\n len += (frame.data.length - 1) * frame.pageSize + frame.cursor\n len += frame.pageSize - frame.cursor\n @log \"rendering finished - filesize #{ Math.round(len / 1000) }kb\"\n data = new Uint8Array len\n offset = 0\n for frame in @imageParts\n for page, i in frame.data\n data.set page, offset\n if i is frame.data.length - 1\n offset += frame.cursor\n else\n offset += frame.pageSize\n\n image = new Blob [data],\n type: 'image/gif'\n\n @emit 'finished', image, data\n\n renderNextFrame: ->\n throw new Error 'No free workers' if @freeWorkers.length is 0\n return if @nextFrame >= @frames.length # no new frame to render\n\n frame = @frames[@nextFrame++]\n worker = @freeWorkers.shift()\n task = @getTask frame\n\n @log \"starting frame #{ task.index + 1 } of #{ @frames.length }\"\n @activeWorkers.push worker\n worker.postMessage task#, [task.data.buffer]\n\n getContextData: (ctx) ->\n return ctx.getImageData(0, 0, @options.width, @options.height).data\n\n getImageData: (image) ->\n if not @_canvas?\n @_canvas = document.createElement 'canvas'\n @_canvas.width = @options.width\n @_canvas.height = @options.height\n\n ctx = @_canvas.getContext '2d'\n ctx.setFill = @options.background\n ctx.fillRect 0, 0, @options.width, @options.height\n ctx.drawImage image, 0, 0\n\n return @getContextData ctx\n\n getTask: (frame) ->\n index = @frames.indexOf frame\n task =\n index: index\n last: index is (@frames.length - 1)\n delay: frame.delay\n transparent: frame.transparent\n width: @options.width\n height: @options.height\n quality: @options.quality\n dither: @options.dither\n globalPalette: @options.globalPalette\n repeat: @options.repeat\n canTransfer: (browser.name is 'chrome')\n\n if frame.data?\n task.data = frame.data\n else if frame.context?\n task.data = @getContextData frame.context\n else if frame.image?\n task.data = @getImageData frame.image\n else\n throw new Error 'Invalid frame'\n\n return task\n\n log: (args...) ->\n return unless @options.debug\n console.log args...\n\n\nmodule.exports = GIF\n"]}
2 |
--------------------------------------------------------------------------------
/app/js/gif.worker.js:
--------------------------------------------------------------------------------
1 | // gif.worker.js 0.2.0 - https://github.com/jnordberg/gif.js
2 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o=ByteArray.pageSize)this.newPage();this.pages[this.page][this.cursor++]=val};ByteArray.prototype.writeUTFBytes=function(string){for(var l=string.length,i=0;i=0)this.dispose=disposalCode};GIFEncoder.prototype.setRepeat=function(repeat){this.repeat=repeat};GIFEncoder.prototype.setTransparent=function(color){this.transparent=color};GIFEncoder.prototype.addFrame=function(imageData){this.image=imageData;this.colorTab=this.globalPalette&&this.globalPalette.slice?this.globalPalette:null;this.getImagePixels();this.analyzePixels();if(this.globalPalette===true)this.globalPalette=this.colorTab;if(this.firstFrame){this.writeLSD();this.writePalette();if(this.repeat>=0){this.writeNetscapeExt()}}this.writeGraphicCtrlExt();this.writeImageDesc();if(!this.firstFrame&&!this.globalPalette)this.writePalette();this.writePixels();this.firstFrame=false};GIFEncoder.prototype.finish=function(){this.out.writeByte(59)};GIFEncoder.prototype.setQuality=function(quality){if(quality<1)quality=1;this.sample=quality};GIFEncoder.prototype.setDither=function(dither){if(dither===true)dither="FloydSteinberg";this.dither=dither};GIFEncoder.prototype.setGlobalPalette=function(palette){this.globalPalette=palette};GIFEncoder.prototype.getGlobalPalette=function(){return this.globalPalette&&this.globalPalette.slice&&this.globalPalette.slice(0)||this.globalPalette};GIFEncoder.prototype.writeHeader=function(){this.out.writeUTFBytes("GIF89a")};GIFEncoder.prototype.analyzePixels=function(){if(!this.colorTab){this.neuQuant=new NeuQuant(this.pixels,this.sample);this.neuQuant.buildColormap();this.colorTab=this.neuQuant.getColormap()}if(this.dither){this.ditherPixels(this.dither.replace("-serpentine",""),this.dither.match(/-serpentine/)!==null)}else{this.indexPixels()}this.pixels=null;this.colorDepth=8;this.palSize=7;if(this.transparent!==null){this.transIndex=this.findClosest(this.transparent,true)}};GIFEncoder.prototype.indexPixels=function(imgq){var nPix=this.pixels.length/3;this.indexedPixels=new Uint8Array(nPix);var k=0;for(var j=0;j=0&&x1+x=0&&y1+y>16,(c&65280)>>8,c&255,used)};GIFEncoder.prototype.findClosestRGB=function(r,g,b,used){if(this.colorTab===null)return-1;if(this.neuQuant&&!used){return this.neuQuant.lookupRGB(r,g,b)}var c=b|g<<8|r<<16;var minpos=0;var dmin=256*256*256;var len=this.colorTab.length;for(var i=0,index=0;i=0){disp=dispose&7}disp<<=2;this.out.writeByte(0|disp|0|transp);this.writeShort(this.delay);this.out.writeByte(this.transIndex);this.out.writeByte(0)};GIFEncoder.prototype.writeImageDesc=function(){this.out.writeByte(44);this.writeShort(0);this.writeShort(0);this.writeShort(this.width);this.writeShort(this.height);if(this.firstFrame||this.globalPalette){this.out.writeByte(0)}else{this.out.writeByte(128|0|0|0|this.palSize)}};GIFEncoder.prototype.writeLSD=function(){this.writeShort(this.width);this.writeShort(this.height);this.out.writeByte(128|112|0|this.palSize);this.out.writeByte(0);this.out.writeByte(0)};GIFEncoder.prototype.writeNetscapeExt=function(){this.out.writeByte(33);this.out.writeByte(255);this.out.writeByte(11);this.out.writeUTFBytes("NETSCAPE2.0");this.out.writeByte(3);this.out.writeByte(1);this.writeShort(this.repeat);this.out.writeByte(0)};GIFEncoder.prototype.writePalette=function(){this.out.writeBytes(this.colorTab);var n=3*256-this.colorTab.length;for(var i=0;i>8&255)};GIFEncoder.prototype.writePixels=function(){var enc=new LZWEncoder(this.width,this.height,this.indexedPixels,this.colorDepth);enc.encode(this.out)};GIFEncoder.prototype.stream=function(){return this.out};module.exports=GIFEncoder},{"./LZWEncoder.js":2,"./TypedNeuQuant.js":3}],2:[function(require,module,exports){var EOF=-1;var BITS=12;var HSIZE=5003;var masks=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535];function LZWEncoder(width,height,pixels,colorDepth){var initCodeSize=Math.max(2,colorDepth);var accum=new Uint8Array(256);var htab=new Int32Array(HSIZE);var codetab=new Int32Array(HSIZE);var cur_accum,cur_bits=0;var a_count;var free_ent=0;var maxcode;var clear_flg=false;var g_init_bits,ClearCode,EOFCode;function char_out(c,outs){accum[a_count++]=c;if(a_count>=254)flush_char(outs)}function cl_block(outs){cl_hash(HSIZE);free_ent=ClearCode+2;clear_flg=true;output(ClearCode,outs)}function cl_hash(hsize){for(var i=0;i=0){disp=hsize_reg-i;if(i===0)disp=1;do{if((i-=disp)<0)i+=hsize_reg;if(htab[i]===fcode){ent=codetab[i];continue outer_loop}}while(htab[i]>=0)}output(ent,outs);ent=c;if(free_ent<1<0){outs.writeByte(a_count);outs.writeBytes(accum,0,a_count);a_count=0}}function MAXCODE(n_bits){return(1<0)cur_accum|=code<=8){char_out(cur_accum&255,outs);cur_accum>>=8;cur_bits-=8}if(free_ent>maxcode||clear_flg){if(clear_flg){maxcode=MAXCODE(n_bits=g_init_bits);clear_flg=false}else{++n_bits;if(n_bits==BITS)maxcode=1<0){char_out(cur_accum&255,outs);cur_accum>>=8;cur_bits-=8}flush_char(outs)}}this.encode=encode}module.exports=LZWEncoder},{}],3:[function(require,module,exports){var ncycles=100;var netsize=256;var maxnetpos=netsize-1;var netbiasshift=4;var intbiasshift=16;var intbias=1<>betashift;var betagamma=intbias<>3;var radiusbiasshift=6;var radiusbias=1<>3);var i,v;for(i=0;i>=netbiasshift;network[i][1]>>=netbiasshift;network[i][2]>>=netbiasshift;network[i][3]=i}}function altersingle(alpha,i,b,g,r){network[i][0]-=alpha*(network[i][0]-b)/initalpha;network[i][1]-=alpha*(network[i][1]-g)/initalpha;network[i][2]-=alpha*(network[i][2]-r)/initalpha}function alterneigh(radius,i,b,g,r){var lo=Math.abs(i-radius);var hi=Math.min(i+radius,netsize);var j=i+1;var k=i-1;var m=1;var p,a;while(jlo){a=radpower[m++];if(jlo){p=network[k--];p[0]-=a*(p[0]-b)/alpharadbias;p[1]-=a*(p[1]-g)/alpharadbias;p[2]-=a*(p[2]-r)/alpharadbias}}}function contest(b,g,r){var bestd=~(1<<31);var bestbiasd=bestd;var bestpos=-1;var bestbiaspos=bestpos;var i,n,dist,biasdist,betafreq;for(i=0;i>intbiasshift-netbiasshift);if(biasdist>betashift;freq[i]-=betafreq;bias[i]+=betafreq<>1;for(j=previouscol+1;j>1;for(j=previouscol+1;j<256;j++)netindex[j]=maxnetpos}function inxsearch(b,g,r){var a,p,dist;var bestd=1e3;var best=-1;var i=netindex[g];var j=i-1;while(i=0){if(i=bestd)i=netsize;else{i++;if(dist<0)dist=-dist;a=p[0]-b;if(a<0)a=-a;dist+=a;if(dist=0){p=network[j];dist=g-p[1];if(dist>=bestd)j=-1;else{j--;if(dist<0)dist=-dist;a=p[0]-b;if(a<0)a=-a;dist+=a;if(dist>radiusbiasshift;if(rad<=1)rad=0;for(i=0;i=lengthcount)pix-=lengthcount;i++;if(delta===0)delta=1;if(i%delta===0){alpha-=alpha/alphadec;radius-=radius/radiusdec;rad=radius>>radiusbiasshift;if(rad<=1)rad=0;for(j=0;j{document.body.removeChild(c),window.URL.revokeObjectURL(r)},100)};var t=[],d=null,n=null,r=e.captureStream();if(null==typeof r||!r)return;const c=document.createElement("video");function i(e){e.data&&e.data.size>0&&t.push(e.data)}function a(e){console.log("Recorder stopped: ",e);const o=new Blob(t,{type:d});c.src=window.URL.createObjectURL(o)}c.style.display="none"}
46 |
47 | /*
48 | * A speed-improved perlin and simplex noise algorithms for 2D.
49 | *
50 | * Based on example code by Stefan Gustavson (stegu@itn.liu.se).
51 | * Optimisations by Peter Eastman (peastman@drizzle.stanford.edu).
52 | * Better rank ordering method by Stefan Gustavson in 2012.
53 | * Converted to Javascript by Joseph Gentle.
54 | *
55 | * Version 2012-03-09
56 | *
57 | * This code was placed in the public domain by its original author,
58 | * Stefan Gustavson. You may use it as you see fit, but
59 | * attribution is appreciated.
60 | *
61 | */
62 | (function(global){var module=window.noise={};function Grad(x,y,z){this.x=x;this.y=y;this.z=z}
63 | Grad.prototype.dot2=function(x,y){return this.x*x+this.y*y};Grad.prototype.dot3=function(x,y,z){return this.x*x+this.y*y+this.z*z};var grad3=[new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0),new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1),new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)];var p=[151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180];var perm=new Array(512);var gradP=new Array(512);module.seed=function(seed){if(seed>0&&seed<1){seed*=65536}
64 | seed=Math.floor(seed);if(seed<256){seed|=seed<<8}
65 | for(var i=0;i<256;i++){var v;if(i&1){v=p[i]^(seed&255)}else{v=p[i]^((seed>>8)&255)}
66 | perm[i]=perm[i+256]=v;gradP[i]=gradP[i+256]=grad3[v%12]}};module.seed(0);var F2=0.5*(Math.sqrt(3)-1);var G2=(3-Math.sqrt(3))/6;var F3=1/3;var G3=1/6;module.simplex2=function(xin,yin){var n0,n1,n2;var s=(xin+yin)*F2;var i=Math.floor(xin+s);var j=Math.floor(yin+s);var t=(i+j)*G2;var x0=xin-i+t;var y0=yin-j+t;var i1,j1;if(x0>y0){i1=1;j1=0}else{i1=0;j1=1}
67 | var x1=x0-i1+G2;var y1=y0-j1+G2;var x2=x0-1+2*G2;var y2=y0-1+2*G2;i&=255;j&=255;var gi0=gradP[i+perm[j]];var gi1=gradP[i+i1+perm[j+j1]];var gi2=gradP[i+1+perm[j+1]];var t0=0.5-x0*x0-y0*y0;if(t0<0){n0=0}else{t0*=t0;n0=t0*t0*gi0.dot2(x0,y0)}
68 | var t1=0.5-x1*x1-y1*y1;if(t1<0){n1=0}else{t1*=t1;n1=t1*t1*gi1.dot2(x1,y1)}
69 | var t2=0.5-x2*x2-y2*y2;if(t2<0){n2=0}else{t2*=t2;n2=t2*t2*gi2.dot2(x2,y2)}
70 | return 70*(n0+n1+n2)};module.simplex3=function(xin,yin,zin){var n0,n1,n2,n3;var s=(xin+yin+zin)*F3;var i=Math.floor(xin+s);var j=Math.floor(yin+s);var k=Math.floor(zin+s);var t=(i+j+k)*G3;var x0=xin-i+t;var y0=yin-j+t;var z0=zin-k+t;var i1,j1,k1;var i2,j2,k2;if(x0>=y0){if(y0>=z0){i1=1;j1=0;k1=0;i2=1;j2=1;k2=0}else if(x0>=z0){i1=1;j1=0;k1=0;i2=1;j2=0;k2=1}else{i1=0;j1=0;k1=1;i2=1;j2=0;k2=1}}else{if(y0 {
15 | requireUpdate()
16 | })
17 | function requireUpdate(){
18 | mainWindow.webContents.send("requireUpdate");
19 | if(guiWindow){
20 | guiWindow.webContents.send("requireUpdate");
21 | }
22 | if(renderWindow){
23 | renderWindow.webContents.send("requireUpdate");
24 | }
25 | }
26 | function checkForEmptyStorage(){
27 | storage.get("config", function(error, data) {
28 | if(error){
29 | throw error
30 | }
31 | else if(!isNotEmptyObject(data)){
32 | resetStorage()
33 | }
34 | })
35 | function isNotEmptyObject(obj){
36 | return !(obj && Object.keys(obj).length === 0 && obj.constructor === Object)
37 | }
38 | }
39 | function resetStorage(){
40 | let data = "{\"typ\":\"mod\",\"settings\":{\"defaultColor\":\"#ffffff\",\"defaultFx\":\"drv\",\"framerate\":\"10\",\"zoom\":0.2972972972972973,\"tips\":\"off\",\"labels\":\"on\",\"buttons\":\"on\",\"transparency\":0.5495495495495496},\"render\":{\"resolution\":0.3,\"preview\":0.3,\"previewframerate\":10,\"grayscale\":0.5,\"mod\":\"rgb\",\"burn\":0,\"clrs\":[],\"optimization\":{\"effects\":\"on\",\"subpixels\":\"on\",\"feedback\":\"on\",\"colormodes\":\"on\"},\"feedback\":{\"quantization\":0,\"intensity\":0,\"mix\":0.5,\"bend\":1,\"skew\":0.8,\"centerY\":0.5,\"centerX\":0.5,\"step\":0.5,\"darken\":0.5},\"channels\":{\"r\":{\"amp\":1,\"base\":0,\"mod\":1,\"active\":true},\"g\":{\"amp\":1,\"base\":0,\"mod\":1,\"active\":true},\"b\":{\"amp\":1,\"base\":0,\"mod\":1,\"active\":true},\"a\":{\"amp\":1,\"base\":0,\"mod\":1,\"active\":true}}},\"osc\":[{\"typ\":\"sin\",\"min\":0,\"max\":0.6676676676676677,\"mix\":\"add\",\"run\":true,\"fx\":{\"c\":[\"exp\",\"rnd\",\"bit\"],\"bit\":0.9009009009009009,\"cmp\":0,\"exp\":0.6846846846846847,\"rnd\":0.03903903903903904,\"drv\":0},\"filter\":{\"lpf\":0,\"hpf\":0},\"config\":{\"x\":{\"frq\":0.4994994994994995,\"off\":0},\"y\":{\"frq\":0.08608608608608609,\"off\":0},\"z\":{\"frq\":0.028028028028028028,\"off\":0,\"len\":0.16216216216216217,\"mod\":0.07307307307307308,\"cen\":0.22422422422422422,\"shp\":0.16216216216216217}},\"channels\":{\"r\":1,\"g\":1,\"b\":1,\"a\":1}},{\"typ\":\"prl\",\"min\":0,\"max\":0.6476476476476476,\"mix\":\"mlt\",\"run\":true,\"fx\":{\"c\":[\"exp\",\"drv\"],\"bit\":0,\"cmp\":0.7107107107107107,\"exp\":0.4174174174174174,\"rnd\":0,\"drv\":0.5555555555555556},\"filter\":{\"lpf\":0,\"hpf\":0},\"config\":{\"x\":{\"frq\":0.1891891891891892,\"off\":0.4994994994994995},\"y\":{\"frq\":0.19519519519519518,\"off\":0.4994994994994995},\"z\":{\"frq\":0.35235235235235235,\"off\":0,\"len\":0.5,\"mod\":0.36236236236236236,\"cen\":0.22422422422422422,\"shp\":0.2962962962962963}},\"channels\":{\"r\":1,\"g\":1,\"b\":1,\"a\":1}},{\"typ\":\"osc\",\"min\":0.44744744744744747,\"max\":1,\"mix\":\"div\",\"run\":true,\"fx\":{\"c\":[\"cmp\"],\"bit\":0,\"cmp\":0.7567567567567568,\"exp\":0,\"rnd\":0,\"drv\":0},\"filter\":{\"lpf\":0,\"hpf\":0},\"config\":{\"x\":{\"frq\":0.5005005005005005,\"off\":0},\"y\":{\"frq\":0.5005005005005005,\"off\":0},\"z\":{\"frq\":0.026026026026026026,\"off\":0,\"len\":0.12512512512512514,\"mod\":0.3023023023023023,\"cen\":0.7387387387387387,\"shp\":0.2902902902902903}},\"channels\":{\"r\":1,\"g\":1,\"b\":1,\"a\":1}},{\"typ\":\"plx\",\"min\":0,\"max\":0.21021021021021022,\"mix\":\"add\",\"run\":true,\"fx\":{\"c\":[\"exp\",\"rnd\"],\"bit\":0,\"cmp\":0,\"exp\":0.8588588588588588,\"rnd\":0.12112112112112113,\"drv\":0},\"filter\":{\"lpf\":0,\"hpf\":0.18018018018018017},\"config\":{\"x\":{\"frq\":0.5005005005005005,\"off\":0.4994994994994995},\"y\":{\"frq\":0.07807807807807808,\"off\":1},\"z\":{\"frq\":0.5195195195195195,\"off\":0.8648648648648649,\"len\":0.17617617617617617,\"mod\":0.16016016016016016,\"cen\":0.5,\"shp\":0.5}},\"channels\":{\"r\":1,\"g\":1,\"b\":1,\"a\":1}},{\"typ\":\"osc\",\"min\":0.43743743743743746,\"max\":0.9819819819819819,\"mix\":\"div\",\"run\":true,\"fx\":{\"c\":[],\"bit\":0,\"cmp\":0,\"exp\":0,\"rnd\":0,\"drv\":0},\"filter\":{\"lpf\":0,\"hpf\":0},\"config\":{\"x\":{\"frq\":0.5005005005005005,\"off\":0},\"y\":{\"frq\":0.5005005005005005,\"off\":0},\"z\":{\"frq\":0,\"off\":0.4994994994994995,\"len\":0.8818818818818819,\"mod\":0,\"cen\":0.8308308308308309,\"shp\":0.7907907907907908}},\"channels\":{\"r\":1,\"g\":1,\"b\":1,\"a\":1}}]}"
41 | storage.set("config", data, function(error) {
42 | if (error){
43 | throw error
44 | }
45 | else{
46 | requireUpdate()
47 | }
48 | })
49 | }
50 | function randomPatch(save){
51 | let config = {}
52 | storage.get("config", function(error, data) {
53 | if(error){
54 | throw error
55 | }
56 | else{
57 | config = JSON.parse(data)
58 | let oscTypes = ["off","prl","plx","org","osc","sqr","pwm","saw","tri","sin"]
59 | let mixTypes = ["add","sub","mlt","div"]
60 | // let colorModes = ["rgb","grd","ndx"]
61 | let fxTypes = ["drv","cmp","exp","rnd","bit"]
62 | // let generateRandomColors = function(n){
63 | // let target = Math.floor(Math.random() * n)
64 | // let pool = []
65 | // for(let i = 0; i < target; i++){
66 | // pool.push("#" + ('00000'+(Math.random()*(1<<24)|0).toString(16)).slice(-6))
67 | // }
68 | // return pool
69 | // }
70 | let generateRandomFx = function(n){
71 | let target = Math.floor(Math.random() * n)
72 | let pool = []
73 | for(let i = 0; i < target; i++){
74 | pool.push(fxTypes[Math.floor(Math.random() * 0.99 * fxTypes.length)])
75 | }
76 | return pool
77 | }
78 | let newData = {
79 | typ: config.typ,
80 | settings: config.settings,
81 | render: {
82 | resolution: config.render.resolution,
83 | preview: config.render.preview,
84 | previewframerate: config.render.previewframerate,
85 | previewwidth: 240,
86 | previewheight: 240,
87 | grayscale: config.render.grayscale,
88 | mod: config.render.mod,
89 | burn: config.render.burn,
90 | clrs:config.render.clrs,
91 | ascii: {
92 | font: "monospace",
93 | fontsize: config.render.ascii.fontsize,
94 | previewfontsize: config.render.ascii.previewfontsize,
95 | fontwidth: config.render.ascii.fontwidth,
96 | previewfontwidth: config.render.ascii.previewfontwidth,
97 | spacing: config.render.ascii.spacing,
98 | opacity: config.render.ascii.opacity,
99 | mix: config.render.ascii.mix,
100 | colors: config.render.ascii.colors,
101 | chars: "-+*",
102 | fixedBackground: config.render.ascii.fixedBackground,
103 | applyToCharacters: config.render.ascii.applyToCharacters
104 | },
105 | optimization: {
106 | ascii: config.render.optimization.ascii,
107 | effects: config.render.optimization.effects,
108 | subpixels: config.render.optimization.subpixels,
109 | feedback: config.render.optimization.feedback,
110 | colormodes: config.render.optimization.colormodes
111 | },
112 | feedback: {
113 | quantization: Math.random(),
114 | intensity: Math.random(),
115 | mix: Math.random(),
116 | bend: Math.random(),
117 | skew: Math.random(),
118 | centerY: Math.random(),
119 | centerX: Math.random(),
120 | step: Math.random(),
121 | darken: Math.random()
122 | },
123 | channels: config.render.channels
124 | },
125 | osc: [
126 | {
127 | typ: oscTypes[Math.floor(Math.random() * 0.99 * oscTypes.length)],
128 | min: save ? 0.5 * Math.random() : Math.random(),
129 | max: save ? 0.5 + Math.random() * 0.5 : Math.random(),
130 | mix: save ? "add" : mixTypes[Math.floor(Math.random() * 0.99 * mixTypes.length)],
131 | run: true,
132 | fx: {
133 | c: generateRandomFx(3),
134 | bit: Math.random(),
135 | cmp: Math.random(),
136 | exp: Math.random(),
137 | rnd: Math.random(),
138 | drv: Math.random()
139 | },
140 | filter: {
141 | lpf: save ? 0.8 * Math.random() : Math.random(),
142 | hpf: save ? 0.8 * Math.random() : Math.random()
143 | },
144 | config: {
145 | x: {
146 | frq: save ? Math.random() * 0.1 : Math.random(),
147 | off: Math.random()
148 | },
149 | y: {
150 | frq: save ? Math.random() * 0.1 : Math.random(),
151 | off: Math.random()
152 | },
153 | z: {
154 | frq: save ? Math.random() * 0.1 : Math.random(),
155 | off: Math.random(),
156 | len: save ? Math.random() * 0.4 : Math.random(),
157 | mod: Math.random(),
158 | cen: Math.random(),
159 | shp: Math.random()
160 | }
161 | },
162 | channels: {
163 | r: Math.random(),
164 | g: Math.random(),
165 | b: Math.random(),
166 | a: Math.random()
167 | }
168 | },
169 | {
170 | typ: oscTypes[Math.floor(Math.random() * 0.99 * oscTypes.length)],
171 | min: 0.5 * Math.random(),
172 | max: 0.5 + Math.random() * 0.5,
173 | mix: save ? "add" : mixTypes[Math.floor(Math.random() * 0.99 * mixTypes.length)],
174 | run: true,
175 | fx: {
176 | c: generateRandomFx(3),
177 | bit: Math.random(),
178 | cmp: Math.random(),
179 | exp: Math.random(),
180 | rnd: Math.random(),
181 | drv: Math.random()
182 | },
183 | filter: {
184 | lpf: 0.8 * Math.random(),
185 | hpf: 0.8 * Math.random()
186 | },
187 | config: {
188 | x: {
189 | frq: Math.random() * 0.1,
190 | off: Math.random()
191 | },
192 | y: {
193 | frq: Math.random() * 0.1,
194 | off: Math.random()
195 | },
196 | z: {
197 | frq: Math.random() * 0.1,
198 | off: Math.random(),
199 | len: Math.random() * 0.4,
200 | mod: Math.random(),
201 | cen: Math.random(),
202 | shp: Math.random()
203 | }
204 | },
205 | channels: {
206 | r: Math.random(),
207 | g: Math.random(),
208 | b: Math.random(),
209 | a: Math.random()
210 | }
211 | },
212 | {
213 | typ: oscTypes[Math.floor(Math.random() * 0.99 * oscTypes.length)],
214 | min: 0.5 * Math.random(),
215 | max: 0.5 + Math.random() * 0.5,
216 | mix: save ? "add" : mixTypes[Math.floor(Math.random() * 0.99 * mixTypes.length)],
217 | run: true,
218 | fx: {
219 | c: generateRandomFx(3),
220 | bit: Math.random(),
221 | cmp: Math.random(),
222 | exp: Math.random(),
223 | rnd: Math.random(),
224 | drv: Math.random()
225 | },
226 | filter: {
227 | lpf: 0.8 * Math.random(),
228 | hpf: 0.8 * Math.random()
229 | },
230 | config: {
231 | x: {
232 | frq: Math.random() * 0.1,
233 | off: Math.random()
234 | },
235 | y: {
236 | frq: Math.random() * 0.1,
237 | off: Math.random()
238 | },
239 | z: {
240 | frq: Math.random() * 0.1,
241 | off: Math.random(),
242 | len: Math.random() * 0.4,
243 | mod: Math.random(),
244 | cen: Math.random(),
245 | shp: Math.random()
246 | }
247 | },
248 | channels: {
249 | r: Math.random(),
250 | g: Math.random(),
251 | b: Math.random(),
252 | a: Math.random()
253 | }
254 | },
255 | {
256 | typ: oscTypes[Math.floor(Math.random() * 0.99 * oscTypes.length)],
257 | min: 0.5 * Math.random(),
258 | max: 0.5 + Math.random() * 0.5,
259 | mix: save ? "add" : mixTypes[Math.floor(Math.random() * 0.99 * mixTypes.length)],
260 | run: true,
261 | fx: {
262 | c: generateRandomFx(3),
263 | bit: Math.random(),
264 | cmp: Math.random(),
265 | exp: Math.random(),
266 | rnd: Math.random(),
267 | drv: Math.random()
268 | },
269 | filter: {
270 | lpf: 0.8 * Math.random(),
271 | hpf: 0.8 * Math.random()
272 | },
273 | config: {
274 | x: {
275 | frq: Math.random() * 0.1,
276 | off: Math.random()
277 | },
278 | y: {
279 | frq: Math.random() * 0.1,
280 | off: Math.random()
281 | },
282 | z: {
283 | frq: Math.random() * 0.1,
284 | off: Math.random(),
285 | len: Math.random() * 0.4,
286 | mod: Math.random(),
287 | cen: Math.random(),
288 | shp: Math.random()
289 | }
290 | },
291 | channels: {
292 | r: Math.random(),
293 | g: Math.random(),
294 | b: Math.random(),
295 | a: Math.random()
296 | }
297 | },
298 | {
299 | typ: oscTypes[Math.floor(Math.random() * 0.99 * oscTypes.length)],
300 | min: 0.5 * Math.random(),
301 | max: 0.5 + Math.random() * 0.5,
302 | mix: save ? "add" : mixTypes[Math.floor(Math.random() * 0.99 * mixTypes.length)],
303 | run: true,
304 | fx: {
305 | c: generateRandomFx(3),
306 | bit: Math.random(),
307 | cmp: Math.random(),
308 | exp: Math.random(),
309 | rnd: Math.random(),
310 | drv: Math.random()
311 | },
312 | filter: {
313 | lpf: 0.8 * Math.random(),
314 | hpf: 0.8 * Math.random()
315 | },
316 | config: {
317 | x: {
318 | frq: Math.random() * 0.1,
319 | off: Math.random()
320 | },
321 | y: {
322 | frq: Math.random() * 0.1,
323 | off: Math.random()
324 | },
325 | z: {
326 | frq: Math.random() * 0.1,
327 | off: Math.random(),
328 | len: Math.random() * 0.4,
329 | mod: Math.random(),
330 | cen: Math.random(),
331 | shp: Math.random()
332 | }
333 | },
334 | channels: {
335 | r: Math.random(),
336 | g: Math.random(),
337 | b: Math.random(),
338 | a: Math.random()
339 | }
340 | }
341 | ]
342 | }
343 | newData = JSON.stringify(newData)
344 | storage.set("config", newData, function(error) {
345 | if (error){
346 | throw error
347 | }
348 | else{
349 | requireUpdate()
350 | }
351 | })
352 | }
353 | })
354 | }
355 | function displayGUI(flag){
356 | if(flag){
357 | mainWindow.webContents.send("requireShowGUI");
358 | }
359 | else{
360 | mainWindow.webContents.send("requireHideGUI");
361 | }
362 | }
363 | function toggleGUI(){
364 | mainWindow.webContents.send("requireToggleGUI");
365 | }
366 | function requireAction(sender,prefix){
367 | prefix = prefix || ""
368 | mainWindow.webContents.send("require" + prefix + sender.label);
369 | }
370 | function requireOneFramejump(){
371 | mainWindow.webContents.send("requireOneFramejump");
372 | }
373 | function requireTenFramesjump(){
374 | mainWindow.webContents.send("requireTenFramesjump");
375 | }
376 | function requireRefresh(){
377 | mainWindow.webContents.send("requireRefresh");
378 | if(renderWindow){
379 | renderWindow.webContents.send("requireRefresh");
380 | }
381 | }
382 |
383 | function openFile(){
384 | dialog.showOpenDialog(mainWindow, {
385 | properties: ['openFile']
386 | }).then(result => {
387 | if(!result.canceled && result.filePaths.length > 0){
388 | let filepath = result.filePaths[0]
389 | fs.readFile(filepath, 'utf-8', (err, data) => {
390 | if(err){
391 | alert("An error ocurred reading the file :" + err.message);
392 | return;
393 | }
394 | else{
395 | storage.set("config", data, function(error) {
396 | if (error){
397 | console.log("Error storing JSON " + error)
398 | }
399 | else{
400 | requireUpdate()
401 | }
402 | })
403 | }
404 | })
405 | }
406 | })
407 | }
408 |
409 |
410 | function createWindow () {
411 | mainWindow = new BrowserWindow({
412 | width: 600,
413 | height: 600,
414 | minWidth: 200,
415 | minHeight: 200,
416 | backgroundColor: '#000000',
417 | icon: path.join(__dirname, { darwin: 'icon.icns', linux: 'icon.png', win32: 'icon.ico' }[process.platform] || 'icon.ico'),
418 | // frame: process.platform !== 'darwin',
419 | // skipTaskbar: process.platform === 'darwin',
420 | // autoHideMenuBar: process.platform === 'darwin',
421 | webPreferences: {
422 | devTools: true,
423 | enableRemoteModule: true,
424 | nodeIntegration: true,
425 | contextIsolation: false,
426 | preload: path.join(__dirname, 'preload.js')
427 | }
428 | })
429 | mainWindow.on('close', function() {
430 | if(guiWindow){
431 | guiWindow.close()
432 | }
433 | if(docWindow){
434 | docWindow.close()
435 | }
436 | });
437 | mainWindow.on('unresponsive', () => {
438 | console.log('ERROR 61 - Window does not respond, let\'s quit')
439 | app.quit()
440 | })
441 |
442 | mainWindow.webContents.on('crashed', () => {
443 | console.log('ERROR 62 - Webcontent renderer crashed, let\'s quit')
444 | app.quit()
445 | })
446 |
447 | mainWindow.webContents.on('destroyed', () => {
448 | console.log('ERROR 63 - Webcontent destroyed, let\'s quit')
449 | app.quit()
450 | })
451 | mainWindow.loadFile('index.html')
452 | }
453 | function createGUI () {
454 | if(!guiWindow){
455 | guiWindow = new BrowserWindow({
456 | width: 800,
457 | height: 400,
458 | backgroundColor: '#000000',
459 | icon: path.join(__dirname, { darwin: 'icon.icns', linux: 'icon.png', win32: 'icon.ico' }[process.platform] || 'icon.ico'),
460 | // frame: process.platform !== 'darwin',
461 | // skipTaskbar: process.platform === 'darwin',
462 | // autoHideMenuBar: process.platform === 'darwin',
463 | webPreferences: {
464 | devTools: true,
465 | enableRemoteModule: true,
466 | nodeIntegration: true,
467 | contextIsolation: false,
468 | preload: path.join(__dirname, 'preload.js')
469 | }
470 | })
471 | guiWindow.on('close', function() {
472 | guiWindow = false
473 | });
474 | guiWindow.loadFile('html/gui.html')
475 | }
476 | }
477 | function destroyGUI () {
478 | if(guiWindow){
479 | guiWindow.close()
480 | }
481 | }
482 | function createRender () {
483 | if(!renderWindow){
484 | renderWindow = new BrowserWindow({
485 | width: 800,
486 | height: 400,
487 | backgroundColor: '#000000',
488 | icon: path.join(__dirname, { darwin: 'icon.icns', linux: 'icon.png', win32: 'icon.ico' }[process.platform] || 'icon.ico'),
489 | // frame: process.platform !== 'darwin',
490 | // skipTaskbar: process.platform === 'darwin',
491 | // autoHideMenuBar: process.platform === 'darwin',
492 | webPreferences: {
493 | devTools: true,
494 | enableRemoteModule: true,
495 | nodeIntegration: true,
496 | contextIsolation: false,
497 | preload: path.join(__dirname, 'preload.js')
498 | }
499 | })
500 | renderWindow.on('close', function() {
501 | renderWindow = false
502 | });
503 | renderWindow.loadFile('html/render.html')
504 | }
505 | }
506 | function destroyRender () {
507 | if(renderWindow){
508 | renderWindow.close()
509 | }
510 | }
511 |
512 | function createDoc() {
513 | if(!docWindow){
514 | docWindow = new BrowserWindow({
515 | width: 600,
516 | height: 800,
517 | backgroundColor: '#000000',
518 | icon: path.join(__dirname, { darwin: 'icon.icns', linux: 'icon.png', win32: 'icon.ico' }[process.platform] || 'icon.ico'),
519 | webPreferences: {
520 | devTools: false,
521 | enableRemoteModule: false,
522 | nodeIntegration: false,
523 | contextIsolation: true
524 | }
525 | })
526 | docWindow.on('close', function() {
527 | docWindow = false
528 | });
529 | docWindow.loadFile('html/readme.html')
530 | }
531 | }
532 |
533 | function createMenu(){
534 |
535 | const isMac = process.platform === 'darwin'
536 |
537 | const template = [
538 | // { role: 'appMenu' }
539 | ...(isMac ? [{
540 | label: app.name,
541 | submenu: [
542 | { role: 'about' },
543 | { type: 'separator' },
544 | { role: 'services' },
545 | { type: 'separator' },
546 | { role: 'hide' },
547 | { role: 'hideothers' },
548 | { role: 'unhide' },
549 | { type: 'separator' },
550 | { role: 'quit' }
551 | ]
552 | }] : []),
553 | // { role: 'fileMenu' }
554 | {
555 | label: 'File',
556 | submenu: [
557 | { click (s){requireAction(s);}, type: 'normal', label: 'Save',accelerator: 'CommandOrControl+S'},
558 | { click (s){openFile();}, type: 'normal', label: 'Open',accelerator: 'CommandOrControl+O' },
559 | { type: 'separator' },
560 | {
561 | label: 'Export As',
562 | submenu: [
563 | { click (s){requireAction(s);}, type: 'normal', label: 'JPG', accelerator: 'CommandOrControl+Shift+E' },
564 | { click (s){requireAction(s);}, type: 'normal', label: 'PNG', accelerator: 'CommandOrControl+E' }
565 | ]
566 | },
567 | { type: 'separator' },
568 | {
569 | label: 'Record GIF',
570 | submenu: [
571 | { click (s){requireAction(s,"GIF");}, type: 'normal', label: 'Start' },
572 | { click (s){requireAction(s,"GIF");}, type: 'normal', label: 'Stop' }
573 | ]
574 | },
575 | {
576 | label: 'Record WEBM',
577 | submenu: [
578 | { click (s){requireAction(s,"WEBM");}, type: 'normal', label: 'Start' },
579 | { click (s){requireAction(s,"WEBM");}, type: 'normal', label: 'Stop' }
580 | ]
581 | },
582 | { type: 'separator' },
583 | { click (s){resetStorage()}, type: 'normal', label: 'Reset Patch',accelerator: process.platform === 'darwin' ? 'Alt+Cmd+R' : 'Alt+Shift+R'},
584 | { click (s){randomPatch(true)}, type: 'normal', label: 'Random Patch', accelerator: 'CommandOrControl+N'},
585 | { click (s){randomPatch(false)}, type: 'normal', label: 'True Random Patch', accelerator: 'CommandOrControl+Shift+N'},
586 | isMac ? { role: 'close' } : { role: 'quit' }
587 | ]
588 | },
589 | {
590 | label: 'Render',
591 | submenu: [
592 | { click (s){requireAction(s);}, type: 'normal', label: 'Play'},
593 | { click (s){requireAction(s);}, type: 'normal', label: 'Pause' },
594 | { click (s){requireAction(s);}, type: 'normal', label: 'Stop' },
595 | { type: 'separator' },
596 | { click (s){requireOneFramejump();}, type: 'normal', label: 'Jump 1 Frame' },
597 | { click (s){requireTenFramesjump(10);}, type: 'normal', label: 'Jump 10 Frames' },
598 | { type: 'separator' },
599 | { click (s){requireRefresh();}, type: 'normal', label: 'Refresh' },
600 | { click (s){requireAction(s);}, type: 'normal', label: 'Reseed' },
601 | ]
602 | },
603 | // { role: 'viewMenu' }
604 | {
605 | label: 'View',
606 | submenu: [
607 | { role: 'reload' },
608 | { role: 'forceReload' },
609 | { role: 'togglefullscreen' },
610 | { role: 'toggleDevTools' }
611 | ]
612 | },
613 | // { role: 'windowMenu' }
614 | {
615 | label: 'Window',
616 | submenu: [
617 | { role: 'minimize' },
618 | { role: 'zoom' },
619 | { type: 'separator' },
620 | { label: 'Toggle GUI', click (s){toggleGUI();}, type: 'normal',accelerator: 'Space'},
621 | { label: 'Show GUI', click (s){displayGUI(true);}, type: 'normal'},
622 | { label: 'Hide GUI', click (s){displayGUI(false);}, type: 'normal'},
623 | { type: 'separator' },
624 | // { label: 'Undock GUI',click (s){createGUI();}, type: 'normal', },
625 | // { label: 'Destroy GUI',click (s){destroyGUI();}, type: 'normal', },
626 | { label: 'Undock Render',click (s){createRender();}, type: 'normal', },
627 | { label: 'Destroy Render',click (s){destroyRender();}, type: 'normal', },
628 | ...(isMac ? [
629 | { type: 'separator' },
630 | { role: 'front' },
631 | { type: 'separator' },
632 | { role: 'window' }
633 | ] : [
634 | { role: 'close' }
635 | ])
636 | ]
637 | },
638 | {
639 | role: 'help',
640 | submenu: [
641 | { label: 'Open Documentation',click (s){createDoc();}, type: 'normal', }
642 | ]
643 | }
644 | ]
645 |
646 | const menu = Menu.buildFromTemplate(template)
647 | Menu.setApplicationMenu(menu)
648 | }
649 |
650 | app.whenReady().then(() => {
651 | checkForEmptyStorage()
652 | createMenu()
653 | createWindow()
654 | app.on('activate', function () {
655 | if (BrowserWindow.getAllWindows().length === 0) createWindow()
656 | })
657 | app.on('gpu-process-crashed', () => {
658 | console.log('ERROR 64 - App GPU process has crashed, let\'s quit')
659 | app.quit()
660 | })
661 |
662 | process.on('uncaughtException', function (err) {
663 | console.log('ERROR 60 - process thrown exception, let\'s quit')
664 | console.log(err)
665 | app.quit()
666 | })
667 | })
668 |
669 | app.on('window-all-closed', function () {
670 | if (process.platform !== 'darwin') app.quit()
671 | })
672 |
--------------------------------------------------------------------------------
/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ACID",
3 | "version": "0.1.2",
4 | "description": "ACID is short for Algorithms Create Image Data. ACID is a general purpose video synthesizer.",
5 | "main": "main.js",
6 | "scripts": {
7 | "start": "electron .",
8 | "build_osx": "electron-packager . ACID --platform=darwin --arch=x64 --out ~/Documents/ --overwrite --icon=icon.icns ; echo 'Built for OSX'",
9 | "build_linux": "electron-packager . ACID --platform=linux --arch=x64 --out ~/Documents/ --overwrite --icon=icon.ico ; echo 'Built for LINUX'",
10 | "build_win": "electron-packager . ACID --platform=win32 --arch=x64 --out ~/Documents/ --overwrite --icon=icon.ico ; echo 'Built for WIN'",
11 | "build_deb": "electron-installer-debian --src ~/Documents/ACID-linux-x64 --dest ~/Documents/ --overwrite --icon=icon.ico --arch amd64"
12 | },
13 | "repository": "https://github.com/electron/electron-quick-start",
14 | "keywords": [],
15 | "author": "Johannes Hassenstein",
16 | "license": "CC0-1.0",
17 | "devDependencies": {
18 | "electron": "^11.3.0",
19 | "electron-installer-debian": "^3.1.0",
20 | "electron-packager": "^15.1.0"
21 | },
22 | "dependencies": {
23 | "electron-json-storage": "^4.3.0"
24 | },
25 | "config": {
26 | "forge": "./forge.config.js"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/preload.js:
--------------------------------------------------------------------------------
1 | // All of the Node.js APIs are available in the preload process.
2 | // It has the same sandbox as a Chrome extension.
3 | window.addEventListener('DOMContentLoaded', () => {
4 | const replaceText = (selector, text) => {
5 | const element = document.getElementById(selector)
6 | if (element) element.innerText = text
7 | }
8 |
9 | for (const type of ['chrome', 'node', 'electron']) {
10 | replaceText(`${type}-version`, process.versions[type])
11 | }
12 | })
13 |
--------------------------------------------------------------------------------
/ideas.txt:
--------------------------------------------------------------------------------
1 | Invert edge param
2 |
3 | ASCII Layer
4 | "ascii": {
5 | "fontsize": 24,
6 | "spacing": 0.2,
7 | "color": "#ffffff",
8 | "chars": "-#+*",
9 | "font": "mon",
10 | "opacity": 0.8,
11 | "mix": "nrm",
12 | "update": 5
13 | },
14 | this.ascii.style.fontSize = this.config.render.ascii.fontsize + "px"
15 | this.ascii.style.opacity = this.config.render.ascii.opacity
16 | this.ascii.style.color = this.config.render.ascii.color
17 | let asciiStyle = "normal"
18 | switch(this.config.render.ascii.mode){
19 | case "col":
20 | asciiStyle = "color"
21 | break
22 | case "brn":
23 | asciiStyle = "color-burn"
24 | break
25 | case "dod":
26 | asciiStyle = "color-dodge"
27 | break
28 | case "drk":
29 | asciiStyle = "darken"
30 | break
31 | case "dif":
32 | asciiStyle = "difference"
33 | break
34 | case "exc":
35 | asciiStyle = "exclusion"
36 | break
37 | case "hlg":
38 | asciiStyle = "hard-light"
39 | break
40 | case "hue":
41 | asciiStyle = "hue"
42 | break
43 | case "lgt":
44 | asciiStyle = "lighten"
45 | break
46 | case "lum":
47 | asciiStyle = "luminosity"
48 | break
49 | case "mlt":
50 | asciiStyle = "multiply"
51 | break
52 | case "ovr":
53 | asciiStyle = "overlay"
54 | break
55 | case "sat":
56 | asciiStyle = "saturation"
57 | break
58 | case "scr":
59 | asciiStyle = "screen"
60 | break
61 | case "slg":
62 | asciiStyle = "soft-light"
63 | break
64 | }
65 | this.ascii.style["mix-blend-mode"] = asciiStyle
66 |
67 | BITMAP
68 |
69 | Bitmap Editor
70 | - clear
71 | - load image
72 | - x and y
73 | - store
74 |
75 | Bitmap oscilator
76 | - sources
77 | - scale and stretch
78 | - interpolate
79 | - scroll x and y
80 | - animation: blend/jump/vertical/horizontal
81 | - animationspeed
82 |
83 |
84 | MATRIX
85 | Inputs on 1 Axis
86 | Outpouts on other axis
87 | Connections can change intensity
88 |
89 | Basic Outputs
90 | Main Clock
91 | Render X
92 | Render Y
93 |
94 | Basic Inputs
95 | Render R
96 | Render G
97 | Render B
98 |
--------------------------------------------------------------------------------
/img/animated_cover.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/img/animated_cover.gif
--------------------------------------------------------------------------------
/img/banner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/img/banner.gif
--------------------------------------------------------------------------------
/img/banner_logo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/img/banner_logo.gif
--------------------------------------------------------------------------------
/img/cover.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/img/cover.gif
--------------------------------------------------------------------------------
/img/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/img/example.gif
--------------------------------------------------------------------------------
/img/screenshot-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/img/screenshot-1.jpg
--------------------------------------------------------------------------------
/img/screenshot-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/img/screenshot-1.png
--------------------------------------------------------------------------------
/img/screenshot-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/img/screenshot-2.jpg
--------------------------------------------------------------------------------
/img/screenshot-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/img/screenshot-2.png
--------------------------------------------------------------------------------
/img/screenshot-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/img/screenshot-3.jpg
--------------------------------------------------------------------------------
/img/screenshot-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softboydev/acid/cdb44a43b7d2c47faf7fcfd6d4c55846ba84c844/img/screenshot-3.png
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | 
2 | # ACID
3 |
4 | ACID is short for **A**lgorithms **C**reate **I**mage **D**ata and is a simple, general purpose video synthesizer for creating live visuals and computer generated images and animations. It works somewhat similar to an analog synthesizer with a little bit of Photoshop thrown in.
5 |
6 | ACID features a clean graphic user interface that can be detached. ACID has built in export to PNG and JPG and can record GIFs and WEBM videos of any length straight out of the program. The render window can be detached to use ACID for live visuals.
7 |
8 | This is how the interface looks:
9 |
10 | 
11 |
12 | *GUI is opened in the main window*
13 |
14 | 
15 |
16 | *GUI is undocked*
17 |
18 | 
19 |
20 | *GUI and Render are both undocked*
21 |
22 | 
23 |
24 | This is how a patch could look. There are currently no available presets but you can use the "Random Patch" function in the menu to get started. You can see 100 random patches in this video: https://www.youtube.com/watch?v=u_rGDhfu_Qk
25 |
26 | ## Installation
27 |
28 | You can either install a build for your platform or run ACID yourself with `npm`.
29 |
30 | To download a build for your platform head over to [acidatm.itch.io/acid](https://acidatm.itch.io/acid) and download a build there. The download is free, there is only an optional donation.
31 |
32 |
33 | Presets can be found in the `/presets` directory or can be downloaded on *itch.io* as well.
34 |
35 |
36 | To run ACID withen *electron.js*, install `npm` and `git` (if you don't have them installed), then open your terminal and run:
37 |
38 | ```bash
39 | git clone https://github.com/acidatm/acid
40 | cd acid/app/
41 | npm install
42 | npm start
43 | ```
44 |
45 | ## Acknowledgement
46 |
47 | I was enspired by the works of these people:
48 |
49 | - The ORCA sequencer by Rekka & Devine: https://hundredrabbits.itch.io/
50 | - The works of Viznut, especially IBNIT: http://countercomplex.blogspot.com/2011/12/ibniz-hardcore-audiovisual-virtual.html
51 | - And various stuff found on esoteric.codes: https://esoteric.codes/s
52 |
53 | ## Documentation
54 |
55 | All values in the GUI range between 0 and 999, where 0 is the minimum value and 999 is the maximum. The GUI can be toggled either with the space bar or using the options in *Menubar > Window*. The GUI can also be opened in a second window.
56 |
57 | The labels next to the sliders can be used to set a slider to specific value. The buttons next to the labels can be used to minimize, center, maximize or randomize the slider value. Both can be disabled from the *set* part of the GUI.
58 |
59 | ### Oscilators
60 |
61 | An oscilator is either a cyclic transfer function or a noise based algorithm. A cyclic transfer function takes a value between 0 and infinity and returns a value between 0 and 1, the exact distribution of the values inbetween is determined by the oscilators waveform. The amount of values after which the oscilator repeats is determined by its frequency.
62 |
63 | You can use oscilators as fixed filters by setting the *spd* parameter to 0. This will stop the oscilator from moving entirely. You can then control the exact character of the filter with the *frq*, *off* and *rot* parameters.
64 |
65 | If you need a constant fixed value from an oscilator, you can use a *sqr* oscilator, with a *spd* of 0 and a low *frq*. You can then control the exact value using the *min* or *max* parameter.
66 |
67 | If you need a completely random texture, create an oscilator with a medium value and apply a high *rnd* effect on it.
68 |
69 | All oscilators have an additional "run" property, which can be set to quickly mute an oscilator. You can toggle it by clicking on "osx" (where x is the oscilator number) in the GUI. The run property behaves identical to the *off* type, but doesnt change the type of the oscilator.
70 |
71 | #### Channels
72 |
73 | All oscilators can send to 3 different channels independently. They send the same basic value to each channel but you can attenuate the value for each channel individually. You can do so from the *rgb* section using the inputs for *r*,*g* and *b*.
74 |
75 | #### Cyclical oscilators
76 |
77 | These are the available cyclical oscilators:
78 |
79 | - **sqr** (Square) - will create a squarewave, that is either high or low, but has no inbetween states
80 | - **pwm** (Pulse) - will create a pulse oscilator (and *Pulse Width Modulation* will be available in the near future)
81 | - **saw** (Sawtooth) - will create a sawtooth wave, that starts high and falls to low in a linear fashion
82 | - **tri** (Triangle) - will create a triangle wave, that switches between high and low in linear fashion
83 | - **sin** (Sine) - will create a sine wave, that switches between high and low in non linear fashion
84 | - **osc** (Oscilator) - will create a flexible oscilator, which can take any shape between a pure triangle over a pure sine to pure square. The pulse width can be modified, which can turn a triangle into a ramp or saw, or change the width of a squarewave. But it can also do any shape inbetween.
85 |
86 |
87 | For each oscilator these are the important parameters:
88 |
89 | - **typ** (Type) - will determine the type of oscilator to use
90 | - **min** (Minimum) - sets the minimum amplitude (normally 0)
91 | - **max** (Maximum) - sets the maximum amplitude (normally 999)
92 | - **lpf** (Low Pass Filter) - Values above this threshold will be cut. The filter behaves relative to *min* and *max*
93 | - **hpf** (High Pass Filter) - Values below this treshold will be cut. The filter behaves relative to *min* and *max*
94 | - **mix** (Mixing) - The way this oscilator should be mixed with other oscilators
95 | - *ADD* (Additive) - Add the value to the mix
96 | - *SUB* (Subtractive) - Removes the value from the mix
97 | - *MLT* (Multiply) - Multiplies the mix with the value
98 | - *DIV* (Divide) - Divides the mix by the value
99 | - **rot** (Oscilator Rotation) - Will rotate the oscilator in 2D space
100 | - **frq** (Oscilator Frequency) - Determines the frequency of the oscilation
101 | - **spd** (Oscilator Speed) - Determines how fast the oscilator moves through 2D space in the direction set by *rot*
102 | - **off** (Oscilator Offset) - Will change the phase of the oscilation, which us really only useful when *speed* is at 0
103 |
104 | The *osc* oscilator has these additional parameters:
105 |
106 | - **cen** (Oscilator Center) - sets the high point of the oscilation relative to the wavelength. 0 means right at the start (which would make a triangle wave a saw wave), 999 means right at the end (which would make a triangle wave a ramp wave)
107 | - **shp** (Oscilator Shape) - determines the general shape of the oscilator. It does so by fading between pure triangle wave (0), pure sine wave (499) and pure squarewave (999)
108 |
109 | #### Noncyclical oscilators
110 |
111 | These are the available, noncyclical oscilators:
112 |
113 | - **plx** (Simplex Noise) - An advanced correlating noise algorithm
114 | - **prl** (Perlin Noise) - A less advanced correlating noise algorithm
115 | - **org** (Organic) - A noise algorithm that creates "organic" shapes like water ripples or woodgrain (it is simplex noise passed through a seeded random number generator)
116 | - **off** (Off) - turns the oscilator off
117 |
118 | The noncyclical oscilators use some of the cyclical oscilator settings, however they are used somewhat different:
119 |
120 | - **frq** (Oscilator Frequency) - Determines the frequency of the noise plane, which will feel more like its resolution or graininess maybe
121 | - **off** (Oscilator Offset) - Will move to a fixed value on the plane of the noise
122 |
123 | The organic oscilator also uses the two additional settings from the *osc* oscilator
124 |
125 | - **cen** (Oscilator Center) - determines how many different steps or layers are generated
126 | - **shp** (Oscilator Shape) - blends between quantised and unquantised noise
127 |
128 | There are also a couple of additional settings for the two noise algorithms, as they are 3 dimensional. The oscilator settings control the z axis, the other two axis are controlled by their respective parameters. All axis have the same set of parameters.
129 |
130 | The noise algorithms are seedable, which means same values in, same values out. You can reseed the noise algorithms from *Menubar > Render > Reseed*.
131 |
132 | ### Effects
133 |
134 | All oscilators can have any number of effects applied to them. Which effects are applied is set by the effects chain ("--- + " in the GUI). Clicking on "+" will add a new effect to the chain, clicking on an effect will flip through the different effect types, clicking on "---" (which will then show "clr") will clear the effect chain. Effects are passed through from left to right.
135 |
136 | - **---** (List) - marks the presence of a list. Clicking will clear the list
137 | - **+** (Add) - can be clicked to add new entrys to the list.
138 |
139 | The settings for all effects in the chain are the same. However you can use the chain to apply effects in different order or multiple times. The settings are set in the *fx* part of the respective GUI section:
140 |
141 | - **bit** (Bitreduction) - Will reduce the number of possible values down to only a single one. 0 means no reduction, 999 means maximum reduction.
142 | - **cmp** (Compression) - Will make lower values higher while influencing higher values less.
143 | - **exp** (Expansion) - Will make lower values even lower while influencing higher values less. Works somewhat in reverse to compression.
144 | - **rnd** (Randomization) - Will randomly change values. A low setting will result in a more "analog" look, while a high setting will make things very glitchy
145 | - **drv** (Drive) - Will amplify all values equally. Can be used as a preamp or overdrive.
146 |
147 | ### Render
148 |
149 | The parameters for the render process can be found under "img". The render process determines how the values generated by ACID and the configuration set in the GUI are used to generate images. Not all settings are available at all times, some may only be visible when a certain color mode or render engine is active.
150 |
151 | - **frm** (Framerate) - the desired framerate for the undocked render window. To not display visible jumbs between frames the render process will render frame after frame and not skip frames. This can result in exported GIFs looking faster. You can see the true FPS in the settings tab
152 | - **res** (Resolution) - resolution for the undocked render window
153 | - **pre**
154 | - **res** (Preview Resolution) - resolution for the main window
155 | - **frm** (Preview Framerate) - framerate for the main window
156 | - **bw** (Black and White) - blends between color and black and white
157 | - **brn** (Burn) - can be used to lighten the image when subpixels are enabled
158 | - **drv** (Drivetype) - this is the clipping stage of the master amplifier, there are 3 settings available:
159 | - **clp** (Clip) - Will simply clip all values over 1 and make them 1
160 | - **mod** (Modify) - Will wrap all values over 1 until they are below 1. 1.5 would become 0.5, 2.3 would become 0.3 and so on.
161 | - **dyn** (Dynamic) - Will redistribute all values on a range between the frames lowest and highest value, making it impossible to clip the amp (however you can use a compressor or drive and a low pass filter to achieve the effect on an oscilator level)
162 | - **clr** (Colormode) - Changes the colormode. You can click on the GUI label to activate a fixed HSL based color mode, which can be helpfull to see how the oscilators effect each other.
163 | - *rgb* (Linear RGB) - ACID can effect a linear RGB space
164 | - *grd* (Gradient) - ACID can effect the value on a range between any amount of colors. The colors are determined by the values in the color list. The black and white values between 0 and 1 are used to determine the position on the gradient.
165 | - *ndx* (Indexed) - works just like gradient. Except its not a gradient but a stepped gradient with no mix between the steps.
166 |
167 | #### Feedback
168 |
169 | The virtual feedback engine simulates true feedback when using a camera that is pointed on a screen that displays the camera image. Simulates, not duplicates. It is different. But based around the same idea. As ACID is deterministic we can now the value of each pixel at any point in time. And that is exactly how the feedback works. We simply don't show all pixels at the same point in time at the same time.
170 |
171 | - **int** (Feedback Intensity) - Intensity of the feedback, basically how far into the future we go at max
172 | - **edg** (Feedback Quantization) - How much the feedback is quantized. This will lead to visible jumps/edges
173 | - **x** (Feedback Center X) - relative x position of the center of the feedback
174 | - **y** (Feedback Center Y) - relative y position of the center of the feedback
175 | - **mix** (Feedback Mix) - mixes between horizontal and vertical feedback
176 | - **bnd** (Feedback Bend) - mixes between linear and feedbacked feedback (you read that right, the feedback can feedback on it self). This will lead to more bended lines then straight lines
177 | - **skw** (Feedback Skew) - mixes between horizontal and vertical bend
178 | - **sqr** (Feedback Squaring/Linearity) - mixes between a linear and a stepped version of the feedback. Linear look like a triangle, stepped like a square (so like classic tv feedback)
179 | - **drk** (Feedback Darken) - makes the feedback darker the further back it is in time (like classic tv feedbacks)
180 |
181 | ### Settings
182 |
183 | The settings part of the GUI can be found under "set". Here you can change default values, GUI styles and some global settings for the render engine.
184 |
185 | - **fps** (True FPS) - display the true FPS
186 | - **wid** (Width) - displays the width of the main window in pixels
187 | - **hei** (Height) - displays the height of the main window in pixels
188 | - **dcl** (Default Color) - Sets the default color when adding a new color in indexed color mode
189 | - **dfx** (Default Effect) - Sets the default effect when adding a new effect to an effects chain
190 | - **fx** (Toggle Effects) - Toggles the usage of effects
191 | - **sub** (Toggle Subpixels) - Toggles the render of subpixels
192 | - **fdb** (Toggle Feedbacl) - Toggles the virtual feedback engine
193 | - **col** (Toggle Colormodes) - Toggles the availability of color modes
194 | - **zom** (Zoom) - Sets the size of the GUI
195 | - **trn** (Transparency) - Sets the transpareny of the GUI in the main window
196 | - **tip** (Tooltips) - Toggles the display of tooltip boxes when hovering over a parameter name
197 | - **lab** (Labels) - Toggles the display of labels next to sliders
198 | - **btn** (Buttons) - Toggles the display of buttons next to sliders
199 |
200 | ### Menubar
201 |
202 | You can access some actions and all import and export dutys from the menubar of the application.
203 |
204 | #### File
205 |
206 | - Save - Save the current patch as a .txt file
207 | - Open - Open a saved patch
208 | - Exports As > JPG - Export the current frame as a JPG of the render (GUI will not be visible)
209 | - Exports As > PNG - Export the current frame as a PNG of the render (GUI will not be visible)
210 | - Record GIF > Start - starts the recording of a GIF of the render (GUI will not be visible). A flashing red dot will appear (the dot is not visible in the GIF).
211 | - Record GIF > Stop - ends the recording of a GIF, creates a .gif file and opens a save dialog
212 | - Record WEBM > Start - recording of a WEBM video of the render (GUI will not be visible). A flashing red dot will appear (the dot is not visible in the WEBM)
213 | - Record WEBM > Stop - ends the recording of a WEBM video, creates a .webm file and opens a save dialog
214 | - Reset Patch - Clears the internal storage and loads the default patch
215 |
216 | #### Render
217 |
218 | - Play - Start the clock for the renderprocess
219 | - Pause - Pauses the clock for the renderprocess
220 | - Stop - Turns the renderprocess off until play is clicked
221 | - Jump 1 Frame - Increments the clock for the render process once and renders once. Useful when trying to get to specific look when having the render paused or stopped.
222 | - Jump 10 Framse - Increments the clock for the render process by 10 and renders once. Useful when trying to get to specific look when having the render paused or stopped.
223 | - Refresh - Simply renders again when the render is stopped manually. Normally any parameter change will trigger a refresh as well
224 | - Reseed - Reseed all noise oscilators and the SRNG for the global effects
225 |
226 | #### Window
227 |
228 | - Open GUI - Opens the GUI in the main window
229 | - Close GUI - Closes the GUI in the main window
230 | - Undock GUI - Creates a new window with the GUI in it, so you can control the render from a seperate window, optimal for VJing
231 | - Destroy GUI - Destroys a created GUI window
232 | - Undock Render - Creates a new window with the render in it, so you can display it in a seperate window, optimal for VJing
233 | - Destroy Render - Destroys a created render window
234 |
235 | #### Help
236 |
237 | - Open Documentation - Opens a new window containing the full documentation (this document)
238 |
239 | ## Releases
240 |
241 | Below you can find release notes on all major releases that had a dedicated build available. Look into the devlog over at [acidatm.itch.io/acid](https://acidatm.itch.io/acid) for more details.
242 |
243 | - **0.1.2** WebGL Update
244 | - ACID is now using WebGL instead of simple canvas which increases performance dramatically
245 | - A new subpixel option to get a more tv or analog look and feel
246 | - A new virtual feedback mode that simulates real camera to tv to camera feedback
247 | - A dedicated render only window can be undocked now, which makes use for VJing way better
248 | - Specific settings for framerate and resolution in main and undocked window
249 | - Additional settings for black and white fading and color burn out
250 | - Color modes are now based on 3 color channels instead of a singular value
251 | - Gradient color modes can now have any amount of steps
252 | - Many performance optimisations in the code
253 | - Additional optimization settings that can disable certain parts of the program for a better performance
254 | - Two new oscilators added: *pwm*, which is a pulse oscilator, and *org* which is a noise algorithm specialised for organic shape creation
255 | - A new random patch option in the menu
256 | - Keyboard shortcuts for various menu functions
257 | - Added analytics such as true framerate, width and height
258 | - Removed hsl color mode (but will be back soon, no worries)
259 | - Removed different render engines for now
260 | - Removed some unused parameters from the codebase
261 | - Removed some unnecessary settings in the GUI
262 | - Reverted to old window styles on Mac OS
263 | - Oscilator frequency as no longer linked to resolution
264 | - Renderloop is now called recursive at the start of the loop, making each frame roughly equal, no matter the calculation time
265 | - **0.1.1** Release of the full alpha version
266 | - Reworked the *lpf* and *hpf* parameters to be relative to the *min* and *max* property
267 | - Removed the *amp* parameter on all oscilators, as it's behavior can be duplicated using the *max* parameter
268 | - Reworked the *amp* parameter on the bus to not be able to overdrive the sum (use a *drv* effect instead)
269 | - Reworked all algorithmic oscilators to use fewer parameters
270 | - Added *off* as an oscilator type. Works just like toggling the oscilator when clicking on *osx*
271 | - Added *hsl* as a color mode
272 | - Enabled full 360 degree turning of oscilators with the *mod* parameter and removed the *rmp* oscilator shape (as its just a rotated *saw* oscilator)
273 | - Added a new oscilator shape *osc*, that can be faded between pure triangle over pure sine to pure square and also has pulse width modulation capabilitys.
274 | - Added sliders to the GUI, made number input optional, added optional buttons
275 | - Made the GUI have linear values for zoom and transparency, instead of different, fixed settings
276 | - Removed global effects (*err*) and instead added two more oscilators
277 | - Reworked the complex 2D render engine (*c2d*) to have dedicated values for the radius of all corners and the padding on all sides as well as a simple 2d render engine running "below" it, to control the background color of each cell
278 | - Made the compressor (*cmp*) work in one direction only, added a new expander (*exp*) effect that now works in reverse to compression
279 | - Added optional tooltips to the GUI
280 | - Added automatic load of a default patch upon first (or resetted) start up
281 | - Added a patch reset option to clear out a faulty storage and to automatically load a default patch
282 | - Added a stop option, to completely disable the rerender of the scene until play is hit
283 | - Added a framejump option, to increment the t value, when the render is paused or stopped
284 | - Fixed a bug, where the GUI would jump when an input was changed
285 | - Removed deprecated electron.js functions
286 | - Added proper error handling in case of crashes
287 | - Did some visual changes on the GUI
288 | - Unused parameters are now hidden in the UI until they are needed
289 | - **0.1.0** Release of the initial alpha version
290 |
291 | ## Future Plans
292 |
293 | This is a very early state of this software, I plan to extend it regularly. I currently plan to do these things:
294 |
295 | - Adding LFOs and sequencers
296 | - Adding an FM based oscilator
297 | - Adding multiple presets within one patch file
298 | - Adding audioreactive functionality
299 | - Adding multiple render engines
300 | - Adding bitmaps, image to bitmap import and tools to manipulate and animate both
301 | - Adding a built-in, keyframe based timeline to automate parameter changes in a video editor like fashion
302 | - Adding basic MIDI support, so that parameters can be controlled with CC and presets may be changed with PCM
303 | - Adding OSC support, so that parameters can be controlled with software like ORCA
304 | - Adding a Serial Port implementation, so that parameters can be controlled with microcontroller based hardware and/or sensors
305 | - Reworking the GUI to use React.js
306 | - Reworking the GUI to use modular patching
307 | - Adding a shell like interface with a command line
308 | - Adding a custom live coding environment
309 | - Restructuring the code to be more dev friendly, so other people can write new engines, effects, oscilators and so on
310 | - Adding live performance features such as momentary effects and preprogrammed parameter changes in scenes
311 |
312 | At this point you know all there is to know. Now go and make something on ACID :)
313 |
--------------------------------------------------------------------------------