blob: 955a2c095332c23c20997edf22642b3ed7470d7b [file] [log] [blame] [edit]
/*
* BRLTTY - A background process providing access to the console screen (when in
* text mode) for a blind person using a refreshable braille display.
*
* Copyright (C) 1995-2023 by The BRLTTY Developers.
*
* BRLTTY comes with ABSOLUTELY NO WARRANTY.
*
* This is free software, placed under the terms of the
* GNU Lesser General Public License, as published by the Free Software
* Foundation; either version 2.1 of the License, or (at your option) any
* later version. Please see the file LICENSE-LGPL for details.
*
* Web Page: http://brltty.app/
*
* This software is maintained by Dave Mielke <dave@mielke.cc>.
*/
#include "prologue.h"
#include "notes.h"
#define NOTE_FREQUENCY_FACTOR 1000
static const uint32_t scaledNoteFrequencies[] = {
/* 0 rest */ 0,
/* 1 -1C# */ 8662,
/* 2 -1D */ 9177,
/* 3 -1D# */ 9723,
/* 4 -1E */ 10301,
/* 5 -1F */ 10913,
/* 6 -1F# */ 11562,
/* 7 -1G */ 12250,
/* 8 -1G# */ 12978,
/* 9 -1A */ 13750,
/* 10 -1A# */ 14568,
/* 11 -1B */ 15434,
/* 12 0C */ 16352,
/* 13 0C# */ 17324,
/* 14 0D */ 18354,
/* 15 0D# */ 19445,
/* 16 0E */ 20602,
/* 17 0F */ 21827,
/* 18 0F# */ 23125,
/* 19 0G */ 24500,
/* 20 0G# */ 25957,
/* 21 0A */ 27500,
/* 22 0A# */ 29135,
/* 23 0B */ 30868,
/* 24 1C */ 32703,
/* 25 1C# */ 34648,
/* 26 1D */ 36708,
/* 27 1D# */ 38891,
/* 28 1E */ 41203,
/* 29 1F */ 43654,
/* 30 1F# */ 46249,
/* 31 1G */ 48999,
/* 32 1G# */ 51913,
/* 33 1A */ 55000,
/* 34 1A# */ 58270,
/* 35 1B */ 61735,
/* 36 2C */ 65406,
/* 37 2C# */ 69296,
/* 38 2D */ 73416,
/* 39 2D# */ 77782,
/* 40 2E */ 82407,
/* 41 2F */ 87307,
/* 42 2F# */ 92499,
/* 43 2G */ 97999,
/* 44 2G# */ 103826,
/* 45 2A */ 110000,
/* 46 2A# */ 116541,
/* 47 2B */ 123471,
/* 48 3C */ 130813,
/* 49 3C# */ 138591,
/* 50 3D */ 146832,
/* 51 3D# */ 155563,
/* 52 3E */ 164814,
/* 53 3F */ 174614,
/* 54 3F# */ 184997,
/* 55 3G */ 195998,
/* 56 3G# */ 207652,
/* 57 3A */ 220000,
/* 58 3A# */ 233082,
/* 59 3B */ 246942,
/* 60 4C */ 261626,
/* 61 4C# */ 277183,
/* 62 4D */ 293665,
/* 63 4D# */ 311127,
/* 64 4E */ 329628,
/* 65 4F */ 349228,
/* 66 4F# */ 369994,
/* 67 4G */ 391995,
/* 68 4G# */ 415305,
/* 69 4A */ 440000,
/* 70 4A# */ 466164,
/* 71 4B */ 493883,
/* 72 5C */ 523251,
/* 73 5C# */ 554365,
/* 74 5D */ 587330,
/* 75 5D# */ 622254,
/* 76 5E */ 659255,
/* 77 5F */ 698456,
/* 78 5F# */ 739989,
/* 79 5G */ 783991,
/* 80 5G# */ 830609,
/* 81 5A */ 880000,
/* 82 5A# */ 932328,
/* 83 5B */ 987767,
/* 84 6C */ 1046502,
/* 85 6C# */ 1108731,
/* 86 6D */ 1174659,
/* 87 6D# */ 1244508,
/* 88 6E */ 1318510,
/* 89 6F */ 1396913,
/* 90 6F# */ 1479978,
/* 91 6G */ 1567982,
/* 92 6G# */ 1661219,
/* 93 6A */ 1760000,
/* 94 6A# */ 1864655,
/* 95 6B */ 1975533,
/* 96 7C */ 2093005,
/* 97 7C# */ 2217461,
/* 98 7D */ 2349318,
/* 99 7D# */ 2489016,
/* 100 7E */ 2637020,
/* 101 7F */ 2793826,
/* 102 7F# */ 2959955,
/* 103 7G */ 3135963,
/* 104 7G# */ 3322438,
/* 105 7A */ 3520000,
/* 106 7A# */ 3729310,
/* 107 7B */ 3951066,
/* 108 8C */ 4186009,
/* 109 8C# */ 4434922,
/* 110 8D */ 4698636,
/* 111 8D# */ 4978032,
/* 112 8E */ 5274041,
/* 113 8F */ 5587652,
/* 114 8F# */ 5919911,
/* 115 8G */ 6271927,
/* 116 8G# */ 6644875,
/* 117 8A */ 7040000,
/* 118 8A# */ 7458620,
/* 119 8B */ 7902133,
/* 120 9C */ 8372018,
/* 121 9C# */ 8869844,
/* 122 9D */ 9397273,
/* 123 9D# */ 9956063,
/* 124 9E */ 10548082,
/* 125 9F */ 11175303,
/* 126 9F# */ 11839822,
/* 127 9G */ 12543854
};
unsigned char
getLowestNote (void) {
return 1;
}
unsigned char
getHighestNote (void) {
return ARRAY_COUNT(scaledNoteFrequencies) - 1;
}
static inline uint32_t
getScaledNoteFrequency (unsigned char note) {
unsigned char highestNote = getHighestNote();
if (note > highestNote) note = highestNote;
return scaledNoteFrequencies[note];
}
uint32_t
getIntegerNoteFrequency (unsigned char note) {
return getScaledNoteFrequency(note) / NOTE_FREQUENCY_FACTOR;
}
#ifndef NO_FLOAT
float
getRealNoteFrequency (unsigned char note) {
return (float)getScaledNoteFrequency(note) / (float)NOTE_FREQUENCY_FACTOR;
}
#endif /* NO_FLOAT */
unsigned char
getNearestNote (NoteFrequency frequency) {
if (!frequency) return 0;
unsigned char lowestNote = getLowestNote();
if (frequency <= getNoteFrequency(lowestNote)) return lowestNote;
unsigned char highestNote = getHighestNote();
if (frequency >= getNoteFrequency(highestNote)) return highestNote;
while (lowestNote <= highestNote) {
unsigned char currentNote = (lowestNote + highestNote) / 2;
if (frequency < getNoteFrequency(currentNote)) {
highestNote = currentNote - 1;
} else {
lowestNote = currentNote + 1;
}
}
unsigned char lowerNote = highestNote;
unsigned char higherNote = lowerNote + 1;
NoteFrequency lowerFrequency = getNoteFrequency(lowerNote);
NoteFrequency higherFrequency = getNoteFrequency(higherNote);
return ((frequency - lowerFrequency) < (higherFrequency - frequency))?
lowerNote: higherNote;
}