3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2005 Angel Ortega <angel@triptico.com>
6 ss_core.c - Softsynth core functions
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 http://www.triptico.com
39 /* main output frequency */
40 int ss_frequency
=44100;
42 /* interpolation type: 0, none; 1, linear; 2, cubic spline; 3, lagrange */
43 int ss_interpolation
=3;
48 /* note frequencies */
49 double ss_middle_A_freq
=440.0;
50 static double note_frequency
[128];
60 * ss_note_frequency - MIDI note to frequency converter
61 * @note: the MIDI note
63 * Accepts a MIDI note number (range 0 to 127) and
64 * returns its frequency in Hz.
66 double ss_note_frequency(int note
)
70 if(note
< 0 || note
> 127)
73 /* builds the table if empty */
74 if(note_frequency
[0] == 0.0)
77 note_frequency
[n
]=(ss_middle_A_freq
/ 32.0) *
78 pow(2.0, (((double)n
- 9.0) / 12.0));
81 return(note_frequency
[note
]);
85 struct ss_wave
* ss_alloc_wave(int size
, int n_channels
, int s_rate
)
89 if((w
=(struct ss_wave
*)malloc(sizeof(struct ss_wave
))) != NULL
)
93 memset(w
, '\0', sizeof(struct ss_wave
));
95 w
->size
=(double) size
;
96 w
->n_channels
=n_channels
;
99 /* alloc space for the pointers to the waves */
100 w
->wave
=(float **)malloc(n_channels
* sizeof(float *));
102 /* alloc space for the waves themselves */
103 for(n
=0;n
< n_channels
;n
++)
104 w
->wave
[n
]=(float *)malloc(size
* sizeof(float));
112 * ss_get_sample - Reads a sample from a wave buffer.
113 * @wave: the wave PCM data
114 * @size: size of the wave in samples
115 * @offset: sample number to be returned
117 * Returns the sample number @offset from the @wave buffer
118 * of @size size, doing interpolation if @offset
121 float ss_get_sample(float * wave
, double size
, double offset
)
123 float d
, s1
, s2
, r
=0.0;
126 /* take care of wrappings */
127 if(offset
< 0) offset
+= size
;
131 switch(ss_interpolation
)
134 /* no interpolation */
139 /* linear interpolation */
140 if(offset
> size
- 2)
144 d
=(float)(offset
- floor(offset
));
146 s2
=(wave
[o
+ 1] - s1
) * d
;
154 /* cubic spline (borrowed from timidity) */
155 if(offset
< 1 || offset
> size
- 3)
168 d
=(float)(offset
- floor(offset
));
171 ((5.0 * s3
- 11.0 * s2
+ 7.0 * s1
- s0
) / 4.0) *
172 (d
+ 1.0) * (d
- 1.0)) * d
;
175 ((5.0 * s0
- 11.0 * s1
+ 7.0 * t
- s3
) / 4.0) *
176 d
* (d
- 2.0)) * (1.0 - d
) + s2
) / 6.0;
184 /* lagrange (borrowed from timidity) */
185 if(offset
< 1 || offset
> size
- 3)
196 d
=(float)(offset
- floor(offset
));
198 s3
+= -3.0 * s2
+ 3.0 * s1
- s0
;
199 s3
*= (d
- 2.0) / 6.0;
200 s3
+= s2
- 2.0 * s1
+ s0
;
201 s3
*= (d
- 1.0) / 2.0;
217 * ss_tempo_from_wave - Calculates a tempo from a wave
219 * @note: note to calculate the tempo from
220 * @len: whole notes the tempo should match
222 * Calculates the optimal tempo for the @w wave, playing the @note,
223 * to last @len whole notes.
225 double ss_tempo_from_wave(struct ss_wave
* w
, int note
, double len
)
229 d
=ss_note_frequency(note
) / w
->base_freq
;
231 /* get the length of a whole, in seconds */
232 d
*= w
->s_rate
/ w
->size
;
234 /* convert to minutes */
246 * ss_pitch_from_tempo - Calculates a pitch from a tempo
248 * @tempo: current tempo
249 * @len: desired length in whole notes
251 * Calculates the optimal frequency (pitch) for the @w wave, at @tempo,
252 * to last @len whole notes.
254 double ss_pitch_from_tempo(struct ss_wave
* w
, double tempo
, double len
)
258 /* calculate number of seconds the wave lasts */
259 d
=w
->size
/ (double) w
->s_rate
;
261 /* convert to minutes, then to wpms */
265 return(w
->base_freq
* d
* len
);