XMMS2
format.c
Go to the documentation of this file.
1 #include <math.h>
2 #include "common.h"
3 
4 #define FFT_LEN XMMSC_VISUALIZATION_WINDOW_SIZE
5 /* TODO: better way, check this! */
6 #define FFT_BITS 9
7 
8 /* Log scale settings */
9 #define AMP_LOG_SCALE_THRESHOLD0 0.001f
10 #define AMP_LOG_SCALE_DIVISOR 6.908f /* divisor = -log threshold */
11 #define FREQ_LOG_SCALE_BASE 2.0f
12 
13 static gfloat window[FFT_LEN];
14 static gfloat spec[FFT_LEN/2];
15 static gboolean fft_ready = FALSE;
16 static gboolean fft_done;
17 
18 void fft_init ()
19 {
20  if (!fft_ready) {
21  int i;
22  /* calculate Hann window used to reduce spectral leakage */
23  for (i = 0; i < FFT_LEN; i++) {
24  window[i] = 0.5 - 0.5 * cos (2.0 * M_PI * i / FFT_LEN);
25  }
26  fft_done = TRUE;
27  }
28  fft_done = FALSE;
29 }
30 
31 /* interesting: data->value.uint32 = xmms_sample_samples_to_ms (vis->format, pos); */
32 
33 static void
34 fft (short *samples, gfloat *spec)
35 {
36  gint nv2, k, l, j = 0, i;
37  gfloat t_r, t_i;
38  gfloat buf[FFT_LEN][2];
39 
40  for (i = 0; i < FFT_LEN; i++){
41  buf[i][0] = (float) samples[j++];
42  buf[i][0] += (float) samples[j++];
43  buf[i][0] /= (float) (1 << 17);
44  buf[i][0] *= window[i];
45  buf[i][1] = 0.0f;
46  }
47 
48  /* reorder... */ /* this is crappy! Go rewrite it using real bitreversing */
49  nv2 = FFT_LEN / 2;
50  j = 1;
51 
52  for (i = 1; i < FFT_LEN; i++) {
53  if (i < j) {
54  t_r = buf[i - 1][0];
55  t_i = buf[i - 1][1];
56  buf[i - 1][0] = buf[j - 1][0];
57  buf[i - 1][1] = buf[j - 1][1];
58  buf[j - 1][0] = t_r;
59  buf[j - 1][1] = t_i;
60  }
61 
62  k = nv2;
63 
64  while (k < j) {
65  j -= k;
66  k >>= 1;
67  }
68 
69  j += k;
70  }
71 
72  /* do fft */
73  for (l = 1; l <= FFT_BITS; l++) {
74  gint le = 1 << l;
75  gint le1 = le / 2;
76  gfloat u_r = 1.0;
77  gfloat u_i = 0.0;
78  gfloat w_r = cosf (M_PI / (float) le1);
79  gfloat w_i = -sinf (M_PI / (float) le1);
80 
81  for (j = 1; j <= le1; j++) {
82  for (i = j; i <= FFT_LEN; i += le) {
83  gint ip = i + le1;
84 
85  t_r = buf[ip - 1][0] * u_r - u_i * buf[ip - 1][1];
86  t_i = buf[ip - 1][1] * u_r + u_i * buf[ip - 1][0];
87 
88  buf[ip - 1][0] = buf[i - 1][0] - t_r;
89  buf[ip - 1][1] = buf[i - 1][1] - t_i;
90 
91  buf[i - 1][0] = buf[i - 1][0] + t_r;
92  buf[i - 1][1] = buf[i - 1][1] + t_i;
93  }
94 
95  t_r = u_r * w_r - w_i * u_i;
96  u_i = w_r * u_i + w_i * u_r;
97  u_r = t_r;
98  }
99  }
100 
101  /* output abs-value instead */
102  for (i = 0; i < nv2; i++) {
103  spec[i] = hypot (buf[i][0], buf[i][1]);
104  }
105 
106  /* correct the scale */
107  spec[0] /= 2;
108  spec[nv2 - 1] /= 2;
109 }
110 
111 /**
112  * Calcualte the FFT on the decoded data buffer.
113  */
114 static short
115 fill_buffer_fft (int16_t* dest, int size, short *src)
116 {
117  int i;
118  float tmp;
119 
120  if (size != FFT_LEN * 2) {
121  return 0;
122  }
123 
124  if (!fft_done) {
125  fft (src, spec);
126  fft_done = TRUE;
127  }
128 
129  /* TODO: more sophisticated! */
130  for (i = 0; i < FFT_LEN / 2; ++i) {
131  if (spec[i] >= 1.0) {
132  dest[i] = htons (SHRT_MAX);
133  } else if (spec[i] < 0.0) {
134  dest[i] = 0;
135  } else {
136  tmp = spec[i];
137  if (tmp > AMP_LOG_SCALE_THRESHOLD0) {
138 // tmp = 1.0f + (logf (tmp) / AMP_LOG_SCALE_DIVISOR);
139  } else {
140  tmp = 0.0f;
141  }
142  dest[i] = htons ((int16_t)(tmp * SHRT_MAX));
143  }
144  }
145  return FFT_LEN / 2;
146 }
147 
148 short
149 fill_buffer (int16_t *dest, xmmsc_vis_properties_t* prop, int channels, int size, short *src)
150 {
151  int i, j;
152  if (prop->type == VIS_PEAK) {
153  short l = 0, r = 0;
154  for (i = 0; i < size; i += channels) {
155  if (src[i] > 0 && src[i] > l) {
156  l = src[i];
157  }
158  if (src[i] < 0 && -src[i] > l) {
159  l = -src[i];
160  }
161  if (channels > 1) {
162  if (src[i+1] > 0 && src[i+1] > r) {
163  r = src[i+1];
164  }
165  if (src[i+1] < 0 && -src[i+1] > r) {
166  r = -src[i+1];
167  }
168  }
169  }
170  if (channels == 1) {
171  r = l;
172  }
173  if (prop->stereo) {
174  dest[0] = htons (l);
175  dest[1] = htons (r);
176  size = 2;
177  } else {
178  dest[0] = htons ((l + r) / 2);
179  size = 1;
180  }
181  }
182  if (prop->type == VIS_PCM) {
183  for (i = 0, j = 0; i < size; i += channels, j++) {
184  short *l, *r;
185  if (prop->pcm_hardwire) {
186  l = &dest[j*2];
187  r = &dest[j*2 + 1];
188  } else {
189  l = &dest[j];
190  r = &dest[size/channels + j];
191  }
192  *l = htons (src[i]);
193  if (prop->stereo) {
194  if (channels > 1) {
195  *r = htons (src[i+1]);
196  } else {
197  *r = htons (src[i]);
198  }
199  }
200  }
201  size /= channels;
202  if (prop->stereo) {
203  size *= 2;
204  }
205  }
206  if (prop->type == VIS_SPECTRUM) {
207  size = fill_buffer_fft (dest, size, src);
208  }
209  return size;
210 }
#define FFT_BITS
Definition: format.c:6
void fft_init()
Definition: format.c:18
Properties of the delivered vis data.
short fill_buffer(int16_t *dest, xmmsc_vis_properties_t *prop, int channels, int size, short *src)
Definition: format.c:149
#define FFT_LEN
Definition: format.c:4
#define AMP_LOG_SCALE_THRESHOLD0
Definition: format.c:9