⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spectrumtimeanalyzer.java

📁 java平台的图形音乐播放器
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * SpectrumTimeAnalyzer.
 *
 * JavaZOOM : jlgui@javazoom.net
 *            http://www.javazoom.net
 *
 *-----------------------------------------------------------------------
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library 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 Library General Public License for more details.
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *----------------------------------------------------------------------
 */
package javazoom.jlgui.player.amp.visual.ui;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;
import javax.sound.sampled.SourceDataLine;
import javax.swing.JPanel;
import javazoom.jlgui.player.amp.skin.AbsoluteConstraints;
import kj.dsp.KJDigitalSignalProcessingAudioDataConsumer;
import kj.dsp.KJDigitalSignalProcessor;
import kj.dsp.KJFFT;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class SpectrumTimeAnalyzer extends JPanel implements KJDigitalSignalProcessor
{
    private static Log log = LogFactory.getLog(SpectrumTimeAnalyzer.class);
    public static final int DISPLAY_MODE_SCOPE = 0;
    public static final int DISPLAY_MODE_SPECTRUM_ANALYSER = 1;
    public static final int DISPLAY_MODE_OFF = 2;
    public static final int DEFAULT_WIDTH = 256;
    public static final int DEFAULT_HEIGHT = 128;
    public static final int DEFAULT_FPS = 50;
    public static final int DEFAULT_SPECTRUM_ANALYSER_FFT_SAMPLE_SIZE = 512;
    public static final int DEFAULT_SPECTRUM_ANALYSER_BAND_COUNT = 19;
    public static final float DEFAULT_SPECTRUM_ANALYSER_DECAY = 0.05f;
    public static final int DEFAULT_SPECTRUM_ANALYSER_PEAK_DELAY = 20;
    public static final float DEFAULT_SPECTRUM_ANALYSER_PEAK_DELAY_FPS_RATIO = 0.4f;
    public static final float DEFAULT_SPECTRUM_ANALYSER_PEAK_DELAY_FPS_RATIO_RANGE = 0.1f;
    public static final float MIN_SPECTRUM_ANALYSER_DECAY = 0.02f;
    public static final float MAX_SPECTRUM_ANALYSER_DECAY = 0.08f;
    public static final Color DEFAULT_BACKGROUND_COLOR = new Color(0, 0, 128);
    public static final Color DEFAULT_SCOPE_COLOR = new Color(255, 192, 0);
    public static final float DEFAULT_VU_METER_DECAY = 0.02f;
    private Image bi;
    private int displayMode = DISPLAY_MODE_SCOPE;
    private Color scopeColor = DEFAULT_SCOPE_COLOR;
    private Color[] spectrumAnalyserColors = getDefaultSpectrumAnalyserColors();
    private KJDigitalSignalProcessingAudioDataConsumer dsp = null;
    private boolean dspStarted = false;
    private Color peakColor = null;
    private int[] peaks = new int[DEFAULT_SPECTRUM_ANALYSER_BAND_COUNT];
    private int[] peaksDelay = new int[DEFAULT_SPECTRUM_ANALYSER_BAND_COUNT];
    private int peakDelay = DEFAULT_SPECTRUM_ANALYSER_PEAK_DELAY;
    private boolean peaksEnabled = true;
    private List visColors = null;
    private int barOffset = 1;
    private int width;
    private int height;
    private int height_2;
    // -- Spectrum analyser variables.
    private KJFFT fft;
    private float[] old_FFT;
    private int saFFTSampleSize;
    private int saBands;
    private float saColorScale;
    private float saMultiplier;
    private float saDecay = DEFAULT_SPECTRUM_ANALYSER_DECAY;
    private float sad;
    private SourceDataLine m_line = null;
    // -- VU Meter
    private float oldLeft;
    private float oldRight;
    //  private float vuAverage;
    //  private float vuSamples;
    private float vuDecay = DEFAULT_VU_METER_DECAY;
    private float vuColorScale;
    // -- FPS calulations.
    private long lfu = 0;
    private int fc = 0;
    private int fps = DEFAULT_FPS;
    private boolean showFPS = false;
    
    private AbsoluteConstraints constraints = null;

    //  private Runnable PAINT_SYNCHRONIZER = new AWTPaintSynchronizer();
    public SpectrumTimeAnalyzer()
    {
        setOpaque(false);
        initialize();
    }

    public void setConstraints(AbsoluteConstraints cnts)
    {
        constraints = cnts;
    }
    
    public AbsoluteConstraints getConstraints()
    {
        return constraints;
    }
    
    public boolean isPeaksEnabled()
    {
        return peaksEnabled;
    }

    public void setPeaksEnabled(boolean peaksEnabled)
    {
        this.peaksEnabled = peaksEnabled;
    }

    public int getFps()
    {
        return fps;
    }

    public void setFps(int fps)
    {
        this.fps = fps;
    }

    /**
     * Starts DSP.
     * @param line
     */
    public void startDSP(SourceDataLine line)
    {
        if (displayMode == DISPLAY_MODE_OFF) return;
        if (line != null) m_line = line;
        if (dsp == null)
        {
            dsp = new KJDigitalSignalProcessingAudioDataConsumer(2048, fps);
            dsp.add(this);
        }
        if ((dsp != null) && (m_line != null))
        {
            if (dspStarted == true)
            {
                stopDSP();
            }
            dsp.start(m_line);
            dspStarted = true;
            log.debug("DSP started");
        }
    }

    /**
     * Stop DSP.
     */
    public void stopDSP()
    {
        if (dsp != null)
        {
            dsp.stop();
            dspStarted = false;
            log.debug("DSP stopped");
        }
    }

    /**
     * Close DSP
     */
    public void closeDSP()
    {
        if (dsp != null)
        {
            stopDSP();
            dsp = null;
            log.debug("DSP closed");
        }
    }

    /**
     * Setup DSP.
     * @param line
     */
    public void setupDSP(SourceDataLine line)
    {
        if (dsp != null)
        {
            int channels = line.getFormat().getChannels();
            if (channels == 1) dsp.setChannelMode(KJDigitalSignalProcessingAudioDataConsumer.CHANNEL_MODE_MONO);
            else dsp.setChannelMode(KJDigitalSignalProcessingAudioDataConsumer.CHANNEL_MODE_STEREO);
            int bits = line.getFormat().getSampleSizeInBits();
            if (bits == 8) dsp.setSampleType(KJDigitalSignalProcessingAudioDataConsumer.SAMPLE_TYPE_EIGHT_BIT);
            else dsp.setSampleType(KJDigitalSignalProcessingAudioDataConsumer.SAMPLE_TYPE_SIXTEEN_BIT);
        }
    }

    /**
     * Write PCM data to DSP.
     * @param pcmdata
     */
    public void writeDSP(byte[] pcmdata)
    {
        if ((dsp != null) && (dspStarted == true)) dsp.writeAudioData(pcmdata);
    }

    /**
     * Return DSP.
     * @return
     */
    public KJDigitalSignalProcessingAudioDataConsumer getDSP()
    {
        return dsp;
    }

    /**
     * Set visual colors from skin.
     * @param viscolor
     */
    public void setVisColor(String viscolor)
    {
        ArrayList visColors = new ArrayList();
        viscolor = viscolor.toLowerCase();
        ByteArrayInputStream in = new ByteArrayInputStream(viscolor.getBytes());
        BufferedReader bin = new BufferedReader(new InputStreamReader(in));
        try
        {
            String line = null;
            while ((line = bin.readLine()) != null)
            {
                visColors.add(getColor(line));
            }
            Color[] colors = new Color[visColors.size()];
            visColors.toArray(colors);
            Color[] specColors = new Color[15];
            System.arraycopy(colors, 2, specColors, 0, 15);
            List specList = Arrays.asList(specColors);
            Collections.reverse(specList);
            specColors = (Color[]) specList.toArray(specColors);
            setSpectrumAnalyserColors(specColors);
            setBackground((Color) visColors.get(0));
            if (visColors.size()>23) setPeakColor((Color) visColors.get(23));
            if (visColors.size()>18) setScopeColor((Color) visColors.get(18));
        }
        catch (IOException ex)
        {
            log.warn("Cannot parse viscolors", ex);
        }
        finally
        {
            try
            {
                if (bin != null) bin.close();
            }
            catch (IOException e)
            {
            }
        }
    }

    /**
     * Set visual peak color.
     * @param c
     */
    public void setPeakColor(Color c)
    {
        peakColor = c;
    }

    /**
     * Set peak falloff delay.
     * @param framestowait
     */
    public void setPeakDelay(int framestowait)
    {
        int min = (int) Math.round((DEFAULT_SPECTRUM_ANALYSER_PEAK_DELAY_FPS_RATIO - DEFAULT_SPECTRUM_ANALYSER_PEAK_DELAY_FPS_RATIO_RANGE) * fps);
        int max = (int) Math.round((DEFAULT_SPECTRUM_ANALYSER_PEAK_DELAY_FPS_RATIO + DEFAULT_SPECTRUM_ANALYSER_PEAK_DELAY_FPS_RATIO_RANGE) * fps);
        if ((framestowait >= min) && (framestowait <= max))
        {
            peakDelay = framestowait;
        }
        else
        {
            peakDelay = (int) Math.round(DEFAULT_SPECTRUM_ANALYSER_PEAK_DELAY_FPS_RATIO * fps);
        }
    }

    /**
     * Return peak falloff delay
     * @return int framestowait
     */
    public int getPeakDelay()
    {
        return peakDelay;
    }

    /**
     * Convert string to color.
     * @param linecolor
     * @return
     */
    public Color getColor(String linecolor)
    {
        Color color = Color.BLACK;
        StringTokenizer st = new StringTokenizer(linecolor, ",");
        int red = 0, green = 0, blue = 0;
        try
        {
            if (st.hasMoreTokens()) red = Integer.parseInt(st.nextToken().trim());
            if (st.hasMoreTokens()) green = Integer.parseInt(st.nextToken().trim());
            if (st.hasMoreTokens())
            {
                String blueStr = st.nextToken().trim();
                if (blueStr.length() > 3) blueStr = (blueStr.substring(0, 3)).trim();
                blue = Integer.parseInt(blueStr);
            }
            color = new Color(red, green, blue);
        }
        catch (NumberFormatException e)
        {
            log.debug("Cannot parse viscolor : "+e.getMessage());
        }
        return color;
    }

    private void computeColorScale()
    {
        saColorScale = ((float) spectrumAnalyserColors.length / height) * barOffset * 1.0f;
        vuColorScale = ((float) spectrumAnalyserColors.length / (width - 32)) * 2.0f;
    }

    private void computeSAMultiplier()
    {
        saMultiplier = (saFFTSampleSize / 2) / saBands;
    }

    private void drawScope(Graphics pGrp, float[] pSample)
    {
        pGrp.setColor(scopeColor);
        int wLas = (int) (pSample[0] * (float) height_2) + height_2;
        int wSt = 2;
        for (int a = wSt, c = 0; c < width; a += wSt, c++)
        {
            int wAs = (int) (pSample[a] * (float) height_2) + height_2;
            pGrp.drawLine(c, wLas, c + 1, wAs);
            wLas = wAs;
        }
    }

    private void drawSpectrumAnalyser(Graphics pGrp, float[] pSample, float pFrrh)
    {
        float c = 0;
        float[] wFFT = fft.calculate(pSample);
        float wSadfrr = (saDecay * pFrrh);
        float wBw = ((float) width / (float) saBands);
        for (int a = 0, bd = 0; bd < saBands; a += saMultiplier, bd++)
        {
            float wFs = 0;
            // -- Average out nearest bands.
            for (int b = 0; b < saMultiplier; b++)
            {
                wFs += wFFT[a + b];
            }
            // -- Log filter.
            wFs = (wFs * (float) Math.log(bd + 2));
            if (wFs > 1.0f)
            {
                wFs = 1.0f;
            }
            // -- Compute SA decay...
            if (wFs >= (old_FFT[a] - wSadfrr))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -