📄 audiochart.java
字号:
/* * To change this template, choose Tools | Templates * and open the template in the editor. */package com.hadeslee.yoyoplayer.util;/** * * @author hadeslee */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.util.List;import java.util.StringTokenizer;import java.util.logging.Level;import java.util.logging.Logger;import javax.sound.sampled.SourceDataLine;import javax.swing.JPanel;import kj.dsp.KJDigitalSignalProcessingAudioDataConsumer;import kj.dsp.KJDigitalSignalProcessor;import kj.dsp.KJFFT;@SuppressWarnings("unchecked")public class AudioChart extends JPanel implements KJDigitalSignalProcessor { private static final long serialVersionUID = 20071214L; private static Logger log = Logger.getLogger(AudioChart.class.getName()); public static final int DISPLAY_MODE_SPECTRUM_ANALYSER = 0; public static final int DISPLAY_MODE_SCOPE = 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 = 20; 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, 0); 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 boolean showFPS = false; private int fp = 0; // private Runnable PAINT_SYNCHRONIZER = new AWTPaintSynchronizer(); public AudioChart() { log.setLevel(Level.OFF); setOpaque(false); initialize(); } public boolean isPeaksEnabled() { return peaksEnabled; } public void setPeaksEnabled(boolean peaksEnabled) { this.peaksEnabled = peaksEnabled; } /** * 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, Config.getConfig().getAudioChartfps()); dsp.add(this); } else { dsp.remove(this); dsp = new KJDigitalSignalProcessingAudioDataConsumer(2048, Config.getConfig().getAudioChartfps()); dsp.add(this); } if ((dsp != null) && (m_line != null)) { if (dspStarted == true) { stopDSP(); } dsp.start(m_line); dspStarted = true; log.info("DSP started"); } } /** * Stop DSP. */ public void stopDSP() { if (dsp != null) { dsp.stop(); dspStarted = false; log.info("DSP stopped"); } } /** * Close DSP */ public void closeDSP() { if (dsp != null) { stopDSP(); dsp = null; log.info("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 peak color. * @param c */ public void setPeakColor(Color c) { peakColor = c; } /** * Set peak falloff delay. * @param framestowait */ public void setPeakDelay(int framestowait) { int fps = Config.getConfig().getAudioChartfps(); int min = Math.round((DEFAULT_SPECTRUM_ANALYSER_PEAK_DELAY_FPS_RATIO - DEFAULT_SPECTRUM_ANALYSER_PEAK_DELAY_FPS_RATIO_RANGE) * fps); int max = 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 = 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.info("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)) { old_FFT[a] = wFs; } else { old_FFT[a] -= wSadfrr; if (old_FFT[a] < 0) { old_FFT[a] = 0; } wFs = old_FFT[a]; } drawSpectrumAnalyserBar(pGrp, (int) c, height, (int) wBw - 1, (int) (wFs * height), bd); c += wBw; } } private void drawVUMeter(Graphics pGrp, float[] pLeft, float[] pRight, float pFrrh) { if (displayMode == DISPLAY_MODE_OFF) { return; } float wLeft = 0.0f; float wRight = 0.0f; float wSadfrr = (vuDecay * pFrrh); for (int a = 0; a < pLeft.length; a++) { wLeft += Math.abs(pLeft[a]); wRight += Math.abs(pRight[a]); } wLeft = ((wLeft * 2.0f) / (float) pLeft.length); wRight = ((wRight * 2.0f) / (float) pRight.length);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -