Search code examples
audiorandomsoundcloudspectrumvisualizer

An Algorithm for producing fake audio visualizer


Does anybody knows an algorithm for making a random series of numbers (like 100 java-byte (>=-127 & <= 127) ) which when are drawn as a bar chart, would be similar to a regular audio spectrum, like those SoundCloud ones?

I'm trying to write one, it has multiple Random and Sinus calculations, but the result is very ugly, it's something between a sinus wave and an old toothbrush. I would be very thankful if you code direct me to a one which is aesthetically convincing

An algorithm with an explanation (and/or picture) is fine. A pseudocode would be very nice of you. An actual JAVA code is bonus. :D

Edit:

This is the code I'm using right now. It's convoluted but I'm basically adding a random deviation to a sinus wave with random amplitude (which I'm not sure if it was a good idea).

private static final int FREQ = 7;
private static final double DEG_TO_RAD = Math.PI / 180;
private static final int MAX_AMPLITUDE = 127;
private static final float DEVIATION = 0.1f; // 10 percent is maximum deviation

private void makeSinusoidRandomBytes() {
    byte[] bytes = new byte[AUDIO_VISUALIZER_DENSITY];
    for (int i = 0; i < AUDIO_VISUALIZER_DENSITY; i++) {

        int amplitude = random.nextInt(MAX_AMPLITUDE) - MAX_AMPLITUDE/2;
        byte dev = (byte) (random.nextInt((int) Math.max(Math.abs(2 * DEVIATION * amplitude), 1))
                - Math.abs(DEVIATION * amplitude));
        bytes[i] = (byte) (Math.sin(i * FREQ * DEG_TO_RAD) * amplitude - dev);
    }
    this.bytes = bytes;
}

Solution

  • A real soundwave is actually a combination of sine waves of different frequencies and amplitudes added together, not random deviations from a sine wave. The difficult part will be to choose a combination of wave amplitudes and frequencies that will produce the output that you will subjectively like! However, most sound waves have a base frequency and then a number of overtones which "fit into" that wavelength - for example it might have an overtone at 3/2 * the base frequency and at amplitude of 2/3 the base frequency. By combining these overtones and scaling the resulting waveform to the -127 - +127 range, you'll get an actual soundwave.

    The following code is C#, but close enough to Java to give you an idea. It's from a game, where I needed to combine many sine waves together to create various types of oscillating effects:

         /// <summary>
        /// Return a value between 0 and 1 based on a sine-wave oscillating with a given combination of periods at a given point in time  
        /// </summary>
        /// <param name="time">time to get wave value at</param>
        /// <param name="periods">lengths of waves</param>
        /// <returns>height of wave</returns>
        public static float MultiPulse(float time, params float[] periods)
        {
            float c = 0;
            foreach (float p in periods)
            {
                float cp = (MathHelper.Pi / p) * time;
                float s = ((float)Math.Sin(cp) + 1) / 2;
                c += s / periods.Length;
            }
            return c;
        }
    

    You probably want to modify that to allow you to specify different amplitudes as well as periods for the waves you are combining.

    By combining many widely varying amplitudes and periods (frequencies) you should by trial and error be able to get something convincing.