XMMS2
|
00001 #include <math.h> 00002 #include "common.h" 00003 00004 #define FFT_LEN XMMSC_VISUALIZATION_WINDOW_SIZE 00005 /* TODO: better way, check this! */ 00006 #define FFT_BITS 9 00007 00008 /* Log scale settings */ 00009 #define AMP_LOG_SCALE_THRESHOLD0 0.001f 00010 #define AMP_LOG_SCALE_DIVISOR 6.908f /* divisor = -log threshold */ 00011 #define FREQ_LOG_SCALE_BASE 2.0f 00012 00013 static gfloat window[FFT_LEN]; 00014 static gfloat spec[FFT_LEN/2]; 00015 static gboolean fft_ready = FALSE; 00016 static gboolean fft_done; 00017 00018 void fft_init () 00019 { 00020 if (!fft_ready) { 00021 int i; 00022 /* calculate Hann window used to reduce spectral leakage */ 00023 for (i = 0; i < FFT_LEN; i++) { 00024 window[i] = 0.5 - 0.5 * cos (2.0 * M_PI * i / FFT_LEN); 00025 } 00026 fft_done = TRUE; 00027 } 00028 fft_done = FALSE; 00029 } 00030 00031 /* interesting: data->value.uint32 = xmms_sample_samples_to_ms (vis->format, pos); */ 00032 00033 static void 00034 fft (short *samples, gfloat *spec) 00035 { 00036 gint nv2, k, l, j = 0, i; 00037 gfloat t_r, t_i; 00038 gfloat buf[FFT_LEN][2]; 00039 00040 for (i = 0; i < FFT_LEN; i++){ 00041 buf[i][0] = (float) samples[j++]; 00042 buf[i][0] += (float) samples[j++]; 00043 buf[i][0] /= (float) (1 << 17); 00044 buf[i][0] *= window[i]; 00045 buf[i][1] = 0.0f; 00046 } 00047 00048 /* reorder... */ /* this is crappy! Go rewrite it using real bitreversing */ 00049 nv2 = FFT_LEN / 2; 00050 j = 1; 00051 00052 for (i = 1; i < FFT_LEN; i++) { 00053 if (i < j) { 00054 t_r = buf[i - 1][0]; 00055 t_i = buf[i - 1][1]; 00056 buf[i - 1][0] = buf[j - 1][0]; 00057 buf[i - 1][1] = buf[j - 1][1]; 00058 buf[j - 1][0] = t_r; 00059 buf[j - 1][1] = t_i; 00060 } 00061 00062 k = nv2; 00063 00064 while (k < j) { 00065 j -= k; 00066 k >>= 1; 00067 } 00068 00069 j += k; 00070 } 00071 00072 /* do fft */ 00073 for (l = 1; l <= FFT_BITS; l++) { 00074 gint le = 1 << l; 00075 gint le1 = le / 2; 00076 gfloat u_r = 1.0; 00077 gfloat u_i = 0.0; 00078 gfloat w_r = cosf (M_PI / (float) le1); 00079 gfloat w_i = -sinf (M_PI / (float) le1); 00080 00081 for (j = 1; j <= le1; j++) { 00082 for (i = j; i <= FFT_LEN; i += le) { 00083 gint ip = i + le1; 00084 00085 t_r = buf[ip - 1][0] * u_r - u_i * buf[ip - 1][1]; 00086 t_i = buf[ip - 1][1] * u_r + u_i * buf[ip - 1][0]; 00087 00088 buf[ip - 1][0] = buf[i - 1][0] - t_r; 00089 buf[ip - 1][1] = buf[i - 1][1] - t_i; 00090 00091 buf[i - 1][0] = buf[i - 1][0] + t_r; 00092 buf[i - 1][1] = buf[i - 1][1] + t_i; 00093 } 00094 00095 t_r = u_r * w_r - w_i * u_i; 00096 u_i = w_r * u_i + w_i * u_r; 00097 u_r = t_r; 00098 } 00099 } 00100 00101 /* output abs-value instead */ 00102 for (i = 0; i < nv2; i++) { 00103 spec[i] = hypot (buf[i][0], buf[i][1]); 00104 } 00105 00106 /* correct the scale */ 00107 spec[0] /= 2; 00108 spec[nv2 - 1] /= 2; 00109 } 00110 00111 /** 00112 * Calcualte the FFT on the decoded data buffer. 00113 */ 00114 static short 00115 fill_buffer_fft (int16_t* dest, int size, short *src) 00116 { 00117 int i; 00118 float tmp; 00119 00120 if (size != FFT_LEN * 2) { 00121 return 0; 00122 } 00123 00124 if (!fft_done) { 00125 fft (src, spec); 00126 fft_done = TRUE; 00127 } 00128 00129 /* TODO: more sophisticated! */ 00130 for (i = 0; i < FFT_LEN / 2; ++i) { 00131 if (spec[i] >= 1.0) { 00132 dest[i] = htons (SHRT_MAX); 00133 } else if (spec[i] < 0.0) { 00134 dest[i] = 0; 00135 } else { 00136 tmp = spec[i]; 00137 if (tmp > AMP_LOG_SCALE_THRESHOLD0) { 00138 // tmp = 1.0f + (logf (tmp) / AMP_LOG_SCALE_DIVISOR); 00139 } else { 00140 tmp = 0.0f; 00141 } 00142 dest[i] = htons ((int16_t)(tmp * SHRT_MAX)); 00143 } 00144 } 00145 return FFT_LEN / 2; 00146 } 00147 00148 short 00149 fill_buffer (int16_t *dest, xmmsc_vis_properties_t* prop, int channels, int size, short *src) 00150 { 00151 int i, j; 00152 if (prop->type == VIS_PEAK) { 00153 short l = 0, r = 0; 00154 for (i = 0; i < size; i += channels) { 00155 if (src[i] > 0 && src[i] > l) { 00156 l = src[i]; 00157 } 00158 if (src[i] < 0 && -src[i] > l) { 00159 l = -src[i]; 00160 } 00161 if (channels > 1) { 00162 if (src[i+1] > 0 && src[i+1] > r) { 00163 r = src[i+1]; 00164 } 00165 if (src[i+1] < 0 && -src[i+1] > r) { 00166 r = -src[i+1]; 00167 } 00168 } 00169 } 00170 if (channels == 1) { 00171 r = l; 00172 } 00173 if (prop->stereo) { 00174 dest[0] = htons (l); 00175 dest[1] = htons (r); 00176 size = 2; 00177 } else { 00178 dest[0] = htons ((l + r) / 2); 00179 size = 1; 00180 } 00181 } 00182 if (prop->type == VIS_PCM) { 00183 for (i = 0, j = 0; i < size; i += channels, j++) { 00184 short *l, *r; 00185 if (prop->pcm_hardwire) { 00186 l = &dest[j*2]; 00187 r = &dest[j*2 + 1]; 00188 } else { 00189 l = &dest[j]; 00190 r = &dest[size/channels + j]; 00191 } 00192 *l = htons (src[i]); 00193 if (prop->stereo) { 00194 if (channels > 1) { 00195 *r = htons (src[i+1]); 00196 } else { 00197 *r = htons (src[i]); 00198 } 00199 } 00200 } 00201 size /= channels; 00202 if (prop->stereo) { 00203 size *= 2; 00204 } 00205 } 00206 if (prop->type == VIS_SPECTRUM) { 00207 size = fill_buffer_fft (dest, size, src); 00208 } 00209 return size; 00210 }