Import fmit upstream version 0.97.6
[fmit.git] / libs / Music / Music.h
1 // Copyright 2004 "Gilles Degottex"
2
3 // This file is part of "Music"
4
5 // "Music" is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation; either version 2.1 of the License, or
8 // (at your option) any later version.
9 //
10 // "Music" is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19
20 #ifndef _Music_h_
21 #define _Music_h_
22
23 #include <assert.h>
24 #include <cmath>
25 #include <string>
26 #include <list>
27 #include <vector>
28 using namespace std;
29 #include <CppAddons/CAMath.h>
30 #include <CppAddons/StringAddons.h>
31
32 namespace Music
33 {
34         enum NotesName{LOCAL_ANGLO, LOCAL_LATIN};
35         extern NotesName s_notes_name;
36         inline NotesName GetNotesName()                                 {return s_notes_name;}
37         inline void SetNotesName(NotesName type)                {s_notes_name = type;}
38
39         extern int s_tonality;
40         inline int GetTonality()                                                {return s_tonality;}
41         inline void SetTonality(int tonality)                   {s_tonality = tonality;}
42
43         extern int s_sampling_rate;
44         inline int GetSamplingRate()                                    {return s_sampling_rate;}
45         void SetSamplingRate(int sampling_rate);
46
47         extern double s_AFreq;
48         inline double GetAFreq()                                                {return s_AFreq;}
49         void SetAFreq(double AFreq);
50
51         extern const int UNDEFINED_SEMITONE;
52         extern int s_semitone_min;
53         extern int s_semitone_max;
54         inline int GetSemitoneMin()                                             {return s_semitone_min;}
55         inline int GetSemitoneMax()                                             {return s_semitone_max;}
56         inline int GetNbSemitones()                                             {return s_semitone_max-s_semitone_min+1;}
57         void SetSemitoneBounds(int semitone_min, int semitone_max);
58
59         struct SettingsListener
60         {
61                 virtual void samplingRateChanged()                      {}
62                 virtual void AFreqChanged()                                     {}
63                 virtual void semitoneBoundsChanged()            {}
64
65                 SettingsListener();
66                 virtual ~SettingsListener();
67         };
68
69         extern list<SettingsListener*>  s_settings_listeners;
70         void AddSettingsListener(SettingsListener* l);
71         void RemoveSettingsListener(SettingsListener* l);
72
73 //! convert frequency to a float number of half-tones from A3
74 /*!
75  * \param freq the frequency to convert to \f$\in R+\f$ {Hz}
76  * \param AFreq tuning frequency of the A3 (Usualy 440) {Hz}
77  * \return the float number of half-tones from A3 \f$\in R\f$
78  */
79 inline double f2hf(double freq, double AFreq=GetAFreq())                {return 12.0*(log(freq)-log(AFreq))/log(2.0);}
80 // TODO VERIF
81 // le ht doit �re le ht le plus proche de freq !! et pas un simple arrondi en dessous de la valeur r�l !!
82 //! convert frequency to number of half-tones from A3
83 /*!
84  * \param freq the frequency to convert to \f$\in R+\f$ {Hz}
85  * \param AFreq tuning frequency of the A3 (Usualy 440) {Hz}
86  * \return the number of half-tones from A3. Rounded to the nearest half-tones(
87  * not a simple integer convertion of \ref f2hf ) \f$\in R\f$
88  */
89 inline int f2h(double freq, double AFreq=GetAFreq())
90 {
91         double ht = f2hf(freq, AFreq);
92         if(ht>0)        return int(ht+0.5);
93         if(ht<0)        return int(ht-0.5);
94         return  0;
95 }
96 //! convert number of half-tones to frequency
97 /*!
98  * \param ht number of half-tones to convert to \f$\in Z\f$
99  * \param AFreq tuning frequency of the A3 (Usualy 440) {Hz}
100  * \return the converted frequency
101  */
102 inline double h2f(double ht, double AFreq=GetAFreq())                   {return AFreq * pow(2.0, ht/12.0);}
103
104 //! convert half-tones from A3 to the corresponding note name
105 /*!
106  * \param ht number of half-tones to convert to \f$\in Z\f$
107  * \param local
108  * \return his name (Do, Re, Mi, Fa, Sol, La, Si; with '#' if needed)
109  */
110 inline string h2n(int ht, NotesName local=GetNotesName(), int tonality=GetTonality(), bool show_oct=true)
111 {
112         ht += tonality;
113
114         int oct = 4;
115         while(ht<0)
116         {
117                 ht += 12;
118                 oct--;
119         }
120         while(ht>11)
121         {
122                 ht -= 12;
123                 oct++;
124         }
125
126         if(ht>2)        oct++;  // octave start from C
127 //      if(oct<=0)      oct--;  // skip 0-octave in occidental notations ??
128
129 //      char coct[3];
130 //      sprintf(coct, "%d", oct);
131 //      string soct = coct;
132
133         string soct;
134         if(show_oct)
135                 soct = StringAddons::toString(oct);
136
137         if(local==LOCAL_ANGLO)
138         {
139                 if(ht==0)               return "A"+soct;
140                 else if(ht==1)  return "A#"+soct;
141                 else if(ht==2)  return "B"+soct;
142                 else if(ht==3)  return "C"+soct;
143                 else if(ht==4)  return "C#"+soct;
144                 else if(ht==5)  return "D"+soct;
145                 else if(ht==6)  return "D#"+soct;
146                 else if(ht==7)  return "E"+soct;
147                 else if(ht==8)  return "F"+soct;
148                 else if(ht==9)  return "F#"+soct;
149                 else if(ht==10) return "G"+soct;
150                 else if(ht==11) return "G#"+soct;
151         }
152         else
153         {
154                 if(ht==0)               return "La"+soct;
155                 else if(ht==1)  return "La#"+soct;
156                 else if(ht==2)  return "Si"+soct;
157                 else if(ht==3)  return "Do"+soct;
158                 else if(ht==4)  return "Do#"+soct;
159                 else if(ht==5)  return "Re"+soct;
160                 else if(ht==6)  return "Re#"+soct;
161                 else if(ht==7)  return "Mi"+soct;
162                 else if(ht==8)  return "Fa"+soct;
163                 else if(ht==9)  return "Fa#"+soct;
164                 else if(ht==10) return "Sol"+soct;
165                 else if(ht==11) return "Sol#"+soct;
166         }
167
168         return "Th#1138";
169 }
170
171 inline int n2h(const std::string& note, NotesName local=LOCAL_ANGLO, int tonality=GetTonality())
172 {
173         // TODO
174         return -1;
175 }
176
177 std::vector<double> conv(const std::vector<double>& u, const std::vector<double>& v);
178
179         // TODO freq reffinement
180 }
181
182 #endif // _Music_h_