Package jm.gui.wave

Source Code of jm.gui.wave.WaveView

/*

<This Java Class is part of the jMusic API>

Copyright (C) 2000 Andrew Sorensen & Andrew Brown

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 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., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

package jm.gui.wave;

import jm.audio.RTMixer;

import java.awt.*;
import java.awt.event.*;

/*
* This class is a jMusic utility that displays an .au file
* as an amplitude-time graph. It will support files of up to
* eight channels.
* A part of the jMusic audio wave file viewing package
* @author Andrew Brown
*/
public class WaveView implements ActionListener, ComponentListener {
    private String lastFileName = "Drunk.au";
    private String lastDirectory = "";
    private WaveFileReader afr;
    /* Dimensions of the frame */
    private int width = 600;
    /* Height on one wave panel */
    private int channelHeight = 200;
    /* Current display magnification of the waveform's amplitude */
    private int amplitude = 1;
    /* The number of cahnnels in the file */
    private int channels;
    /* an array that contains the read sample data */
    private float[] data;
    /* The screen display resolution */
    private int resolution = 256;
    /* the amount of data to read from the file */
    private int segmentSize;
    /* The current sample position to start reading from */
    private int startPos = 0;
    // menu items
    private MenuItem size1, size2, size4, size8, size16, size32,
            size64, size128, size256, size512, size1024, size2048,
            size4096, openFile, quit, changeColor,
            vSmall, small, medium, large, huge, times1, times2, times3, times4;

    private Frame f = new Frame();
    private WaveCanvas[] canvases = new WaveCanvas[8];
    private ScrollPane sp = new ScrollPane(ScrollPane.SCROLLBARS_NEVER);
    private WaveScrollPanel scrollPanel = new WaveScrollPanel();
    private boolean whiteColor = true;
    /**
     * The RTMixer object for playback
     */
    private RTMixer mixer;
    private int lastStartPos = -1;

    /*
* A constructor that prompts the user for a file to be displayed.
*/
    public WaveView() {
        super();
        openFile();
        drawWave(0, 0);
    }

    /*
     * A constructor that displays a specified audio file.
     * @param fileName The name (and path) of a file to be displayed.
     */
    public WaveView(String fileName) {
        this(fileName, 0, 0);
    }

    /*
* A constructor that displays a specified audio file.
* @param fileName The name (and path) of a file to be displayed.
     * @param int The horizontal location for the display.
     * @param int The vertical location for the display.
*/
    public WaveView(String fileName, int xLoc, int yLoc) {
        super();
        this.lastFileName = fileName;
        afr = new WaveFileReader(fileName);
        init();
        drawWave(xLoc, yLoc);
        f.setTitle("jMusic Wave Viewer: " + lastFileName);
    }

    /**
     * Dialog to import an audio file
     */
    public void openFile() {
        FileDialog loadFile = new FileDialog(f,
                "Select a 16 bit audio file in .au format (no compression).",
                FileDialog.LOAD);
        loadFile.setDirectory(lastDirectory);
        loadFile.setFile(lastFileName);
        loadFile.show(); // loadFile.setVisible(true); // show depreicated from 1.5 but not used to allow 1.3 compatability
        String fileName = loadFile.getFile();
        if (fileName != null) {
            lastFileName = fileName;
            lastDirectory = loadFile.getDirectory();
            afr = new WaveFileReader(lastDirectory + fileName);
            updateScrollInfo();
            init();
            setupPanel();
            lastFileName = fileName;
            f.setTitle("jMusic Wave Viewer: " + lastFileName);
            if (!whiteColor) {
                changeColor();
                // maintain color setting
                whiteColor = !whiteColor;
            }
            if (channels <= 2) setHeight(200);
            if (channels > 2) setHeight(100);
            if (channels > 4) setHeight(50);
            f.repaint();
        }
    }

    private void init() {
        channels = afr.getChannels();
        if (channels > 8) {
            System.out.println("jMusic wave viewer error: " +
                    "Files with more than 8 channels are not supported :(");
            System.exit(1);
        }
        //segmentSize = samples; // the whole file
        segmentSize = width * resolution * channels;
        //data = new float[segmentSize];
        // Fill array from a sample start point
        data = afr.getSamples(segmentSize, startPos);
        setupChannels();
        if (channels <= 2) setHeight(200);
        if (channels > 2) setHeight(100);
        if (channels > 4) setHeight(50);
        scrollPanel.setScrollbarAttributes(afr.getWaveSize(), width, resolution);
    }

    private void drawWave(int xLoc, int yLoc) {
        f.setName("jMusic Wave Viewer: " + lastFileName);
        f.setLocation(xLoc, yLoc);
        f.setLayout(new BorderLayout());
        sp.setSize(new Dimension(width, (channelHeight + 1) * channels));
        setupPanel();
        f.add(sp, "Center");
        // set up scroll bar panel
        scrollPanel.setViewer(this);
        updateScrollInfo();
        scrollPanel.setScrollbarAttributes(afr.getWaveSize(), width, resolution);
        f.add(scrollPanel, "South");

        // menus
        MenuBar menus = new MenuBar();
        Menu fileMenu = new Menu("Wave", true);
        Menu heightMenu = new Menu("Height", true);
        Menu resolutionMenu = new Menu("Resolution", true);
        Menu amplitudeMenu = new Menu("Amplitude", true);

        size1 = new MenuItem("1:1");
        size1.addActionListener(this);
        resolutionMenu.add(size1);

        size2 = new MenuItem("1:2");
        size2.addActionListener(this);
        resolutionMenu.add(size2);

        size4 = new MenuItem("1:4");
        size4.addActionListener(this);
        resolutionMenu.add(size4);

        size8 = new MenuItem("1:8");
        size8.addActionListener(this);
        resolutionMenu.add(size8);

        size16 = new MenuItem("1:16");
        size16.addActionListener(this);
        resolutionMenu.add(size16);

        size32 = new MenuItem("1:32");
        size32.addActionListener(this);
        resolutionMenu.add(size32);

        size64 = new MenuItem("1:64");
        size64.addActionListener(this);
        resolutionMenu.add(size64);

        size128 = new MenuItem("1:128");
        size128.addActionListener(this);
        resolutionMenu.add(size128);

        size256 = new MenuItem("1:256");
        size256.addActionListener(this);
        resolutionMenu.add(size256);

        size512 = new MenuItem("1:512");
        size512.addActionListener(this);
        resolutionMenu.add(size512);

        size1024 = new MenuItem("1:1024");
        size1024.addActionListener(this);
        resolutionMenu.add(size1024);

        size2048 = new MenuItem("1:2048");
        size2048.addActionListener(this);
        resolutionMenu.add(size2048);
                /*
        size4096 = new MenuItem("1:4096");
    size4096.addActionListener(this);
    resolutionMenu.add(size4096);
                */
        openFile = new MenuItem("Open...", new MenuShortcut(KeyEvent.VK_O));
        openFile.addActionListener(this);
        fileMenu.add(openFile);

        changeColor = new MenuItem("Change Color", new MenuShortcut(KeyEvent.VK_C));
        changeColor.addActionListener(this);
        fileMenu.add(changeColor);

        quit = new MenuItem("Quit", new MenuShortcut(KeyEvent.VK_Q));
        quit.addActionListener(this);
        fileMenu.add(quit);

        vSmall = new MenuItem("X Small");
        vSmall.addActionListener(this);
        heightMenu.add(vSmall);

        small = new MenuItem("Small");
        small.addActionListener(this);
        heightMenu.add(small);

        medium = new MenuItem("Medium");
        medium.addActionListener(this);
        heightMenu.add(medium);

        large = new MenuItem("Large");
        large.addActionListener(this);
        heightMenu.add(large);

        huge = new MenuItem("X Large");
        huge.addActionListener(this);
        heightMenu.add(huge);

        times1 = new MenuItem("x1");
        times1.addActionListener(this);
        amplitudeMenu.add(times1);

        times2 = new MenuItem("x2");
        times2.addActionListener(this);
        amplitudeMenu.add(times2);

        times3 = new MenuItem("x3");
        times3.addActionListener(this);
        amplitudeMenu.add(times3);

        times4 = new MenuItem("x4");
        times4.addActionListener(this);
        amplitudeMenu.add(times4);

        menus.add(fileMenu);
        menus.add(heightMenu);
        menus.add(resolutionMenu);
        menus.add(amplitudeMenu);
        f.setMenuBar(menus);

        // display
        sp.setSize(new Dimension(width, (channelHeight + 1) * channels));
        f.pack();
        width = f.getSize().width;
        f.setVisible(true);
        f.addComponentListener(this);
    }

    private void updateScrollInfo() {
        // update scrollpanel info
        scrollPanel.setFileName(this.lastFileName);
        scrollPanel.setBitSize(afr.getBitResolution());
        scrollPanel.setSampleRate(afr.getSampleRate());
        scrollPanel.setChannels(afr.getChannels());
        scrollPanel.getWaveRuler().setMarkerWidth(afr.getSampleRate() / resolution);
        scrollPanel.setScrollbarValue(startPos);
        scrollPanel.setScrollbarResolution(resolution);
    }


    private void setupChannels() {
        channels = afr.getChannels();
        float[][] tracks = new float[channels][segmentSize / channels];
        int counter = 0;
        for (int i = 0; i < segmentSize; i += channels) {
            for (int j = 0; j < channels; j++) {
                tracks[j][counter] = data[i + j];
            }
            counter++;
        }
        // set up canvases for each channel
        for (int i = 0; i < channels; i++) {
            canvases[i] = new WaveCanvas();
            canvases[i].setSize(new Dimension(this.width, this.channelHeight + 1));
            canvases[i].setData(tracks[i]);
            canvases[i].setResolution(this.resolution);
            canvases[i].setHeight(this.channelHeight);
            canvases[i].setAmplitude(this.amplitude);
            canvases[i].setWaveSize(afr.getWaveSize());
        }
    }

    /*
    * Report the horizontal view location of the wave
    */
    public int getStartPos() {
        return this.startPos;
    }

    /*
    * Respond to a change is horizontal view location of the wave
    */
    public void setStartPos(int newOffset) {
        this.startPos = newOffset;
        reRead();
        //f.repaint();
        /*
        for (int i=0; i<channels; i++) {
            canvases[i].setFastDraw(true);
            canvases[i].repaint();
        }
         */
        for (int i = 0; i < channels; i++) {
            canvases[i].setFastDraw(false);
            canvases[i].repaint();
        }
    }

    private void reRead() {
        segmentSize = width * resolution * channels;
        if (segmentSize < 0) return; // avoid bad values
        // stop unnessesarily excessive array sizes
        if (segmentSize > afr.getWaveSize() * channels * resolution)
            segmentSize = afr.getWaveSize() * channels * resolution;
        //data = new float[segmentSize];
        // Fill array from a sample startPos point
        if (startPos != lastStartPos) {
            data = afr.getSamples(segmentSize, startPos);
            updateChannelData();
            lastStartPos = startPos;
        }
    }

    private void updateChannelData() {
        float[][] tracks = new float[channels][segmentSize / channels];
        int counter = 0;
        for (int i = 0; i < segmentSize; i += channels) {
            for (int j = 0; j < channels; j++) {
                tracks[j][counter] = data[i + j];
            }
            counter++;
        }
        for (int i = 0; i < channels; i++) {
            canvases[i].setData(tracks[i]);
            canvases[i].setResolution(this.resolution);
        }
    }

    private void setupPanel() {
        Panel panel = new Panel();
        panel.setLayout(new GridLayout(channels, 1));
        panel.setSize(new Dimension(width, channelHeight * channels));
        for (int i = 0; i < channels; i++) {
            panel.add(canvases[i]);
        }
        sp.add(panel);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == size1) setResolution(1);
        if (e.getSource() == size2) setResolution(2);
        if (e.getSource() == size4) setResolution(4);
        if (e.getSource() == size8) setResolution(8);
        if (e.getSource() == size16) setResolution(16);
        if (e.getSource() == size32) setResolution(32);
        if (e.getSource() == size64) setResolution(64);
        if (e.getSource() == size128) setResolution(128);
        if (e.getSource() == size256) setResolution(256);
        if (e.getSource() == size512) setResolution(512);
        if (e.getSource() == size1024) setResolution(1024);
        if (e.getSource() == size2048) setResolution(2048);
        if (e.getSource() == openFile) openFile();
        if (e.getSource() == quit) System.exit(0);
        if (e.getSource() == vSmall) setHeight(25);
        if (e.getSource() == small) setHeight(50);
        if (e.getSource() == medium) setHeight(100);
        if (e.getSource() == large) setHeight(200);
        if (e.getSource() == huge) setHeight(300);
        if (e.getSource() == times1) setAmplitude(1);
        if (e.getSource() == times2) setAmplitude(2);
        if (e.getSource() == times3) setAmplitude(3);
        if (e.getSource() == times4) setAmplitude(4);
        if (e.getSource() == changeColor) changeColor();
    }

    // Switch to a different display color combination
    private void changeColor() {
        for (int i = 0; i < channels; i++) {
            canvases[i].toggleColor();
        }
        whiteColor = !whiteColor;
    }

    /**
     * Pass back the current display resolution.
     *
     * @return int The resolution value
     */
    public int getResolution() {
        return this.resolution;
    }

    /**
     * Change the horizontal zoom size of the displayed waveform.
     *
     * @param size The new resolution value.
     */
    public void setResolution(int size) {
        if (size > 0 && size <= 2048) { // 8000
            this.resolution = size;
            if (afr.getWaveSize() / resolution < width) startPos = 0;
            reRead();
            scrollPanel.setResolution(size);
            scrollPanel.setScrollbarResolution(size);
            for (int i = 0; i < channels; i++) {
                canvases[i].setResolution(size);
            }
            //f.repaint();
        }
    }

    /**
     * Pass on the sample rate of the currently displayed file.
     */
    public int getSampleRate() {
        return afr.getSampleRate();
    }

    /**
     * Pass back the number of channels in the file currently being displayed.
     */
    public int getChannels() {
        return afr.getChannels();
    }

    /**
     * Pass on the file name of the currently displayed file.
     */
    public String getFileName() {
        return lastDirectory + lastFileName;
    }

    /**
     * Pass the current width of this frame.
     */
    public int getWidth() {
        return this.width;
    }

    public void repaint() {
        sp.setSize(f.getSize().width, f.getSize().height);
        for (int i = 0; i < channels; i++) {
            canvases[i].setSize(f.getSize().width, canvases[i].getSize().height);
            canvases[i].repaint();
        }
    }

    // component listener methods

    public void componentResized(ComponentEvent e) {
        if (f.getSize().width > width) {
            width = f.getSize().width;
            reRead();
        } else width = f.getSize().width;
        for (int i = 0; i < channels; i++) {
            canvases[i].setSize(width, canvases[i].getSize().height);
            canvases[i].setResized(true);
        }
    }

    public void componentHidden(ComponentEvent e) {
    }

    public void componentMoved(ComponentEvent e) {
    }

    public void componentShown(ComponentEvent e) {
    }

    /**
     * Change the virtical zoom size of the displayed waveform.
     *
     * @param val The new height value.
     */
    public void setHeight(int val) {
        this.channelHeight = val;
        setupChannels();
        setupPanel();
        sp.setSize(new Dimension(width, (channelHeight + 1) * channels));
        if (!whiteColor) {
            changeColor();
            // maintain color setting
            whiteColor = !whiteColor;
        }
        f.pack();
        repaint();
        sp.repaint();
    }


    /**
     * Change the waveform amplitude magnification of the displayed waveform.
     *
     * @param size The new resolution value.
     */
    public void setAmplitude(int size) {
        this.amplitude = size;
        for (int i = 0; i < channels; i++) {
            canvases[i].setAmplitude(size);
        }
    }

    public void playFile() {
        if (channels > 2) {
            System.out.println("jMusic Wave View notification:" +
                    " Sorry, only mono and stereo files can be played at present.");
        } else {
            System.out.println("---- Playing audio file '" + getFileName() + "'... Sample rate = "
                    + afr.getSampleRate() + " Channels = " + afr.getChannels() + " ----");
            jm.music.rt.RTLine[] lineArray = {new jm.util.AudioRTLine(getFileName())};
            mixer = new RTMixer(lineArray);
            mixer.begin();
        }
    }

    /**
     * Pause playback of an audio file jMusic audio playback via javaSound.
     * This method requires the javax.sound packages in Java 1.3 or higher.
     */
    public void pauseFile() {
        if (mixer != null) ;
        mixer.pause();
    }

    /**
     * Continue playback an audio file jMusic audio playback via javaSound.
     * This method requires the javax.sound packages in Java 1.3 or higher.
     *
     * @param String The name of the file to be played.
     */
    public void unPauseFile() {
        if (mixer != null) mixer.unPause();
    }

}
TOP

Related Classes of jm.gui.wave.WaveView

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.