Messages for track ids < 0 don't have their MIDI channel (incorrectly) set;
[ahxm.git] / ss_core.c
blob2e631be1bd2715629cffdf2a9008449a9065d34e
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 <math.h>
32 #include "ss_core.h"
34 /*******************
35 Data
36 ********************/
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;
44 /* output channels */
45 int ss_nchannels=2;
47 /* note frequencies */
48 double ss_middle_A_freq=440.0;
49 static double note_frequency[NUM_NOTES];
51 /* debug level */
52 int ss_debug=1;
54 /*******************
55 Code
56 ********************/
58 /**
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)
67 int n;
69 if(!VALID_NOTE(note))
70 return(0);
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]);
84 /**
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
92 * is not an integer.
94 float ss_get_sample_raw(float * wave, double size, double offset)
96 float d, s1, s2, r;
97 int o;
99 /* take care of wrappings */
100 if(offset < 0) offset += size;
102 o=(int) offset;
104 switch(ss_interpolation)
106 case 0:
107 /* no interpolation */
108 r=wave[o];
109 break;
111 case 1:
112 /* linear interpolation */
113 if(offset > size - 2)
114 r=wave[o];
115 else
117 d=(float)(offset - floor(offset));
118 s1=wave[o];
119 s2=(wave[o + 1] - s1) * d;
121 r=s1 + s2;
124 break;
126 case 2:
127 /* cubic spline (borrowed from timidity) */
128 if(offset < 1 || offset > size - 3)
129 r=wave[o];
130 else
132 float s0, s3, t;
134 s0=wave[o - 1];
135 s1=wave[o];
136 s2=wave[o + 1];
137 s3=wave[o + 2];
139 t=s2;
141 d=(float)(offset - floor(offset));
143 s2=(6.0 * s2 +
144 ((5.0 * s3 - 11.0 * s2 + 7.0 * s1 - s0) / 4.0) *
145 (d + 1.0) * (d - 1.0)) * d;
147 s1=((6.0 * s1 +
148 ((5.0 * s0 - 11.0 * s1 + 7.0 * t - s3) / 4.0) *
149 d * (d - 2.0)) * (1.0 - d) + s2) / 6.0;
151 r=s1;
154 break;
156 case 3:
157 /* lagrange (borrowed from timidity) */
158 if(offset < 1 || offset > size - 3)
159 r=wave[o];
160 else
162 float s0, s3;
164 s0=wave[o - 1];
165 s1=wave[o];
166 s2=wave[o + 1];
167 s3=wave[o + 2];
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;
175 s3 += s1 - s0;
176 s3 *= d;
177 s3 += s0;
179 r=s3;
182 break;
185 return(r);
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
197 * @w: the 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)
206 double d;
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 */
214 d *= 60.0;
216 /* convert to the desired whole notes */
217 d *= len;
219 return(d);
224 * ss_pitch_from_wave - Calculates a pitch from a wave
225 * @w: the 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)
234 double d;
236 /* calculate number of seconds the wave lasts */
237 d=w->size / (double) w->s_rate;
239 /* convert to minutes, then to wpms */
240 d /= 60.0;
241 d *= (tempo / 4.0);
243 return(w->base_freq * d * len);