New function ss_gen_vibrato() (API still not clear).
[ahxm.git] / core.c
blob5c43243c8575fd2765e0018c5041bfd83722f8ea
1 /*
3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2004 Angel Ortega <angel@triptico.com>
6 core.c - 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 "core.h"
34 /*******************
35 Data
36 ********************/
38 /* main output frequency */
39 int _frequency=44100;
41 /* interpolation type: 0, none; 1, linear; 2, cubic spline; 3, lagrange */
42 int _interpolation=1;
44 /* output channels */
45 int _n_channels=2;
47 /* note frequencies */
48 double _middle_A_freq=440.0;
49 static double _note_frequency[NUM_NOTES];
51 /*******************
52 Code
53 ********************/
55 /**
56 * note_frequency - MIDI note to frequency converter
57 * @note: the MIDI note
59 * Accepts a MIDI note number (range 0 to 127) and
60 * returns its frequency in Hz.
62 double note_frequency(int note)
64 int n;
66 if(!VALID_NOTE(note))
67 return(0);
69 /* builds the table if empty */
70 if(_note_frequency[0] == 0.0)
72 for(n=0;n < NUM_NOTES;n++)
73 _note_frequency[n]=(_middle_A_freq / 32.0) *
74 pow(2.0, (((double)n - 9.0) / 12.0));
77 return(_note_frequency[note]);
81 /**
82 * get_sample - Reads a sample from a wave buffer.
83 * @wave: the wave PCM data
84 * @size: size of the wave in samples
85 * @offset: sample number to be returned
87 * Returns the sample number @offset from the @wave buffer
88 * of @size size, doing interpolation if @offset
89 * is not an integer.
91 float get_sample(float * wave, double size, double offset)
93 float d, s1, s2, r;
94 int o;
96 o=(int) offset;
98 switch(_interpolation)
100 case 0:
101 /* no interpolation */
102 r=wave[o];
103 break;
105 case 1:
106 /* linear interpolation */
107 d=(float)(offset - floor(offset));
108 s1=wave[o];
109 if(offset + 1 > size) o=0; else o++;
110 s2=(wave[o] - s1) * d;
112 r=s1 + s2;
113 break;
115 case 2:
116 /* cubic spline (borrowed from timidity) */
117 if(offset < 1 || offset > size - 2)
118 r=wave[o];
119 else
121 float s0, s3, t;
123 s0=wave[o - 1];
124 s1=wave[o];
125 s2=wave[o + 1];
126 s3=wave[o + 2];
128 t=s2;
130 d=(float)(offset - floor(offset));
132 s2=(6.0 * s2 +
133 ((5.0 * s3 - 11.0 * s2 + 7.0 * s1 - s0) / 4.0) *
134 (d + 1.0) * (d - 1.0)) * d;
136 s1=((6.0 * s1 +
137 ((5.0 * s0 - 11.0 * s1 + 7.0 * t - s3) / 4.0) *
138 d * (d - 2.0)) * (1.0 - d) + s2) / 6.0;
140 r=s1;
143 break;
145 case 3:
146 /* lagrange (borrowed from timidity) */
147 if(offset < 1 || offset > size - 2)
148 r=wave[o];
149 else
151 float s0, s3;
153 s0=wave[o - 1];
154 s1=wave[o];
155 s2=wave[o + 1];
156 s3=wave[o + 2];
158 d=(float)(offset - floor(offset));
160 s3 += -3.0 * s2 + 3.0 * s1 - s0;
161 s3 *= (d - 2.0) / 6.0;
162 s3 += s2 - 2.0 * s1 + s0;
163 s3 *= (d - 1.0) / 2.0;
164 s3 += s1 - s0;
165 s3 *= d;
166 s3 += s0;
168 r=s3;
171 break;
174 return(r);
179 * wave_resample - Resamples a wave.
180 * @freq: original frequency of the wave
181 * @size: size of the wave in samples
182 * @n_channels: number of channels
183 * @wave: the wave PCM data
185 * Resamples the @wave from its original @freq frequency to
186 * the global output frequency. The resampled wave is stored
187 * in @wave.
189 * Returns the conversion ratio; the original size (and other
190 * pointers to the data as loop starts and ends) should be
191 * divided by this number to match the new wave.
193 double wave_resample(int freq, double size, int n_channels, float * wave[])
195 double ratio;
196 int new_size;
197 float * old_wave;
198 int n,m;
199 double i;
201 ratio=(double) freq / (double) _frequency;
202 new_size=(int)(size / ratio);
204 printf("wave_resample: ratio %f\n", (float)ratio);
206 for(n=0;n < n_channels;n++)
208 old_wave=wave[n];
209 wave[n]=(float *) malloc(new_size * sizeof(float));
211 for(m=i=0;m < new_size;m++,i+=ratio)
212 wave[n][m]=get_sample(old_wave, size, i);
214 /* free the old wave */
215 free(old_wave);
218 return(ratio);