/*
* Copyright (c) 2007 P.J.Leonard
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.frinika.audio.analysis.gui;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.MemoryImageSource;
import javax.swing.JPanel;
import com.frinika.audio.analysis.Mapper;
/**
*
* notifies observers if it need to be redrawn (typically the panel(s))
*
* update() redoes all the drawing.
*
* SpectrogramListener - does image resize - incrementally redraws as the data
* become ready.
*
* @author pjl
*
*/
public class CyclicSpectrogramImage extends JPanel implements
CyclicSpectrogramDataListener {
private static final long serialVersionUID = 1L;
Dimension size;
private int[] screenBuffer;
private boolean dirty = true;
private double thresh;
private MemoryImageSource screenConverter;
private boolean screenRepaint = false;
int nChunks;
int nBins;
int ptr = 0;
Image offscreen;
Mapper mapper;
public CyclicSpectrogramImage(Mapper mapper, int nChunks) {
this.nChunks = nChunks;
this.mapper = mapper;
// setDoubleBuffered(true);
}
final Object imagSync = new Object();
void createGraphics() {
synchronized (imagSync) {
size = new Dimension(nChunks, nBins);
int width = nChunks;
int height = nBins;
screenBuffer = new int[width * height];
screenConverter = new MemoryImageSource(width, height,
screenBuffer, 0, width);
screenConverter.setAnimated(true);
screenConverter.setFullBufferUpdates(false);
offscreen = Toolkit.getDefaultToolkit()
.createImage(screenConverter);
setPreferredSize(size);
}
}
boolean recursion = false;
public void notifyMoreDataReady(float[] bins) {
if (recursion)
System.err.println(" RECURSION ");
nBins = bins.length;
if (nBins == 0)
return;
recursion = true;
if (size == null || nBins != size.height || nChunks != size.width)
createGraphics();
int width = size.width;
for (int i = 0; i < nBins; i++) {
int bin = nBins - i - 1;
float val = mapper.eval(bins[bin]);
if (val < 0)
val = 0.0f;
if (val > 1.0)
val = 1.0f;
int c_r = (int) (255 * val);
int c_g = c_r;
int c_b = 255 - c_r;
int color = (c_b) + (c_g << 8) + (c_r << 16) + (0xFF << 24);
screenBuffer[i * width + ptr] = (255 << 24) + color;
// rgbarray[i] = color;
}
if (ptr % 1 == 0) {
screenConverter.newPixels(ptr, 0, 1, nBins);
screenRepaint = true;
repaint();
}
ptr = (ptr + 1) % size.width;
recursion = false;
}
// public void paintX(Graphics g) {
// if (screenRepaint) {
// g.drawImage(offscreen, 0, 0, this);
// screenRepaint = false;
// }
// }
@Override
public void paint(Graphics g) {
// super.paintComponent(g);
if (!screenRepaint)
return;
// System.out.println(" Spectro DRAWIMAGE");
int w = size.width - ptr;
int h = size.height;
g.drawImage(offscreen, 0, 0, w, h, ptr, 0, size.width, h, this);
if (ptr != 0) {
g.drawImage(offscreen, w, 0, size.width, h, 0, 0, ptr, h, this);
}
screenRepaint = false;
}
public int getHeightXX() {
if (size == null)
return 200;
return size.height;
}
}