138 lines
4.0 KiB
C++
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;
|
|
}
|
|
|