initial commit
This commit is contained in:
305
piano_process.cpp
Normal file
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user