Version 1.0.1 RELEASED.
[ahxm.git] / ss_core.c
blobd9fb93f13b99834cf5aca2f8b8f4941bd53ecd31
1 /*
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
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 struct ss_wave * ss_alloc_wave(int size, int n_channels, int s_rate)
84 struct ss_wave * w;
86 if((w=(struct ss_wave *)malloc(sizeof(struct ss_wave))) != NULL)
88 int n;
90 memset(w, '\0', sizeof(struct ss_wave));
92 w->size=(double) size;
93 w->n_channels=n_channels;
94 w->s_rate=s_rate;
96 /* alloc space for the pointers to the waves */
97 w->wave=(sample_t **)malloc(n_channels * sizeof(sample_t *));
99 /* alloc space for the waves themselves */
100 for(n=0;n < n_channels;n++)
101 w->wave[n]=(sample_t *)malloc(size * sizeof(sample_t));
104 return(w);
109 * ss_gesample_t - Reads a sample from a wave buffer.
110 * @wave: the wave PCM data
111 * @size: size of the wave in samples
112 * @offset: sample number to be returned
114 * Returns the sample number @offset from the @wave buffer
115 * of @size size, doing interpolation if @offset
116 * is not an integer.
118 sample_t ss_gesample_t(sample_t * wave, double size, double offset)
120 sample_t d, s1, s2, r=0.0;
121 int o;
123 /* take care of wrappings */
124 if(offset < 0) offset += size;
126 o=(int) offset;
128 switch(ss_interpolation)
130 case 0:
131 /* no interpolation */
132 r=wave[o];
133 break;
135 case 1:
136 /* linear interpolation */
137 if(offset > size - 2)
138 r=wave[o];
139 else
141 d=(sample_t)(offset - floor(offset));
142 s1=wave[o];
143 s2=(wave[o + 1] - s1) * d;
145 r=s1 + s2;
148 break;
150 case 2:
151 /* cubic spline (borrowed from timidity) */
152 if(offset < 1 || offset > size - 3)
153 r=wave[o];
154 else
156 sample_t s0, s3, t;
158 s0=wave[o - 1];
159 s1=wave[o];
160 s2=wave[o + 1];
161 s3=wave[o + 2];
163 t=s2;
165 d=(sample_t)(offset - floor(offset));
167 s2=(6.0 * s2 +
168 ((5.0 * s3 - 11.0 * s2 + 7.0 * s1 - s0) / 4.0) *
169 (d + 1.0) * (d - 1.0)) * d;
171 s1=((6.0 * s1 +
172 ((5.0 * s0 - 11.0 * s1 + 7.0 * t - s3) / 4.0) *
173 d * (d - 2.0)) * (1.0 - d) + s2) / 6.0;
175 r=s1;
178 break;
180 case 3:
181 /* lagrange (borrowed from timidity) */
182 if(offset < 1 || offset > size - 3)
183 r=wave[o];
184 else
186 sample_t s0, s3;
188 s0=wave[o - 1];
189 s1=wave[o];
190 s2=wave[o + 1];
191 s3=wave[o + 2];
193 d=(sample_t)(offset - floor(offset));
195 s3 += -3.0 * s2 + 3.0 * s1 - s0;
196 s3 *= (d - 2.0) / 6.0;
197 s3 += s2 - 2.0 * s1 + s0;
198 s3 *= (d - 1.0) / 2.0;
199 s3 += s1 - s0;
200 s3 *= d;
201 s3 += s0;
203 r=s3;
206 break;
209 return(r);
214 * ss_tempo_from_wave - Calculates a tempo from a wave
215 * @w: the wave
216 * @note: note to calculate the tempo from
217 * @len: whole notes the tempo should match
219 * Calculates the optimal tempo for the @w wave, playing the @note,
220 * to last @len whole notes.
222 double ss_tempo_from_wave(struct ss_wave * w, int note, double len)
224 double d;
226 d=ss_note_frequency(note) / w->base_freq;
228 /* get the length of a whole, in seconds */
229 d *= w->s_rate / w->size;
231 /* convert to minutes */
232 d *= 60.0;
234 /* then to bpm,s */
235 d *= 4.0;
236 d *= len;
238 return(d);
243 * ss_pitch_from_tempo - Calculates a pitch from a tempo
244 * @w: the wave
245 * @tempo: current tempo
246 * @len: desired length in whole notes
248 * Calculates the optimal frequency (pitch) for the @w wave, at @tempo,
249 * to last @len whole notes.
251 double ss_pitch_from_tempo(struct ss_wave * w, double tempo, double len)
253 double d;
255 /* calculate number of seconds the wave lasts */
256 d=w->size / (double) w->s_rate;
258 /* convert to minutes, then to wpms */
259 d /= 60.0;
260 d *= (tempo / 4.0);
262 return(w->base_freq * d * len);