Compare commits
	
		
			12 Commits
		
	
	
		
			v0.1
			...
			1e745b6d1c
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 1e745b6d1c | ||
|   | e0720d56d0 | ||
|   | eb392746ed | ||
|   | dc9840b6e5 | ||
|   | 69e9fa695c | ||
|   | 7b23946e44 | ||
|   | c0f48964ca | ||
|   | 2ae030df92 | ||
|   | dff0b993d3 | ||
|   | c56a664a2a | ||
|   | 544c15be1d | ||
|   | 31e441e886 | 
| @@ -5,8 +5,8 @@ FreqSample is a tool made in Java that will play a frequency. | ||||
|  | ||||
| ### Compiling | ||||
| Make sure you have the JDK installed along with Apache Ant. Then go to the root directory of this project and run: | ||||
| ``` | ||||
| $ ant jar | ||||
| ```bash | ||||
| $ ant | ||||
| ``` | ||||
|  | ||||
| ### Contributing | ||||
|   | ||||
| @@ -11,7 +11,7 @@ | ||||
| 	 | ||||
| 	<target name="compile" > | ||||
| 		<mkdir dir="${classes.dir}" /> | ||||
| 		<javac srcdir="${src.dir}" destdir="${classes.dir}" /> | ||||
| 		<javac includeantruntime="false" srcdir="${src.dir}" destdir="${classes.dir}" /> | ||||
| 	</target> | ||||
| 	 | ||||
| 	<target name="jar" depends="compile" > | ||||
| @@ -22,4 +22,10 @@ | ||||
| 			</manifest> | ||||
| 		</jar> | ||||
| 	</target> | ||||
|  | ||||
| 	<target name="main" depends="jar" /> | ||||
|  | ||||
| 	<target name="run" depends="jar" > | ||||
| 		<java jar="${jar.dir}/${ant.project.name}.jar" fork="true" /> | ||||
| 	</target> | ||||
| </project> | ||||
|   | ||||
| @@ -1,101 +1,141 @@ | ||||
| package freqsample; | ||||
|  | ||||
| import java.nio.ByteBuffer; | ||||
| import javax.sound.sampled.*; | ||||
| import java.awt.event.*; | ||||
| import javax.swing.*; | ||||
| import javax.sound.sampled.*; | ||||
|  | ||||
| /** | ||||
|  * @author Nicolás A. Ortega | ||||
|  * @copyright Nicolás A. Ortega | ||||
|  * @license GPLv3 | ||||
|  * @license GNU GPLv3 | ||||
|  * @year 2014 | ||||
|  *  | ||||
|  */ | ||||
| public class FreqSample { | ||||
| 	private static final String version = "v0.1"; | ||||
| 	private static final String version = "v1.1.1"; | ||||
| 	private JFrame frame; | ||||
| 	private JPanel panel; | ||||
| 	private JTextField hzField, msField; | ||||
| 	private JLabel hzLabel, msLabel; | ||||
| 	private JButton playButton; | ||||
|  | ||||
| 	public FreqSample(double hz, double msecs) throws InterruptedException, LineUnavailableException { | ||||
| 		final int SAMPLE_RATE = 44100; | ||||
| 		final int SAMPLE_SIZE = 2; | ||||
| 	private JMenuBar menuBar; | ||||
| 	private JMenu fsMenu, helpMenu; | ||||
| 	private JMenuItem quitItem, copyrightItem, aboutItem; | ||||
|  | ||||
| 		SourceDataLine line; | ||||
| 		double fFreq = hz; | ||||
| 	public FreqSample() { | ||||
| 		frame = new JFrame("FreqSample"); | ||||
| 		frame.setSize(400, 200); | ||||
| 		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | ||||
|  | ||||
| 		double fCyclePosition = 0; | ||||
| 		panel = new JPanel(); | ||||
| 		frame.add(panel); | ||||
|  | ||||
| 		AudioFormat af = new AudioFormat(SAMPLE_RATE, 16, 1, true, true); | ||||
| 		DataLine.Info info = new DataLine.Info(SourceDataLine.class, af); | ||||
| 		setupMenu(); | ||||
| 		setupUI(); | ||||
|  | ||||
| 		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(); | ||||
| 		frame.setVisible(true); | ||||
| 	} | ||||
|  | ||||
| 	public static void main(String[] args) throws InterruptedException, LineUnavailableException { | ||||
| 		if(args.length <= 2 && args.length != 0) { | ||||
| 			if(args.length == 1) { | ||||
| 				if(args[0].equals("-h")) printHelp(); | ||||
| 				else if(args[0].equals("-c")) printCopyright(); | ||||
| 				else if(args[0].equals("-v")) System.out.println(version); | ||||
| 				else printHelp(); | ||||
| 			} else { | ||||
| 				double hz = Double.parseDouble(args[0]); | ||||
| 				double ms = Double.parseDouble(args[1]); | ||||
| 				new FreqSample(hz, ms); | ||||
| 	private void setupMenu() { | ||||
| 		menuBar = new JMenuBar(); | ||||
| 		fsMenu = new JMenu("FreqSample"); | ||||
| 		helpMenu = new JMenu("Help"); | ||||
|  | ||||
| 		quitItem = new JMenuItem("Quit"); | ||||
| 		quitItem.addActionListener(new ActionListener() { | ||||
| 			@Override | ||||
| 			public void actionPerformed(ActionEvent ae) { | ||||
| 				System.exit(0); | ||||
| 			} | ||||
| 		} else { | ||||
| 			printHelp(); | ||||
| 		}); | ||||
| 		quitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_MASK)); | ||||
| 		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); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	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."); | ||||
| 	} | ||||
| 	public static void main(String[] args) { new FreqSample(); } | ||||
| } | ||||
|   | ||||
							
								
								
									
										70
									
								
								src/freqsample/Generator.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/freqsample/Generator.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| 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(); | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user