📄 visualization.c
字号:
/* XMMS - Cross-platform multimedia player * Copyright (C) 1998-2001 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies * Copyright (C) 1999-2001 Haavard Kvaalen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "xmms.h"#include "fft.h"struct VisPluginData *vp_data;extern Vis *active_vis;extern SVis *mainwin_svis;GList *get_vis_list(void){ return vp_data->vis_list;}GList *get_vis_enabled_list(void){ return vp_data->enabled_list;}void vis_disable_plugin(VisPlugin *vp){ gint i = g_list_index(vp_data->vis_list,vp); enable_vis_plugin(i, FALSE); prefswin_vplugins_rescan();}void vis_about(int i){ GList *node = g_list_nth(vp_data->vis_list, i); if (node && node->data && ((VisPlugin *) node->data)->about) ((VisPlugin *) node->data)->about();}void vis_configure(int i){ GList *node = g_list_nth(vp_data->vis_list, i); if (node && node->data && ((VisPlugin *) node->data)->configure) ((VisPlugin *) node->data)->configure();}void vis_playback_start(void){ GList *node = vp_data->enabled_list; VisPlugin *vp; if(vp_data->playback_started) return; while(node) { vp = node->data; if(vp->playback_start) vp->playback_start(); node = g_list_next(node); } vp_data->playback_started = TRUE;}void vis_playback_stop(void){ GList *node = vp_data->enabled_list; VisPlugin *vp; if(!vp_data->playback_started) return; while(node) { vp = node->data; if(vp->playback_stop) vp->playback_stop(); node = g_list_next(node); } vp_data->playback_started = FALSE;}void enable_vis_plugin(int i, gboolean enable){ GList *node = g_list_nth(vp_data->vis_list, i); VisPlugin *vp; if (!node || !(node->data)) return; vp = (VisPlugin *) node->data; if (enable && !g_list_find(vp_data->enabled_list, vp)) { vp_data->enabled_list = g_list_append(vp_data->enabled_list, vp); if (vp->init) vp->init(); if(get_input_playing() && vp->playback_start) vp->playback_start(); } else if (!enable && g_list_find(vp_data->enabled_list, vp)) { vp_data->enabled_list = g_list_remove(vp_data->enabled_list, vp); if(get_input_playing() && vp->playback_stop) vp->playback_stop(); if (vp->cleanup) vp->cleanup(); }}gboolean vis_enabled(int i){ return (g_list_find(vp_data->enabled_list, (VisPlugin *) g_list_nth(vp_data->vis_list, i)->data) ? TRUE : FALSE);}gchar *vis_stringify_enabled_list(void){ gchar *enalist = NULL, *temp, *temp2; GList *node = vp_data->enabled_list; if (g_list_length(node)) { enalist = g_strdup(g_basename(((VisPlugin *) node->data)->filename)); node = node->next; while (node) { temp = enalist; temp2 = g_strdup(g_basename(((VisPlugin *) node->data)->filename)); enalist = g_strconcat(temp, ",", temp2, NULL); g_free(temp); g_free(temp2); node = node->next; } } return enalist;}void vis_enable_from_stringified_list(gchar * list){ gchar **plugins, *base; GList *node; gint i; VisPlugin *vp; if (!list || !strcmp(list, "")) return; plugins = g_strsplit(list, ",", 0); for(i = 0; plugins[i]; i++) { node = vp_data->vis_list; while (node) { base = g_basename(((VisPlugin *) node->data)->filename); if (!strcmp(plugins[i], base)) { vp = node->data; vp_data->enabled_list = g_list_append(vp_data->enabled_list, (VisPlugin *) vp); if(vp->init) vp->init(); if(get_input_playing() && vp->playback_start) vp->playback_start(); } node = node->next; } } g_strfreev(plugins);}static void calc_stereo_pcm(gint16 dest[2][512], gint16 src[2][512], gint nch){ memcpy(dest[0], src[0], 512 * sizeof(gint16)); if(nch == 1) memcpy(dest[1], src[0], 512 * sizeof(gint16)); else memcpy(dest[1], src[1], 512 * sizeof(gint16));}static void calc_mono_pcm(gint16 dest[2][512], gint16 src[2][512], gint nch){ gint i; gint16 *d, *sl, *sr; if(nch == 1) memcpy(dest[0], src[0], 512 * sizeof(gint16)); else { d = dest[0]; sl = src[0]; sr = src[1]; for(i = 0; i < 512; i++) { *(d++) = (*(sl++) + *(sr++)) >> 1; } }}static void calc_freq(gint16 *dest, gint16 *src){ static fft_state *state = NULL; gfloat tmp_out[257]; gint i; if(!state) state = fft_init(); fft_perform(src,tmp_out,state); for(i = 0; i < 256; i++) dest[i] = ((gint)sqrt(tmp_out[i + 1])) >> 8;}static void calc_mono_freq(gint16 dest[2][256], gint16 src[2][512], gint nch){ gint i; gint16 *d, *sl, *sr, tmp[512]; if(nch == 1) calc_freq(dest[0], src[0]); else { d = tmp; sl = src[0]; sr = src[1]; for(i = 0; i < 512; i++) { *(d++) = (*(sl++) + *(sr++)) >> 1; } calc_freq(dest[0], tmp); }}static void calc_stereo_freq(gint16 dest[2][256], gint16 src[2][512], gint nch){ calc_freq(dest[0], src[0]); if(nch == 2) calc_freq(dest[1], src[1]); else memcpy(dest[1], dest[0], 256 * sizeof(gint16));} void vis_send_data(gint16 pcm_data[2][512], int nch, int length){ GList *node = vp_data->enabled_list; VisPlugin *vp; gint16 mono_freq[2][256], stereo_freq[2][256]; gboolean mono_freq_calced = FALSE, stereo_freq_calced = FALSE; gint16 mono_pcm[2][512], stereo_pcm[2][512]; gboolean mono_pcm_calced = FALSE, stereo_pcm_calced = FALSE; gint8 intern_vis_data[512]; gint i; if (!pcm_data || nch < 1) { if (cfg.vis_type != VIS_OFF) { if (cfg.player_shaded && cfg.player_visible) svis_timeout_func(mainwin_svis, NULL); else vis_timeout_func(active_vis, NULL); } return; } while (node) { vp = node->data; if (vp->num_pcm_chs_wanted > 0 && vp->render_pcm) { if (vp->num_pcm_chs_wanted == 1) { if (!mono_pcm_calced) { calc_mono_pcm(mono_pcm, pcm_data, nch); mono_pcm_calced = TRUE; } vp->render_pcm(mono_pcm); } else { if (!stereo_pcm_calced) { calc_stereo_pcm(stereo_pcm, pcm_data, nch); stereo_pcm_calced = TRUE; } vp->render_pcm(stereo_pcm); } } if (vp->num_freq_chs_wanted > 0 && vp->render_freq) { if (vp->num_freq_chs_wanted == 1) { if (!mono_freq_calced) { calc_mono_freq(mono_freq, pcm_data, nch); mono_freq_calced = TRUE; } vp->render_freq(mono_freq); } else { if (!stereo_freq_calced) { calc_stereo_freq(stereo_freq, pcm_data, nch); stereo_freq_calced = TRUE; } vp->render_freq(stereo_freq); } } node = g_list_next(node); } if (cfg.vis_type == VIS_OFF) return; if (cfg.vis_type == VIS_ANALYZER) { if (cfg.player_shaded && cfg.player_visible) { /* VU */ gint vu ,val; if (!stereo_pcm_calced) calc_stereo_pcm(stereo_pcm, pcm_data, nch); vu = 0; for (i = 0; i < 512; i++) { val = abs(stereo_pcm[0][i]); if (val > vu) vu = val; } intern_vis_data[0] = (vu * 37) >> 15; if (intern_vis_data[0] > 37) intern_vis_data[0] = 37; if (nch == 2) { vu = 0; for (i = 0; i < 512; i++) { val = abs(stereo_pcm[1][i]); if (val > vu) vu = val; } intern_vis_data[1] = (vu * 37) >> 15; if (intern_vis_data[1] > 37) intern_vis_data[1] = 37; } else intern_vis_data[1] = intern_vis_data[0]; } else { /* Spectrum analyzer */ /* 76 values */ const int long_xscale[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18, 19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34, 35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51, 52,53,54,55,56,57,58,61,66,71,76,81,87,93,100,107, 114,122,131,140,150,161,172,184,255}; /* 20 values */ const int short_xscale[] = {0,1,2,3,4,5,6,7,8,11,15,20,27, 36,47,62,82,107,141,184,255}; const double y_scale = 3.60673760222; /* 20.0 / log(256) */ const int *xscale; gint j, y, max; if (!mono_freq_calced) calc_mono_freq(mono_freq, pcm_data, nch); memset(intern_vis_data, 0, 75); if (cfg.analyzer_type == ANALYZER_BARS) { max = 19; xscale = short_xscale; } else { max = 75; xscale = long_xscale; } for (i = 0; i < max; i++) { for (j = xscale[i], y = 0; j < xscale[i + 1]; j++) { if (mono_freq[0][j] > y) y = mono_freq[0][j]; } y >>= 7; if (y != 0) { intern_vis_data[i] = log(y) * y_scale; if (intern_vis_data[i] > 15) intern_vis_data[i] = 15; } else intern_vis_data[i] = 0; } } } else /* (cfg.vis_type == VIS_SCOPE) */ { /* Osciloscope */ gint pos, step; if (!mono_pcm_calced) calc_mono_pcm(mono_pcm, pcm_data, nch); step = (length << 8) / 74; for (i = 0, pos = 0; i < 75; i++, pos += step) { intern_vis_data[i] = ((mono_pcm[0][pos >> 8]) >> 11) + 6; if (intern_vis_data[i] > 12) intern_vis_data[i] = 12; if (intern_vis_data[i] < 0) intern_vis_data[i] = 0; } } if (cfg.player_shaded && cfg.player_visible) svis_timeout_func(mainwin_svis, intern_vis_data); else vis_timeout_func(active_vis, intern_vis_data);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -