initial commit
51
CMakeLists.txt
Normal 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
@@ -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
@@ -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}>>")
|
||||||
58
audio_buffer_manager_class.cpp
Normal 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
@@ -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
@@ -0,0 +1 @@
|
|||||||
|
/home/maallyn/sound-scope/sdl2/fft/build/scope 1700 1000
|
||||||
BIN
keyboard-key-blank.bmp
Executable file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
keyboard-key1.bmp
Executable file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
keyboard-key10.bmp
Executable file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
keyboard-key11.bmp
Executable file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
keyboard-key12.bmp
Executable file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
keyboard-key2.bmp
Executable file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
keyboard-key3.bmp
Executable file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
keyboard-key4.bmp
Executable file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
keyboard-key5.bmp
Executable file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
keyboard-key6.bmp
Executable file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
keyboard-key7.bmp
Executable file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
keyboard-key8.bmp
Executable file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
keyboard-key9.bmp
Executable file
|
After Width: | Height: | Size: 1.4 MiB |
79
main_buffer_manager_class.cpp
Normal 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
@@ -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
|
After Width: | Height: | Size: 1.7 MiB |
BIN
octive-2.bmp
Executable file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
octive-3.bmp
Executable file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
octive-4.bmp
Executable file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
octive-5.bmp
Executable file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
octive-6.bmp
Executable file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
octive-7.bmp
Executable file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
octive-8.bmp
Executable file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
octive-blank.bmp
Executable file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
piano-keys.bmp
Executable file
|
After Width: | Height: | Size: 554 KiB |
232
piano_class.cpp
Normal 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
@@ -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
@@ -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
@@ -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
|
After Width: | Height: | Size: 45 KiB |
137
spectrum_buffer_manager_class.cpp
Normal 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
@@ -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);
|
||||||
|
}
|
||||||