3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2008 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;
46 int ss_nchannels
= -1;
48 /* note frequencies */
49 double ss_middle_A_freq
= 440.0;
50 static double note_frequency
[128];
57 * ss_note_frequency - MIDI note to frequency converter
58 * @note: the MIDI note
60 * Accepts a MIDI note number (range 0 to 127) and
61 * returns its frequency in Hz.
63 double ss_note_frequency(int note
)
67 if (note
< 0 || note
> 127)
70 /* builds the table if empty */
71 if (note_frequency
[0] == 0.0) {
72 for (n
= 0; n
< 128; n
++)
73 note_frequency
[n
] = (ss_middle_A_freq
/ 32.0) *
74 pow(2.0, (((double) n
- 9.0) / 12.0));
77 return note_frequency
[note
];
82 * ss_alloc_wave - Allocates a wave structure.
83 * @size: size in frames
84 * @n_channels: number of channels
85 * @s_rate: sampling rate
86 * @p_size: size of the sound page
88 * Allocates a wave structure. If @p_size is -1, it's assumed to be the
89 * same as @size (so the sound will live entirely in memory).
91 struct ss_wave
*ss_alloc_wave(int size
, int n_channels
, int s_rate
, int p_size
)
93 struct ss_wave
*w
= NULL
;
98 if ((w
= (struct ss_wave
*) malloc(sizeof(struct ss_wave
))) != NULL
) {
99 memset(w
, '\0', sizeof(struct ss_wave
));
101 w
->size
= (double) size
;
103 w
->n_channels
= n_channels
;
106 /* alloc space for the pointers to the waves */
107 w
->wave
= (sample_t
**) malloc(n_channels
* sizeof(sample_t
*));
108 memset(w
->wave
, '\0', n_channels
* sizeof(sample_t
*));
116 * ss_free_wave - Frees a wave structure.
117 * @w: the wave structure
119 * Frees a struct ss_wave allocated by ss_alloc_wave().
121 void ss_free_wave(struct ss_wave
*w
)
123 if (w
->wave
!= NULL
) {
126 /* frees the buffers */
127 for (n
= 0; n
< w
->n_channels
; n
++)
128 if (w
->wave
[n
] != NULL
)
131 /* frees the space for the pointers to the waves */
134 /* if it has a filename, also free it */
135 if (w
->filename
!= NULL
)
136 free((char *)w
->filename
);
139 /* frees the wave itself */
144 void ss_prepare_wave(struct ss_wave
*w
)
145 /* prepares a wave file for usage (creates the page buffers) */
149 /* alloc space for the waves themselves */
150 for (n
= 0; n
< w
->n_channels
; n
++) {
151 w
->wave
[n
] = (sample_t
*) realloc(w
->wave
[n
], w
->p_size
* sizeof(sample_t
));
153 memset(w
->wave
[n
], '\0', w
->p_size
* sizeof(sample_t
));
158 static void ss_load_page(struct ss_wave
*w
, int offset
)
159 /* loads a page from a wave file into memory */
164 /* set the offset to some samples behind the
165 wanted offset (to avoid possible page bounces) */
166 if ((w
->p_offset
= offset
- 441) < 0)
169 /* too much page faults for this wave? */
170 if (w
->page_faults
>= 8) {
172 if ((w
->p_size
*= 2) > (int) w
->size
) {
173 /* if this resize is too much, just
174 set it to load the full wave */
175 w
->p_size
= (int) w
->size
;
179 /* trigger a page resizing and restart statistics */
183 if (w
->page_faults
== 0)
186 if ((f
= fopen(w
->filename
, "r")) == NULL
) {
187 fprintf(stderr
, "Can't open '%s'\n", w
->filename
);
192 printf("load_page [%s,%d,%d,%d]\n", w
->filename
,
193 w
->p_offset
, w
->p_size
, w
->page_faults
);
195 /* calculate the frame size */
196 s
= w
->p_offset
* (w
->bits
/ 8) * w
->n_channels
;
199 fseek(f
, w
->f_pos
+ s
, SEEK_SET
);
210 static sample_t
ss_pick_sample(struct ss_wave
*w
, int channel
, double offset
)
211 /* picks a sample from a ss_wave, forcing a call to ss_load_page() if
212 the wanted sample is not in memory */
219 /* is the wanted sample not in memory? */
220 if (o
< w
->p_offset
|| o
> w
->p_offset
+ w
->p_size
) {
223 printf("ss_pick_sample: offset: %lf, p_offset: %d, p_size: %d, size: %lf, loop_end: %lf\n",
224 offset
, w
->p_offset
, w
->p_size
, w
->size
, w
->loop_end
);
229 wave
= w
->wave
[channel
];
230 return wave
[o
- w
->p_offset
];
235 * ss_get_sample - Reads a sample from a wave.
237 * @channel: the channel
238 * @offset: sample number to be returned
240 * Returns the sample number @offset from the @channel of the @wave. @Offset
241 * can be a non-integer value.
243 sample_t
ss_get_sample(struct ss_wave
* w
, int channel
, double offset
)
245 sample_t d
, t
, r
= 0.0;
246 sample_t s0
, s1
, s2
, s3
;
248 /* take care of wrappings */
252 /* pick sample at offset */
253 s1
= ss_pick_sample(w
, channel
, offset
);
255 switch (ss_interpolation
) {
257 /* no interpolation */
262 /* linear interpolation */
263 if (offset
> w
->size
- 2)
266 d
= (sample_t
) (offset
- floor(offset
));
267 s2
= (ss_pick_sample(w
, channel
, offset
+ 1) - s1
) * d
;
275 /* cubic spline (borrowed from timidity) */
276 if (offset
< 1 || offset
> w
->size
- 3)
279 s0
= ss_pick_sample(w
, channel
, offset
- 1);
280 s2
= ss_pick_sample(w
, channel
, offset
+ 1);
281 s3
= ss_pick_sample(w
, channel
, offset
+ 2);
285 d
= (sample_t
) (offset
- floor(offset
));
288 ((5.0 * s3
- 11.0 * s2
+ 7.0 * s1
- s0
) / 4.0) *
289 (d
+ 1.0) * (d
- 1.0)) * d
;
292 ((5.0 * s0
- 11.0 * s1
+ 7.0 * t
- s3
) / 4.0) *
293 d
* (d
- 2.0)) * (1.0 - d
) + s2
) / 6.0;
301 /* lagrange (borrowed from timidity) */
302 if (offset
< 1 || offset
> w
->size
- 3)
305 s0
= ss_pick_sample(w
, channel
, offset
- 1);
306 s2
= ss_pick_sample(w
, channel
, offset
+ 1);
307 s3
= ss_pick_sample(w
, channel
, offset
+ 2);
309 d
= (sample_t
) (offset
- floor(offset
));
311 s3
+= -3.0 * s2
+ 3.0 * s1
- s0
;
312 s3
*= (d
- 2.0) / 6.0;
313 s3
+= s2
- 2.0 * s1
+ s0
;
314 s3
*= (d
- 1.0) / 2.0;
330 * ss_tempo_from_wave - Calculates a tempo from a wave
332 * @note: note to calculate the tempo from
333 * @len: whole notes the tempo should match
335 * Calculates the optimal tempo for the @w wave, playing the @note,
336 * to last @len whole notes.
338 double ss_tempo_from_wave(const struct ss_wave
*w
, int note
, double len
)
342 d
= ss_note_frequency(note
) / w
->base_freq
;
344 /* get the length of a whole, in seconds */
345 d
*= w
->s_rate
/ w
->size
;
347 /* convert to minutes */
359 * ss_pitch_from_tempo - Calculates a pitch from a tempo
361 * @tempo: current tempo
362 * @len: desired length in whole notes
364 * Calculates the optimal frequency (pitch) for the @w wave, at @tempo,
365 * to last @len whole notes.
367 double ss_pitch_from_tempo(const struct ss_wave
*w
, double tempo
, double len
)
371 /* calculate number of seconds the wave lasts */
372 d
= w
->size
/ (double) w
->s_rate
;
374 /* convert to minutes, then to wpms */
378 return w
->base_freq
* d
* len
;