forked from len0rd/rockbox
pitch_detector: cleanup
- cosmetics: remove trailing white space
- mark all functions and variables as static
- merge struct definition and declaration when possible
- rename tuner_settings -> settings (because it's shorter)
- remove unused enums
- don't give pointer to settings struct as argument since there is only
one struct, same for the settings filename
- fix error cases in settings load:
reset settings when loading failed
close file when it hasn't the right size
- inline small load/save functions only used once
- remove unused print_char_xy
- inline print_str and print_int_xy, and use lcd_putsf (added to the
plugin API)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27918 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
5628096e51
commit
e09ebc4213
3 changed files with 171 additions and 229 deletions
|
|
@ -721,6 +721,8 @@ static const struct plugin_api rockbox_api = {
|
||||||
|
|
||||||
/* new stuff at the end, sort into place next time
|
/* new stuff at the end, sort into place next time
|
||||||
the API gets incompatible */
|
the API gets incompatible */
|
||||||
|
|
||||||
|
lcd_putsf,
|
||||||
};
|
};
|
||||||
|
|
||||||
int plugin_load(const char* plugin, const void* parameter)
|
int plugin_load(const char* plugin, const void* parameter)
|
||||||
|
|
|
||||||
|
|
@ -894,6 +894,8 @@ struct plugin_api {
|
||||||
|
|
||||||
/* new stuff at the end, sort into place next time
|
/* new stuff at the end, sort into place next time
|
||||||
the API gets incompatible */
|
the API gets incompatible */
|
||||||
|
|
||||||
|
void (*lcd_putsf)(int x, int y, const unsigned char *fmt, ...);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* plugin header */
|
/* plugin header */
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ typedef struct _fixed fixed;
|
||||||
#define LCD_FACTOR (fp_div(int2fixed(LCD_WIDTH), int2fixed(100)))
|
#define LCD_FACTOR (fp_div(int2fixed(LCD_WIDTH), int2fixed(100)))
|
||||||
/* The threshold for the YIN algorithm */
|
/* The threshold for the YIN algorithm */
|
||||||
#define DEFAULT_YIN_THRESHOLD 5 /* 0.10 */
|
#define DEFAULT_YIN_THRESHOLD 5 /* 0.10 */
|
||||||
const fixed yin_threshold_table[] IDATA_ATTR =
|
static const fixed yin_threshold_table[] IDATA_ATTR =
|
||||||
{
|
{
|
||||||
float2fixed(0.01),
|
float2fixed(0.01),
|
||||||
float2fixed(0.02),
|
float2fixed(0.02),
|
||||||
|
|
@ -173,14 +173,12 @@ const fixed yin_threshold_table[] IDATA_ATTR =
|
||||||
* the note. The frequency is scaled in a way that the main
|
* the note. The frequency is scaled in a way that the main
|
||||||
* algorithm can assume the frequency of A to be 440 Hz.
|
* algorithm can assume the frequency of A to be 440 Hz.
|
||||||
*/
|
*/
|
||||||
struct freq_A_entry
|
static const struct
|
||||||
{
|
{
|
||||||
const int frequency; /* Frequency in Hz */
|
const int frequency; /* Frequency in Hz */
|
||||||
const fixed ratio; /* 440/frequency */
|
const fixed ratio; /* 440/frequency */
|
||||||
const fixed logratio; /* log2(factor) */
|
const fixed logratio; /* log2(factor) */
|
||||||
};
|
} freq_A[] =
|
||||||
|
|
||||||
const struct freq_A_entry freq_A[] =
|
|
||||||
{
|
{
|
||||||
{435, float2fixed(1.011363636), float2fixed( 0.016301812)},
|
{435, float2fixed(1.011363636), float2fixed( 0.016301812)},
|
||||||
{436, float2fixed(1.009090909), float2fixed( 0.013056153)},
|
{436, float2fixed(1.009090909), float2fixed( 0.013056153)},
|
||||||
|
|
@ -214,8 +212,8 @@ const struct freq_A_entry freq_A[] =
|
||||||
#define DISPLAY_HZ_PRECISION 100
|
#define DISPLAY_HZ_PRECISION 100
|
||||||
|
|
||||||
/* Where to put the various GUI elements */
|
/* Where to put the various GUI elements */
|
||||||
int note_y;
|
static int note_y;
|
||||||
int bar_grad_y;
|
static int bar_grad_y;
|
||||||
#define LCD_RES_MIN (LCD_HEIGHT < LCD_WIDTH ? LCD_HEIGHT : LCD_WIDTH)
|
#define LCD_RES_MIN (LCD_HEIGHT < LCD_WIDTH ? LCD_HEIGHT : LCD_WIDTH)
|
||||||
#define BAR_PADDING (LCD_RES_MIN / 32)
|
#define BAR_PADDING (LCD_RES_MIN / 32)
|
||||||
#define BAR_Y (LCD_HEIGHT * 3 / 4)
|
#define BAR_Y (LCD_HEIGHT * 3 / 4)
|
||||||
|
|
@ -238,7 +236,8 @@ int bar_grad_y;
|
||||||
#define NOTE_INDEX_G 6
|
#define NOTE_INDEX_G 6
|
||||||
#define NOTE_INDEX_SHARP 7
|
#define NOTE_INDEX_SHARP 7
|
||||||
#define NOTE_INDEX_FLAT 8
|
#define NOTE_INDEX_FLAT 8
|
||||||
const struct picture note_bitmaps =
|
|
||||||
|
static const struct picture note_bitmaps =
|
||||||
{
|
{
|
||||||
pitch_notes,
|
pitch_notes,
|
||||||
BMPWIDTH_pitch_notes,
|
BMPWIDTH_pitch_notes,
|
||||||
|
|
@ -261,16 +260,13 @@ static int16_t iram_audio_data[BUFFER_SIZE] IBSS_ATTR;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Description of a note of scale */
|
/* Notes within one (reference) scale */
|
||||||
struct note_entry
|
static const struct
|
||||||
{
|
{
|
||||||
const char *name; /* Name of the note, e.g. "A#" */
|
const char *name; /* Name of the note, e.g. "A#" */
|
||||||
const fixed freq; /* Note frequency, Hz */
|
const fixed freq; /* Note frequency, Hz */
|
||||||
const fixed logfreq; /* log2(frequency) */
|
const fixed logfreq; /* log2(frequency) */
|
||||||
};
|
} notes[] =
|
||||||
|
|
||||||
/* Notes within one (reference) scale */
|
|
||||||
static const struct note_entry notes[] =
|
|
||||||
{
|
{
|
||||||
{"A" , float2fixed(440.0000000f), float2fixed(8.781359714f)},
|
{"A" , float2fixed(440.0000000f), float2fixed(8.781359714f)},
|
||||||
{"A#", float2fixed(466.1637615f), float2fixed(8.864693047f)},
|
{"A#", float2fixed(466.1637615f), float2fixed(8.864693047f)},
|
||||||
|
|
@ -295,7 +291,7 @@ static int bar_x_0;
|
||||||
static int lbl_x_minus_50, lbl_x_minus_20, lbl_x_0, lbl_x_20, lbl_x_50;
|
static int lbl_x_minus_50, lbl_x_minus_20, lbl_x_0, lbl_x_20, lbl_x_50;
|
||||||
|
|
||||||
/* Settings for the plugin */
|
/* Settings for the plugin */
|
||||||
struct tuner_settings
|
static struct tuner_settings
|
||||||
{
|
{
|
||||||
unsigned volume_threshold;
|
unsigned volume_threshold;
|
||||||
unsigned record_gain;
|
unsigned record_gain;
|
||||||
|
|
@ -305,7 +301,7 @@ struct tuner_settings
|
||||||
int freq_A; /* Index of the frequency of A */
|
int freq_A; /* Index of the frequency of A */
|
||||||
bool use_sharps;
|
bool use_sharps;
|
||||||
bool display_hz;
|
bool display_hz;
|
||||||
} tuner_settings;
|
} settings;
|
||||||
|
|
||||||
/*=================================================================*/
|
/*=================================================================*/
|
||||||
/* Settings loading and saving(adapted from the clock plugin) */
|
/* Settings loading and saving(adapted from the clock plugin) */
|
||||||
|
|
@ -313,98 +309,68 @@ struct tuner_settings
|
||||||
|
|
||||||
#define SETTINGS_FILENAME PLUGIN_APPS_DIR "/.pitch_settings"
|
#define SETTINGS_FILENAME PLUGIN_APPS_DIR "/.pitch_settings"
|
||||||
|
|
||||||
enum message
|
|
||||||
{
|
|
||||||
MESSAGE_LOADING,
|
|
||||||
MESSAGE_LOADED,
|
|
||||||
MESSAGE_ERRLOAD,
|
|
||||||
MESSAGE_SAVING,
|
|
||||||
MESSAGE_SAVED,
|
|
||||||
MESSAGE_ERRSAVE
|
|
||||||
};
|
|
||||||
|
|
||||||
enum settings_file_status
|
|
||||||
{
|
|
||||||
LOADED, ERRLOAD,
|
|
||||||
SAVED, ERRSAVE
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The settings as they exist on the hard disk, so that
|
/* The settings as they exist on the hard disk, so that
|
||||||
* we can know at saving time if changes have been made */
|
* we can know at saving time if changes have been made */
|
||||||
struct tuner_settings hdd_tuner_settings;
|
static struct tuner_settings hdd_settings;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
|
|
||||||
bool settings_needs_saving(struct tuner_settings* settings)
|
static bool settings_needs_saving(void)
|
||||||
{
|
{
|
||||||
return(rb->memcmp(settings, &hdd_tuner_settings, sizeof(*settings)));
|
return(rb->memcmp(&settings, &hdd_settings, sizeof(settings)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
|
|
||||||
void tuner_settings_reset(struct tuner_settings* settings)
|
static void tuner_settings_reset(void)
|
||||||
{
|
{
|
||||||
settings->volume_threshold = VOLUME_THRESHOLD;
|
settings = (struct tuner_settings) {
|
||||||
settings->record_gain = rb->global_settings->rec_mic_gain;
|
.volume_threshold = VOLUME_THRESHOLD,
|
||||||
settings->sample_size = BUFFER_SIZE;
|
.record_gain = rb->global_settings->rec_mic_gain,
|
||||||
settings->lowest_freq = period2freq(BUFFER_SIZE / 4);
|
.sample_size = BUFFER_SIZE,
|
||||||
settings->yin_threshold = DEFAULT_YIN_THRESHOLD;
|
.lowest_freq = period2freq(BUFFER_SIZE / 4),
|
||||||
settings->freq_A = DEFAULT_FREQ_A;
|
.yin_threshold = DEFAULT_YIN_THRESHOLD,
|
||||||
settings->use_sharps = true;
|
.freq_A = DEFAULT_FREQ_A,
|
||||||
settings->display_hz = false;
|
.use_sharps = true,
|
||||||
|
.display_hz = false,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
|
|
||||||
enum settings_file_status tuner_settings_load(struct tuner_settings* settings,
|
static void load_settings(void)
|
||||||
char* filename)
|
|
||||||
{
|
{
|
||||||
int fd = rb->open(filename, O_RDONLY);
|
int fd = rb->open(SETTINGS_FILENAME, O_RDONLY);
|
||||||
if(fd >= 0){ /* does file exist? */
|
if(fd < 0){ /* file doesn't exist */
|
||||||
/* basic consistency check */
|
|
||||||
if(rb->filesize(fd) == sizeof(*settings)){
|
|
||||||
rb->read(fd, settings, sizeof(*settings));
|
|
||||||
rb->close(fd);
|
|
||||||
rb->memcpy(&hdd_tuner_settings, settings, sizeof(*settings));
|
|
||||||
return(LOADED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Initializes the settings with default values at least */
|
/* Initializes the settings with default values at least */
|
||||||
tuner_settings_reset(settings);
|
tuner_settings_reset();
|
||||||
return(ERRLOAD);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
/* basic consistency check */
|
||||||
|
if(rb->filesize(fd) == sizeof(settings)){
|
||||||
|
rb->read(fd, &settings, sizeof(settings));
|
||||||
|
rb->memcpy(&hdd_settings, &settings, sizeof(settings));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
tuner_settings_reset();
|
||||||
|
}
|
||||||
|
|
||||||
enum settings_file_status tuner_settings_save(struct tuner_settings* settings,
|
|
||||||
char* filename)
|
|
||||||
{
|
|
||||||
int fd = rb->creat(filename, 0666);
|
|
||||||
if(fd >= 0){ /* does file exist? */
|
|
||||||
rb->write (fd, settings, sizeof(*settings));
|
|
||||||
rb->close(fd);
|
rb->close(fd);
|
||||||
return(SAVED);
|
|
||||||
}
|
|
||||||
return(ERRSAVE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
|
|
||||||
void load_settings(void)
|
static void save_settings(void)
|
||||||
{
|
{
|
||||||
tuner_settings_load(&tuner_settings, SETTINGS_FILENAME);
|
if(!settings_needs_saving())
|
||||||
|
|
||||||
rb->storage_sleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void save_settings(void)
|
|
||||||
{
|
|
||||||
if(!settings_needs_saving(&tuner_settings))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tuner_settings_save(&tuner_settings, SETTINGS_FILENAME);
|
int fd = rb->creat(SETTINGS_FILENAME, 0666);
|
||||||
|
if(fd >= 0){ /* does file exist? */
|
||||||
|
rb->write (fd, &settings, sizeof(settings));
|
||||||
|
rb->close(fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*=================================================================*/
|
/*=================================================================*/
|
||||||
|
|
@ -447,21 +413,21 @@ static const struct opt_items accidental_text[] =
|
||||||
{ "Sharp", -1 },
|
{ "Sharp", -1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
void set_min_freq(int new_freq)
|
static void set_min_freq(int new_freq)
|
||||||
{
|
{
|
||||||
tuner_settings.sample_size = freq2period(new_freq) * 4;
|
settings.sample_size = freq2period(new_freq) * 4;
|
||||||
|
|
||||||
/* clamp the sample size between min and max */
|
/* clamp the sample size between min and max */
|
||||||
if(tuner_settings.sample_size <= SAMPLE_SIZE_MIN)
|
if(settings.sample_size <= SAMPLE_SIZE_MIN)
|
||||||
tuner_settings.sample_size = SAMPLE_SIZE_MIN;
|
settings.sample_size = SAMPLE_SIZE_MIN;
|
||||||
else if(tuner_settings.sample_size >= BUFFER_SIZE)
|
else if(settings.sample_size >= BUFFER_SIZE)
|
||||||
tuner_settings.sample_size = BUFFER_SIZE;
|
settings.sample_size = BUFFER_SIZE;
|
||||||
|
|
||||||
/* sample size must be divisible by 4 - round up */
|
/* sample size must be divisible by 4 - round up */
|
||||||
tuner_settings.sample_size = (tuner_settings.sample_size + 3) & ~3;
|
settings.sample_size = (settings.sample_size + 3) & ~3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool main_menu(void)
|
static bool main_menu(void)
|
||||||
{
|
{
|
||||||
int selection = 0;
|
int selection = 0;
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
@ -494,18 +460,18 @@ bool main_menu(void)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
rb->set_int("Volume Threshold", "%", UNIT_INT,
|
rb->set_int("Volume Threshold", "%", UNIT_INT,
|
||||||
&tuner_settings.volume_threshold,
|
&settings.volume_threshold,
|
||||||
NULL, 5, 5, 95, NULL);
|
NULL, 5, 5, 95, NULL);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
rb->set_int("Listening Volume", "%", UNIT_INT,
|
rb->set_int("Listening Volume", "%", UNIT_INT,
|
||||||
&tuner_settings.record_gain,
|
&settings.record_gain,
|
||||||
NULL, 1, rb->sound_min(SOUND_MIC_GAIN),
|
NULL, 1, rb->sound_min(SOUND_MIC_GAIN),
|
||||||
rb->sound_max(SOUND_MIC_GAIN), NULL);
|
rb->sound_max(SOUND_MIC_GAIN), NULL);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
rb->set_int("Lowest Frequency", "Hz", UNIT_INT,
|
rb->set_int("Lowest Frequency", "Hz", UNIT_INT,
|
||||||
&tuner_settings.lowest_freq, set_min_freq, 1,
|
&settings.lowest_freq, set_min_freq, 1,
|
||||||
/* Range depends on the size of the buffer */
|
/* Range depends on the size of the buffer */
|
||||||
sample_rate / (BUFFER_SIZE / 4),
|
sample_rate / (BUFFER_SIZE / 4),
|
||||||
sample_rate / (SAMPLE_SIZE_MIN / 4), NULL);
|
sample_rate / (SAMPLE_SIZE_MIN / 4), NULL);
|
||||||
|
|
@ -513,33 +479,33 @@ bool main_menu(void)
|
||||||
case 4:
|
case 4:
|
||||||
rb->set_option(
|
rb->set_option(
|
||||||
"Algorithm Pickiness (Lower -> more discriminating)",
|
"Algorithm Pickiness (Lower -> more discriminating)",
|
||||||
&tuner_settings.yin_threshold,
|
&settings.yin_threshold,
|
||||||
INT, yin_threshold_text,
|
INT, yin_threshold_text,
|
||||||
sizeof(yin_threshold_text) / sizeof(yin_threshold_text[0]),
|
sizeof(yin_threshold_text) / sizeof(yin_threshold_text[0]),
|
||||||
NULL);
|
NULL);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
rb->set_option("Display Accidentals As",
|
rb->set_option("Display Accidentals As",
|
||||||
&tuner_settings.use_sharps,
|
&settings.use_sharps,
|
||||||
BOOL, accidental_text, 2, NULL);
|
BOOL, accidental_text, 2, NULL);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
rb->set_bool("Display Frequency (Hz)",
|
rb->set_bool("Display Frequency (Hz)",
|
||||||
&tuner_settings.display_hz);
|
&settings.display_hz);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
freq_val = freq_A[tuner_settings.freq_A].frequency;
|
freq_val = freq_A[settings.freq_A].frequency;
|
||||||
rb->set_int("Frequency of A (Hz)",
|
rb->set_int("Frequency of A (Hz)",
|
||||||
"Hz", UNIT_INT, &freq_val, NULL,
|
"Hz", UNIT_INT, &freq_val, NULL,
|
||||||
1, freq_A[0].frequency, freq_A[NUM_FREQ_A-1].frequency,
|
1, freq_A[0].frequency, freq_A[NUM_FREQ_A-1].frequency,
|
||||||
NULL);
|
NULL);
|
||||||
tuner_settings.freq_A = freq_val - freq_A[0].frequency;
|
settings.freq_A = freq_val - freq_A[0].frequency;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
reset = false;
|
reset = false;
|
||||||
rb->set_bool("Reset Tuner Settings?", &reset);
|
rb->set_bool("Reset Tuner Settings?", &reset);
|
||||||
if (reset)
|
if (reset)
|
||||||
tuner_settings_reset(&tuner_settings);
|
tuner_settings_reset();
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
exit_tuner = true;
|
exit_tuner = true;
|
||||||
|
|
@ -565,7 +531,7 @@ bool main_menu(void)
|
||||||
/* Adapted from python code at
|
/* Adapted from python code at
|
||||||
http://en.wikipedia.org/wiki/Binary_logarithm#Algorithm
|
http://en.wikipedia.org/wiki/Binary_logarithm#Algorithm
|
||||||
*/
|
*/
|
||||||
fixed log(fixed inp)
|
static fixed log(fixed inp)
|
||||||
{
|
{
|
||||||
fixed x = inp;
|
fixed x = inp;
|
||||||
fixed fp = int2fixed(1);
|
fixed fp = int2fixed(1);
|
||||||
|
|
@ -611,42 +577,8 @@ fixed log(fixed inp)
|
||||||
/* GUI Stuff */
|
/* GUI Stuff */
|
||||||
/*=================================================================*/
|
/*=================================================================*/
|
||||||
|
|
||||||
/* The function name is pretty self-explaining ;) */
|
|
||||||
void print_int_xy(int x, int y, int v)
|
|
||||||
{
|
|
||||||
char temp[20];
|
|
||||||
#if LCD_DEPTH > 1
|
|
||||||
rb->lcd_set_foreground(front_color);
|
|
||||||
#endif
|
|
||||||
rb->snprintf(temp,20,"%d",v);
|
|
||||||
rb->lcd_putsxy(x,y,temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print out the frequency etc */
|
|
||||||
void print_str(char* s)
|
|
||||||
{
|
|
||||||
#if LCD_DEPTH > 1
|
|
||||||
rb->lcd_set_foreground(front_color);
|
|
||||||
#endif
|
|
||||||
rb->lcd_putsxy(0, HZ_Y, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* What can I say? Read the function name... */
|
|
||||||
void print_char_xy(int x, int y, char c)
|
|
||||||
{
|
|
||||||
char temp[2];
|
|
||||||
|
|
||||||
temp[0]=c;
|
|
||||||
temp[1]=0;
|
|
||||||
#if LCD_DEPTH > 1
|
|
||||||
rb->lcd_set_foreground(front_color);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rb->lcd_putsxy(x, y, temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Draw the note bitmap */
|
/* Draw the note bitmap */
|
||||||
void draw_note(const char *note)
|
static void draw_note(const char *note)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int note_x = (LCD_WIDTH - BMPWIDTH_pitch_notes) / 2;
|
int note_x = (LCD_WIDTH - BMPWIDTH_pitch_notes) / 2;
|
||||||
|
|
@ -656,7 +588,7 @@ void draw_note(const char *note)
|
||||||
|
|
||||||
if(note[1] == '#')
|
if(note[1] == '#')
|
||||||
{
|
{
|
||||||
if(!(tuner_settings.use_sharps))
|
if(!(settings.use_sharps))
|
||||||
{
|
{
|
||||||
i = (i + 1) % 7;
|
i = (i + 1) % 7;
|
||||||
accidental_index = NOTE_INDEX_FLAT;
|
accidental_index = NOTE_INDEX_FLAT;
|
||||||
|
|
@ -674,8 +606,9 @@ void draw_note(const char *note)
|
||||||
note_x,
|
note_x,
|
||||||
note_y);
|
note_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw the red bar and the white lines */
|
/* Draw the red bar and the white lines */
|
||||||
void draw_bar(fixed wrong_by_cents)
|
static void draw_bar(fixed wrong_by_cents)
|
||||||
{
|
{
|
||||||
unsigned n;
|
unsigned n;
|
||||||
int x;
|
int x;
|
||||||
|
|
@ -698,11 +631,14 @@ void draw_bar(fixed wrong_by_cents)
|
||||||
rb->lcd_vline(x, BAR_HLINE_Y, BAR_HLINE_Y2);
|
rb->lcd_vline(x, BAR_HLINE_Y, BAR_HLINE_Y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
print_int_xy(lbl_x_minus_50 ,bar_grad_y, -50);
|
#if LCD_DEPTH > 1
|
||||||
print_int_xy(lbl_x_minus_20 ,bar_grad_y, -20);
|
rb->lcd_set_foreground(front_color);
|
||||||
print_int_xy(lbl_x_0 ,bar_grad_y, 0);
|
#endif
|
||||||
print_int_xy(lbl_x_20 ,bar_grad_y, 20);
|
rb->lcd_putsf(lbl_x_minus_50 ,bar_grad_y, "%d", -50);
|
||||||
print_int_xy(lbl_x_50 ,bar_grad_y, 50);
|
rb->lcd_putsf(lbl_x_minus_20 ,bar_grad_y, "%d", -20);
|
||||||
|
rb->lcd_putsf(lbl_x_0 ,bar_grad_y, "%d", 0);
|
||||||
|
rb->lcd_putsf(lbl_x_20 ,bar_grad_y, "%d", 20);
|
||||||
|
rb->lcd_putsf(lbl_x_50 ,bar_grad_y, "%d", 50);
|
||||||
|
|
||||||
#ifdef HAVE_LCD_COLOR
|
#ifdef HAVE_LCD_COLOR
|
||||||
rb->lcd_set_foreground(LCD_RGBPACK(255,0,0)); /* Color screens */
|
rb->lcd_set_foreground(LCD_RGBPACK(255,0,0)); /* Color screens */
|
||||||
|
|
@ -725,13 +661,12 @@ void draw_bar(fixed wrong_by_cents)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate how wrong the note is and draw the GUI */
|
/* Calculate how wrong the note is and draw the GUI */
|
||||||
void display_frequency (fixed freq)
|
static void display_frequency (fixed freq)
|
||||||
{
|
{
|
||||||
fixed ldf, mldf;
|
fixed ldf, mldf;
|
||||||
fixed lfreq, nfreq;
|
fixed lfreq, nfreq;
|
||||||
fixed orig_freq;
|
fixed orig_freq;
|
||||||
int i, note = 0;
|
int i, note = 0;
|
||||||
char str_buf[30];
|
|
||||||
|
|
||||||
if (fp_lt(freq, FP_LOW))
|
if (fp_lt(freq, FP_LOW))
|
||||||
freq = FP_LOW;
|
freq = FP_LOW;
|
||||||
|
|
@ -739,8 +674,8 @@ void display_frequency (fixed freq)
|
||||||
/* We calculate the frequency and its log as if */
|
/* We calculate the frequency and its log as if */
|
||||||
/* the reference frequency of A were 440 Hz. */
|
/* the reference frequency of A were 440 Hz. */
|
||||||
orig_freq = freq;
|
orig_freq = freq;
|
||||||
lfreq = fp_add(log(freq), freq_A[tuner_settings.freq_A].logratio);
|
lfreq = fp_add(log(freq), freq_A[settings.freq_A].logratio);
|
||||||
freq = fp_mul(freq, freq_A[tuner_settings.freq_A].ratio);
|
freq = fp_mul(freq, freq_A[settings.freq_A].ratio);
|
||||||
|
|
||||||
/* This calculates a log freq offset for note A */
|
/* This calculates a log freq offset for note A */
|
||||||
/* Get the frequency to within the range of our reference table, */
|
/* Get the frequency to within the range of our reference table, */
|
||||||
|
|
@ -775,13 +710,15 @@ void display_frequency (fixed freq)
|
||||||
if(fp_round(freq) != 0)
|
if(fp_round(freq) != 0)
|
||||||
{
|
{
|
||||||
draw_note(notes[note].name);
|
draw_note(notes[note].name);
|
||||||
if(tuner_settings.display_hz)
|
if(settings.display_hz)
|
||||||
{
|
{
|
||||||
rb->snprintf(str_buf,30, "%s : %d cents (%d.%02dHz)",
|
#if LCD_DEPTH > 1
|
||||||
|
rb->lcd_set_foreground(front_color);
|
||||||
|
#endif
|
||||||
|
rb->lcd_putsf(0, HZ_Y, "%s : %d cents (%d.%02dHz)",
|
||||||
notes[note].name, fp_round(ldf) ,fixed2int(orig_freq),
|
notes[note].name, fp_round(ldf) ,fixed2int(orig_freq),
|
||||||
fp_round(fp_mul(fp_frac(orig_freq),
|
fp_round(fp_mul(fp_frac(orig_freq),
|
||||||
int2fixed(DISPLAY_HZ_PRECISION))));
|
int2fixed(DISPLAY_HZ_PRECISION))));
|
||||||
print_str(str_buf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rb->lcd_update();
|
rb->lcd_update();
|
||||||
|
|
@ -803,7 +740,7 @@ void display_frequency (fixed freq)
|
||||||
-------------------------------------------------------------------------*/
|
-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* Find the index of the minimum element of an array of floats */
|
/* Find the index of the minimum element of an array of floats */
|
||||||
unsigned vec_min_elem(fixed *s, unsigned buflen)
|
static unsigned vec_min_elem(fixed *s, unsigned buflen)
|
||||||
{
|
{
|
||||||
unsigned j, pos=0.0f;
|
unsigned j, pos=0.0f;
|
||||||
fixed tmp = s[0];
|
fixed tmp = s[0];
|
||||||
|
|
@ -873,7 +810,7 @@ static inline fixed aubio_quadfrac(fixed s0, fixed s1, fixed s2, fixed pf)
|
||||||
|
|
||||||
#define QUADINT_STEP float2fixed(1.0f/200.0f)
|
#define QUADINT_STEP float2fixed(1.0f/200.0f)
|
||||||
|
|
||||||
fixed ICODE_ATTR vec_quadint_min(fixed *x, unsigned bufsize, unsigned pos, unsigned span)
|
static fixed ICODE_ATTR vec_quadint_min(fixed *x, unsigned bufsize, unsigned pos, unsigned span)
|
||||||
{
|
{
|
||||||
fixed res, frac, s0, s1, s2;
|
fixed res, frac, s0, s1, s2;
|
||||||
fixed exactpos = int2fixed(pos);
|
fixed exactpos = int2fixed(pos);
|
||||||
|
|
@ -920,12 +857,12 @@ fixed ICODE_ATTR vec_quadint_min(fixed *x, unsigned bufsize, unsigned pos, unsig
|
||||||
/* The yin pointer is just a buffer that the algorithm uses as a work
|
/* The yin pointer is just a buffer that the algorithm uses as a work
|
||||||
space. It needs to be half the length of the input buffer. */
|
space. It needs to be half the length of the input buffer. */
|
||||||
|
|
||||||
fixed ICODE_ATTR pitchyin(int16_t *input, fixed *yin)
|
static fixed ICODE_ATTR pitchyin(int16_t *input, fixed *yin)
|
||||||
{
|
{
|
||||||
fixed retval;
|
fixed retval;
|
||||||
unsigned j,tau = 0;
|
unsigned j,tau = 0;
|
||||||
int period;
|
int period;
|
||||||
unsigned yin_size = tuner_settings.sample_size / 4;
|
unsigned yin_size = settings.sample_size / 4;
|
||||||
|
|
||||||
fixed tmp = FP_ZERO, tmp2 = FP_ZERO;
|
fixed tmp = FP_ZERO, tmp2 = FP_ZERO;
|
||||||
yin[0] = int2fixed(1);
|
yin[0] = int2fixed(1);
|
||||||
|
|
@ -945,7 +882,7 @@ fixed ICODE_ATTR pitchyin(int16_t *input, fixed *yin)
|
||||||
}
|
}
|
||||||
period = tau - 3;
|
period = tau - 3;
|
||||||
if(tau > 4 && fp_lt(yin[period],
|
if(tau > 4 && fp_lt(yin[period],
|
||||||
yin_threshold_table[tuner_settings.yin_threshold])
|
yin_threshold_table[settings.yin_threshold])
|
||||||
&& fp_lt(yin[period], yin[period+1]))
|
&& fp_lt(yin[period], yin[period+1]))
|
||||||
{
|
{
|
||||||
retval = vec_quadint_min(yin, yin_size, period, 1);
|
retval = vec_quadint_min(yin, yin_size, period, 1);
|
||||||
|
|
@ -960,11 +897,11 @@ fixed ICODE_ATTR pitchyin(int16_t *input, fixed *yin)
|
||||||
|
|
||||||
/*-----------------------------------------------------------------*/
|
/*-----------------------------------------------------------------*/
|
||||||
|
|
||||||
uint32_t ICODE_ATTR buffer_magnitude(int16_t *input)
|
static uint32_t ICODE_ATTR buffer_magnitude(int16_t *input)
|
||||||
{
|
{
|
||||||
unsigned n;
|
unsigned n;
|
||||||
uint64_t tally = 0;
|
uint64_t tally = 0;
|
||||||
const unsigned size = tuner_settings.sample_size;
|
const unsigned size = settings.sample_size;
|
||||||
|
|
||||||
/* Operate on only one channel of the stereo signal */
|
/* Operate on only one channel of the stereo signal */
|
||||||
for(n = 0; n < size; n+=2)
|
for(n = 0; n < size; n+=2)
|
||||||
|
|
@ -982,7 +919,7 @@ uint32_t ICODE_ATTR buffer_magnitude(int16_t *input)
|
||||||
|
|
||||||
/* Stop the recording when the buffer is full */
|
/* Stop the recording when the buffer is full */
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
void recording_callback(int status, void **start, size_t *size)
|
static void recording_callback(int status, void **start, size_t *size)
|
||||||
{
|
{
|
||||||
int tail = audio_tail ^ 1;
|
int tail = audio_tail ^ 1;
|
||||||
|
|
||||||
|
|
@ -1009,7 +946,7 @@ static void record_data(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The main program loop */
|
/* The main program loop */
|
||||||
void record_and_get_pitch(void)
|
static void record_and_get_pitch(void)
|
||||||
{
|
{
|
||||||
int quit=0, button;
|
int quit=0, button;
|
||||||
bool redraw = true;
|
bool redraw = true;
|
||||||
|
|
@ -1060,7 +997,7 @@ void record_and_get_pitch(void)
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
/* Only do the heavy lifting if the volume is high enough */
|
/* Only do the heavy lifting if the volume is high enough */
|
||||||
if(buffer_magnitude(audio_data[audio_head]) >
|
if(buffer_magnitude(audio_data[audio_head]) >
|
||||||
sqr(tuner_settings.volume_threshold *
|
sqr(settings.volume_threshold *
|
||||||
rb->sound_max(SOUND_MIC_GAIN)))
|
rb->sound_max(SOUND_MIC_GAIN)))
|
||||||
{
|
{
|
||||||
waiting = false;
|
waiting = false;
|
||||||
|
|
@ -1071,7 +1008,7 @@ void record_and_get_pitch(void)
|
||||||
#endif
|
#endif
|
||||||
#ifdef PLUGIN_USE_IRAM
|
#ifdef PLUGIN_USE_IRAM
|
||||||
rb->memcpy(iram_audio_data, audio_data[audio_head],
|
rb->memcpy(iram_audio_data, audio_data[audio_head],
|
||||||
tuner_settings.sample_size * sizeof (int16_t));
|
settings.sample_size * sizeof (int16_t));
|
||||||
#endif
|
#endif
|
||||||
/* This returns the period of the detected pitch in samples */
|
/* This returns the period of the detected pitch in samples */
|
||||||
period = pitchyin(iram_audio_data, yin_buffer);
|
period = pitchyin(iram_audio_data, yin_buffer);
|
||||||
|
|
@ -1115,7 +1052,7 @@ void record_and_get_pitch(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init recording, tuning, and GUI */
|
/* Init recording, tuning, and GUI */
|
||||||
void init_everything(void)
|
static void init_everything(void)
|
||||||
{
|
{
|
||||||
/* Disable all talking before initializing IRAM */
|
/* Disable all talking before initializing IRAM */
|
||||||
rb->talk_disable(true);
|
rb->talk_disable(true);
|
||||||
|
|
@ -1123,6 +1060,7 @@ void init_everything(void)
|
||||||
PLUGIN_IRAM_INIT(rb);
|
PLUGIN_IRAM_INIT(rb);
|
||||||
|
|
||||||
load_settings();
|
load_settings();
|
||||||
|
rb->storage_sleep();
|
||||||
|
|
||||||
/* Stop all playback (if no IRAM, otherwise IRAM_INIT would have) */
|
/* Stop all playback (if no IRAM, otherwise IRAM_INIT would have) */
|
||||||
rb->plugin_get_audio_buffer(NULL);
|
rb->plugin_get_audio_buffer(NULL);
|
||||||
|
|
@ -1132,8 +1070,8 @@ void init_everything(void)
|
||||||
rb->audio_set_input_source(INPUT_TYPE, SRCF_RECORDING);
|
rb->audio_set_input_source(INPUT_TYPE, SRCF_RECORDING);
|
||||||
|
|
||||||
/* set to maximum gain */
|
/* set to maximum gain */
|
||||||
rb->audio_set_recording_gain(tuner_settings.record_gain,
|
rb->audio_set_recording_gain(settings.record_gain,
|
||||||
tuner_settings.record_gain,
|
settings.record_gain,
|
||||||
AUDIO_GAIN_MIC);
|
AUDIO_GAIN_MIC);
|
||||||
|
|
||||||
/* Highest C on piano is approx 4.186 kHz, so we need just over
|
/* Highest C on piano is approx 4.186 kHz, so we need just over
|
||||||
|
|
@ -1145,8 +1083,8 @@ void init_everything(void)
|
||||||
rb->pcm_init_recording();
|
rb->pcm_init_recording();
|
||||||
|
|
||||||
/* avoid divsion by zero */
|
/* avoid divsion by zero */
|
||||||
if(tuner_settings.lowest_freq == 0)
|
if(settings.lowest_freq == 0)
|
||||||
tuner_settings.lowest_freq = period2freq(BUFFER_SIZE / 4);
|
settings.lowest_freq = period2freq(BUFFER_SIZE / 4);
|
||||||
|
|
||||||
/* GUI */
|
/* GUI */
|
||||||
#if LCD_DEPTH > 1
|
#if LCD_DEPTH > 1
|
||||||
|
|
@ -1179,5 +1117,5 @@ enum plugin_status plugin_start(const void* parameter) NO_PROF_ATTR
|
||||||
record_and_get_pitch();
|
record_and_get_pitch();
|
||||||
save_settings();
|
save_settings();
|
||||||
|
|
||||||
return 0;
|
return PLUGIN_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue