/*
* Created on Mar 20, 2007
*
* Copyright (c) 2006-2007 P.J.Leonard
*
* http://www.frinika.com
*
* This file is part of Frinika.
*
* Frinika 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.
* Frinika 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 Frinika; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.frinika.audio.analysis.gui;
import com.frinika.global.FrinikaConfig;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.Timer;
import com.frinika.util.tweaks.gui.TweakerPanel;
import com.frinika.util.tweaks.Tweakable;
import com.frinika.util.tweaks.TweakableDouble;
import com.frinika.audio.analysis.CycliclyBufferedAudio;
import com.frinika.audio.analysis.Mapper;
import com.frinika.audio.analysis.dft.CyclicBufferFFTSpectrogramDataBuilder;
import uk.org.toot.audio.core.AudioProcess;
/**
*
* TOp level panel for the audioanalysis GUI
*
* @author pjl
*
*/
public class CyclicBufferFFTAnalysisPanel extends JPanel {
Vector<Tweakable> tweaks = new Vector<Tweakable>();
TweakableDouble mindB = new TweakableDouble(tweaks, -400.0, 100.0, -40.0,
5.0, "minDb");
TweakableDouble maxdB = new TweakableDouble(tweaks, -400.0, 100.0, -50.0,
5.0, "maxDb");
JToggleButton linearBut;
/**
*
*/
private static final long serialVersionUID = 1L;
// AudioAnalysisTimePanel timePanel;
// SingleImagePanel spectroSlicePanel;
AudioProcess reader;
private ValMapper valMapper;
// private Mapper freqMapper;
CyclicSpectrogramImage image;
CyclicBufferFFTSpectrogramDataBuilder spectroData;
// SpectrumController spectroController;
JPanel spectroPanel;
// ' private KeyboardFocusManager kbd;
FFTOption fftOpts[] = { new FFTOption(512, 256), new FFTOption(512, 128),
new FFTOption(1024, 512), new FFTOption(1024, 256),
new FFTOption(1024, 128), new FFTOption(2048, 1024),
new FFTOption(2048, 512), new FFTOption(2048, 256) };
private float maxFreq;
public CyclicBufferFFTAnalysisPanel(final CycliclyBufferedAudio bp) {
setLayout(new BorderLayout());
valMapper = new ValMapper();
maxdB.addObserver(valMapper);
mindB.addObserver(valMapper);
spectroData = new CyclicBufferFFTSpectrogramDataBuilder(bp.out, 1000,FrinikaConfig.sampleRate);
// spectroController=new
// FFTSpectrumController((FFTSpectrogramControlable) spectroData);
spectroData.setParameters(fftOpts[0].chunkSize, fftOpts[0].fftSize,bp.getSampleRate());
final JComboBox combo = new JComboBox(fftOpts);
combo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
final FFTOption opt = (FFTOption) combo.getSelectedItem();
System.err.println(" xxxxxxxxxxxxxx ");
new Thread(new Runnable() {
public void run() {
spectroData.setParameters(opt.chunkSize, opt.fftSize,bp.getSampleRate());
revalidate();
}
}).start();
}
});
image = new CyclicSpectrogramImage(valMapper,800);
// JLabel p=new JLabel(" HELKP ME WORK ");
JScrollPane sp=new JScrollPane(image);
spectroData.addSizeObserver(image);
add(sp, BorderLayout.CENTER);
JPanel buts = new JPanel();
buts.setLayout(new BoxLayout(buts, BoxLayout.Y_AXIS));
// Log linear switch
linearBut = new JToggleButton("linear");
linearBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (!linearBut.isSelected()) {
linearBut.setText("Linear");
} else {
linearBut.setText("Log10");
}
valMapper.update(null, null);
}
});
buts.add(linearBut);
// Switch to static synth
final JToggleButton synthBut = new JToggleButton("Synth Mode");
synthBut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
// timePanel.setSynthMode(synthBut.isSelected());
}
});
buts.add(synthBut);
TweakerPanel tpanel = new TweakerPanel(2, 4);
for (Tweakable t : tweaks) {
tpanel.addSpinTweaker(t);
}
JPanel control = new JPanel();
control.add(buts);
control.add(tpanel);
control.add(combo); // spectroController.getTweakPanel());
add(control, BorderLayout.SOUTH);
valMapper.update(null, null);
// spectroController.update();
revalidate();
repaint();
final JLabel label=new JLabel(" ");;
control.add(label);
new Timer(200, new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
label.setText(String.valueOf(bp.getLag()));
}
}).start();
}
// public void dispose() {
// timePanel.dispose();
// }
final class ValMapper implements Observer, Mapper {
double maxdb;
double mindb;
double max;
double min;
boolean linear;
private Thread thread;
public final float eval(float val) {
if (linear) {
float vv = (float) ((val - min) / (max - min));
return vv;
} else {
double dB = 20 * Math.log10(val + 1e-15);
float vv = (float) ((dB - mindb) / (maxdb - mindb));
return vv;
}
}
public void update(Observable o, Object arg) {
linear = linearBut.isSelected();
maxdb = maxdB.doubleValue();
max = Math.pow(10, maxdb / 20.0);
mindb = mindB.doubleValue();
min = Math.pow(10, mindb / 20.0);
repaint();
// if (thread != null)
// thread.interrupt();
// thread = new Thread(new Runnable() {
// public void run() {
// spectroSlicePanel.repaint();
// timePanel.spectroImage.update(null, null);
// thread = null;
// }
// });
// thread.start();
}
}
}
class FFTOption {
int fftSize;
int chunkSize;
public FFTOption(int i, int j) {
fftSize = i;
chunkSize = j;
}
public String toString() {
return fftSize + "/" + chunkSize;
}
}