summaryrefslogtreecommitdiff
path: root/apps/plugins/pitch_detector.c
diff options
context:
space:
mode:
authorAlexander Levin <al.le@rockbox.org>2009-09-20 16:16:32 +0000
committerAlexander Levin <al.le@rockbox.org>2009-09-20 16:16:32 +0000
commit46bb567ec4df041426372afaae75931636575695 (patch)
tree1f887b2212f4e8d53a950ee8637a215f94169d93 /apps/plugins/pitch_detector.c
parent2474708498dfb197ea7a06567aacde5a9fec39b7 (diff)
downloadrockbox-46bb567ec4df041426372afaae75931636575695.tar.gz
rockbox-46bb567ec4df041426372afaae75931636575695.zip
Pitch Detector: add the possibility to set the reference frequency of A (last part of FS#8768)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22753 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/pitch_detector.c')
-rw-r--r--apps/plugins/pitch_detector.c91
1 files changed, 72 insertions, 19 deletions
diff --git a/apps/plugins/pitch_detector.c b/apps/plugins/pitch_detector.c
index 857d74afc4..eb3b56ca92 100644
--- a/apps/plugins/pitch_detector.c
+++ b/apps/plugins/pitch_detector.c
@@ -178,6 +178,37 @@ const fixed yin_threshold_table[] =
178 float2fixed(0.50), 178 float2fixed(0.50),
179}; 179};
180 180
181/* Structure for the reference frequency (frequency of A)
182 * It's used for scaling the frequency before finding out
183 * the note. The frequency is scaled in a way that the main
184 * algorithm can assume the frequency of A to be 440 Hz.
185 */
186struct freq_A_entry
187{
188 const int frequency; /* Frequency in Hz */
189 const fixed ratio; /* 440/frequency */
190 const fixed logratio; /* log2(factor) */
191};
192
193const struct freq_A_entry freq_A[] =
194{
195 {435, float2fixed(1.011363636), float2fixed( 0.016301812)},
196 {436, float2fixed(1.009090909), float2fixed( 0.013056153)},
197 {437, float2fixed(1.006818182), float2fixed( 0.009803175)},
198 {438, float2fixed(1.004545455), float2fixed( 0.006542846)},
199 {439, float2fixed(1.002272727), float2fixed( 0.003275132)},
200 {440, float2fixed(1.000000000), float2fixed( 0.000000000)},
201 {441, float2fixed(0.997727273), float2fixed(-0.003282584)},
202 {442, float2fixed(0.995454545), float2fixed(-0.006572654)},
203 {443, float2fixed(0.993181818), float2fixed(-0.009870244)},
204 {444, float2fixed(0.990909091), float2fixed(-0.013175389)},
205 {445, float2fixed(0.988636364), float2fixed(-0.016488123)},
206};
207
208/* Index of the entry for 440 Hz in the table (default frequency for A) */
209#define DEFAULT_FREQ_A 5
210#define NUM_FREQ_A (sizeof(freq_A)/sizeof(freq_A[0]))
211
181/* How loud the audio has to be to start displaying pitch */ 212/* How loud the audio has to be to start displaying pitch */
182/* Must be between 0 and 100 */ 213/* Must be between 0 and 100 */
183#define VOLUME_THRESHOLD (50) 214#define VOLUME_THRESHOLD (50)
@@ -279,8 +310,9 @@ struct tuner_settings
279 unsigned sample_size; 310 unsigned sample_size;
280 unsigned lowest_freq; 311 unsigned lowest_freq;
281 unsigned yin_threshold; 312 unsigned yin_threshold;
282 bool use_sharps; 313 int freq_A; /* Index of the frequency of A */
283 bool display_hz; 314 bool use_sharps;
315 bool display_hz;
284} tuner_settings; 316} tuner_settings;
285 317
286/*=================================================================*/ 318/*=================================================================*/
@@ -325,6 +357,7 @@ void tuner_settings_reset(struct tuner_settings* settings)
325 settings->sample_size = BUFFER_SIZE; 357 settings->sample_size = BUFFER_SIZE;
326 settings->lowest_freq = period2freq(BUFFER_SIZE / 4); 358 settings->lowest_freq = period2freq(BUFFER_SIZE / 4);
327 settings->yin_threshold = DEFAULT_YIN_THRESHOLD; 359 settings->yin_threshold = DEFAULT_YIN_THRESHOLD;
360 settings->freq_A = DEFAULT_FREQ_A;
328 settings->use_sharps = true; 361 settings->use_sharps = true;
329 settings->display_hz = false; 362 settings->display_hz = false;
330} 363}
@@ -454,11 +487,12 @@ void set_min_freq(int new_freq)
454 487
455bool main_menu(void) 488bool main_menu(void)
456{ 489{
457 int selection=0; 490 int selection = 0;
458 bool done = false; 491 bool done = false;
459 bool exit_tuner=false; 492 bool exit_tuner = false;
460 int choice; 493 int choice;
461 bool reset = false; 494 int freq_val;
495 bool reset;
462 496
463 MENUITEM_STRINGLIST(menu,"Tuner Settings",NULL, 497 MENUITEM_STRINGLIST(menu,"Tuner Settings",NULL,
464 "Return to Tuner", 498 "Return to Tuner",
@@ -468,6 +502,7 @@ bool main_menu(void)
468 "Algorithm Pickiness", 502 "Algorithm Pickiness",
469 "Accidentals", 503 "Accidentals",
470 "Display Frequency (Hz)", 504 "Display Frequency (Hz)",
505 "Frequency of A (Hz)",
471 "Reset Settings", 506 "Reset Settings",
472 "Quit"); 507 "Quit");
473 508
@@ -514,21 +549,31 @@ bool main_menu(void)
514 BOOL, noyes_text, 2, NULL); 549 BOOL, noyes_text, 2, NULL);
515 break; 550 break;
516 case 7: 551 case 7:
552 freq_val = freq_A[tuner_settings.freq_A].frequency;
553 rb->set_int("Frequency of A (Hz)",
554 "Hz", UNIT_INT, &freq_val, NULL,
555 1, freq_A[0].frequency, freq_A[NUM_FREQ_A-1].frequency,
556 NULL);
557 tuner_settings.freq_A = freq_val - freq_A[0].frequency;
558 break;
559 case 8:
560 reset = false;
517 rb->set_option("Reset Tuner Settings?", 561 rb->set_option("Reset Tuner Settings?",
518 &reset, 562 &reset,
519 BOOL, noyes_text, 2, tuner_settings_reset_query); 563 BOOL, noyes_text, 2, tuner_settings_reset_query);
520 break; 564 break;
521 case 8: 565 case 9:
522 exit_tuner = true; 566 exit_tuner = true;
567 done = true;
568 break;
523 case 0: 569 case 0:
524 default: 570 default:
525 /* Return to the tuner */ 571 /* Return to the tuner */
526 done = true; 572 done = true;
527 break; 573 break;
528
529 } 574 }
530 } 575 }
531 return(exit_tuner); 576 return exit_tuner;
532} 577}
533 578
534/*=================================================================*/ 579/*=================================================================*/
@@ -650,11 +695,11 @@ void draw_bar(fixed wrong_by_cents)
650 int x; 695 int x;
651 696
652#ifdef HAVE_LCD_COLOR 697#ifdef HAVE_LCD_COLOR
653 rb->lcd_set_foreground(LCD_RGBPACK(255,255,255)); /* Color screens */ 698 rb->lcd_set_foreground(LCD_RGBPACK(255,255,255)); /* Color screens */
654#elif LCD_DEPTH > 1 699#elif LCD_DEPTH > 1
655 rb->lcd_set_foreground(LCD_BLACK); /* Greyscale screens */ 700 rb->lcd_set_foreground(LCD_BLACK); /* Greyscale screens */
656#else 701#else
657 rb->lcd_set_foreground(LCD_BLACK); /* Black and white screens */ 702 rb->lcd_set_foreground(LCD_BLACK); /* Black and white screens */
658#endif 703#endif
659 704
660 rb->lcd_hline(0,LCD_WIDTH-1, BAR_HLINE_Y); 705 rb->lcd_hline(0,LCD_WIDTH-1, BAR_HLINE_Y);
@@ -702,14 +747,22 @@ void display_frequency (fixed freq)
702{ 747{
703 fixed ldf, mldf; 748 fixed ldf, mldf;
704 fixed lfreq, nfreq; 749 fixed lfreq, nfreq;
750 fixed orig_freq;
705 int i, note = 0; 751 int i, note = 0;
706 char str_buf[30]; 752 char str_buf[30];
707 753
708 if (fp_lt(freq, FP_LOW)) 754 if (fp_lt(freq, FP_LOW))
709 freq = FP_LOW; 755 freq = FP_LOW;
710 lfreq = log(freq); 756
711 757 /* We calculate the frequency and its log as if */
712 /* Get the frequency to within the range of our reference table */ 758 /* the reference frequency of A were 440 Hz. */
759 orig_freq = freq;
760 lfreq = fp_add(log(freq), freq_A[tuner_settings.freq_A].logratio);
761 freq = fp_mul(freq, freq_A[tuner_settings.freq_A].ratio);
762
763 /* This calculates a log freq offset for note A */
764 /* Get the frequency to within the range of our reference table, */
765 /* i.e. into the right octave. */
713 while (fp_lt(lfreq, fp_sub(lfreqs[0], fp_shr(LOG_D_NOTE, 1)))) 766 while (fp_lt(lfreq, fp_sub(lfreqs[0], fp_shr(LOG_D_NOTE, 1))))
714 lfreq = fp_add(lfreq, LOG_2); 767 lfreq = fp_add(lfreq, LOG_2);
715 while (fp_gte(lfreq, fp_sub(fp_add(lfreqs[0], LOG_2), 768 while (fp_gte(lfreq, fp_sub(fp_add(lfreqs[0], LOG_2),
@@ -722,19 +775,19 @@ void display_frequency (fixed freq)
722 fp_sub(lfreq,lfreqs[i]) : fp_neg(fp_sub(lfreq,lfreqs[i])); 775 fp_sub(lfreq,lfreqs[i]) : fp_neg(fp_sub(lfreq,lfreqs[i]));
723 if (fp_lt(ldf, mldf)) 776 if (fp_lt(ldf, mldf))
724 { 777 {
725 mldf = ldf; 778 mldf = ldf;
726 note = i; 779 note = i;
727 } 780 }
728 } 781 }
729 nfreq = freqs[note]; 782 nfreq = freqs[note];
730 while (fp_gt(fp_div(nfreq, freq), D_NOTE_SQRT)) 783 while (fp_gt(fp_div(nfreq, freq), D_NOTE_SQRT))
731 nfreq = fp_shr(nfreq, 1); 784 nfreq = fp_shr(nfreq, 1);
732 while (fp_gt(fp_div(freq, nfreq), D_NOTE_SQRT)) 785 while (fp_gt(fp_div(freq, nfreq), D_NOTE_SQRT))
733 { 786 {
734 nfreq = fp_shl(nfreq, 1); 787 nfreq = fp_shl(nfreq, 1);
735 } 788 }
736 789
737 ldf=fp_mul(int2fixed(1200), log(fp_div(freq,nfreq))); 790 ldf = fp_mul(int2fixed(1200), log(fp_div(freq,nfreq)));
738 791
739 rb->lcd_clear_display(); 792 rb->lcd_clear_display();
740 draw_bar(ldf); /* The red bar */ 793 draw_bar(ldf); /* The red bar */
@@ -744,8 +797,8 @@ void display_frequency (fixed freq)
744 if(tuner_settings.display_hz) 797 if(tuner_settings.display_hz)
745 { 798 {
746 rb->snprintf(str_buf,30, "%s : %d cents (%d.%02dHz)", 799 rb->snprintf(str_buf,30, "%s : %d cents (%d.%02dHz)",
747 notes[note], fp_round(ldf) ,fixed2int(freq), 800 notes[note], fp_round(ldf) ,fixed2int(orig_freq),
748 fp_round(fp_mul(fp_frac(freq), 801 fp_round(fp_mul(fp_frac(orig_freq),
749 int2fixed(DISPLAY_HZ_PRECISION)))); 802 int2fixed(DISPLAY_HZ_PRECISION))));
750 print_str(str_buf); 803 print_str(str_buf);
751 } 804 }