initial commit

This commit is contained in:
2026-03-27 10:26:47 -07:00
commit 5df346e342
38 changed files with 1687 additions and 0 deletions

51
CMakeLists.txt Normal file
View File

@@ -0,0 +1,51 @@
cmake_minimum_required (VERSION 3.22)
set (CMAKE_CXX_STANDARD 11)
cmake_policy(SET CMP0072 NEW)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
project (scope)
# SDL2
find_package(SDL2 REQUIRED)
# find_package(SDL_ttf REQUIRED)
# Pulse
find_path(PULSEAUDIO_INCLUDE_DIR
NAMES pulse/pulseaudio.h
DOC "The PulseAudio include directory"
)
find_library(PULSEAUDIO_LIBRARY
NAMES pulse
DOC "The PulseAudio library"
)
include_directories(${PULSEAUDIO_INCLUDE_DIRS})
include_directories(${SDL2_INCLUDE_DIRS})
# include_directories(${SDL_TTF_INCLUDE_DIRS})
message(STATUS "<<${SDL2_INCLUDE_DIRS}>>")
# message(STATUS "<<${OPENGL_INCLUDE_DIR}>>")
# Main Executable
add_definitions("-Wall -O0 -g")
#add_definitions("-Wall -Werror -O0 -g")
add_executable(scope main_buffer_manager_class.cpp audio_buffer_manager_class.cpp
spectrum_buffer_manager_class.cpp piano_process.cpp
main_class.cpp piano_class.cpp spectrum_class.cpp
audio_class.cpp scope.cpp)
target_include_directories(scope PUBLIC ${CMAKE_SOURCE_DIR}/src)
# Libraries
target_link_libraries(scope ${SDL2_LIBRARIES})
target_link_libraries(scope m /usr/lib/)
target_link_libraries(scope /usr/lib/x86_64-linux-gnu/libSDL2_ttf-2.0.so)
# target_link_libraries(scope ${SDL_TTF_LIBRARIES})
target_link_libraries(scope pulse-simple pulse)
target_link_libraries(scope fftw3)
message(STATUS "<<${SDL2_LIBRARIES}>>")

31
CMakeLists.txt.save Normal file
View File

@@ -0,0 +1,31 @@
cmake_minimum_required (VERSION 3.2)
set (CMAKE_CXX_STANDARD 11)
cmake_policy(SET CMP0072 NEW)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
project (attempt1)
# SDL2
find_package(SDL2 REQUIRED)
# find_package(OpenGL REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
# include_directories(${OPENGL_INCLUDE_DIR})
message(STATUS "<<${SDL2_INCLUDE_DIRS}>>")
# message(STATUS "<<${OPENGL_INCLUDE_DIR}>>")
# Main Executable
add_definitions("-Wall -O0 -g")
#add_definitions("-Wall -Werror -O0 -g")
add_executable(attempt1 attempt1.cpp)
target_include_directories(attempt1 PUBLIC ${CMAKE_SOURCE_DIR}/src)
# Libraries
target_link_libraries(attempt1 ${SDL2_LIBRARIES})
# target_link_libraries(attempt1 ${OPENGL_LIBRARIES})
message(STATUS "<<${SDL2_LIBRARIES}>>")
# message(STATUS "<<${OPENGL_LIBRARIES}>>")

31
CMakeLists.txt.testing Normal file
View File

@@ -0,0 +1,31 @@
cmake_minimum_required (VERSION 3.2)
set (CMAKE_CXX_STANDARD 11)
cmake_policy(SET CMP0072 NEW)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
project (mark1)
# SDL2
find_package(SDL2 REQUIRED)
# find_package(OpenGL REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
# include_directories(${OPENGL_INCLUDE_DIR})
message(STATUS "<<${SDL2_INCLUDE_DIRS}>>")
# message(STATUS "<<${OPENGL_INCLUDE_DIR}>>")
# Main Executable
add_definitions("-Wall -O0 -g")
#add_definitions("-Wall -Werror -O0 -g")
add_executable(mark1 mark1.cpp)
target_include_directories(mark1 PUBLIC ${CMAKE_SOURCE_DIR}/src)
# Libraries
target_link_libraries(mark1 ${SDL2_LIBRARIES})
# target_link_libraries(mark1 ${OPENGL_LIBRARIES})
message(STATUS "<<${SDL2_LIBRARIES}>>")
# message(STATUS "<<${OPENGL_LIBRARIES}>>")

View File

@@ -0,0 +1,58 @@
#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 "scope.h"
audio_buffer_manager_class::audio_buffer_manager_class()
{
my_formatted_audio_buffer = NULL;
}
audio_buffer_manager_class::~audio_buffer_manager_class()
{
if (my_formatted_audio_buffer != NULL)
{
free(my_formatted_audio_buffer);
}
}
int audio_buffer_manager_class::initialize_audio(int horizontal_size,
int vertical_size, Sint16 *main_buffer)
{
my_formatted_audio_buffer = (int *)malloc ((sizeof(int) * AUDIO_BUFFER_SIZE));
if (my_formatted_audio_buffer == NULL)
{
printf ("cannot allocate formatted audio audio buffer\n");
perror ("error is");
return 1;
}
my_audio_horizontal_size = horizontal_size;
my_audio_vertical_size = vertical_size;
my_main_buffer = main_buffer;
return 0;
}
int *audio_buffer_manager_class::process_audio()
{
my_read_audio_index = 0;
// Transform Sint16 to int for each element
for (my_read_audio_index = 0; my_read_audio_index < my_audio_horizontal_size;
my_read_audio_index += 1)
{
audio_holding = *(my_main_buffer + my_read_audio_index);
*(my_formatted_audio_buffer + my_read_audio_index) = (int)audio_holding;
}
return my_formatted_audio_buffer;
}

127
audio_class.cpp Normal file
View File

@@ -0,0 +1,127 @@
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>
#include <cmath>
#include <unistd.h>
#include <iostream>
#include <chrono>
#include "scope.h"
// Audio class method bodies
// Audio window
int audio_window_class::draw_trace(int *audio_data, int audio_data_size)
{
int audio_data_counter;
int *current_audio_data_value;
int *prev_audio_data_value;
int this_audio_data_size;
if (audio_data_size >= max_audio_trace_width)
{
this_audio_data_size = max_audio_trace_width;
}
else
{
this_audio_data_size = audio_data_size;
}
//printf("this size %d\n", this_audio_data_size);
//Clear the window
SDL_SetRenderDrawColor(renderer_for_audio, (Uint8)40, (Uint8)40, (Uint8)0, (Uint8)255);
SDL_RenderClear(renderer_for_audio);
// Render word Oscilloscope
SDL_RenderCopy(renderer_for_audio, texture_for_audio, NULL, &rect_for_audio);
// green trace
SDL_SetRenderDrawColor(renderer_for_audio, (Uint8)0, (Uint8)(255), (Uint8)0, (Uint8)255);
for (audio_data_counter = 1; audio_data_counter < this_audio_data_size; audio_data_counter += 1)
{
current_audio_data_value = audio_data + audio_data_counter;
prev_audio_data_value = audio_data + audio_data_counter - 1;
SDL_RenderDrawLine (renderer_for_audio, x_audio_window_trace_base + audio_data_counter -1,
y_audio_window_trace_base + *prev_audio_data_value,
x_audio_window_trace_base + audio_data_counter,
y_audio_window_trace_base + *current_audio_data_value);
}
SDL_RenderPresent(renderer_for_audio);
return 0;
}
int audio_window_class::get_max_audio_trace_width()
{
return max_audio_trace_width;
}
int audio_window_class::get_max_audio_trace_height()
{
return max_audio_trace_height;
}
audio_window_class::audio_window_class (int x_main_window_size, int y_main_window_size)
{
x_audio_window_position = 5;
y_audio_window_position = 5;
x_audio_window_size = ((int)(x_main_window_size / 2)) - 20;
y_audio_window_size = (((int)(y_main_window_size / 3)) * 2) - 10;
x_audio_window_trace_base = x_audio_window_position;
y_audio_window_trace_base = (int)(y_audio_window_size / 2) + y_audio_window_position;
max_audio_trace_width = x_audio_window_size;
max_audio_trace_height = y_audio_window_size;
if ((window_for_audio = SDL_CreateWindow("Oscilloscope",
x_audio_window_position, y_audio_window_position,
x_audio_window_size, y_audio_window_size,0)) == NULL) {
printf("error opening audio window SDL: %s\n", SDL_GetError());
exit (0);
}
printf("audio window: window_size %d x pos %d max trace width %d\n",
x_audio_window_size, x_audio_window_position, max_audio_trace_width);
SDL_SetWindowBordered(window_for_audio, SDL_FALSE);
if ((renderer_for_audio = SDL_CreateRenderer(window_for_audio, -1, 0)) == NULL) {
printf("error opening audio renderer SDL: %s\n", SDL_GetError());
exit (0);
}
if ((font_for_audio = TTF_OpenFont("/usr/share/fonts/truetype/freefont/FreeSans.ttf",
24)) == NULL) {
printf("error opening audio font SDL: %s\n", SDL_GetError());
exit (0);
}
color_for_audio = {255,255,255};
if ((surface_for_audio = TTF_RenderText_Solid(font_for_audio,
"OSCILLOSCOPE", color_for_audio)) == NULL) {
printf("error opening audio surface SDL: %s\n", SDL_GetError());
exit (0);
}
if ((texture_for_audio = SDL_CreateTextureFromSurface(renderer_for_audio,
surface_for_audio)) == NULL) {
printf("error opening audio texture SDL: %s\n", SDL_GetError());
exit (0);
}
rect_for_audio.x = x_audio_window_trace_base + ((int)(max_audio_trace_width/2) -
(int)(surface_for_audio->w / 2));
rect_for_audio.y = 20;
rect_for_audio.w = surface_for_audio->w;
rect_for_audio.h = surface_for_audio->h;
SDL_SetRenderDrawColor(renderer_for_audio, (Uint8)40, (Uint8)40, (Uint8)0, (Uint8)255);
SDL_RenderClear(renderer_for_audio);
SDL_RenderCopy(renderer_for_audio, texture_for_audio, NULL, &rect_for_audio);
SDL_RenderPresent(renderer_for_audio);
}

1
do_run.sh Executable file
View File

@@ -0,0 +1 @@
/home/maallyn/sound-scope/sdl2/fft/build/scope 1700 1000

BIN
keyboard-key-blank.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
keyboard-key1.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
keyboard-key10.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
keyboard-key11.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
keyboard-key12.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
keyboard-key2.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
keyboard-key3.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
keyboard-key4.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
keyboard-key5.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
keyboard-key6.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
keyboard-key7.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
keyboard-key8.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
keyboard-key9.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -0,0 +1,79 @@
#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 "scope.h"
// Pulse
static const pa_sample_spec my_pa_spec = {
.format = PA_SAMPLE_S16LE,
.rate = 44100,
.channels = 1
};
// audio buffer
main_buffer_manager_class::main_buffer_manager_class()
{
my_read_main_buffer = NULL;
}
main_buffer_manager_class::~main_buffer_manager_class()
{
if (my_read_main_buffer != NULL)
{
free(my_read_main_buffer);
}
}
Sint16 *main_buffer_manager_class::initial_preparation()
{
my_read_main_buffer = (Sint16 *)malloc ((sizeof(Sint16) * READ_BUFFER_SIZE));
if (my_read_main_buffer == NULL)
{
printf ("cannot allocate read buffer\n");
perror ("error is");
return NULL;
}
// Open pulse
pulse_s = pa_simple_new(NULL,"scope sound", PA_STREAM_RECORD, NULL, "record",
&my_pa_spec, NULL, NULL, &function_return);
if (pulse_s == NULL) {
printf("pa_simple_new() failed: %s\n", pa_strerror(function_return));
return NULL;
}
return my_read_main_buffer;
}
Sint16 *main_buffer_manager_class::read_main_buffer()
{
// grab the buffer from the audio device
printf("about to grab sound\n");
if (pa_simple_read(pulse_s, (Uint8 *)my_read_main_buffer,
(READ_BUFFER_SIZE * sizeof(Sint16)), &function_return) < 0) {
printf("sound read failed %s\n", pa_strerror(function_return));
return NULL;
}
printf("just grabbed the buffer from device\n");
// Turn the volume down
for (main_buffer_index = 0; main_buffer_index < READ_BUFFER_SIZE;
main_buffer_index += 1)
{
main_buffer_hold = (Sint16)(*(my_read_main_buffer + main_buffer_index) * MAIN_VOLUME);
*(my_read_main_buffer + main_buffer_index) = main_buffer_hold;
}
return my_read_main_buffer;
}

38
main_class.cpp Normal file
View File

@@ -0,0 +1,38 @@
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>
#include <cmath>
#include <unistd.h>
#include <iostream>
#include <chrono>
#include "scope.h"
// Main window
main_window_class::main_window_class (int x_main_window_size, int y_main_window_size)
{
if ((window_for_main = SDL_CreateWindow("Audio Analyzer",
0, 0, x_main_window_size, y_main_window_size, 0)) == NULL) {
printf("error opening main window SDL: %s\n", SDL_GetError());
exit (0);
}
//if ((call_result = SDL_SetWindowFullscreen(window_for_main,
// SDL_WINDOW_FULLSCREEN_DESKTOP)) !=0) {
// printf("error setting main to fullscreen SDL: %s\n", SDL_GetError());
// exit (0);
//}
SDL_SetWindowBordered(window_for_main, SDL_FALSE);
if ((renderer_for_main = SDL_CreateRenderer(window_for_main, -1, 0)) == NULL) {
printf("error opening main renderer SDL: %s\n", SDL_GetError());
exit (0);
}
SDL_SetRenderDrawColor(renderer_for_main, (Uint8)30, (Uint8)50, (Uint8)50, (Uint8)255);
SDL_RenderClear(renderer_for_main);
SDL_RenderPresent(renderer_for_main);
}

BIN
octive-1.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
octive-2.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
octive-3.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
octive-4.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
octive-5.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
octive-6.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
octive-7.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
octive-8.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
octive-blank.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
piano-keys.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 KiB

232
piano_class.cpp Normal file
View File

@@ -0,0 +1,232 @@
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>
#include <cmath>
#include <unistd.h>
#include <iostream>
#include <chrono>
#include "scope.h"
// Piano class method bodies
// Piano window
int piano_window_class::draw_trace(piano_data_struct *input_piano_data)
{
//printf("this size %d\n", this_piano_data_size);
//Clear the window
SDL_SetRenderDrawColor(renderer_for_piano, (Uint8)40, (Uint8)40, (Uint8)0, (Uint8)255);
SDL_RenderClear(renderer_for_piano);
// Render word Piano
// SDL_RenderCopy(renderer_for_piano, texture_for_piano, NULL, &rect_for_piano_text);
my_piano_data = input_piano_data;
// point to piano_key_texture
if (my_piano_data->keyboard_key == 0)
{
texture_current_piano_light = texture_key_blank;
}
else
{
texture_current_piano_light = texture_keys[my_piano_data->keyboard_key - 1];
}
// point to octive_texture
if (my_piano_data->octive == 0)
{
texture_current_octive_light = texture_octive_blank;
}
else
{
texture_current_octive_light = texture_octives[my_piano_data->octive - 1];
}
// Put on screen
SDL_RenderCopy(renderer_for_piano, texture_current_piano_light, NULL, &rect_for_keys);
SDL_RenderCopy(renderer_for_piano, texture_current_octive_light, NULL, &rect_for_octives);
SDL_RenderPresent(renderer_for_piano);
return 0;
}
int piano_window_class::get_max_piano_trace_width()
{
return max_piano_trace_width;
}
int piano_window_class::get_max_piano_trace_height()
{
return max_piano_trace_height;
}
piano_window_class::piano_window_class (int x_main_window_size, int y_main_window_size)
{
x_piano_window_position = 15;
y_piano_window_position = (int)((y_main_window_size / 3) * 2) + 30;
x_piano_window_size = x_main_window_size - 40;
y_piano_window_size = (((int)(y_main_window_size / 3)) * 1) - 10;
x_piano_window_trace_base = 1;
y_piano_window_trace_base = y_piano_window_size - 2;
max_piano_trace_width = x_piano_window_size - 2;
max_piano_trace_height = y_piano_window_size;
if ((window_for_piano = SDL_CreateWindow("Piano",
x_piano_window_position, y_piano_window_position,
x_piano_window_size, y_piano_window_size,0)) == NULL) {
printf("error opening piano window SDL: %s\n", SDL_GetError());
exit (0);
}
printf("piano window: window_size %d x pos %d max trace width %d\n",
x_piano_window_size, x_piano_window_position, max_piano_trace_width);
SDL_SetWindowBordered(window_for_piano, SDL_FALSE);
if ((renderer_for_piano = SDL_CreateRenderer(window_for_piano, -1, 0)) == NULL) {
printf("error opening piano renderer SDL: %s\n", SDL_GetError());
exit (0);
}
// Working on the title text
if ((font_for_piano = TTF_OpenFont("/usr/share/fonts/truetype/freefont/FreeSans.ttf",
24)) == NULL) {
printf("error opening piano font SDL: %s\n", SDL_GetError());
exit (0);
}
color_for_piano = {255,255,255};
if ((surface_for_piano_text = TTF_RenderText_Solid(font_for_piano,
"PIANO KEYBOARD", color_for_piano)) == NULL) {
printf("error opening piano surface SDL: %s\n", SDL_GetError());
exit (0);
}
if ((texture_for_piano = SDL_CreateTextureFromSurface(renderer_for_piano,
surface_for_piano_text)) == NULL) {
printf("error opening piano texture SDL: %s\n", SDL_GetError());
exit (0);
}
rect_for_piano_text.x = x_piano_window_trace_base + 5;
rect_for_piano_text.y = 20;
rect_for_piano_text.w = surface_for_piano_text->w;
rect_for_piano_text.h = surface_for_piano_text->h;
// Load all images
// Load blanks
surface_key_blank = SDL_LoadBMP(
"/home/maallyn/sound-scope/sdl2/fft/keyboard-key-blank.bmp");
if (surface_key_blank == NULL) {
printf("cannot load keyboard blank keymap file\n");
printf("%s\n",SDL_GetError());
printf("\n");
exit (0);
}
surface_octive_blank = SDL_LoadBMP(
"/home/maallyn/sound-scope/sdl2/fft/octive-blank.bmp");
if (surface_octive_blank == NULL) {
printf("cannot load octive blank keymap file\n");
printf("%s\n",SDL_GetError());
printf("\n");
exit (0);
}
// Scale the rect for all keyboards (all same size)
rect_for_keys.w = (int)(surface_key_blank->w * PIANO_SIZE_MULTIPLY);
rect_for_keys.h = (int)(surface_key_blank->h * PIANO_SIZE_MULTIPLY);
rect_for_keys.x = KEYBOARD_POSITION_X;
rect_for_keys.y = KEYBOARD_POSITION_Y;
// Scale the rect for all octives (all same size)
rect_for_octives.w = (int)(surface_octive_blank->w * PIANO_SIZE_MULTIPLY);
rect_for_octives.h = (int)(surface_octive_blank->h * PIANO_SIZE_MULTIPLY);
rect_for_octives.x = OCTIVE_POSITION_X;
rect_for_octives.y = OCTIVE_POSITION_Y;
texture_key_blank = SDL_CreateTextureFromSurface(renderer_for_piano,
surface_key_blank);
if (texture_key_blank == NULL) {
printf("cannot texture keyboard blank keymap file\n");
printf("%s\n", SDL_GetError());
printf("\n");
exit (0);
}
texture_octive_blank = SDL_CreateTextureFromSurface(renderer_for_piano,
surface_octive_blank);
if (texture_octive_blank == NULL) {
printf("cannot texture octive blank keymap file\n");
printf("%s\n", SDL_GetError());
printf("\n");
exit (0);
}
// do rest of keys and octives
// keys
for (loop_counter = 0; loop_counter < NUMBER_KEY_LIGHTS; loop_counter += 1)
{
surface_keys[loop_counter] = SDL_LoadBMP(keyboard_lights[loop_counter]);
if (surface_keys[loop_counter] == NULL) {
printf("cannot load light file keymap file %s\n", keyboard_lights[loop_counter]);
printf("%s\n",SDL_GetError());
printf("\n");
exit (0);
}
texture_keys[loop_counter] = SDL_CreateTextureFromSurface(renderer_for_piano,
surface_keys[loop_counter]);
if (texture_keys[loop_counter] == NULL) {
printf("cannot texture keyboard light %d\n", loop_counter);
printf("%s\n", SDL_GetError());
printf("\n");
exit (0);
}
}
// octives
for (loop_counter = 0; loop_counter < NUMBER_OCTIVE_LIGHTS; loop_counter += 1)
{
surface_octives[loop_counter] = SDL_LoadBMP(octive_lights[loop_counter]);
if (surface_octives[loop_counter] == NULL) {
printf("cannot load light file octive file %s\n", octive_lights[loop_counter]);
printf("%s\n",SDL_GetError());
printf("\n");
exit (0);
}
texture_octives[loop_counter] = SDL_CreateTextureFromSurface(renderer_for_piano,
surface_octives[loop_counter]);
if (texture_octives[loop_counter] == NULL) {
printf("cannot texture octive light %d\n", loop_counter);
printf("%s\n", SDL_GetError());
printf("\n");
exit (0);
}
}
// Put stuff on screen
SDL_SetRenderDrawColor(renderer_for_piano, (Uint8)40, (Uint8)40, (Uint8)0, (Uint8)255);
SDL_RenderClear(renderer_for_piano);
// SDL_RenderCopy(renderer_for_piano, texture_for_piano, NULL, &rect_for_piano_text);
SDL_RenderCopy(renderer_for_piano, texture_key_blank, NULL, &rect_for_keys);
SDL_RenderCopy(renderer_for_piano, texture_octive_blank, NULL, &rect_for_octives);
SDL_RenderPresent(renderer_for_piano);
}

305
piano_process.cpp Normal file
View File

@@ -0,0 +1,305 @@
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>
#include <cmath>
#include <unistd.h>
#include <iostream>
#include <chrono>
#include "scope.h"
// Functions to try to process Constant Q transform
piano_process_class::piano_process_class()
{
}
piano_process_class::~piano_process_class()
{
}
double piano_process_class::goertzel(int num_samples, int target_frequency, int sample_rate,
Sint16 *input_buffer)
{
double dinput_buffer;
double magnatude;
int k, i;
double doublenumsamples;
double omega, sine, cosine, coeff, q0, q1, q2, real, imag;
double scalingfactor;
// Initialize constant stuff
doublenumsamples = (double)num_samples;
scalingfactor = doublenumsamples / 2.0;
k = (int)(0.5 + ((doublenumsamples * (double)(target_frequency)) / (double)sample_rate));
omega = (2.0 * M_PI * (double)k) / doublenumsamples;
sine = sin(omega);
cosine= cos(omega);
coeff = 2.0 * cosine;
// Init q's
q0 = 0;
q1 = 0;
q2 = 0;
// First stage (2nd order IIR filter)
for (i = 0; i < num_samples; i += 1)
{
dinput_buffer = (double)*(input_buffer + i);
q2 = q1;
q1 = q0;
q0 = coeff * q1 - q2 + dinput_buffer;
// printf("q0 %f; dinput_buffer %f: integer_input_buffer %d\n", q0, dinput_buffer, *(input_buffer + i));
}
// Seconod stage (FIR filter)
real = (q0 - q1 *cosine) / scalingfactor;
imag = (-q1 * sine) / scalingfactor;
magnatude = sqrt((real * real) + (imag * imag));
// Test Prints
// printf("doublesamples %f; scalingfactor %f; k %d\n", doublenumsamples, scalingfactor, k);
// printf("omega %f; sine %f; cosine %f; coeff %f\n", omega, sine, cosine, coeff);
// printf("magnatude %f\n", magnatude);
// printf("goertzel done\n");
return magnatude;
}
struct piano_data_struct *piano_process_class::process_piano_data(Sint16 *input_buffer)
{
int bucket_counter;
bucket_data_struct *current_bucket;
FILE *result_plot_file;
FILE *input_waveform_file;
FILE *note_result_plot_file;
Sint16 *current_read_buffer_in;
Sint16 *current_read_buffer_out;
int print_file_counter;
int count_for_transfering_buffers;
struct piano_note_struct *working_note;
struct piano_note_struct *strongest_note;
int note_counter;
// Before doing anything, we need to 1) update the full size buffer
// and ensure that it is full before processing,
// Otherwize return NULL if not.
if (main_buffer_read_count < FFT_NUMBER_READ_BUFFERS)
{
current_read_buffer_in = input_buffer;
current_read_buffer_out = full_size_buffer + READ_BUFFER_SIZE * main_buffer_read_count;
for (count_for_transfering_buffers = 0; count_for_transfering_buffers < READ_BUFFER_SIZE;
count_for_transfering_buffers += 1)
{
*current_read_buffer_out = *current_read_buffer_in;
current_read_buffer_out += 1;
current_read_buffer_in += 1;
}
main_buffer_read_count += 1;
return NULL;
}
else
{
main_buffer_read_count = 0;
}
input_waveform_file = fopen("waveform_of_input","w");
if (input_waveform_file == NULL)
{
printf("cant open input waveform_file\n");
exit (0);
}
for (print_file_counter = 0; print_file_counter < READ_BUFFER_SIZE * FFT_NUMBER_READ_BUFFERS;
print_file_counter += 2)
{
fprintf(input_waveform_file, "%d %d\n", print_file_counter, *(full_size_buffer + print_file_counter));
// printf("%d %f\n", print_file_counter, (double)*(full_size_buffer + print_file_counter));
}
fclose (input_waveform_file);
// Go through all of the buckets to get their strenght using Goertzel
// Test plotfile
result_plot_file = fopen("result_data_for_gnuplot", "w");
if (result_plot_file == NULL)
{
printf("oops cant open result file\n");
perror("cant open file\n");
exit(0);
}
note_result_plot_file = fopen("note_data_for_gnuplot", "w");
if (note_result_plot_file == NULL)
{
printf("oops cant open note result file\n");
perror("cant open file\n");
exit(0);
}
//clear the strengh in all notes
working_note = my_piano_notes;
for (note_counter = 0; note_counter < TOTAL_NOTES; note_counter += 1)
{
(working_note + note_counter)->note_strength = (double)0.0;
}
for (bucket_counter = 0; bucket_counter < TOTAL_BUCKETS; bucket_counter += 1)
{
current_bucket = my_bucket_data + bucket_counter;
current_bucket->bucket_strength = goertzel(current_bucket->buffer_size,
current_bucket->bucket_frequency,
SAMPLE_RATE,
full_size_buffer);
current_bucket->this_piano_note->note_strength += current_bucket->bucket_strength;
//Test print
fprintf(result_plot_file,
"%d %f\n",
bucket_counter, current_bucket->bucket_strength);
}
working_note = my_piano_notes;
for (note_counter = 0; note_counter < TOTAL_NOTES; note_counter += 1)
{
fprintf(note_result_plot_file, "%d %f\n", note_counter, (working_note + note_counter)->note_strength);
}
fclose (note_result_plot_file);
//now find the strongest note
strongest_note = my_piano_notes;
working_note = my_piano_notes;
for (note_counter = 0; note_counter < TOTAL_NOTES; note_counter += 1)
{
if (working_note->note_strength > strongest_note->note_strength)
{
strongest_note = working_note;
}
working_note += 1;
}
my_piano_data_struct.keyboard_key = strongest_note->keyboard_key;
my_piano_data_struct.octive = strongest_note->octive;
my_piano_data_struct.done = 1;
fclose (result_plot_file);
// printf ("done process \n");
return &my_piano_data_struct;
}
int piano_process_class::initialize_piano_data()
{
double current_bucket_frequency;
double previous_bucket_frequency;
int current_octive;
int current_bucket;
int current_note;
int bucket_in_note;
int note_in_octive;
double semi_interval;
struct bucket_data_struct *current_bucket_pointer;
struct piano_note_struct *current_note_pointer;
FILE *print_records;
int array_counter;
note_in_octive = 0;
current_bucket_frequency = (double)32.0;
previous_bucket_frequency = (double)32.0;
current_note = 0;
current_octive = 0;
bucket_in_note = 0;
semi_interval = (double)(pow(2.0, 1.0/(double(BUCKETS_PER_OCTIVE))));
// printf("semi is %f\n", semi_interval);
print_records = fopen("my_bucket_record","w");
if (print_records == NULL)
{
printf ("cannot open records file \n");
}
// initialize full_size_buffer
for (array_counter = 0; array_counter < PIANO_FULL_ARRAY_SIZE; array_counter += 1)
{
full_size_buffer[array_counter] = (Sint16)0;
}
main_buffer_read_count = 0;
for (current_bucket = 0; current_bucket < TOTAL_BUCKETS; current_bucket += 1)
{
// Set pointers to bucket structure
current_bucket_pointer = my_bucket_data + current_bucket;
// Set pointer to note
current_note_pointer = my_piano_notes + (int)(current_bucket / BUCKETS_PER_NOTE) + bucket_in_note;
// Fill out both bucket and note structures
current_bucket_pointer->this_piano_note = current_note_pointer;
current_bucket_pointer->bucket_strength = 0.0;
current_note_pointer->note_strength = 0.0;
current_note_pointer->keyboard_key = note_in_octive;
current_note_pointer->octive = current_octive;
//Set current bucket frequency
//First is handled differently
if (current_bucket == 0)
{
current_bucket_pointer->bucket_frequency = current_bucket_frequency;
previous_bucket_frequency = current_bucket_frequency;
}
else
{
current_bucket_frequency = previous_bucket_frequency * semi_interval;
previous_bucket_frequency = current_bucket_frequency;
}
current_bucket_pointer->bucket_frequency = current_bucket_frequency;
// Radians on cycle per sample
current_bucket_pointer->radians_per_sample = (double)RADIANS_PER_SAMPLE_AT_1_HZ *
(double)current_bucket_pointer->bucket_frequency;
// Buffer size for this bucket's frequency
current_bucket_pointer->buffer_size = (int)((double)(SAMPLE_RATE)/
current_bucket_pointer->bucket_frequency) * Q_QUALITY;
//Verification prints
fprintf (print_records, "current bucket - %d; bucket in note - %d; note in octive - %d; current note %d; current octive - %d ; bucket_frequency - %f ; degree per sample - %f; buffer size - %d; which note - %d\n",
current_bucket, bucket_in_note, note_in_octive, current_note, current_octive,
current_bucket_pointer->bucket_frequency, current_bucket_pointer->radians_per_sample,
current_bucket_pointer->buffer_size,
(int)(current_bucket / BUCKETS_PER_NOTE));
// Bump up for next; reset if necessary
// Note frequency
// Update bucket in note and note in octive
bucket_in_note += 1;
if (bucket_in_note == BUCKETS_PER_NOTE)
{
bucket_in_note = 0;
current_note += 1;
note_in_octive += 1;
if (note_in_octive == NOTES_PER_OCTIVE)
{
note_in_octive = 0;
current_octive += 1;
}
}
}
fclose(print_records);
printf ("done initialize \n");
return 0;
}

204
scope.cpp Normal file
View File

@@ -0,0 +1,204 @@
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>
#include <cmath>
#include <unistd.h>
#include <iostream>
#include <sys/time.h>
#include <chrono>
#include "scope.h"
// Main window size (location is 0, 0)
int x_window_size = 0;
int y_window_size = 0;
char input_our_audio_device_name[100];
main_window_class *my_main_window = NULL;
audio_window_class *my_audio_window = NULL;
spectrum_window_class *my_spectrum_window = NULL;
piano_window_class *my_piano_window = NULL;
main_buffer_manager_class *my_main_buffer_manager = NULL;
audio_buffer_manager_class *my_audio_buffer_manager = NULL;
spectrum_buffer_manager_class *my_spectrum_buffer_manager = NULL;
piano_process_class *my_piano_process = NULL;
struct piano_data_struct *piano_data_pointer=NULL;
Uint64 last_time;
Uint64 this_time;
// SDL Event to stop application on pressing a key on the keyboard
SDL_Event my_event;
int get_me_out = 0;
int main(int argc, char *argv[])
{
// function result
int main_function_result = 0;
// Get parameters for size
if (argc < 3)
{
printf ("needs x and y size \n");
exit (0);
}
x_window_size = atoi(argv[1]);
y_window_size = atoi(argv[2]);
int our_audio_trace_width;
int our_audio_trace_height;
int our_spectrum_trace_width;
int our_spectrum_trace_height;
Sint16 *my_main_buffer;
int *return_audio_buffer;
int *return_spectrum_buffer;
printf ("window is %d by %d\n", x_window_size, y_window_size);
// returns zero on success else non-zero
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
printf("error initializing SDL: %s\n", SDL_GetError());
}
// returns zero on success else non-zero
if (TTF_Init() != 0 ){
printf("error initializing TTF: %s\n", SDL_GetError());
}
// Windows
my_main_window = new main_window_class(x_window_size, y_window_size);
my_audio_window = new audio_window_class(x_window_size, y_window_size);
my_spectrum_window = new spectrum_window_class(x_window_size, y_window_size);
my_piano_window = new piano_window_class(x_window_size, y_window_size);
// main buffer
my_main_buffer_manager = new main_buffer_manager_class();
// audio_buffer
my_audio_buffer_manager = new audio_buffer_manager_class();
// spectrum buffer
my_spectrum_buffer_manager = new spectrum_buffer_manager_class();
// piano_process
my_piano_process = new piano_process_class();
// audio window width and height
our_audio_trace_width = my_audio_window->get_max_audio_trace_width();
our_audio_trace_height = my_audio_window->get_max_audio_trace_height();
// spectrum window width and height
our_spectrum_trace_width = my_spectrum_window->get_max_spectrum_trace_width();
our_spectrum_trace_height = my_spectrum_window->get_max_spectrum_trace_height();
// buffer initializations
my_main_buffer = my_main_buffer_manager->initial_preparation();
if (my_main_buffer == NULL)
{
printf("error initialize main_buffer\n");
exit (0);
}
main_function_result = my_audio_buffer_manager->initialize_audio
(our_audio_trace_width, our_audio_trace_height, my_main_buffer);
if (main_function_result)
{
printf("error initialize audio_buffer\n");
exit (0);
}
main_function_result = my_spectrum_buffer_manager->initialize_spectrum
(our_spectrum_trace_width, our_spectrum_trace_height, my_main_buffer);
if (main_function_result)
{
printf("error initialize spectrum_buffer\n");
exit (0);
}
//Initialize Piano Data Processor
main_function_result = my_piano_process->initialize_piano_data();
if (main_function_result)
{
printf("error initialize piano processing\n");
exit (0);
}
//Read and process and display loop
last_time = 0;
while (get_me_out == 0) {
while(SDL_PollEvent(&my_event)) {
printf("got event event type is %d\n", my_event.type);
switch (my_event.type) {
case SDL_QUIT: get_me_out = 1;
case SDL_KEYDOWN: get_me_out = 1;
break;
}
}
// SDL_Delay(100);
my_main_buffer = my_main_buffer_manager->read_main_buffer();
if (my_main_buffer == NULL)
{
printf("error resding into main_buffer\n");
exit (0);
}
return_audio_buffer = my_audio_buffer_manager->process_audio();
if (return_audio_buffer == NULL)
{
printf("error processing audio to return_audio_buffer\n");
exit (0);
}
return_spectrum_buffer = my_spectrum_buffer_manager->process_spectrum();
//gettimeofday(&stop_time, NULL);
//gettimeofday(&start_time, NULL);
this_time = SDL_GetTicks64();
if (this_time >= last_time)
{
while ((last_time + FRAME_TIME) > this_time)
{
usleep(1000);
this_time = SDL_GetTicks64();
}
}
last_time = this_time;
main_function_result = my_audio_window->draw_trace(return_audio_buffer,
our_audio_trace_width);
// display fft only when the entire fft buffer is done
if (return_spectrum_buffer != NULL)
{
main_function_result = my_spectrum_window->draw_trace(return_spectrum_buffer,
our_spectrum_trace_width);
}
// Piano section
piano_data_pointer = my_piano_process->process_piano_data(my_main_buffer);
if (piano_data_pointer == NULL)
{
printf("piano not done\n");
}
else
{
printf ("piano done\n");
my_piano_window->draw_trace(piano_data_pointer);
}
}
return main_function_result;
}

267
scope.h Normal file
View File

@@ -0,0 +1,267 @@
#ifndef SCOPE
#define SCOPE
#include <pulse/simple.h>
#include <pulse/error.h>
#include <fftw3.h>
#define SAMPLE_RATE 44100
#define FRAME_TIME 17
// this must be in power of 2 for fourier transform
#define READ_BUFFER_SIZE 2048
#define FFT_NUMBER_READ_BUFFERS 4
#define FFT_BUFFER_SIZE (READ_BUFFER_SIZE * FFT_NUMBER_READ_BUFFERS)
#define MAIN_BUFFER_SIZE 8192
#define AUDIO_BUFFER_SIZE 6000
#define FFT_START_BUCKET 0
#define MAIN_VOLUME .1
#define SPECTRUM_VOLUME .1
#define PIANO_SIZE_MULTIPLY .65
#define KEYBOARD_POSITION_X 50
#define KEYBOARD_POSITION_Y 10
#define OCTIVE_POSITION_X 800
#define OCTIVE_POSITION_Y 10
#define NUMBER_KEY_LIGHTS 12
#define NUMBER_OCTIVE_LIGHTS 8
#define RADIANS_PER_SAMPLE_AT_1_HZ (double)6.28319/(double)SAMPLE_RATE
#define NUMBER_OCTIVES 6
#define BUCKETS_PER_NOTE 2
#define NOTES_PER_OCTIVE 12
#define BUCKETS_PER_OCTIVE BUCKETS_PER_NOTE*NOTES_PER_OCTIVE
#define TOTAL_BUCKETS BUCKETS_PER_OCTIVE*NUMBER_OCTIVES
#define TOTAL_NOTES NOTES_PER_OCTIVE*NUMBER_OCTIVES
#define Q_QUALITY 6
#define FIRST_FREQUENCY 32
#define PIANO_FULL_ARRAY_SIZE 10000
//Structure for piano notes
struct piano_note_struct {
double note_strength;
int keyboard_key;
int octive;;
};
//Structure for processing buckets
struct bucket_data_struct {
double bucket_frequency;
double bucket_strength;
int buffer_size;
double radians_per_sample;
struct piano_note_struct *this_piano_note;
};
// Structure used by both piano and main classes
struct piano_data_struct {
int keyboard_key;
int octive;
int done;
};
class main_window_class {
public:
main_window_class (int x_main_window_size, int y_main_window_size);
private:
SDL_Window *window_for_main;
SDL_Renderer *renderer_for_main;
int call_result;
};
class audio_window_class {
public:
audio_window_class (int x_main_window_size, int y_main_window_size);
int draw_trace(int *audio_data, int audio_data_size);
int get_max_audio_trace_width();
int get_max_audio_trace_height();
private:
int x_audio_window_position;
int y_audio_window_position;
int x_audio_window_size;
int y_audio_window_size;
int x_audio_window_trace_base;
int y_audio_window_trace_base;
int max_audio_trace_width;
int max_audio_trace_height;
SDL_Window *window_for_audio;
SDL_Renderer *renderer_for_audio;
SDL_Rect rect_for_audio;
SDL_Texture *texture_for_audio;
SDL_Surface *surface_for_audio;
TTF_Font *font_for_audio;
SDL_Color color_for_audio;
};
class spectrum_window_class {
public:
spectrum_window_class (int x_main_window_size, int y_main_window_size);
int draw_trace(int *spectrum_data, int spectrum_data_size);
int get_max_spectrum_trace_width();
int get_max_spectrum_trace_height();
private:
int x_spectrum_window_position;
int y_spectrum_window_position;
int x_spectrum_window_size;
int y_spectrum_window_size;
int x_spectrum_window_trace_base;
int y_spectrum_window_trace_base;
int max_spectrum_trace_width;
int max_spectrum_trace_height;
SDL_Window *window_for_spectrum;
SDL_Renderer *renderer_for_spectrum;
SDL_Rect rect_for_spectrum;
SDL_Texture *texture_for_spectrum;
SDL_Surface *surface_for_spectrum;
TTF_Font *font_for_spectrum;
SDL_Color color_for_spectrum;
};
class piano_window_class {
public:
piano_window_class (int x_main_window_size, int y_main_window_size);
int draw_trace(piano_data_struct *input_piano_data);
int get_max_piano_trace_width();
int get_max_piano_trace_height();
private:
const char* keyboard_lights[12] = {
"/home/maallyn/sound-scope/sdl2/fft/keyboard-key1.bmp",
"/home/maallyn/sound-scope/sdl2/fft/keyboard-key2.bmp",
"/home/maallyn/sound-scope/sdl2/fft/keyboard-key3.bmp",
"/home/maallyn/sound-scope/sdl2/fft/keyboard-key4.bmp",
"/home/maallyn/sound-scope/sdl2/fft/keyboard-key5.bmp",
"/home/maallyn/sound-scope/sdl2/fft/keyboard-key6.bmp",
"/home/maallyn/sound-scope/sdl2/fft/keyboard-key7.bmp",
"/home/maallyn/sound-scope/sdl2/fft/keyboard-key8.bmp",
"/home/maallyn/sound-scope/sdl2/fft/keyboard-key9.bmp",
"/home/maallyn/sound-scope/sdl2/fft/keyboard-key10.bmp",
"/home/maallyn/sound-scope/sdl2/fft/keyboard-key11.bmp",
"/home/maallyn/sound-scope/sdl2/fft/keyboard-key12.bmp"};
const char* octive_lights[8] = {
"/home/maallyn/sound-scope/sdl2/fft/octive-1.bmp",
"/home/maallyn/sound-scope/sdl2/fft/octive-2.bmp",
"/home/maallyn/sound-scope/sdl2/fft/octive-3.bmp",
"/home/maallyn/sound-scope/sdl2/fft/octive-4.bmp",
"/home/maallyn/sound-scope/sdl2/fft/octive-5.bmp",
"/home/maallyn/sound-scope/sdl2/fft/octive-6.bmp",
"/home/maallyn/sound-scope/sdl2/fft/octive-7.bmp",
"/home/maallyn/sound-scope/sdl2/fft/octive-8.bmp"};
struct piano_data_struct *my_piano_data;
int x_piano_window_position;
int y_piano_window_position;
int x_piano_window_size;
int y_piano_window_size;
int x_piano_window_trace_base;
int y_piano_window_trace_base;
int max_piano_trace_width;
int max_piano_trace_height;
int function_result;
int loop_counter;
SDL_Window *window_for_piano;
SDL_Renderer *renderer_for_piano;
SDL_Rect rect_for_piano_text;
SDL_Texture *texture_for_piano;
SDL_Surface *surface_for_piano_text;
SDL_Surface *surface_key_blank;
SDL_Surface *surface_keys[12];
SDL_Surface *surface_octive_blank;
SDL_Surface *surface_octives[8];
SDL_Texture *texture_key_blank;
SDL_Texture *texture_keys[12];
SDL_Texture *texture_octive_blank;
SDL_Texture *texture_octives[8];
SDL_Texture *texture_current_piano_light;
SDL_Texture *texture_current_octive_light;
SDL_Rect rect_for_keys;
SDL_Rect rect_for_octives;
TTF_Font *font_for_piano;
SDL_Color color_for_piano;
SDL_Rect rect_for_piano_image;
SDL_Surface *piano_image_surface;
SDL_Texture *texture_of_piano_image;
};
class main_buffer_manager_class {
public:
main_buffer_manager_class();
~main_buffer_manager_class();
Sint16 *initial_preparation();
Sint16 *read_main_buffer();
private:
Sint16 *my_read_main_buffer;
int pulse_error;
int function_return;
pa_simple *pulse_s = NULL;
int main_buffer_index;
Sint16 main_buffer_hold;
};
class audio_buffer_manager_class {
public:
audio_buffer_manager_class();
~audio_buffer_manager_class();
int initialize_audio(int horizontal_size,int vertical_size, Sint16 *main_buffer);
int *process_audio();
private:
Sint16 *my_main_buffer;
int *my_formatted_audio_buffer;
int my_audio_horizontal_size;
int my_audio_vertical_size;
int my_read_audio_index;
int function_return;
Sint16 audio_holding;
};
class spectrum_buffer_manager_class {
public:
spectrum_buffer_manager_class();
~spectrum_buffer_manager_class();
int initialize_spectrum(int horizontal_size,int vertical_size, Sint16 *main_buffer);
int *process_spectrum();
private:
Sint16 *my_main_buffer;
int *my_formatted_spectrum_buffer;
int my_spectrum_horizontal_size;
int my_spectrum_vertical_size;
int my_read_spectrum_index;
int my_output_fft_buffer_index;
int function_return;
int read_buffer_counter;
Sint16 spectrum_holding;
fftw_plan my_fftw_plan;
double *input_fftw;
double *input_fftw_write_position;
Sint16 main_buffer_hold;
fftw_complex *output_fftw;
};
class piano_process_class {
public:
piano_process_class();
~piano_process_class();
int initialize_piano_data();
struct piano_data_struct *process_piano_data(Sint16 *input_buffer);
double goertzel(int num_samples, int target_frequency, int sample_rate, Sint16 *input_buffer);
private:
struct piano_data_struct my_piano_data_struct;
Sint16 *local_main_buffer;
int ctr1;
struct piano_note_struct my_piano_notes[TOTAL_NOTES];
struct bucket_data_struct my_bucket_data[TOTAL_BUCKETS];
Sint16 full_size_buffer[PIANO_FULL_ARRAY_SIZE];
int main_buffer_read_count;
};
#endif

BIN
sized-piano-keys.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -0,0 +1,137 @@
#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;
}

126
spectrum_class.cpp Normal file
View File

@@ -0,0 +1,126 @@
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_ttf.h>
#include <stdio.h>
#include <cmath>
#include <unistd.h>
#include <iostream>
#include <chrono>
#include "scope.h"
// Spectrum class method bodies
// Spectrum window
int spectrum_window_class::draw_trace(int *spectrum_data, int spectrum_data_size)
{
int spectrum_data_counter;
int *current_spectrum_data_value;
int *prev_spectrum_data_value;
int this_spectrum_data_size;
if (spectrum_data_size >= max_spectrum_trace_width)
{
this_spectrum_data_size = max_spectrum_trace_width;
}
else
{
this_spectrum_data_size = spectrum_data_size;
}
//printf("this size %d\n", this_spectrum_data_size);
//Clear the window
SDL_SetRenderDrawColor(renderer_for_spectrum, (Uint8)40, (Uint8)40, (Uint8)0, (Uint8)255);
SDL_RenderClear(renderer_for_spectrum);
// Render word Spectrum
SDL_RenderCopy(renderer_for_spectrum, texture_for_spectrum, NULL, &rect_for_spectrum);
// green trace
SDL_SetRenderDrawColor(renderer_for_spectrum, (Uint8)0, (Uint8)(255), (Uint8)255, (Uint8)255);
for (spectrum_data_counter = 1; spectrum_data_counter < this_spectrum_data_size; spectrum_data_counter += 1)
{
current_spectrum_data_value = spectrum_data + spectrum_data_counter;
prev_spectrum_data_value = spectrum_data + spectrum_data_counter - 1;
SDL_RenderDrawLine (renderer_for_spectrum, x_spectrum_window_trace_base + spectrum_data_counter -1,
y_spectrum_window_trace_base + *prev_spectrum_data_value,
x_spectrum_window_trace_base + spectrum_data_counter,
y_spectrum_window_trace_base + *current_spectrum_data_value);
}
SDL_RenderPresent(renderer_for_spectrum);
return 0;
}
int spectrum_window_class::get_max_spectrum_trace_width()
{
return max_spectrum_trace_width;
}
int spectrum_window_class::get_max_spectrum_trace_height()
{
return max_spectrum_trace_height;
}
spectrum_window_class::spectrum_window_class (int x_main_window_size, int y_main_window_size)
{
x_spectrum_window_position = 30 + (int)(x_main_window_size / 2);
y_spectrum_window_position = 5;
x_spectrum_window_size = ((int)(x_main_window_size / 2)) - 10;
y_spectrum_window_size = (((int)(y_main_window_size / 3)) * 2) - 10;
x_spectrum_window_trace_base = 1;
y_spectrum_window_trace_base = y_spectrum_window_size - 2;
max_spectrum_trace_width = x_spectrum_window_size - 2;
max_spectrum_trace_height = y_spectrum_window_size;
if ((window_for_spectrum = SDL_CreateWindow("Spectrum",
x_spectrum_window_position, y_spectrum_window_position,
x_spectrum_window_size, y_spectrum_window_size,0)) == NULL) {
printf("error opening spectrum window SDL: %s\n", SDL_GetError());
exit (0);
}
printf("spectrum window: window_size %d x pos %d max trace width %d\n",
x_spectrum_window_size, x_spectrum_window_position, max_spectrum_trace_width);
SDL_SetWindowBordered(window_for_spectrum, SDL_FALSE);
if ((renderer_for_spectrum = SDL_CreateRenderer(window_for_spectrum, -1, 0)) == NULL) {
printf("error opening spectrum renderer SDL: %s\n", SDL_GetError());
exit (0);
}
if ((font_for_spectrum = TTF_OpenFont("/usr/share/fonts/truetype/freefont/FreeSans.ttf",
24)) == NULL) {
printf("error opening spectrum font SDL: %s\n", SDL_GetError());
exit (0);
}
color_for_spectrum = {255,255,255};
if ((surface_for_spectrum = TTF_RenderText_Solid(font_for_spectrum,
"SPECTRUM ANALYZER", color_for_spectrum)) == NULL) {
printf("error opening spectrum surface SDL: %s\n", SDL_GetError());
exit (0);
}
if ((texture_for_spectrum = SDL_CreateTextureFromSurface(renderer_for_spectrum,
surface_for_spectrum)) == NULL) {
printf("error opening spectrum texture SDL: %s\n", SDL_GetError());
exit (0);
}
rect_for_spectrum.x = x_spectrum_window_trace_base + ((int)(max_spectrum_trace_width/2) -
(int)(surface_for_spectrum->w / 2));
rect_for_spectrum.y = 20;
rect_for_spectrum.w = surface_for_spectrum->w;
rect_for_spectrum.h = surface_for_spectrum->h;
SDL_SetRenderDrawColor(renderer_for_spectrum, (Uint8)40, (Uint8)40, (Uint8)0, (Uint8)255);
SDL_RenderClear(renderer_for_spectrum);
SDL_RenderCopy(renderer_for_spectrum, texture_for_spectrum, NULL, &rect_for_spectrum);
SDL_RenderPresent(renderer_for_spectrum);
}