Updated README.
[ahxm.git] / ss_core.c
blob48d8d315e64044207c3b4d3315bd2969098a2b85
1 /*
3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2006 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
26 #include "config.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <math.h>
33 #include "annhell.h"
35 /*******************
36 Data
37 ********************/
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;
45 /* output channels */
46 int ss_nchannels = 2;
48 /* note frequencies */
49 double ss_middle_A_freq = 440.0;
50 static double note_frequency[128];
52 /*******************
53 Code
54 ********************/
56 /**
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)
65 int n;
67 if(note < 0 || note > 127)
68 return(0);
70 /* builds the table if empty */
71 if(note_frequency[0] == 0.0)
73 for(n = 0;n < 128;n++)
74 note_frequency[n] = (ss_middle_A_freq / 32.0) *
75 pow(2.0, (((double)n - 9.0) / 12.0));
78 return(note_frequency[note]);
82 /**
83 * ss_alloc_wave - Allocates a wave structure.
84 * @size: size in frames
85 * @n_channels: number of channels
86 * @s_rate: sampling rate
87 * @p_size: size of the sound page
89 * Allocates a wave structure. If @p_size is -1, it's assumed to be the
90 * same as @size (so the sound will live entirely in memory).
92 struct ss_wave * ss_alloc_wave(int size, int n_channels, int s_rate, int p_size)
94 struct ss_wave * w = NULL;
96 if(p_size == -1) p_size = size;
98 if((w = (struct ss_wave *)malloc(sizeof(struct ss_wave))) != NULL)
100 memset(w, '\0', sizeof(struct ss_wave));
102 w->size = (double) size;
103 w->p_size = p_size;
104 w->n_channels = n_channels;
105 w->s_rate = s_rate;
107 /* alloc space for the pointers to the waves */
108 w->wave = (sample_t **)malloc(n_channels * sizeof(sample_t *));
109 memset(w->wave, '\0', n_channels * sizeof(sample_t *));
112 return(w);
117 * ss_free_wave - Frees a wave structure.
118 * @w: the wave structure
120 * Frees a struct ss_wave allocated by ss_alloc_wave().
122 void ss_free_wave(struct ss_wave * w)
124 if(w->wave != NULL)
126 int n;
128 /* frees the buffers */
129 for(n = 0;n < w->n_channels;n++)
130 if(w->wave[n] != NULL)
131 free(w->wave[n]);
133 /* frees the space for the pointers to the waves */
134 free(w->wave);
136 /* if it has a filename, also free it */
137 if(w->filename != NULL) free(w->filename);
140 /* frees the wave itself */
141 free(w);
145 void ss_prepare_wave(struct ss_wave * w)
146 /* prepares a wave file for usage (creates the page buffers) */
148 int n;
150 /* if the buffers exist, do nothing */
151 if(w->wave[0] != NULL)
152 return;
154 /* alloc space for the waves themselves */
155 for(n = 0;n < w->n_channels;n++)
157 w->wave[n] = (sample_t *)malloc(w->p_size * sizeof(sample_t));
158 memset(w->wave[n], '\0', w->p_size * sizeof(sample_t));
163 static void ss_load_page(struct ss_wave * w, int offset)
164 /* loads a page from a wave file into memory */
166 FILE * f;
167 int s;
169 ss_prepare_wave(w);
171 if((f = fopen(w->filename, "r")) == NULL)
173 fprintf(stderr, "Can't open '%s'\n", w->filename);
174 return;
177 /* calculate the frame size */
178 w->p_offset = offset;
179 s = offset * (w->bits / 8) * w->n_channels;
181 /* move there */
182 fseek(f, w->f_pos + s, SEEK_SET);
184 /* fill the page */
185 load_pcm_wave(f, w);
187 fclose(f);
191 static sample_t ss_pick_sample(struct ss_wave * w, int channel, double offset)
192 /* picks a sample from a ss_wave, forcing a call to ss_load_page() if
193 the wanted sample is not in memory */
195 int o;
196 sample_t * wave;
198 o = (int) offset;
200 /* is the wanted sample not in memory? */
201 if(o < w->p_offset || o > w->p_offset + w->p_size)
202 ss_load_page(w, o);
204 wave = w->wave[channel];
205 return(wave[o - w->p_offset]);
210 * ss_get_sample - Reads a sample from a wave.
211 * @wave: the wave
212 * @channel: the channel
213 * @offset: sample number to be returned
215 * Returns the sample number @offset from the @channel of the @wave. @Offset
216 * can be a non-integer value.
218 sample_t ss_get_sample(struct ss_wave * w, int channel, double offset)
220 sample_t d, t, r = 0.0;
221 sample_t s0, s1, s2, s3;
223 /* take care of wrappings */
224 if(offset < 0) offset += w->size;
226 /* pick sample at offset */
227 s1 = ss_pick_sample(w, channel, offset);
229 switch(ss_interpolation)
231 case 0:
232 /* no interpolation */
233 r = s1;
234 break;
236 case 1:
237 /* linear interpolation */
238 if(offset > w->size - 2)
239 r = s1;
240 else
242 d = (sample_t)(offset - floor(offset));
243 s2 = (ss_pick_sample(w, channel, offset + 1) - s1) * d;
245 r = s1 + s2;
248 break;
250 case 2:
251 /* cubic spline (borrowed from timidity) */
252 if(offset < 1 || offset > w->size - 3)
253 r = s1;
254 else
256 s0 = ss_pick_sample(w, channel, offset - 1);
257 s2 = ss_pick_sample(w, channel, offset + 1);
258 s3 = ss_pick_sample(w, channel, offset + 2);
260 t = s2;
262 d = (sample_t)(offset - floor(offset));
264 s2 = (6.0 * s2 +
265 ((5.0 * s3 - 11.0 * s2 + 7.0 * s1 - s0) / 4.0) *
266 (d + 1.0) * (d - 1.0)) * d;
268 s1 = ((6.0 * s1 +
269 ((5.0 * s0 - 11.0 * s1 + 7.0 * t - s3) / 4.0) *
270 d * (d - 2.0)) * (1.0 - d) + s2) / 6.0;
272 r = s1;
275 break;
277 case 3:
278 /* lagrange (borrowed from timidity) */
279 if(offset < 1 || offset > w->size - 3)
280 r = s1;
281 else
283 s0 = ss_pick_sample(w, channel, offset - 1);
284 s2 = ss_pick_sample(w, channel, offset + 1);
285 s3 = ss_pick_sample(w, channel, offset + 2);
287 d = (sample_t)(offset - floor(offset));
289 s3 += -3.0 * s2 + 3.0 * s1 - s0;
290 s3 *= (d - 2.0) / 6.0;
291 s3 += s2 - 2.0 * s1 + s0;
292 s3 *= (d - 1.0) / 2.0;
293 s3 += s1 - s0;
294 s3 *= d;
295 s3 += s0;
297 r = s3;
300 break;
303 return(r);
308 * ss_tempo_from_wave - Calculates a tempo from a wave
309 * @w: the wave
310 * @note: note to calculate the tempo from
311 * @len: whole notes the tempo should match
313 * Calculates the optimal tempo for the @w wave, playing the @note,
314 * to last @len whole notes.
316 double ss_tempo_from_wave(struct ss_wave * w, int note, double len)
318 double d;
320 d = ss_note_frequency(note) / w->base_freq;
322 /* get the length of a whole, in seconds */
323 d *= w->s_rate / w->size;
325 /* convert to minutes */
326 d *= 60.0;
328 /* then to bpm,s */
329 d *= 4.0;
330 d *= len;
332 return(d);
337 * ss_pitch_from_tempo - Calculates a pitch from a tempo
338 * @w: the wave
339 * @tempo: current tempo
340 * @len: desired length in whole notes
342 * Calculates the optimal frequency (pitch) for the @w wave, at @tempo,
343 * to last @len whole notes.
345 double ss_pitch_from_tempo(struct ss_wave * w, double tempo, double len)
347 double d;
349 /* calculate number of seconds the wave lasts */
350 d = w->size / (double) w->s_rate;
352 /* convert to minutes, then to wpms */
353 d /= 60.0;
354 d *= (tempo / 4.0);
356 return(w->base_freq * d * len);