Search code examples
androidc++audiosuperpowered

Android SuperPowered SDK Audio - Frequency Domain example - memset frequency manipulation


I'm trying to understand the Superpowered SDK, but new to both Android and C++, as well as audio signals. I have Frequency Domain example from here: https://github.com/superpoweredSDK/Low-Latency-Android-Audio-iOS-Audio-Engine/tree/master/Examples_Android/FrequencyDomain

running on my Nexus 5X. In the FrequencyDomain.cpp file:

static SuperpoweredFrequencyDomain *frequencyDomain;
static float *magnitudeLeft, *magnitudeRight, *phaseLeft, *phaseRight, *fifoOutput, *inputBufferFloat;
static int fifoOutputFirstSample, fifoOutputLastSample, stepSize, fifoCapacity;

#define FFT_LOG_SIZE 11 // 2^11 = 2048

static bool audioProcessing(void * __unused clientdata, short int *audioInputOutput, int numberOfSamples, int __unused samplerate) {
SuperpoweredShortIntToFloat(audioInputOutput, inputBufferFloat, (unsigned int)numberOfSamples); // Converting the 16-bit integer samples to 32-bit floating point.
frequencyDomain->addInput(inputBufferFloat, numberOfSamples); // Input goes to the frequency domain.

// In the frequency domain we are working with 1024 magnitudes and phases for every channel (left, right), if the fft size is 2048.
while (frequencyDomain->timeDomainToFrequencyDomain(magnitudeLeft, magnitudeRight, phaseLeft, phaseRight)) {
    // You can work with frequency domain data from this point.


 // This is just a quick example: we remove the magnitude of the first 20 bins, meaning total bass cut between 0-430 Hz.
    memset(magnitudeLeft, 0, 80);
    memset(magnitudeRight, 0, 80);

I understand how the first 20 bins is 0-430 Hz from here: How do I obtain the frequencies of each value in an FFT?

but I don't understand the value of 80 in memset... being 4*20, is it 4 bytes for a float * 20 bins? Does magnitudeLeft hold data for all the frequencies? How would I then remove, for example, 10 bins of frequencies from the middle or the highest from the end? Thank you!


Solution

  • Every value in magnitudeLeft and magnitudeRight is a float, which is 32-bits, 4 bytes.

    memset takes a number of bytes parameter, so 20 bins * 4 bytes = 80 bytes. memset clears the first 20 bins this way.

    Both magnitudeLeft and magnitudeRight represents the full frequency range with 1024 floats. Their size is always FFT size divided by two, so 2048 / 2 in the example.

    Removing from the middle and the top looks something like:

    memset(&magnitudeLeft[index_of_first_bin_to_remove], 0, number_of_bins * sizeof(float));

    Note that the first parameter is not multiplied with sizeof(float), because the compiler knows that magnitudeLeft is a float, so it will automatically input the correct address.