Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REQUEST] Building libprojectM for WASM/emscripten #864

Open
2 tasks done
D0rk23 opened this issue Dec 24, 2024 · 13 comments
Open
2 tasks done

[REQUEST] Building libprojectM for WASM/emscripten #864

D0rk23 opened this issue Dec 24, 2024 · 13 comments
Labels
emscripten Anything related to building libprojectM for WASM/emscripten question

Comments

@D0rk23
Copy link

D0rk23 commented Dec 24, 2024

Please confirm the following points:

  • This question is NOT about the Android apps in the Play Store
  • I have searched the project page to check if the question was already asked elsewhere

Topic

Development and Contributing

Your Request

Im looking to adapt this for web use
was able to get butterchurn setup
https://azmanagedit.net/product/wordpress-butterchurn-audio-visualizer/
Sounds like theres is an option to run ProjectM in a browser via WebAssembly, which makes it usable on websites.
Option 1: WebAssembly Version

  • WebAssembly enables ProjectM to run in a browser, rendering MilkDrop presets via WebGL.

What's Needed?

  • A WebAssembly-compatible build of ProjectM (projectm.js and projectm.wasm).
  • MilkDrop presets for visualization.
  • JavaScript code to handle the audio source and attach it to the visualization.

Creating a WebAssembly-compatible build of ProjectM involves compiling its C++ codebase into WebAssembly using a toolchain like Emscripten.
+===+
Imported Docker Image
image

Step 1: Clone the ProjectM Repository
Clone the ProjectM source code into the container:

git clone https://github.com/projectM-visualizer/projectm.git
Navigate to the projectm directory:

cd projectm
Step 2: Create a Build Directory
To keep the build files separate from the source files, create a build directory and navigate into it:

mkdir build
cd build

Step 3: Configure the Build
Use Emscripten’s CMake wrapper (emcmake) to configure the build for WebAssembly:
emcmake cmake ..
This command sets up the build system to use Emscripten as the toolchain.
image
it appears that CMake is encountering an issue related to the projectM-Eval package or module, which is required for the build. This issue happens because the necessary configuration files for projectM-Eval cannot be found in the expected locations.
image
The error indicates that the projectm-eval directory under /src/projectm/vendor/ is missing the necessary CMakeLists.txt file, which is required for the build process. This likely means that the submodule or dependency for projectm-eval wasn’t cloned properly.

Step 1: Initialize and Update Submodules
Navigate to the root of the ProjectM repository:
cd /src/projectm
Initialize and update all submodules:
git submodule update --init --recursive

Step 2: Verify Submodule Directory
After updating submodules, verify that the projectm-eval directory contains a CMakeLists.txt file:
ls vendor/projectm-eval
image
Step 3: Retry the Build Configuration
Once the submodule is correctly set up, rerun the emcmake cmake .. command from the build directory:
cd /src/projectm/build
emcmake cmake ..
If this completes successfully, proceed with the build:
image

Next Steps: Compile the Code
Now, you need to build the project using the emmake command. Here’s how to proceed:

Run the Build Command: In the build directory, run:
emmake make
Monitor the Output:
image

The build process may take a few minutes, depending on the complexity of the code and your system resources.
Look for any errors or warnings during the process. If you encounter errors, take note of them so we can troubleshoot.
Check the Output: After the build completes, check the build directory for the following files:

projectm.js: JavaScript glue code for WebAssembly.
projectm.wasm: The WebAssembly binary.
Any additional runtime or configuration files needed.
You can verify the files are present by running:
ls
Testing the Output
Once the build is successful, you can:
image
it seems that while the build has successfully completed, the expected output files (projectm.js and projectm.wasm) are not present in the build directory. This indicates that either:

The build configuration didn't produce the WebAssembly artifacts.
Some additional steps are needed to generate the WebAssembly files.


Copy the generated files (.js and .wasm) to your host machine using:
docker cp naughty_faraday:/src/projectm/build/projectm.js .
docker cp naughty_faraday:/src/projectm/build/projectm.wasm .
Serve these files using a simple local web server and create an HTML file to test them.

Confirm WebAssembly Support in ProjectM
Before proceeding further, check if the ProjectM repository explicitly supports WebAssembly. Inside the main source directory (/src/projectm), search for mentions of WebAssembly or Emscripten in the codebase:
grep -ri "EMSCRIPTEN" /src/projectm
image

Steps to Replicate the Workflow
Install Required Packages
Run the following commands inside your Docker container to ensure all dependencies are installed:

apt-get update
apt-get install -y libgl1-mesa-dev mesa-common-dev libsdl2-dev libglu1-mesa-dev ninja-build
Sorry to much to add here.
image
Im about to Verify that wrapper.js and wrapper.wasm

@revmischa
Copy link
Collaborator

There is some support for WebAssembly, yes!

@D0rk23
Copy link
Author

D0rk23 commented Dec 24, 2024

Sweet I'll keep my notes here if that's cool.
Just going to update the original post with my work.

@D0rk23
Copy link
Author

D0rk23 commented Dec 25, 2024

I will update my notes soon. This is what i have so far not even sure what to say AI is crazy.
wrapper.zip
(import "a" "a" (func (;0;) (type 15)))
(import "a" "b" (func (;1;) (type 4)))
(import "a" "c" (func (;2;) (type 1)))
(import "a" "d" (func (;3;) (type 2)))
(import "a" "e" (func (;4;) (type 5)))
(import "a" "f" (func (;5;) (type 6)))
(import "a" "g" (func (;6;) (type 0)))
(import "a" "h" (func (;7;) (type 7)))
(import "a" "i" (func (;8;) (type 51)))
(import "a" "j" (func (;9;) (type 11)))
(import "a" "k" (func (;10;) (type 3)))
(import "a" "l" (func (;11;) (type 1)))
(import "a" "m" (func (;12;) (type 16)))
(import "a" "n" (func (;13;) (type 1)))
(import "a" "o" (func (;14;) (type 5)))
(import "a" "p" (func (;15;) (type 10)))
(import "a" "q" (func (;16;) (type 9)))
(import "a" "r" (func (;17;) (type 1)))
(import "a" "s" (func (;18;) (type 5)))
(import "a" "t" (func (;19;) (type 5)))
(import "a" "u" (func (;20;) (type 0)))
(import "a" "v" (func (;21;) (type 0)))
(import "a" "w" (func (;22;) (type 10)))
(import "a" "x" (func (;23;) (type 0)))
(import "a" "y" (func (;24;) (type 3)))
(import "a" "z" (func (;25;) (type 3)))
(import "a" "A" (func (;26;) (type 4)))
(import "a" "B" (func (;27;) (type 6)))
(import "a" "C" (func (;28;) (type 14)))
(import "a" "D" (func (;29;) (type 8)))
(import "a" "E" (func (;30;) (type 3)))
(import "a" "F" (func (;31;) (type 12)))
(import "a" "G" (func (;32;) (type 29)))
(import "a" "H" (func (;33;) (type 29)))
(import "a" "I" (func (;34;) (type 1)))
(import "a" "J" (func (;35;) (type 0)))
(import "a" "K" (func (;36;) (type 1)))
(import "a" "L" (func (;37;) (type 6)))
(import "a" "M" (func (;38;) (type 1)))
(import "a" "N" (func (;39;) (type 0)))
(import "a" "O" (func (;40;) (type 17)))
(import "a" "P" (func (;41;) (type 4)))
(import "a" "Q" (func (;42;) (type 0)))
(import "a" "R" (func (;43;) (type 0)))
(import "a" "S" (func (;44;) (type 5)))
(import "a" "T" (func (;45;) (type 1)))
(import "a" "U" (func (;46;) (type 22)))
(import "a" "V" (func (;47;) (type 15)))
(import "a" "W" (func (;48;) (type 52)))
(import "a" "X" (func (;49;) (type 0)))
(import "a" "Y" (func (;50;) (type 0)))
(import "a" "Z" (func (;51;) (type 3)))
(import "a" "_" (func (;52;) (type 25)))
(import "a" "$" (func (;53;) (type 6)))
(import "a" "aa" (func (;54;) (type 0)))
(import "a" "ba" (func (;55;) (type 1)))
(import "a" "ca" (func (;56;) (type 30)))
(import "a" "da" (func (;57;) (type 2)))
(import "a" "ea" (func (;58;) (type 53)))
(import "a" "fa" (func (;59;) (type 54)))
(import "a" "ga" (func (;60;) (type 55)))
(import "a" "ha" (func (;61;) (type 11)))
(import "a" "ia" (func (;62;) (type 5)))
(import "a" "ja" (func (;63;) (type 5)))
(import "a" "ka" (func (;64;) (type 0)))
(import "a" "la" (func (;65;) (type 0)))
(import "a" "ma" (func (;66;) (type 13)))
(import "a" "na" (func (;67;) (type 1)))
(import "a" "oa" (func (;68;) (type 56)))
(import "a" "pa" (func (;69;) (type 0)))
(import "a" "qa" (func (;70;) (type 3)))
(import "a" "ra" (func (;71;) (type 7)))
(import "a" "sa" (func (;72;) (type 2)))
(import "a" "ta" (func (;73;) (type 7)))
(import "a" "ua" (func (;74;) (type 12)))
(import "a" "va" (func (;75;) (type 6)))
(import "a" "wa" (func (;76;) (type 11)))
(import "a" "xa" (func (;77;) (type 57)))
(import "a" "ya" (func (;78;) (type 31)))
(import "a" "za" (func (;79;) (type 17)))
(import "a" "Aa" (func (;80;) (type 1)))
(import "a" "Ba" (func (;81;) (type 32)))
(import "a" "Ca" (func (;82;) (type 0)))
(import "a" "Da" (func (;83;) (type 0)))
(import "a" "Ea" (func (;84;) (type 0)))
(import "a" "Fa" (func (;85;) (type 0)))
(import "a" "Ga" (func (;86;) (type 0)))
(import "a" "Ha" (func (;87;) (type 6)))
(import "a" "Ia" (func (;88;) (type 6)))
(import "a" "Ja" (func (;89;) (type 5)))
(import "a" "Ka" (func (;90;) (type 5)))
(import "a" "La" (func (;91;) (type 5)))
(import "a" "Ma" (func (;92;) (type 5)))
(import "a" "Na" (func (;93;) (type 5)))
(import "a" "Oa" (func (;94;) (type 6)))
(import "a" "Pa" (func (;95;) (type 1)))
(import "a" "Qa" (func (;96;) (type 6)))
(import "a" "Ra" (func (;97;) (type 3)))
(import "a" "Sa" (func (;98;) (type 6)))
(import "a" "Ta" (func (;99;) (type 1)))
(import "a" "Ua" (func (;100;) (type 1)))
(import "a" "Va" (func (;101;) (type 15)))
(import "a" "Wa" (func (;102;) (type 22)))
(import "a" "Xa" (func (;103;) (type 0)))
(import "a" "Ya" (func (;104;) (type 0)))
(import "a" "Za" (func (;105;) (type 7)))
(import "a" "_a" (func (;106;) (type 8)))
(import "a" "$a" (func (;107;) (type 4)))
(import "a" "ab" (func (;108;) (type 4)))
(import "a" "bb" (func (;109;) (type 7)))
(import "a" "cb" (func (;110;) (type 4)))
(import "a" "db" (func (;111;) (type 7)))
(import "a" "eb" (func (;112;) (type 6)))
(import "a" "fb" (func (;113;) (type 4)))
(import "a" "gb" (func (;114;) (type 4)))
(import "a" "hb" (func (;115;) (type 12)))
(import "a" "ib" (func (;116;) (type 2)))
(import "a" "jb" (func (;117;) (type 3)))
(import "a" "kb" (func (;118;) (type 58)))
(import "a" "lb" (func (;119;) (type 7)))
(import "a" "mb" (func (;120;) (type 2)))
(import "a" "nb" (func (;121;) (type 59)))
(import "a" "ob" (func (;122;) (type 5)))
(import "a" "pb" (func (;123;) (type 60)))
The issue here is that your WebAssembly module (wrapper.wasm) is expecting imports for various functions (e.g., a.a, a.b, etc.) that are not defined in the imports object provided in your JavaScript wrapper.js. These placeholder functions are being generated dynamically by the current code to avoid crashes but aren't functional, which likely leads to the blank page.

What Does This Mean?
The WebAssembly module (wrapper.wasm) has a series of imports declared, and these imports must be satisfied by your JavaScript code.
If an import is not provided, the WebAssembly runtime creates placeholders, which aren't functional and result in the behavior you're seeing.
Defining Imports One-by-One
You can create an imports object like this, where each function is explicitly defined:
const imports = {
a: {
a: () => console.log("Function 'a.a' called"),
b: () => console.log("Function 'a.b' called"),
c: () => console.log("Function 'a.c' called"),
d: () => console.log("Function 'a.d' called"),
e: () => console.log("Function 'a.e' called"),
f: () => console.log("Function 'a.f' called"),
g: () => console.log("Function 'a.g' called"),
h: () => console.log("Function 'a.h' called"),
i: () => console.log("Function 'a.i' called"),
j: () => console.log("Function 'a.j' called"),
k: () => console.log("Function 'a.k' called"),
l: () => console.log("Function 'a.l' called"),
m: () => console.log("Function 'a.m' called"),
n: () => console.log("Function 'a.n' called"),
o: () => console.log("Function 'a.o' called"),
p: () => console.log("Function 'a.p' called"),
q: () => console.log("Function 'a.q' called"),
r: () => console.log("Function 'a.r' called"),
s: () => console.log("Function 'a.s' called"),
t: () => console.log("Function 'a.t' called"),
u: () => console.log("Function 'a.u' called"),
v: () => console.log("Function 'a.v' called"),
w: () => console.log("Function 'a.w' called"),
x: () => console.log("Function 'a.x' called"),
y: () => console.log("Function 'a.y' called"),
z: () => console.log("Function 'a.z' called"),
A: () => console.log("Function 'a.A' called"),
B: () => console.log("Function 'a.B' called"),
C: () => console.log("Function 'a.C' called"),
D: () => console.log("Function 'a.D' called"),
E: () => console.log("Function 'a.E' called"),
F: () => console.log("Function 'a.F' called"),
G: () => console.log("Function 'a.G' called"),
H: () => console.log("Function 'a.H' called"),
I: () => console.log("Function 'a.I' called"),
J: () => console.log("Function 'a.J' called"),
K: () => console.log("Function 'a.K' called"),
L: () => console.log("Function 'a.L' called"),
M: () => console.log("Function 'a.M' called"),
N: () => console.log("Function 'a.N' called"),
O: () => console.log("Function 'a.O' called"),
P: () => console.log("Function 'a.P' called"),
Q: () => console.log("Function 'a.Q' called"),
R: () => console.log("Function 'a.R' called"),
S: () => console.log("Function 'a.S' called"),
T: () => console.log("Function 'a.T' called"),
U: () => console.log("Function 'a.U' called"),
V: () => console.log("Function 'a.V' called"),
W: () => console.log("Function 'a.W' called"),
X: () => console.log("Function 'a.X' called"),
Y: () => console.log("Function 'a.Y' called"),
Z: () => console.log("Function 'a.Z' called"),
: () => console.log("Function 'a.' called"),
$: () => console.log("Function 'a.$' called"),
aa: () => console.log("Function 'a.aa' called"),
ba: () => console.log("Function 'a.ba' called"),
ca: () => console.log("Function 'a.ca' called"),
da: () => console.log("Function 'a.da' called"),
ea: () => console.log("Function 'a.ea' called"),
fa: () => console.log("Function 'a.fa' called"),
ga: () => console.log("Function 'a.ga' called"),
ha: () => console.log("Function 'a.ha' called"),
ia: () => console.log("Function 'a.ia' called"),
ja: () => console.log("Function 'a.ja' called"),
ka: () => console.log("Function 'a.ka' called"),
la: () => console.log("Function 'a.la' called"),
ma: () => console.log("Function 'a.ma' called"),
na: () => console.log("Function 'a.na' called"),
oa: () => console.log("Function 'a.oa' called"),
pa: () => console.log("Function 'a.pa' called"),
qa: () => console.log("Function 'a.qa' called"),
ra: () => console.log("Function 'a.ra' called"),
sa: () => console.log("Function 'a.sa' called"),
ta: () => console.log("Function 'a.ta' called"),
ua: () => console.log("Function 'a.ua' called"),
va: () => console.log("Function 'a.va' called"),
wa: () => console.log("Function 'a.wa' called"),
xa: () => console.log("Function 'a.xa' called"),
ya: () => console.log("Function 'a.ya' called"),
za: () => console.log("Function 'a.za' called"),
Aa: () => console.log("Function 'a.Aa' called"),
Ba: () => console.log("Function 'a.Ba' called"),
Ca: () => console.log("Function 'a.Ca' called"),
Da: () => console.log("Function 'a.Da' called"),
Ea: () => console.log("Function 'a.Ea' called"),
Fa: () => console.log("Function 'a.Fa' called"),
Ga: () => console.log("Function 'a.Ga' called"),
Ha: () => console.log("Function 'a.Ha' called"),
Ia: () => console.log("Function 'a.Ia' called"),
Ja: () => console.log("Function 'a.Ja' called"),
Ka: () => console.log("Function 'a.Ka' called"),
La: () => console.log("Function 'a.La' called"),
Ma: () => console.log("Function 'a.Ma' called"),
Na: () => console.log("Function 'a.Na' called"),
Oa: () => console.log("Function 'a.Oa' called"),
Pa: () => console.log("Function 'a.Pa' called"),
Qa: () => console.log("Function 'a.Qa' called"),
Ra: () => console.log("Function 'a.Ra' called"),
Sa: () => console.log("Function 'a.Sa' called"),
Ta: () => console.log("Function 'a.Ta' called"),
Ua: () => console.log("Function 'a.Ua' called"),
Va: () => console.log("Function 'a.Va' called"),
Wa: () => console.log("Function 'a.Wa' called"),
Xa: () => console.log("Function 'a.Xa' called"),
Ya: () => console.log("Function 'a.Ya' called"),
Za: () => console.log("Function 'a.Za' called"),
_a: () => console.log("Function 'a._a' called"),
$a: () => console.log("Function 'a.$a' called"),
ab: () => console.log("Function 'a.ab' called"),
bb: () => console.log("Function 'a.bb' called"),
cb: () => console.log("Function 'a.cb' called"),
db: () => console.log("Function 'a.db' called"),
eb: () => console.log("Function 'a.eb' called"),
fb: () => console.log("Function 'a.fb' called"),
gb: () => console.log("Function 'a.gb' called"),
hb: () => console.log("Function 'a.hb' called"),
ib: () => console.log("Function 'a.ib' called"),
jb: () => console.log("Function 'a.jb' called"),
kb: () => console.log("Function 'a.kb' called"),
lb: () => console.log("Function 'a.lb' called"),
mb: () => console.log("Function 'a.mb' called"),
nb: () => console.log("Function 'a.nb' called"),
ob: () => console.log("Function 'a.ob' called"),
pb: () => console.log("Function 'a.pb' called"),
}
};
The WASM file was converted to WAT and then analyzed to figure out the imports, it seems like the import functions and their structure are now correctly defined in wrapper.js. Given that you're still seeing a blank screen, the issue now lies in how the WebAssembly exports are being utilized in your HTML/JavaScript files.
image
Root Cause
The issue seems to be that your WebAssembly module (wrapper.wasm) does not include the _initialize or render functions, which are expected by the wrapper.js script. These functions are typically used to initialize the module and render the WebGL scene.
image
Check for _initialize and render. If they are missing, you need to add them to your source code (e.g., Rust, C++, or another language used to generate the WebAssembly module).

@kblaschke
Copy link
Member

kblaschke commented Dec 26, 2024

That's a long post, some of it basically documenting your journey to properly check out and build libprojectM with emscripten (e.g. checking out the projectm-eval submodule).

What I can't see in the screenshots and textual information is how you did wrap the projectM library and provide the functionality via WASM.

My guess is that you didn't do that, e.g. you just compiled libprojectM to wasm. This is fine, but will not work in its own, e.g. provide a working JS-to-WASM interface, as libprojectM only provides a C API. That said, it doesn't provide any render, initialize or main() function at all, as libprojectM is simply a library for use with other appplications - and as such, it doesn't work as a standalone WASM package you can run - the same is true for any other platform.

There are two ways this would work:

  1. Write a WASM application in C/C++ that initializes and uses libprojectM.
  2. Write a wrapper in C/C++ that exposes libprojectM's C API via WASM to JS.

Depending on your use case, both options can be viable. The first is easier to intergrate, as everything happen inside WASM and you don't need to bother too much about glueing the C/C++ code to JS. The second option would be the better one if you prefer to control everything from JS, including providing audio data and controlling projectM settings.

We currently only provide a minimalistic emscripten example which implements option 1, but there is no WASM glue/shim for libprojectM yet that makes the library API available to JS. If you're interested in writing one, that'd be great!

I hope this helps to clear some of the confusion.

@kblaschke kblaschke changed the title [REQUEST] [REQUEST] Building libprojectM for WASM/emscripten Dec 26, 2024
@kblaschke kblaschke added emscripten Anything related to building libprojectM for WASM/emscripten and removed triage labels Dec 26, 2024
@D0rk23
Copy link
Author

D0rk23 commented Dec 28, 2024

Hey @kblashske, !

Thank you so much for the valuable information! Honestly, I had no idea what I was doing I'm a system administrator not a developer but have enough experience to debug and use AI to build. - and was just hoping to figure things out as I went. Your insights really helped clarify things, and I appreciate it. Running this through AI seems like a great approach, and I plan to explore that further.

I spent some time working on a personal project, but after reading your comments, I think I'll loop back to this one and give it another shot. I’d really like to become a contributor and help out wherever I can. Have you considered running this through AI as well?

Sorry for the sloppy thread I was just trying to be informative but then I couldn't keep up with the notes. Do you have someone that would work with me directly for pay of course? to help get this going the web version of this?

Started something I can call my own. Maybe I'll be able to get it going no idea just like to explorer.
**
image
**
image

+=============+
ok back to projectm;
Thanks for sharing this informative insight! Here's a summary of the current situation and next steps:

Key Points:
libprojectM is a library, not a standalone application.

It doesn't provide render, initialize, or main() functions.
The library is designed to be embedded within other applications.

Current Issue:

You've compiled libprojectM to WASM, but since it lacks the aforementioned entry points or bindings, it doesn't expose a usable interface for JavaScript (JS).
Two Options to Make libprojectM Work:

Option 1: Write a WASM application in C/C++ that uses libprojectM.
You would write the necessary initialize, render, or other functions that make use of libprojectM.
These functions can be exported to WASM.
This option is better for self-contained WASM applications.
(I will try and get this done soon. Sounds like this is where we are at. Ill post my code here to share.)

Option 2: Write a C/C++ wrapper that exposes libprojectM's C API to JavaScript.
This option exposes functions from libprojectM to JavaScript directly, enabling you to call its API from your wrapper.js.
It requires "glue" code to bridge the C API with JavaScript.
Recommended Steps:

  1. Choose Your Path:
    If you want a self-contained WASM module that works independently of JavaScript, choose Option 1.
    If you want JavaScript control over the functionality (e.g., feeding audio data, changing settings), choose Option 2.
  2. Implement the Chosen Option:
    Option 1 (Standalone WASM Application):
    Create a C/C++ file that initializes and uses libprojectM.
    For example, the application could load an audio file, process it with libprojectM, and render visuals.
    Compile this file to WASM using Emscripten.
    Option 2 (JS-to-WASM Interface):
    Write a C/C++ wrapper that exposes the functions of libprojectM to JavaScript using Emscripten's EMSCRIPTEN_KEEPALIVE macros.
    (I'm going to also attempt method.)
    +=============+
    also
    One thing I wanted to explore further (or maybe have AI analyze) is improving transitions and figuring out why things occasionally get stuck. Do you know what might cause that?

+===+
After a few hours I made a traingle reactive
image

@revmischa
Copy link
Collaborator

Yeah I see that my example emscripten app is now 10 years old, which is crazy https://github.com/projectM-visualizer/examples-emscripten/tree/master

Another option is to build it with rust instead of C++ if that suits you. Rust goes pretty well with wasm. I made a basic rust frontend using SDL3 which you can find on our github.

@D0rk23
Copy link
Author

D0rk23 commented Dec 29, 2024

Oh, wow Revmischa cool link man had no idea thank you!
TIME FLYS !
Exploring Music Visualization and Custom ProjectM-Inspired Work
🎉 Update:
Got some stuff to work! Check out this video for a peek at my progress. In the description, I’ve shared the details of the tools and technologies I’m using to create my custom music visualizer. I’m still in the learning phase, figuring out how to apply everything effectively, but it’s been such an exciting journey.

💡 Shoutout:
Big thanks to Revmisha for dropping by and commenting! Your support is appreciated more than you know. Also, a fun side note: I noticed some AI nudging me towards exploring RUST for this—interesting idea, and I might give it a shot in the future!

❤️ ProjectM Love:
I’ve been a huge fan of ProjectM for years now, and this project is my tribute to everything I’ve loved about it. Honestly, you can check out my channel to see how deep my passion for music visualization runs.

🙋 Looking for connections:
If you know anyone who’s into this kind of work or does side projects in the field, I’d love to connect! Collaboration and feedback are always welcome, and I’m eager to learn from others in this space.

🛠️ Future Plans:
The options I’m working with don’t seem too hard to implement, and I can’t wait to clean up the code and share it here on GitHub. If I deliver something worthwhile, I’d be honored to be added as a contributor.

Thanks for being part of this exciting journey—more updates coming soon!
Currently looking into Shader programming and dynamic transformations.

@revmischa
Copy link
Collaborator

Cool, join the projectm discord

@D0rk23
Copy link
Author

D0rk23 commented Dec 29, 2024

ok i will tomorrow got some more done check it out
https://www.youtube.com/watch?v=6vFGLVNTjSE
its actaully a bit bigger than what in the video i didnt realize -
image

@kblaschke
Copy link
Member

kblaschke commented Dec 29, 2024

As a word of caution regarding AI/LLMs:

Take whatever it tells you with a huge grain of salt, as it's only as "intelligent" as the data it has been fed with. It's still just a language model (a huge database with weighed word relations) which reassembles knows texts into a new one depending on a query, so there's absolutely no guarantee that the result is correct and will work as intended.

It's nice to use if you have a very simple problem/question which was already asked hundreds of times, as then the LLM will have a good set of correct answers, but on the other hand, the LLM will certainly also contain all the bad suggestions or even the code posted in the question, e.g. if StackOverflow pages were used. This will end up as a mix of correct and incorrect answers in the LLM, as it it not an "intelligence" which can distinguish between good and bad data.

I'd suggest asking only easy questions to the LLM and use the answer to research a proper how-to, tutorial or find the required reference. If in doubt, better ask real people like us, as experience and real humand minds are (still) a lot better than those wannabe AIs.

@D0rk23
Copy link
Author

D0rk23 commented Dec 29, 2024

Thanks, Kblaschke—ProjectM is truly a masterpiece, and I genuinely appreciate your insights.

I’ve always loved tinkering and learning new things, and AI has enabled me to tackle complex tasks I never thought I’d be capable of handling. It’s been an incredible journey! Honestly, I wasn’t familiar with the term “LLMs” until now, but I’ll definitely dive deeper into researching them—thank you for bringing them up.

It’s fascinating to think about how AI might evaluate human-made projects. I feel like it works both ways—it not only helps create but also offers insights that might otherwise be overlooked.

Recently, I’ve worked on some exciting projects for DotNetNuke and developed around 40 WordPress plugins, all without formal programming knowledge. AI has opened up a world of possibilities, and I’m excited to see just how far I can push this project.

Thanks again, man. I’ll hop on Discord soon to chat more—thank you both for being so welcoming! You all are incredibly kind here.

Before this, I was trying to implement FFT functionality in Blender, but it didn’t seem feasible. That led me to explore Touch Designer, and eventually, I found myself here after creating the Burn Churn WordPress plugin. Funny how these projects take you on such unexpected journeys!

@revmischa
Copy link
Collaborator

Oh cool what wordpress plugins did you make?

@D0rk23
Copy link
Author

D0rk23 commented Dec 30, 2024

Hi Revmischa
Just got the selector setup
image
image
setup git repo for this thinking about making public -

https://azmanagedit.net/product/wordpress-butterchurn-audio-visualizer/
Heres the list;
https://azmanagedit.net/services/category-wordpress-plugin-development/

this is a custom visualizer;
https://azmanagedit.net/product/wordpress-audio-visualizer/
check out the templates;
image
some are 3d so barspectrum you can make move it has mouse control

now that i step back for a sec im like dam butterchurns looking pretty good -

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
emscripten Anything related to building libprojectM for WASM/emscripten question
Projects
None yet
Development

No branches or pull requests

3 participants