package com.Eiyeron.SFXRPP; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Random; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JSlider; import javax.swing.JSpinner; import javax.swing.SpinnerListModel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.filechooser.FileFilter; import net.miginfocom.swing.MigLayout; import com.Eiyeron.SFXRPP.SFXREngine.FX; import com.Eiyeron.SFXRPP.SFXREngine.SFXRPreset; import com.Eiyeron.SFXRPP.SFXREngine.SFXRSynth; import com.Eiyeron.SFXRPP.SFXREngine.WaveForm; /** * @author Eiyeron SFXR++ SoundBox * @version 1.00 | Finished */ public class SFXRpp extends JFrame implements ActionListener, ChangeListener { private static final long serialVersionUID = 4648172894076113183L; public static SFXRpp main; Random rand; SFXRPreset sound; SFXRSynth synth; JSlider sliders[]; JLabel label[]; JLabel value[]; JSlider volume; JLabel volumeVal; JButton play; JButton random; JButton mutate; JButton open; JButton save; JButton about; JButton[] options; JSpinner waveForm; JPanel slidersContainer; JPanel presetsContainer; SoundVisualizer soundVis; final int sliderPrecision = 10000; private String fieldsName[] = { "WaveForm", "Start Frequency", "Slide", "Delta Slide", "Square Duty", "Duty Sweep", "Vibrato Strength", "Vibrato Speed", "Attack", "Sustain", "Decay", "Punch", "LP Filter Resonance", "LP Filter Cutoff", " LP Filter Sweep", "HP Filter Cutoff", " HP Filter Sweep", "Phaser Offset", "Phaser Sweep", "Repeat Speed", "Change Amount", "Change Speed" }; public void initTopButtons() { play = new JButton("Play"); play.addActionListener(this); random = new JButton("Random"); random.addActionListener(this); mutate = new JButton("Mutate"); mutate.addActionListener(this); open = new JButton("Open"); open.addActionListener(this); save = new JButton("Save"); save.addActionListener(this); about = new JButton("About"); about.addActionListener(this); getContentPane().add(play, "center, growx, gap unrelated"); getContentPane().add(random, "split 2, center"); getContentPane().add(mutate, "gap unrelated"); getContentPane().add(open, "split 2, center"); getContentPane().add(save, "gap unrelated"); getContentPane().add(about, "wrap"); } public void initLeftDock() { presetsContainer = new JPanel(new MigLayout()); options = new JButton[FX.values().length]; for (int i = 0; i < options.length; i++) { options[i] = new JButton(FX.values()[i].toString()); options[i].addActionListener(this); presetsContainer.add(options[i], "center, wrap, growx"); } getContentPane().add(presetsContainer, "west, growy"); } public void initSliders() { for (int i = 0; i < label.length; i++) { if (i + 1 < fieldsName.length) label[i] = new JLabel(fieldsName[i + 1]); else label[i] = new JLabel("l" + i); if (i == 1 || i == 2 || i == 4 || i == 13 || i == 15 || i == 16 || i == 17) { sliders[i] = new JSlider(-sliderPrecision / 2, sliderPrecision / 2, 0); sliders[i].setMajorTickSpacing(sliderPrecision / 2); } else { sliders[i] = new JSlider(0, sliderPrecision, 0); sliders[i].setMajorTickSpacing(sliderPrecision); } sliders[i].setPaintTicks(true); sliders[i].setMajorTickSpacing(sliderPrecision / 2); sliders[i].addChangeListener(this); slidersContainer.add(label[i]); slidersContainer.add(sliders[i], "growx"); value[i] = new JLabel(String.valueOf(sliders[i].getValue() / (float) sliderPrecision)); slidersContainer.add(value[i], "span, wrap, growx"); if (i == 4 || i == 6 || i == 10 || i == 15 | i == 17 || i == 18) { JSeparator sep = new JSeparator(); sep.setPreferredSize(new Dimension(120, 2)); slidersContainer.add(sep, "span"); } } } public void initWin() { getContentPane().setLayout(new MigLayout("center, fill")); initTopButtons(); initLeftDock(); getContentPane().add(new JLabel("Wave Form"), "center"); waveForm = new JSpinner(new SpinnerListModel(WaveForm.values())); getContentPane().add(waveForm, "span, growx, wrap"); volume = new JSlider(0, sliderPrecision); volume.addChangeListener(this); volumeVal = new JLabel(); getContentPane().add(new JLabel("Master Volume")); getContentPane().add(volume, "growx"); getContentPane().add(volumeVal, "wrap"); slidersContainer = new JPanel(new MigLayout("center, fill")); initSliders(); for (int i = 0; i < sliders.length; i++) { sliders[i].addChangeListener(this); } JScrollPane slidersC = new JScrollPane(slidersContainer, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); getContentPane().add(slidersC, "growx, span, wrap, center"); soundVis = new SoundVisualizer(); getContentPane().add(soundVis, "dock south, growx, span"); } public void updateOptions() { waveForm.setValue(sound.wave_type); sliders[0].setValue((int) (sound.p_base_freq * sliderPrecision)); sliders[1].setValue((int) (sound.p_freq_ramp * sliderPrecision / 2)); sliders[2].setValue((int) (sound.p_freq_dramp * sliderPrecision / 2)); sliders[3].setValue((int) (sound.p_duty * sliderPrecision)); sliders[4].setValue((int) (sound.p_duty_ramp * sliderPrecision / 2)); sliders[5].setValue((int) (sound.p_duty * sliderPrecision)); sliders[6].setValue((int) (sound.p_duty * sliderPrecision)); sliders[7].setValue((int) (sound.p_env_attack * sliderPrecision)); sliders[8].setValue((int) (sound.p_env_sustain * sliderPrecision)); sliders[9].setValue((int) (sound.p_env_decay * sliderPrecision)); sliders[10].setValue((int) (sound.p_env_punch * sliderPrecision)); sliders[11].setValue((int) (sound.p_lpf_resonance * sliderPrecision)); sliders[12].setValue((int) (sound.p_lpf_freq * sliderPrecision)); sliders[13].setValue((int) (sound.p_lpf_ramp * sliderPrecision / 2)); sliders[14].setValue((int) (sound.p_hpf_freq * sliderPrecision)); sliders[15].setValue((int) (sound.p_hpf_ramp * sliderPrecision / 2)); sliders[16].setValue((int) (sound.p_pha_offset * sliderPrecision / 2)); sliders[17].setValue((int) (sound.p_pha_ramp * sliderPrecision / 2)); sliders[18].setValue((int) (sound.p_repeat_speed * sliderPrecision)); sliders[19].setValue((int) (sound.p_arp_mod * sliderPrecision)); sliders[20].setValue((int) (sound.p_arp_speed * sliderPrecision)); volume.setValue((int) (sound.master_vol * sliderPrecision)); } public void updateLabels() { for (int i = 0; i < value.length; i++) { value[i].setText(String.valueOf(sliders[i].getValue() / (float) sliderPrecision)); } volumeVal.setText(String.valueOf(volume.getValue() / (float) sliderPrecision)); } public void updateVis() { SFXRSynth syn = new SFXRSynth(sound); soundVis.updateHistogram(syn.synthSound()); soundVis.repaint(); } public SFXRpp() { this.setTitle("SFXR++ Soundbox"); this.setResizable(true); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); rand = new Random(); sound = new SFXRPreset(FX.BEEP); sound.randomize(); sliders = new JSlider[fieldsName.length - 1]; label = new JLabel[fieldsName.length - 1]; value = new JLabel[fieldsName.length - 1]; initWin(); updateOptions(); updateLabels(); this.pack(); this.setSize(getContentPane().getPreferredSize().width + 20, getContentPane().getPreferredSize().height); this.setVisible(true); } @Override public void actionPerformed(ActionEvent evt) { String composant = evt.getActionCommand(); FX preset = null; try { preset = FX.valueOf(composant); } catch (Exception e) { } if (composant == "Play") { updateVis(); doSound(); } else if (composant == "Random") { sound.randomize(); updateOptions(); updateVis(); doSound(); } else if (composant == "Mutate") { sound.mutate(); updateOptions(); updateVis(); doSound(); } else if (composant == "Save") { System.out.println("Saving"); JFileChooser fc = new JFileChooser(); fc.addChoosableFileFilter(new SFPFileChooser()); int returnVal = fc.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); String filePath = file.getPath(); if(!filePath.toLowerCase().endsWith(".sfp")) { file = new File(filePath + ".sfp"); } FileWriter fw; try { fw = new FileWriter(file); WaveForm wf = (WaveForm) (waveForm.getValue()); fw.write(wf.ordinal()); for (JSlider js : sliders) { fw.write(sliderPrecision - js.getValue()); System.out.println(js.getValue()); } fw.flush(); fw.close(); } catch (IOException e) { System.err.println("Saving Error"); e.printStackTrace(); } } } else if (composant =="About") { JOptionPane.showMessageDialog(this, "SFXR++ Soundbox\nby Eiyeron\nUses MiGLayout.\n2013 GPL License."); } else if (composant == "Open") { JFileChooser fc = new JFileChooser(); fc.addChoosableFileFilter(new SFPFileChooser()); int returnVal = fc.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); FileReader fr; try { fr = new FileReader(file); waveForm.setValue(WaveForm.values()[fr.read()]); for (JSlider js : sliders) { int value = -fr.read() + sliderPrecision; js.setValue(value); System.out.println(value); } fr.close(); } catch (IOException e) { System.err.println("Opening Error"); e.printStackTrace(); } } } else if (preset != null) { sound.random(preset); updateOptions(); updateVis(); } } public void doSound() { sound.resetParams(); sound.wave_type = (WaveForm) waveForm.getValue(); sound.p_base_freq = sliders[0].getValue() / (float) sliderPrecision; sound.p_freq_ramp = sliders[1].getValue() / (float) (sliderPrecision / 2); sound.p_freq_dramp = sliders[2].getValue() / (float) (sliderPrecision / 2); sound.p_duty = sliders[3].getValue() / (float) sliderPrecision; sound.p_duty_ramp = sliders[4].getValue() / (float) (sliderPrecision / 2); sound.p_vib_strength = sliders[5].getValue() / (float) sliderPrecision; sound.p_vib_speed = sliders[6].getValue() / (float) sliderPrecision; sound.p_env_attack = sliders[7].getValue() / (float) sliderPrecision; sound.p_env_sustain = sliders[8].getValue() / (float) sliderPrecision; sound.p_env_decay = sliders[9].getValue() / (float) sliderPrecision; sound.p_env_punch = sliders[10].getValue() / (float) sliderPrecision; sound.p_lpf_resonance = sliders[11].getValue() / (float) sliderPrecision; sound.p_lpf_freq = sliders[12].getValue() / (float) sliderPrecision; sound.p_lpf_ramp = sliders[13].getValue() / (float) (sliderPrecision / 2); sound.p_hpf_freq = sliders[14].getValue() / (float) sliderPrecision; sound.p_hpf_ramp = sliders[15].getValue() / (float) (sliderPrecision / 2); sound.p_pha_offset = sliders[16].getValue() / (float) (sliderPrecision / 2); sound.p_pha_ramp = sliders[17].getValue() / (float) (sliderPrecision / 2); sound.p_repeat_speed = sliders[18].getValue() / (float) sliderPrecision; sound.p_arp_mod = sliders[19].getValue() / (float) sliderPrecision; sound.p_arp_speed = sliders[20].getValue() / (float) sliderPrecision; sound.master_vol = volume.getValue() / (float) sliderPrecision; sound.play(); } public static void main(String args[]) { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); UIManager.put("Slider.paintValue", Boolean.FALSE); } catch (UnsupportedLookAndFeelException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } main = new SFXRpp(); } @Override public void stateChanged(ChangeEvent e) { updateLabels(); } } class SFPFileChooser extends FileFilter { @Override public String getDescription() { return null; } @Override public boolean accept(File f) { if (f.isDirectory()) { return true; } String ext = null; String s = f.getName(); int i = s.lastIndexOf('.'); if (i > 0 && i < s.length() - 1) { ext = s.substring(i + 1).toLowerCase(); } System.out.println(ext); return ext.equals("sfp"); } }