1 /*
2     wavedata.h - Structures to represent a set of wavetables
3 
4     Copyright (C) 2003  Mike Rawes
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20 
21 #ifndef blop_wavedata_h
22 #define blop_wavedata_h
23 
24 #include <ladspa.h>
25 #include <config.h>
26 #include "math_func.h"
27 #include "interpolate.h"
28 #include "common.h"
29 
30 /* Functions identifying wavedata dlls */
31 #define BLOP_DLSYM_SAWTOOTH "blop_get_sawtooth"
32 #define BLOP_DLSYM_SQUARE   "blop_get_square"
33 #define BLOP_DLSYM_PARABOLA "blop_get_parabola"
34 
35 /*
36  * Structure holding a single segment of sample data
37  * along with information relating to playback.
38  */
39 typedef struct
40 {
41 	unsigned long sample_count;         /* Sample count */
42 	LADSPA_Data * samples_lf;           /* Sample data played back at amplitude
43 	                                        inversely proportional to frequency */
44 	LADSPA_Data * samples_hf;           /* Sample data played back at amplitude
45 	                                        proportional to frequency */
46 	unsigned long harmonics;            /* Max harmonic content of sample data */
47 
48 	LADSPA_Data phase_scale_factor;     /* Phase scale factor for playback */
49 	LADSPA_Data min_frequency;          /* Minimum playback frequency */
50 	LADSPA_Data max_frequency;          /* Maximum playback frequency */
51 	LADSPA_Data range_scale_factor;     /* Blend scale factor for cross fading */
52 } Wavetable;
53 
54 /*
55  * Structure holding the wavetable data and playback state
56  */
57 typedef struct
58 {
59 	void * data_handle;                     /* Data DLL handle */
60 	unsigned long table_count;              /* Number of wavetables in wavedata */
61 	Wavetable ** tables;                    /* One or more wavetables, plus pair of
62 	                                            extra tables for frequency extremes */
63 	unsigned long * lookup;                 /* Wavetable lookup vector */
64 	unsigned long lookup_max;               /* For clipping lookup indices */
65 
66 	LADSPA_Data sample_rate;                /* Sample rate */
67 	LADSPA_Data nyquist;                    /* Nyquist rate (sample_rate / 2) */
68 
69 /* Playback state */
70 	LADSPA_Data frequency;                  /* Current playback frequency */
71 	LADSPA_Data abs_freq;                   /* Absolute playback frequency */
72 	LADSPA_Data xfade;                      /* Crossfade factor for fading */
73 	Wavetable * table;                      /* Wavetable to playback */
74 } Wavedata;
75 
76 #ifdef __cplusplus
77 extern "C" {
78 #endif
79 
80 int
81 wavedata_load (Wavedata * w,
82                const char * wdat_descriptor_name,
83                unsigned long sample_rate);
84 
85 void
86 wavedata_unload (Wavedata * w);
87 
88 /*****************************************************************************
89  * Description: Get interpolated sample from current wavetable in wavedata
90  *               at given phase offset
91  *
92  *   Arguments: w               Wavedata containing playback state and data
93  *              phase           Phase offset [0.0, sample_rate]
94  *
95  *     Returns: Interpolated sample
96  *
97  *       Notes: Cubic (or quintic) interpolation requires four consecutive
98  *               samples for operation:
99  *
100  *                              phase
101  *                                :
102  *                    p1      p0  :   n0      n1
103  *                    |       |   x   |       |
104  *                            :   :
105  *                            <-o->
106  *                              :
107  *                           interval
108  *
109  *              Phase values less than one make p0 the first sample in
110  *               the table - p1 will be the last sample, as a previous
111  *               sample does not exist. To avoid checking for this case,
112  *               a copy of the last sample is stored before the first
113  *               sample in each table.
114  *              Likewise, if the phase means p0 is the last sample, n0
115  *               and n1 will be the first and second samples respectively.
116  *               Copies of these samples are stored after the last sample
117  *               in each table.
118  *
119  *****************************************************************************/
120 static inline LADSPA_Data
wavedata_get_sample(Wavedata * w,LADSPA_Data phase)121 wavedata_get_sample (Wavedata * w,
122                      LADSPA_Data phase)
123 {
124 	LADSPA_Data * samples_hf = w->table->samples_hf;
125 	LADSPA_Data * samples_lf = w->table->samples_lf;
126 	LADSPA_Data p1, p0, n0, n1;
127 	LADSPA_Data phase_f;
128 	long int index;
129 
130 /* Scale phase to map to position in wavetable */
131 	phase *= w->table->phase_scale_factor;
132 
133 /* Get position of first contributing sample (p1) */
134 	index = LRINTF ((float) phase - 0.5f);
135 	phase_f = (LADSPA_Data) index;
136 
137 	index %= w->table->sample_count;
138 
139 /* Cross-fade table pairs */
140 /* Previous two samples */
141 	p1 = w->xfade * (samples_lf[index] - samples_hf[index]) + samples_hf[index];
142 	index++;
143 	p0 = w->xfade * (samples_lf[index] - samples_hf[index]) + samples_hf[index];
144 	index++;
145 /* Next two samples */
146 	n0 = w->xfade * (samples_lf[index] - samples_hf[index]) + samples_hf[index];
147 	index++;
148 	n1 = w->xfade * (samples_lf[index] - samples_hf[index]) + samples_hf[index];
149 
150 /* Return interpolated sample */
151 	return interpolate_cubic (phase - phase_f, p1, p0, n0, n1);
152 }
153 
154 /*****************************************************************************
155  * Description: Get wavetable to use for playback frequency.
156  *
157  *   Arguments: w               Wavedata object (contains all table info)
158  *              frequency       Playback frequency
159  *
160  *       Notes: The lookup vector used to determine the wavetable
161  *               is indexed by harmonic number.
162  *
163  *              The maximum playback frequency for a wavetable is
164  *               determined by its harmonic content and the sample rate,
165  *               and equals sample_rate / 2 / max_harmonic_in_table.
166  *
167  *****************************************************************************/
168 static inline void
wavedata_get_table(Wavedata * w,LADSPA_Data frequency)169 wavedata_get_table (Wavedata * w,
170                     LADSPA_Data frequency)
171 {
172 	unsigned long harmonic;
173 
174 	w->frequency = frequency;
175 	w->abs_freq = (LADSPA_Data) FABSF ((float) frequency);
176 
177 /* Get highest harmonic possible in frequency */
178 	harmonic = LRINTF (w->nyquist / w->abs_freq - 0.5f);
179 
180 /* Clip so lookup is within bounds */
181 	if (harmonic > w->lookup_max)
182 		harmonic = w->lookup_max;
183 
184 /* Set playback table */
185 	w->table = w->tables[w->lookup[harmonic]];
186 
187 /* Get cross fade factor */
188 	w->xfade = f_max (w->table->max_frequency - w->abs_freq, 0.0f) * w->table->range_scale_factor;
189 	w->xfade = f_min (w->xfade, 1.0f);
190 }
191 
192 #ifdef __cplusplus
193 } /* extern "C" { */
194 #endif
195 
196 #endif /* blop_wavedata_h */
197