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
38 /* main output frequency */
39 int ss_frequency
=44100;
41 /* interpolation type: 0, none; 1, linear; 2, cubic spline; 3, lagrange */
42 int ss_interpolation
=1;
47 /* note frequencies */
48 double ss_middle_A_freq
=440.0;
49 static double note_frequency
[NUM_NOTES
];
59 * ss_note_frequency - MIDI note to frequency converter
60 * @note: the MIDI note
62 * Accepts a MIDI note number (range 0 to 127) and
63 * returns its frequency in Hz.
65 double ss_note_frequency(int note
)
72 /* builds the table if empty */
73 if(note_frequency
[0] == 0.0)
75 for(n
=0;n
< NUM_NOTES
;n
++)
76 note_frequency
[n
]=(ss_middle_A_freq
/ 32.0) *
77 pow(2.0, (((double)n
- 9.0) / 12.0));
80 return(note_frequency
[note
]);
85 * ss_get_sample_raw - Reads a sample from a wave buffer.
86 * @wave: the wave PCM data
87 * @size: size of the wave in samples
88 * @offset: sample number to be returned
90 * Returns the sample number @offset from the @wave buffer
91 * of @size size, doing interpolation if @offset
94 float ss_get_sample_raw(float * wave
, double size
, double offset
)
99 /* take care of wrappings */
100 if(offset
< 0) offset
+= size
;
104 switch(ss_interpolation
)
107 /* no interpolation */
112 /* linear interpolation */
113 if(offset
> size
- 2)
117 d
=(float)(offset
- floor(offset
));
119 s2
=(wave
[o
+ 1] - s1
) * d
;
127 /* cubic spline (borrowed from timidity) */
128 if(offset
< 1 || offset
> size
- 3)
141 d
=(float)(offset
- floor(offset
));
144 ((5.0 * s3
- 11.0 * s2
+ 7.0 * s1
- s0
) / 4.0) *
145 (d
+ 1.0) * (d
- 1.0)) * d
;
148 ((5.0 * s0
- 11.0 * s1
+ 7.0 * t
- s3
) / 4.0) *
149 d
* (d
- 2.0)) * (1.0 - d
) + s2
) / 6.0;
157 /* lagrange (borrowed from timidity) */
158 if(offset
< 1 || offset
> size
- 3)
169 d
=(float)(offset
- floor(offset
));
171 s3
+= -3.0 * s2
+ 3.0 * s1
- s0
;
172 s3
*= (d
- 2.0) / 6.0;
173 s3
+= s2
- 2.0 * s1
+ s0
;
174 s3
*= (d
- 1.0) / 2.0;
189 float ss_get_sample(struct ss_wave
* w
, int channel
, double offset
)
191 return(ss_get_sample_raw(w
->wave
[channel
], w
->size
, offset
));
196 * ss_tempo_from_wave - Calculates a tempo from a wave
198 * @note: note to calculate the tempo from
199 * @len: whole notes the tempo should match
201 * Calculates the optimal tempo for the @w wave, playing the @note,
202 * to last @len whole notes.
204 double ss_tempo_from_wave(struct ss_wave
* w
, int note
, double len
)
208 d
=ss_note_frequency(note
) / w
->base_freq
;
210 /* get the length of a whole, in seconds */
211 d
*= w
->size
/ w
->s_rate
;
213 /* convert to minutes */
216 /* convert to the desired whole notes */
224 * ss_pitch_from_wave - Calculates a pitch from a wave
226 * @tempo: current tempo
227 * @len: desired length in whole notes
229 * Calculates the optimal frequency (pitch) for the @w wave, at @tempo,
230 * to last @len whole notes.
232 double ss_pitch_from_wave(struct ss_wave
* w
, double tempo
, double len
)
236 /* calculate number of seconds the wave lasts */
237 d
=w
->size
/ (double) w
->s_rate
;
239 /* convert to minutes, then to wpms */
243 return(w
->base_freq
* d
* len
);