Added graph making, used 32-bit float samples.
[aftubes.git] / effects.c
blobbacc5cb1e83d0d5b865e703c9ed42aaff794ca2a
1 #include "effects.h"
2 #include "effect.h"
3 #include "math.h"
4 #include "stdlib.h"
5 #include "string.h"
6 #include "attr.h"
8 #include "wavefile.h"
9 #include "soundout.h"
11 #ifndef M_PI
12 #define M_PI 3.14159265358979323846
13 #endif
15 /***** silly_effect (it's a ring modulator right now, but may change) *****/
17 struct silly_effect {
18 struct effect e;
21 static int silly_effect_process(struct effect *ef, void **buf, long n_samples)
23 float *bufp;
24 int i;
26 if (!*buf){
27 // we're not a source
28 return 1;
31 bufp = *buf;
32 for (i = 0; i < n_samples; ++i){
33 bufp[i * 2] *= cos((i * 2 * M_PI) / 441.0);
34 bufp[i * 2 + 1] *= cos((i * 2 * M_PI) / 441.0);
36 return 0;
39 static void silly_effect_destroy(struct effect *ef)
41 free(ef);
44 static const struct effect_vtab silly_effect_vtab = {
45 silly_effect_process,
46 silly_effect_destroy,
49 struct effect *silly_effect_create(void)
51 struct silly_effect *se;
52 se = malloc(sizeof *se);
53 if (!se){
54 return NULL;
56 se->e.vtab = &silly_effect_vtab;
57 return &se->e;
60 void silly_effect_free(struct effect *e)
62 free(e);
65 ///// wavefile_source /////
67 struct wavefile_source {
68 struct effect e;
69 struct wavefile wf;
70 off_t pos;
73 static int wavefile_source_process(struct effect *ef, void **buf, long n_samples)
75 struct wavefile_source *wfs = (struct wavefile_source *) ef;
76 short *rbuf, *rbuf_p;
77 float *fbuf;
78 int i;
79 if (!*buf){
80 *buf = malloc(8 * n_samples); // XXXX!
81 if (!*buf){
82 return 1;
85 rbuf = malloc(n_samples * 4); // XXX!
86 fbuf = *buf;
87 wavefile_read_at(&wfs->wf, wfs->pos, rbuf, n_samples);
88 rbuf_p = rbuf;
89 for (i = n_samples * 2; i; --i){
90 *fbuf = *rbuf_p / 32768.0;
91 ++fbuf;
92 ++rbuf_p;
94 free(rbuf);
96 wfs->pos += n_samples;
97 return 0;
100 static void wavefile_source_destroy(struct effect *ef)
102 // struct wavefile_source *wfs = (struct wavefile_source *) ef;
103 // wavefile_destroy(&wfs->wf);
104 free(ef);
107 static const struct effect_vtab wavefile_source_vtab = {
108 wavefile_source_process,
109 wavefile_source_destroy,
112 struct effect *wavefile_source_create(const char *filename)
114 struct wavefile_source *wfs;
115 wfs = malloc(sizeof *wfs);
116 if (!wfs){
117 return NULL;
119 wfs->e.vtab = &wavefile_source_vtab;
120 wfs->pos = 0;
121 if (wavefile_open(&wfs->wf, filename)){
122 free(wfs);
123 return NULL;
125 return &wfs->e;
128 ///// play_sink /////
130 struct play_sink {
131 struct effect e;
132 struct soundout so;
135 static int play_sink_process(struct effect *ef, void **buf, long n_samples)
137 struct play_sink *ps = (struct play_sink *) ef;
138 short *wbuf, *wbuf_p;
139 float *fbuf;
140 int i;
141 if (!*buf){
142 // we're not a source
143 return 1;
145 wbuf = malloc(n_samples * 4); // XXXX!!
146 wbuf_p = wbuf;
147 fbuf = *buf;
148 for (i = n_samples * 2; i; --i){
149 *wbuf_p = (short) (*fbuf * 32768.0);
150 ++wbuf_p;
151 ++fbuf;
153 soundout_write(&ps->so, wbuf, n_samples * 4); // XXX!
154 free(wbuf);
155 return 0;
158 static void play_sink_destroy(struct effect *ef)
160 // struct play_sink *ps = (struct play_sink *) ef;
161 // soundout_destroy(&ps->so);
162 free(ef);
165 static const struct effect_vtab play_sink_vtab = {
166 play_sink_process,
167 play_sink_destroy,
170 struct effect *play_sink_create(const struct aformat *fmt)
172 struct play_sink *ps;
173 ps = malloc(sizeof *ps);
174 if (!ps){
175 return NULL;
177 if (soundout_open(&ps->so, fmt) != 0){
178 free(ps);
179 return NULL;
181 ps->e.vtab = &play_sink_vtab;
182 return &ps->e;
185 ///// distortion /////
187 struct distortion {
188 struct effect e;
189 int level;
192 static pure inline int mult_clamp16(int a, int b)
194 int c = a * b;
195 if (c > 0x7FFF){
196 c = 0x7FFF;
197 } else if (c < -0x7FFF){
198 c = -0x7FFF;
200 return c;
203 static int distortion_process(struct effect *restrict ef, void **buf, long n_samples)
205 struct distortion *dist = (struct distortion *) ef;
206 int i, c, chan_average;
207 float *restrict pbuf;
208 float rms, rms_1;
209 // struct distortion *dist = (struct distortion *) ef;
210 if (!*buf){
211 // we're not a source
212 return 1;
214 pbuf = *buf;
215 // calc rms
216 rms = 0.0;
217 for (i = n_samples; i; --i){
218 for (c = 0; c < 2; ++c){
219 rms += powf(pbuf[c], 2);
221 pbuf += 2;
223 rms = sqrtf(rms / (n_samples * 2));
224 rms_1 = 0.25 / rms;
225 // amplify!!
226 pbuf = *buf;
227 for (i = n_samples; i; --i){
228 for (c = 0; c < 2; ++c){
229 pbuf[c] *= rms_1;
231 pbuf += 2;
233 return 0;
236 static void distortion_destroy(struct effect *ef)
238 // struct distortion *dist = (struct distortion *) ef;
239 // soundout_destroy(&dist->so);
240 free(ef);
243 static const struct effect_vtab distortion_vtab = {
244 distortion_process,
245 distortion_destroy,
248 struct effect *distortion_create(void)
250 struct distortion *dist;
251 dist = malloc(sizeof *dist);
252 if (!dist){
253 return NULL;
255 dist->level = 0x7FFF;
256 dist->e.vtab = &distortion_vtab;
257 return &dist->e;