Compare commits
No commits in common. "master" and "v0.1" have entirely different histories.
@ -5,8 +5,8 @@ FreqSample is a tool made in Java that will play a frequency.
|
|||||||
|
|
||||||
### Compiling
|
### Compiling
|
||||||
Make sure you have the JDK installed along with Apache Ant. Then go to the root directory of this project and run:
|
Make sure you have the JDK installed along with Apache Ant. Then go to the root directory of this project and run:
|
||||||
```bash
|
```
|
||||||
$ ant
|
$ ant jar
|
||||||
```
|
```
|
||||||
|
|
||||||
### Contributing
|
### Contributing
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<target name="compile" >
|
<target name="compile" >
|
||||||
<mkdir dir="${classes.dir}" />
|
<mkdir dir="${classes.dir}" />
|
||||||
<javac includeantruntime="false" srcdir="${src.dir}" destdir="${classes.dir}" />
|
<javac srcdir="${src.dir}" destdir="${classes.dir}" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="jar" depends="compile" >
|
<target name="jar" depends="compile" >
|
||||||
@ -22,10 +22,4 @@
|
|||||||
</manifest>
|
</manifest>
|
||||||
</jar>
|
</jar>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="main" depends="jar" />
|
|
||||||
|
|
||||||
<target name="run" depends="jar" >
|
|
||||||
<java jar="${jar.dir}/${ant.project.name}.jar" fork="true" />
|
|
||||||
</target>
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,141 +1,101 @@
|
|||||||
package freqsample;
|
package freqsample;
|
||||||
|
|
||||||
import java.awt.event.*;
|
import java.nio.ByteBuffer;
|
||||||
import javax.swing.*;
|
|
||||||
import javax.sound.sampled.*;
|
import javax.sound.sampled.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nicolás A. Ortega
|
* @author Nicolás A. Ortega
|
||||||
* @copyright Nicolás A. Ortega
|
* @copyright Nicolás A. Ortega
|
||||||
* @license GNU GPLv3
|
* @license GPLv3
|
||||||
* @year 2014
|
* @year 2014
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class FreqSample {
|
public class FreqSample {
|
||||||
private static final String version = "v1.1.1";
|
private static final String version = "v0.1";
|
||||||
private JFrame frame;
|
|
||||||
private JPanel panel;
|
|
||||||
private JTextField hzField, msField;
|
|
||||||
private JLabel hzLabel, msLabel;
|
|
||||||
private JButton playButton;
|
|
||||||
|
|
||||||
private JMenuBar menuBar;
|
public FreqSample(double hz, double msecs) throws InterruptedException, LineUnavailableException {
|
||||||
private JMenu fsMenu, helpMenu;
|
final int SAMPLE_RATE = 44100;
|
||||||
private JMenuItem quitItem, copyrightItem, aboutItem;
|
final int SAMPLE_SIZE = 2;
|
||||||
|
|
||||||
public FreqSample() {
|
SourceDataLine line;
|
||||||
frame = new JFrame("FreqSample");
|
double fFreq = hz;
|
||||||
frame.setSize(400, 200);
|
|
||||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
||||||
|
|
||||||
panel = new JPanel();
|
double fCyclePosition = 0;
|
||||||
frame.add(panel);
|
|
||||||
|
|
||||||
setupMenu();
|
AudioFormat af = new AudioFormat(SAMPLE_RATE, 16, 1, true, true);
|
||||||
setupUI();
|
DataLine.Info info = new DataLine.Info(SourceDataLine.class, af);
|
||||||
|
|
||||||
frame.setVisible(true);
|
if(!AudioSystem.isLineSupported(info)) {
|
||||||
|
System.out.println("Line matching " + info + " is not supported.");
|
||||||
|
throw new LineUnavailableException();
|
||||||
|
}
|
||||||
|
|
||||||
|
line = (SourceDataLine)AudioSystem.getLine(info);
|
||||||
|
line.open(af);
|
||||||
|
line.start();
|
||||||
|
|
||||||
|
ByteBuffer cBuf = ByteBuffer.allocate(line.getBufferSize());
|
||||||
|
|
||||||
|
int ctSamplesTotal = SAMPLE_RATE * (int)(msecs / 1000);
|
||||||
|
|
||||||
|
while(ctSamplesTotal > 0) {
|
||||||
|
double fCycleInc = fFreq/SAMPLE_RATE;
|
||||||
|
|
||||||
|
cBuf.clear();
|
||||||
|
|
||||||
|
int ctSamplesThisPass = line.available() / SAMPLE_SIZE;
|
||||||
|
for(int i = 0; i < ctSamplesThisPass; i++) {
|
||||||
|
cBuf.putShort((short)(Short.MAX_VALUE * Math.sin(2 * Math.PI * fCyclePosition)));
|
||||||
|
fCyclePosition += fCycleInc;
|
||||||
|
if(fCyclePosition > 1) fCyclePosition -= 1;
|
||||||
|
}
|
||||||
|
line.write(cBuf.array(), 0, cBuf.position());
|
||||||
|
ctSamplesTotal -= ctSamplesThisPass;
|
||||||
|
|
||||||
|
while(line.getBufferSize() / 2 < line.available()) {
|
||||||
|
Thread.sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
line.drain();
|
||||||
|
line.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupMenu() {
|
public static void main(String[] args) throws InterruptedException, LineUnavailableException {
|
||||||
menuBar = new JMenuBar();
|
if(args.length <= 2 && args.length != 0) {
|
||||||
fsMenu = new JMenu("FreqSample");
|
if(args.length == 1) {
|
||||||
helpMenu = new JMenu("Help");
|
if(args[0].equals("-h")) printHelp();
|
||||||
|
else if(args[0].equals("-c")) printCopyright();
|
||||||
quitItem = new JMenuItem("Quit");
|
else if(args[0].equals("-v")) System.out.println(version);
|
||||||
quitItem.addActionListener(new ActionListener() {
|
else printHelp();
|
||||||
@Override
|
} else {
|
||||||
public void actionPerformed(ActionEvent ae) {
|
double hz = Double.parseDouble(args[0]);
|
||||||
System.exit(0);
|
double ms = Double.parseDouble(args[1]);
|
||||||
|
new FreqSample(hz, ms);
|
||||||
}
|
}
|
||||||
});
|
} else {
|
||||||
quitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_MASK));
|
printHelp();
|
||||||
fsMenu.add(quitItem);
|
|
||||||
|
|
||||||
copyrightItem = new JMenuItem("Copyright Info");
|
|
||||||
copyrightItem.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent ae) {
|
|
||||||
new Window("Copyright Information",
|
|
||||||
"FreqSample " + version + ", play frequencies.\n" +
|
|
||||||
"Copyright (C) 2014 Nicolás A. Ortega\n\n" +
|
|
||||||
"This program is free software: you can redistribute it and/or modify\n" +
|
|
||||||
"it under the terms of the GNU General Public License as published by\n" +
|
|
||||||
"the Free Software Foundation, either version 3 of the License, or\n" +
|
|
||||||
"(at your option) any later version.\n" +
|
|
||||||
"This program is distributed in the hope that it will be useful,\n" +
|
|
||||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
|
|
||||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +
|
|
||||||
"GNU General Public License for more details.\n\n" +
|
|
||||||
"You should have received a copy of the GNU General Public License\n" +
|
|
||||||
"along with this program. If not, see <http://www.gnu.org/licenses/>.\n\n");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
helpMenu.add(copyrightItem);
|
|
||||||
|
|
||||||
aboutItem = new JMenuItem("About");
|
|
||||||
aboutItem.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent ae) {
|
|
||||||
new Window("About",
|
|
||||||
"FreqSample " + version + "\n" +
|
|
||||||
"Copyright (C) 2014 Nicolás A. Ortega\n" +
|
|
||||||
"License: GNU GPLv3\n" +
|
|
||||||
"Contact: nicolas.ortega.froysa@gmail.com\n" +
|
|
||||||
"Source-Code: https://github.com/Deathsbreed/FreqSample\n" +
|
|
||||||
"Developers: Nicolás Ortega\n\n");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
helpMenu.add(aboutItem);
|
|
||||||
|
|
||||||
menuBar.add(fsMenu);
|
|
||||||
menuBar.add(helpMenu);
|
|
||||||
frame.setJMenuBar(menuBar);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupUI() {
|
|
||||||
panel.setLayout(null);
|
|
||||||
|
|
||||||
hzLabel = new JLabel("Frequency (Hz):");
|
|
||||||
hzLabel.setBounds(10, 10, 150, 25);
|
|
||||||
panel.add(hzLabel);
|
|
||||||
hzField = new JTextField();
|
|
||||||
hzField.setBounds(170, 10, 220, 25);
|
|
||||||
panel.add(hzField);
|
|
||||||
|
|
||||||
msLabel = new JLabel("Duration (ms):");
|
|
||||||
msLabel.setBounds(10, 40, 150, 25);
|
|
||||||
panel.add(msLabel);
|
|
||||||
msField = new JTextField();
|
|
||||||
msField.setBounds(170, 40, 220, 25);
|
|
||||||
panel.add(msField);
|
|
||||||
|
|
||||||
playButton = new JButton("Play");
|
|
||||||
playButton.setBounds(160, 80, 80, 25);
|
|
||||||
playButton.addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent ae) {
|
|
||||||
double hz = Double.parseDouble(hzField.getText());
|
|
||||||
double ms = Double.parseDouble(msField.getText());
|
|
||||||
try {
|
|
||||||
Generator.generateTone(hz, ms);
|
|
||||||
} catch(InterruptedException ie) {
|
|
||||||
ie.printStackTrace();
|
|
||||||
System.exit(1);
|
|
||||||
} catch(LineUnavailableException lue) {
|
|
||||||
lue.printStackTrace();
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
panel.add(playButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Window {
|
|
||||||
public Window(String title, String msg) {
|
|
||||||
JOptionPane.showMessageDialog(null, msg, title, JOptionPane.INFORMATION_MESSAGE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) { new FreqSample(); }
|
private static void printHelp() {
|
||||||
|
System.out.println("Usage: java -jar FreqSample.jar [option][<hz> <ms>]");
|
||||||
|
System.out.println(" -h -- Print this help information");
|
||||||
|
System.out.println(" -c -- Print copyright information");
|
||||||
|
System.out.println(" -v -- Print version\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void printCopyright() {
|
||||||
|
System.out.println("FreqSample, a simple frequency sampler.\n" +
|
||||||
|
"Copyright (C) 2014 Nicolás A. Ortega\n" +
|
||||||
|
"This program is free software: you can redistribute it and/or modify\n" +
|
||||||
|
"it under the terms of the GNU General Public License as published by\n" +
|
||||||
|
"the Free Software Foundation, either version 3 of the License, or\n" +
|
||||||
|
"(at your option) any later version.\n\n" +
|
||||||
|
"This program is distributed in the hope that it will be useful,\n" +
|
||||||
|
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
|
||||||
|
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +
|
||||||
|
"GNU General Public License for more details.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
package freqsample;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import javax.sound.sampled.*;
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Nicolás A. Ortega
|
|
||||||
* @copyright Nicolás A. Ortega
|
|
||||||
* @license GNU GPLv3
|
|
||||||
* @year 2014
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Generator {
|
|
||||||
public static void generateTone(double hz, double msecs) throws InterruptedException, LineUnavailableException {
|
|
||||||
final int SAMPLE_RATE = 44100;
|
|
||||||
final int SAMPLE_SIZE = 2;
|
|
||||||
|
|
||||||
SourceDataLine line;
|
|
||||||
double fFreq = hz;
|
|
||||||
|
|
||||||
double fCyclePosition = 0;
|
|
||||||
|
|
||||||
// Open Audio Device
|
|
||||||
AudioFormat af = new AudioFormat(SAMPLE_RATE, 16, 1, true, true);
|
|
||||||
DataLine.Info info = new DataLine.Info(SourceDataLine.class, af);
|
|
||||||
|
|
||||||
if(!AudioSystem.isLineSupported(info)) {
|
|
||||||
System.out.println("Line matching " + info + " is not supported.");
|
|
||||||
throw new LineUnavailableException();
|
|
||||||
}
|
|
||||||
|
|
||||||
line = (SourceDataLine)AudioSystem.getLine(info);
|
|
||||||
line.open(af);
|
|
||||||
line.start();
|
|
||||||
|
|
||||||
// The audio bytebuffer
|
|
||||||
ByteBuffer cBuf = ByteBuffer.allocate(line.getBufferSize());
|
|
||||||
|
|
||||||
// Set the total samples to loop through
|
|
||||||
if(msecs < 150) msecs = 150;
|
|
||||||
int ctSamplesTotal = (int)(SAMPLE_RATE * (msecs / 1000));
|
|
||||||
|
|
||||||
while(ctSamplesTotal > 0) {
|
|
||||||
// Define the frequency at the given sample rate
|
|
||||||
double fCycleInc = fFreq/SAMPLE_RATE;
|
|
||||||
|
|
||||||
// Clear the buffer
|
|
||||||
cBuf.clear();
|
|
||||||
|
|
||||||
// Play the frequency
|
|
||||||
int ctSamplesThisPass = line.available() / SAMPLE_SIZE;
|
|
||||||
for(int i = 0; i < ctSamplesThisPass; i++) {
|
|
||||||
cBuf.putShort((short)(Short.MAX_VALUE * Math.sin(2 * Math.PI * fCyclePosition)));
|
|
||||||
fCyclePosition += fCycleInc;
|
|
||||||
if(fCyclePosition > 1) fCyclePosition -= 1;
|
|
||||||
}
|
|
||||||
line.write(cBuf.array(), 0, cBuf.position());
|
|
||||||
ctSamplesTotal -= ctSamplesThisPass;
|
|
||||||
|
|
||||||
while(line.getBufferSize() / 2 < line.available()) {
|
|
||||||
Thread.sleep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the audioline
|
|
||||||
line.drain();
|
|
||||||
line.close();
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user