Files
sound-scope/spectrum_buffer_manager_class.cpp
2026-03-27 10:26:47 -07:00

138 lines
4.0 KiB
C++

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <unistd.h>
#include <iostream>
#include <chrono>
#include <pulse/simple.h>
#include <pulse/error.h>
#include <fftw3.h>
#include "scope.h"
spectrum_buffer_manager_class::spectrum_buffer_manager_class()
{
my_formatted_spectrum_buffer = NULL;
}
spectrum_buffer_manager_class::~spectrum_buffer_manager_class()
{
if (my_formatted_spectrum_buffer != NULL)
{
free(my_formatted_spectrum_buffer);
}
}
int spectrum_buffer_manager_class::initialize_spectrum(int horizontal_size,
int vertical_size, Sint16 *main_buffer)
{
// This is the formatted buffer that will be fed to the display
my_formatted_spectrum_buffer = (int *)malloc ((sizeof(int) * AUDIO_BUFFER_SIZE));
if (my_formatted_spectrum_buffer == NULL)
{
printf ("cannot allocate formatted spectrum spectrum buffer\n");
perror ("error is");
return 1;
}
//Allocate output fftw buffer
if ((output_fftw = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)
* FFT_BUFFER_SIZE * 2)) == NULL)
{
printf ("cannot allocate fftw output buffer\n");
perror ("error is");
return 1;
}
//Allocate input fftw buffer
if ((input_fftw = (double*) fftw_malloc(sizeof(double) * FFT_BUFFER_SIZE)) == NULL)
{
printf ("cannot allocate fftw input buffer\n");
perror ("error is");
return 1;
}
// Now lets attempt to perform an fftw plan
if ((my_fftw_plan = fftw_plan_dft_r2c_1d(FFT_BUFFER_SIZE, input_fftw,
output_fftw, FFTW_MEASURE)) == NULL)
{
printf ("cannot fftw plan");
perror ("error is");
return 1;
}
// my_read_spectrum_index is which chunk we will put the read buffer into
my_read_spectrum_index = 0;
// index to read the individual elements into the fftw input buffer
read_buffer_counter = 0;
// my_output_fft_buffer_index is used to flip output buffer
// members all to negative for display purposes
my_output_fft_buffer_index = 0;
my_spectrum_horizontal_size = horizontal_size;
my_spectrum_vertical_size = vertical_size;
// The main buffer is the read buffer from main buffer read
my_main_buffer = main_buffer;
return 0;
}
// Returns address for formatted fft buffer for ready to display
// Return NULL for waiting for buffer fill
int *spectrum_buffer_manager_class::process_spectrum()
{
// Fill the fftw input array
// Fill in section corresponging to the current read_buffer_counter
input_fftw_write_position = input_fftw + my_read_spectrum_index;
for (read_buffer_counter = 0; read_buffer_counter < READ_BUFFER_SIZE;
read_buffer_counter += 1)
{
main_buffer_hold = (Sint16)(*(my_main_buffer + read_buffer_counter) * SPECTRUM_VOLUME);
*(input_fftw_write_position + read_buffer_counter) = (double)main_buffer_hold;
}
/* prep for next time */
my_read_spectrum_index += 1;
// Are we still working on filling this buffer?
if (my_read_spectrum_index < FFT_NUMBER_READ_BUFFERS)
{
// Lets wait
return NULL;
}
else
// Done filling up fft buffer - lets process
{
// First, reset the spectrum index to 0
my_read_spectrum_index = 0;
// Perform the fft
fftw_execute(my_fftw_plan);
// Now grab the real part of the complex output
for (my_output_fft_buffer_index = 0;
my_output_fft_buffer_index < my_spectrum_horizontal_size;
my_output_fft_buffer_index += 1)
{
*(my_formatted_spectrum_buffer + my_output_fft_buffer_index)
= (int)(output_fftw[(FFT_START_BUCKET +
(my_output_fft_buffer_index))][0] * SPECTRUM_VOLUME);
if (*(my_formatted_spectrum_buffer + my_output_fft_buffer_index) > 0 )
{
// Flip any positive values to negative because negative causes location
// to go up on the sdl coordinate system
*(my_formatted_spectrum_buffer + my_output_fft_buffer_index) =
- *(my_formatted_spectrum_buffer + my_output_fft_buffer_index);
}
}
}
return my_formatted_spectrum_buffer;
}