Go to the documentation of this file.00001 #include <math.h>
00002 #include "common.h"
00003
00004 #define FFT_LEN XMMSC_VISUALIZATION_WINDOW_SIZE
00005
00006 #define FFT_BITS 9
00007
00008
00009 #define AMP_LOG_SCALE_THRESHOLD0 0.001f
00010 #define AMP_LOG_SCALE_DIVISOR 6.908f
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
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
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
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
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
00102 for (i = 0; i < nv2; i++) {
00103 spec[i] = hypot (buf[i][0], buf[i][1]);
00104 }
00105
00106
00107 spec[0] /= 2;
00108 spec[nv2 - 1] /= 2;
00109 }
00110
00111
00112
00113
00114 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
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
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 }