Release version 0.99.2-1
[fmit.git] / libs / Music / Instrument.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 _Instrument_h_
21 #define _Instrument_h_
22
23 #include <assert.h>
24 #include <vector>
25 #include <iostream>
26 #include <fstream>
27 using namespace std;
28 #include <CppAddons/Math.h>
29 using namespace Math;
30 #include "Music.h"
31
32 namespace Music
33 {
34
35 #define MAX_NB_FREQ 24
36 #define MAX_NB_HARM 7
37 #define MAX_RDM_HT -12
38 #define MIN_RDM_HT 12
39
40 //! an abstract instrument
41 struct Instrument
42 {
43         virtual vector< Math::polar<double> >* getFreqs(){return NULL;}
44
45         virtual double gen_value(int k, double phase=0.0)=0;
46
47         virtual ~Instrument(){}
48 };
49
50 //! an harmonic instrument
51 /*!
52  * une fondamentale choisie dans un interval et des composantes harmoniques
53  */
54 struct HarmInstrument : Instrument
55 {
56         int m_dataBySecond;
57         double m_time;
58         vector< Math::polar<double> > m_freqs;
59         int m_base_ht;
60         double m_base_freq;
61
62         HarmInstrument(int dataBySecond, double AFreq, int nb_harm=int((rand()/RAND_MAX)*MAX_NB_HARM), int min_rdm_ht=-12, int max_rdm_ht=12)
63         : m_dataBySecond(dataBySecond)
64         , m_time(0.0)
65         , m_freqs(nb_harm+1)
66         , m_base_ht(int(min_rdm_ht+(rand()/RAND_MAX)*(max_rdm_ht-min_rdm_ht+1)))
67         , m_base_freq(h2f(m_base_ht, AFreq))
68         {
69                 for(size_t i=0; i<m_freqs.size(); i++)
70                         m_freqs[i] = Math::polar<double>(Random::s_random.nextDouble(), 2*Math::Pi*Random::s_random.nextDouble());
71
72                 // s'il n'y a pas de composantes, ça ne sert à rien de choisir une amplitude au hazard pour la fondamentale
73                 if(m_freqs.size()==1)
74                         m_freqs[0].mod = 1.0;
75
76                 // la fondamentale doit avoir une amplitude minimale
77                 m_freqs[0].mod = m_freqs[0].mod*0.8 + 0.2;
78         }
79
80         HarmInstrument(int dataBySecond, vector< Math::polar<double> >& freqs, double base_freq)
81         : m_dataBySecond(dataBySecond)
82         , m_time(0.0)
83         , m_freqs(freqs)
84         , m_base_freq(base_freq)
85         {
86         }
87
88         virtual vector< Math::polar<double> >* getFreqs(){return &m_freqs;}
89
90         virtual double gen_value(int k, double phase=0.0)
91         {
92                 double value = 0.0;
93
94                 for(size_t i=0; i<m_freqs.size(); i++)
95                         value += m_freqs[i].mod * sin(h2f(k, m_base_freq)*(i+1)*m_time+m_freqs[i].arg + phase);
96
97                 m_time += 2*Math::Pi/m_dataBySecond;
98
99                 return value;
100         }
101 };
102
103 inline ostream& operator<<(ostream& out, const HarmInstrument& instr)
104 {
105         cout << "HarmInstrument (mod:arg)" << endl;
106         for(size_t i=0; i<instr.m_freqs.size(); i++)
107                 out << "\t" << instr.m_base_freq*(i+1) << " (" << instr.m_freqs[i].mod << ":" << instr.m_freqs[i].arg << ")" << endl;
108
109         return out;
110 }
111
112 /* basé sur un motif pré-enregistré
113 */
114 struct WaveInstrument : Instrument
115 {
116         vector<double> m_data;
117
118         double m_time;
119         
120         int m_dataBySecond;
121         double m_AFreq;
122
123         WaveInstrument(int dataBySecond, double AFreq, const string& file_name)
124         : m_time(0.0)
125         , m_dataBySecond(dataBySecond)
126         , m_AFreq(AFreq)
127         {
128                 ifstream file(file_name.c_str());
129
130                 assert(file.is_open());
131
132                 double index;
133                 double value;
134                 file >> index;
135                 file >> value;
136                 while(!file.eof())
137                 {
138                         m_data.push_back(value);
139
140                         file >> index;
141                         file >> value;
142                 }
143         }
144
145         WaveInstrument(int dataBySecond, double AFreq, const deque<double>& data)
146         : m_data(data.size())
147         , m_time(0.0)
148         , m_dataBySecond(dataBySecond)
149         , m_AFreq(AFreq)
150         {
151                 for(size_t i=0; i<data.size(); i++)
152                         m_data[i] = data[i];
153         }
154
155         WaveInstrument(int dataBySecond, double AFreq, const vector<double>& data)
156         : m_data(data)
157         , m_time(0.0)
158         , m_dataBySecond(dataBySecond)
159         , m_AFreq(AFreq)
160         {
161         }
162
163         virtual double gen_value(int k, double phase=0.0)
164         {
165                 double f = h2f(k, m_AFreq);
166
167                 int i = int(f*(m_time+phase)*m_data.size()/(2*Math::Pi))%m_data.size();
168
169                 m_time += 2*Math::Pi/m_dataBySecond;
170
171                 return m_data[i];
172         }
173 };
174
175 /* faux instrument: les composantes devraient toujours être des harmoniques
176 */
177 struct FreqInstrument : Instrument
178 {
179         static double get_freq(double lowest_freq, int i, double AFreq)
180         {
181                 return h2f(int(f2h(lowest_freq, AFreq)+i), AFreq);
182         }
183
184         int m_dataBySecond;
185         double m_AFreq;
186         double m_time;
187         vector< Math::polar<double> > m_freqs;
188         double m_lowest_freq;
189
190         virtual vector< Math::polar<double> >* getFreqs(){return &m_freqs;}
191
192         FreqInstrument(int dataBySecond, double AFreq, double lowest_freq, int nb_freq=int((rand()/RAND_MAX)*MAX_NB_FREQ))
193         : m_dataBySecond(dataBySecond)
194         , m_AFreq(AFreq)
195         , m_time(0.0)
196         , m_freqs(nb_freq)
197         , m_lowest_freq(lowest_freq)
198         {
199                 //              cout << "FreqInstrument::FreqInstrument" << endl;
200
201                 for(size_t i=0; i<m_freqs.size(); i++)
202                         m_freqs[i] = Math::polar<double>((rand()/RAND_MAX), Math::Pi*(rand()/RAND_MAX));
203
204                 // s'il n'y a pas de composantes, ça ne sert à rien de choisir une amplitude au hazard pour la fondamentale
205                 if(m_freqs.size()==1)
206                         m_freqs[0].mod = 1.0;
207
208                 m_freqs[1].mod = 0.0;           // TEMP
209
210                 // la fondamentale doit avoir une amplitude minimale
211                 m_freqs[0].mod = m_freqs[0].mod*0.8 + 0.2;
212
213                 // rajoute un bruit sur la vitesse
214                 double upper_freq = h2f(1, m_lowest_freq);
215                 double lower_freq = h2f(-1, m_lowest_freq);
216                 cout << "m_lowest_freq=" << m_lowest_freq << " upper_freq="<<upper_freq<<" lower_freq="<<lower_freq;
217                 m_lowest_freq += (rand()/RAND_MAX)*(upper_freq-lower_freq)/16 - (m_lowest_freq-lower_freq)/16;
218                 cout << " => " << m_lowest_freq << endl;
219
220                 //              cout << "/FreqInstrument::FreqInstrument" << endl;
221         }
222
223         FreqInstrument(int dataBySecond, double AFreq, vector< Math::polar<double> >& freqs, double lowest_freq)
224         : m_dataBySecond(dataBySecond)
225         , m_AFreq(AFreq)
226         , m_time(0.0)
227         , m_freqs(freqs)
228         , m_lowest_freq(lowest_freq)
229         {
230         }
231
232         virtual double gen_value(int k, double phase=0.0)
233         {
234                 //              cout << "FreqInstrument::gen_value" << endl;
235
236                 double value = 0.0;
237
238                 for(size_t i=0; i<m_freqs.size(); i++)
239                         value += m_freqs[i].mod * sin(get_freq(m_lowest_freq,i+k,m_AFreq)*m_time + m_freqs[i].arg);
240
241                 m_time += 2*Math::Pi/m_dataBySecond;
242
243                 return value;
244         }
245 };
246
247 inline ostream& operator<<(ostream& out, const FreqInstrument& instr)
248 {
249         cout << "FreqInstrument (mod:arg)" << endl;
250         for(size_t i=0; i<instr.m_freqs.size(); i++)
251                 out << "\t" << FreqInstrument::get_freq(instr.m_lowest_freq,i,instr.m_AFreq) << " (" << instr.m_freqs[i].mod << ":" << instr.m_freqs[i].arg << ")" << endl;
252
253         return out;
254 }
255
256 }
257
258 #endif // _Instrument_h_
259