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

Improve Audio Data Processing and Spectrum Analyzer #745

Merged

Conversation

kblaschke
Copy link
Member

Reimplemented audio data processing to closely match Milkdrop's algorithms and resulting sample/spectrum values.

proejctM's previous implementation was very simplistic, and thus resulted in sample/beat detection values which weren't even close to what Milkdrop passes to presets. This PR changes/fixes the following audio-related issues:

  • Waveform scaling is now using the same value range as Milkdrop, which is a floating-point representation of an 8-bit signed sample format. Milkdrop only gets 8-bit samples from Winamp, so the values are always whole numbers. projectM can also process floating-point samples. These are scaled to the same range (-128.0 to +127.0), but also have their decimals preserved. Waveform data scaling in the custom/default wave drawing code has been restored to Milkdrop's values.
  • The spectrum analyzer is now a (modernized) copy of Milkdrop's FFT class. It also smoothes and equalized the spectrum a bit to remove noise. Now spectrum-based custom waveforms draw properly.
  • The bass/mid/treb and attenuated beat-detection values are now calculated as relative values to the previous frame(s), as in Milkdrop. They're no longer absolute sums of the spectrum, but a difference value revolving around 1.0.
  • Waveforms are now best-match aligned to the previous frame, resulting in a more stable, less jaggy waveform rendering as the wave doesn't jump randomly around as much as before.

Fixes issue #708.

@kblaschke kblaschke added this to the 4.1 milestone Nov 16, 2023
@kblaschke kblaschke force-pushed the bugfix/fix-spectrum-analyzer branch 2 times, most recently from 89fbe8e to 9f411fe Compare November 16, 2023 18:50
@kblaschke kblaschke linked an issue Nov 16, 2023 that may be closed by this pull request
Comment on lines +94 to +96
* You might want to slightly damp (blur) the input if your signal isn't
* of a very high quality, to reduce high-frequency noise that would
* otherwise show up in the output.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any audio we expect people to feed in that will not be of "a very high quality"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know, probably not relevant anymore today. Most of the Doxygen text in this class is just a 1:1 copy of the comments in Milkdrop's code, I didn't change it for "historical reasons". 😁

@@ -0,0 +1,55 @@
/**
* @file WaveformAligner.hpp
* @brief Mip-based waveform alignment algorithm
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doc is duplicated

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah... Will just keep the class doc, and only add a "brief" description for the file.

/**
* @brief Calculates equalization factors for each frequency domain.
*
* @param equalize If false, all factors will be set to 1, otherwise will calculate a frequency-based multiplier.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the purpose of the equalizer?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I understand of the code, it adds a log-based scaling curve over the frequencies. I don't know the reasoning behind this, so I just kept the code as-is to match Milkdrop's spectrum analyzer results.

The equalizer curve which is applied to the frequency bands looks like this:
image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The envelope table, which is also used for scaling the input waveform samples (basically using more of the waveform's center than the edges), looks like this:
image

Copy link
Collaborator

@revmischa revmischa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sweet

Removed the previous FFT algorithm, now using a modernized version of the original Milkdrop FFT transform which also has both an equalizer and frequency envelope, making it slightly more sophisticated.

Modernization mainly included replacing raw pointer arrays with std::vector and using STL types/functions for the calculation, specifically std::complex as the FFT heavily uses these numbers. This makes the code more compact and readable.

Manually tested both original and modernized versions of the class to test if the algorithm still returns the exact same results, which is the case.
Consolidated audio processing code into the PCM class, removing the BeatDetect class in the process. Beat detection now uses the same algorithm as Milkdrop, passing the proper relative bass/mid/treb values to presets. Makes many presets look less jumpy/flickering, as the values are now (smoothly) alternating around 1.0.

Updating frame audio is now done in a function that must specifically be called. Any subsequent calls to GetFrameAudioData() will then return the exact same copy of the audio data. As of now with the exception that new waveform data may be passed in via a separate thread, which will then be returned and might not match the spectrum data. Will fix that in a later commit.
Also consolidated the waveform sample count constant to keep it aligned over all classes.
The "+1" somehow disappeared at some point...
Directly passing references to the affected members is easier to read in the main UpdateFrameAudioData() method.
@kblaschke kblaschke merged commit 9c68339 into projectM-visualizer:master Nov 25, 2023
9 checks passed
@kblaschke kblaschke deleted the bugfix/fix-spectrum-analyzer branch November 25, 2023 02:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

Beat detection values (bass, mid, treb + _att variants) are too high.
3 participants