1

Currently, I am trying to split a buffered audio signal (buffer size = 1024 samples), read in real-time from ALSA on Linux, into several bands in order to output a bunch of numeric values of their levels (calculated as RMS values). So far, I have the following code:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>

#define BUFFER_SIZE 1024

// Random numbers generated with the command
// python -c 'import random; ran = random.Random(); print([ran.randint(0, 65536) for _ in range(1024)])'
// for testing purposes
// Ommited from StackExchange post for length reasons
short buffer[BUFFER_SIZE] = { 57054, 11874, ..., 22716, 57055 };

int main(int argc, char** argv) {
    long buffer_sum;
    for (int i = 0; i < BUFFER_SIZE; i++) {
        buffer_sum += buffer[i]*buffer[i];
    }

    double rms = sqrt(buffer_sum/BUFFER_SIZE);
    double Pvalue = rms * 0.45255;
    double dB = 20 * log10(Pvalue);

    printf("%lf\n", dB);

    return 0;
}

However, this code can only output the average gain of the entire frequency spectrum. Essentially, what I am trying to achieve is an effect like you can see in this video, but with raw numbers being output (printed to stdout as a simple comma-separated list) instead of a graphical visualization. What would be a good way to go about this? To be clear, the primary goal is to be a basic visualizer, so the filter doesn't need to be very accurate. Phase issues and such aren't very important here. It should, however, be fast to calculate in real time. The goal is not to generate a graph ahead of time, like what the app Spek does. This is also part of the reason why I chose C.

PS: Please note that I am very new to both DSP and the C programming language, as well as not being particularly great at math.

SkyyySi
  • 53
  • 5
  • 1
    Note that `long buffer_sum;` is unitialized. Also `buffer_sum/BUFFER_SIZE` will be integer division, if that's what you want. And the array values are `unsigned short` not `short` if you intended 16-bits. – Weather Vane Jul 15 '22 at 13:26
  • 1
    @SkyyySi, code suffers from overflow issues: Perahps: `unsigned short buffer[BUFFER_SIZE] ... unsigned long long buffer_sum = 0; ... buffer_sum += (unsigned) buffer[i] * buffer[i];`. – chux - Reinstate Monica Jul 15 '22 at 13:35
  • 2
    You are probably looking for something like a *[fast Fourier transform](https://en.wikipedia.org/wiki/Fast_Fourier_transform)*. Pick a chunk of audio data, do an FFT, ignore the phase and get just the amplitude, do some smoothing out to make the visualization nicer at your discretion. You will need to know complex numbers. – user253751 Jul 15 '22 at 14:12
  • @WeatherVane You're right, it would have to be an unsigned number to use these numbers. Although as far as I understand it, audio signals are normally signed, so the issue is more of a logical one where the numbers themselves should have a different range, not the array being of a different type. My mistake. And yes, I totally forgot to initialize the `buffer_sum` long. – SkyyySi Jul 15 '22 at 16:07
  • It depends on what you want by squaring the amplitude. If unsigned and `32768` represents `0` you'll have to make an offset. – Weather Vane Jul 15 '22 at 16:10
  • @user253751 From the bit I just read, it looks like FFT is what I'm looking for. Guess I'll just have to do a lot of reading up on math now first, because a lot of the concepts, including the Fourier transform and complex numbers, are completely foreign to me... – SkyyySi Jul 15 '22 at 16:11
  • 1
    @SkyyySi assuming you use a library to calculate the FFT, here's some info about interpreting the results: https://stackoverflow.com/questions/604453/analyze-audio-using-fast-fourier-transform – user253751 Jul 15 '22 at 16:50

0 Answers0