Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

First Look at projectM

Roar. Bears, as I look at how I can draw my singing videos, I think it would be useful to look at audio visualisation software, or music players that has visualisation in them. Then I found one example project called projectM1. It seems to implement some aspects of visualisations in Winamp, which is a famous visualisation set I know. Its source code should be helpful in learning the tricks in them.

The two questions to answer are:

The GitHub repo linked from above only contained development libraries and a simple SDL2 programme for testing visuals, but the most important bits - the code that extracts features from audio and draws them - are all in there.

Features from Audio

Features used for visualisation include

These are stored in a FrameAudioData object. When new samples come in from the audio input (which projectM does not handle and must be converted to floating point (float) or integer values (uint8 or int16) before calling PCM::Add), the waveform and spectrum in the PCM object get updated. The data class containing these is the FrameAudioData class, but instances are created only when PCM::GetFrameAudioData is called. This is also when the base, mid, treb and volume values (both versions) are calculated.

The features used are typical of what I use in visualisation. But projectM made their own adjustments in every of these to make the visualisation smooth.

Drawing the Features

The centre of a projectM visualisation is a preset file. The repo includes some simple ones in the presets/tests folder, but you never know how creative this file can get until you see the idle preset in the IdlePreset class3!

ProjectM parses the preset file and creates a MilkdropPreset object, which initialises, amongst other things, frame buffers, static shaders (for warping and composite effects), meshes for custom waveforms and shapes, and most importantly, a PresetState object.

A PresetState object holds preset variables, audio data, initialisation, per-frame and per-pixel shader code (per-point for custom waveforms) and shader code for other things. If you know OpenGL, you might think of per-frame updates as uniform updates, per-pixel shaders as fragment shaders and per-point shaders as vertex shaders. In projectM, almost anything custom can have a per-frame context.

So where are the audio data used? From what I found, at these places at least:

Conclusion

I was slightly disappointed after reading the source code as I expected projectM to have used much more advanced signal processing techniques than waveform, spectrum and beats. But at the same time, I deeply admire how much thought its developers put into implementing the details in the calculation of these data to make the visualisation look smooth.

I was also surprised how these simple features can create such flashy visuals in their demo playlist4. If the data source is not that different, then it would be the drawing process that made all the difference. Just what kind of maths were in the shaders that created those? Studying the idle preset and the built-in waveforms can be a useful exercise.

ProjectM lacked one feature that I want in my videos: the lyric (or pre-recorded timed sequence) display. This is another piece of data needed to make the videos I want. The way projectM separates the feature computation from drawing code, and manages double buffer to implement frame warping will both be helpful for such development.

References
  1. GitHub - projectM-visualizer/projectm: projectM - Cross-platform Music Visualization Library. Open-source and Milkdrop-compatible. · GitHub. (n.d.). Retrieved May 3, 2026, from https://github.com/projectM-visualizer/projectm
  2. NOC17 EE09. (2017). Week8-Lecture21.1. https://www.youtube.com/watch?v=0Jh0Xnm0L-8
  3. projectM-visualizer. (n.d.). projectm/src/libprojectM/MilkdropPreset/IdlePreset.cpp at v4.1.6 · projectM-visualizer/projectm. In GitHub. Retrieved May 3, 2026, from https://github.com/projectM-visualizer/projectm/blob/v4.1.6/src/libprojectM/MilkdropPreset/IdlePreset.cpp
  4. cybermischa. (2025). ProjectM Gstreamer offline render test 9. https://www.youtube.com/watch?v=jJmLQGhYWys