/********************************************************************************** * $URL$ * $Id$ *********************************************************************************** * * Copyright (c) 2005, 2006, 2007, 2008 The Sakai Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.osedu.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **********************************************************************************/ /* AudioFormatPanel.java * Originally based on code from CapturePlayback.java * @(#)CapturePlayback.java 1.11 99/12/03 * * portions Copyright (c) 1999 Sun Microsystems, Inc. All Rights Reserved. * * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, * modify and redistribute this software in source and binary code form, * provided that i) this copyright notice and license appear on all copies of * the software; and ii) Licensee does not utilize the software in a manner * which is disparaging to Sun. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * This software is not designed or intended for use in on-line control of * aircraft, air traffic, aircraft navigation or aircraft communications; or in * the design, construction, operation or maintenance of any nuclear * facility. Licensee represents and warrants that it will not use or * redistribute the Software for such purposes. */ package org.sakaiproject.tool.assessment.audio; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.util.Enumeration; import java.util.Locale; import java.util.ResourceBundle; import java.util.Vector; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import javax.sound.sampled.TargetDataLine; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridLayout; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.awt.geom.Line2D; import javax.swing.AbstractButton; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.JToggleButton; import javax.swing.border.BevelBorder; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.SoftBevelBorder; import javax.swing.filechooser.FileFilter; import javax.swing.border.Border; public class AudioFormatPanel extends JPanel { static ResourceBundle res = AudioUtil.getInstance().getResourceBundle(); protected AudioRecorderParams params; Vector groups = new Vector(); JToggleButton linrB, ulawB, alawB, rate8B, rate11B, rate16B, rate22B, rate44B; JToggleButton size8B, size16B, signB, unsignB, litB, bigB, monoB, sterB; public AudioFormatPanel(AudioRecorderParams params) { this.params = params; setLayout(new GridLayout(0, 1)); EmptyBorder eb = new EmptyBorder(0, 0, 0, 5); BevelBorder bb = new BevelBorder(BevelBorder.LOWERED); CompoundBorder cb = new CompoundBorder(eb, bb); setBorder(new CompoundBorder(cb, new EmptyBorder(8, 5, 5, 5))); JPanel p1 = new ColorBackgroundPanel(false); ButtonGroup encodingGroup = makeEncodingGroup(params, p1); add(p1); groups.addElement(encodingGroup); JPanel p2 = new ColorBackgroundPanel(false); JPanel p2b = new ColorBackgroundPanel(false); ButtonGroup sampleRateGroup = makeSampleRateGroup(params, p2, p2b); add(p2); add(p2b); groups.addElement(sampleRateGroup); JPanel p3 = new ColorBackgroundPanel(false); ButtonGroup sampleSizeInBitsGroup = makeSizeInBitsGroup(params, p3); add(p3); groups.addElement(sampleSizeInBitsGroup); JPanel p4 = new ColorBackgroundPanel(false); ButtonGroup signGroup = makeSignGroup(params, p4); add(p4); groups.addElement(signGroup); JPanel p5 = new ColorBackgroundPanel(false); ButtonGroup endianGroup = makeEndianGroup(params, p5); add(p5); groups.addElement(endianGroup); JPanel p6 = new ColorBackgroundPanel(false); ButtonGroup channelsGroup = makeChannelsGroup(params, p6); add(p6); groups.addElement(channelsGroup); } private ButtonGroup makeEncodingGroup(AudioRecorderParams params, JPanel p1) { ButtonGroup encodingGroup = new ButtonGroup(); boolean linear = false; boolean ulaw = false; boolean alaw = false; if ("linear".equals(params.getCompression())) { linear = true; } else if ("ulaw".equals(params.getCompression())) { ulaw = true; } else { alaw = true; } linrB = addToggleButton(p1, encodingGroup, res.getString("linear"), linear); ulawB = addToggleButton(p1, encodingGroup, res.getString("ulaw"), ulaw); alawB = addToggleButton(p1, encodingGroup, res.getString("alaw"), alaw); return encodingGroup; } private ButtonGroup makeSampleRateGroup(AudioRecorderParams params, JPanel p2, JPanel p2b) { ButtonGroup sampleRateGroup = new ButtonGroup(); boolean rates[] = { false, false, false, false, false,}; int rate = params.getFrequency(); for (int i = 0; i < params.frequenciesAllowed.length; i++) { if (rate==params.frequenciesAllowed[i]) { rates[i] = true; break; } } rate8B = addToggleButton(p2, sampleRateGroup, "8000", rates[0]); rate11B = addToggleButton(p2, sampleRateGroup, "11025", rates[1]); rate16B = addToggleButton(p2b, sampleRateGroup, "16000", rates[2]); rate22B = addToggleButton(p2b, sampleRateGroup, "22050", rates[3]); rate44B = addToggleButton(p2b, sampleRateGroup, "44100", rates[4]); return sampleRateGroup; } private ButtonGroup makeSizeInBitsGroup(AudioRecorderParams params, JPanel p3) { ButtonGroup sampleSizeInBitsGroup = new ButtonGroup(); boolean bit8 = params.getBits()==8 ? true : false; size8B = addToggleButton(p3, sampleSizeInBitsGroup, "8", bit8); size16B = addToggleButton(p3, sampleSizeInBitsGroup, "16", !bit8); return sampleSizeInBitsGroup; } private ButtonGroup makeSignGroup(AudioRecorderParams params, JPanel p4) { ButtonGroup signGroup = new ButtonGroup(); signB = addToggleButton(p4, signGroup, res.getString("signed"), params.isSigned()); unsignB = addToggleButton(p4, signGroup, res.getString("unsigned"), !params.isSigned()); return signGroup; } private ButtonGroup makeEndianGroup(AudioRecorderParams params, JPanel p5) { ButtonGroup endianGroup = new ButtonGroup(); litB = addToggleButton(p5, endianGroup, res.getString("little_endian"), !params.isBigendian()); bigB = addToggleButton(p5, endianGroup, res.getString("big_endian"), params.isBigendian()); return endianGroup; } private ButtonGroup makeChannelsGroup(AudioRecorderParams params, JPanel p6) { ButtonGroup channelsGroup = new ButtonGroup(); monoB = addToggleButton(p6, channelsGroup, res.getString("mono"), !params.isStereo()); sterB = addToggleButton(p6, channelsGroup, res.getString("stereo"), params.isStereo()); return channelsGroup; } private JToggleButton addToggleButton(JPanel p, ButtonGroup g, String name, boolean state) { JToggleButton b = new JToggleButton(name, state); p.add(b); g.add(b); return b; } public AudioFormat getFormat() { Vector v = new Vector(groups.size()); for (int i = 0; i < groups.size(); i++) { ButtonGroup g = (ButtonGroup) groups.get(i); for (Enumeration e = g.getElements(); e.hasMoreElements(); ) { AbstractButton b = (AbstractButton) e.nextElement(); if (b.isSelected()) { v.add(b.getText()); break; } } } AudioFormat.Encoding encoding = AudioFormat.Encoding.ULAW; String encString = (String) v.get(0); float rate = Float.valueOf( (String) v.get(1)).floatValue(); int sampleSize = Integer.valueOf( (String) v.get(2)).intValue(); String signedString = (String) v.get(3); boolean bigEndian = ( (String) v.get(4)).startsWith(res.getString("big")); int channels = ( (String) v.get(5)).equals(res.getString("mono")) ? 1 : 2; if (encString.equals(res.getString("linear"))) { if (signedString.equals(res.getString("signed"))) { encoding = AudioFormat.Encoding.PCM_SIGNED; } else { encoding = AudioFormat.Encoding.PCM_UNSIGNED; } } else if (encString.equals(res.getString("alaw"))) { encoding = AudioFormat.Encoding.ALAW; } return new AudioFormat(encoding, rate, sampleSize, channels, (sampleSize / 8) * channels, rate, bigEndian); } public void setFormat(AudioFormat format) { AudioFormat.Encoding type = format.getEncoding(); if (type == AudioFormat.Encoding.ULAW) { ulawB.doClick(); } else if (type == AudioFormat.Encoding.ALAW) { alawB.doClick(); } else if (type == AudioFormat.Encoding.PCM_SIGNED) { linrB.doClick(); signB.doClick(); } else if (type == AudioFormat.Encoding.PCM_UNSIGNED) { linrB.doClick(); unsignB.doClick(); } float rate = format.getFrameRate(); if (rate == 8000) { rate8B.doClick(); } else if (rate == 11025) { rate11B.doClick(); } else if (rate == 16000) { rate16B.doClick(); } else if (rate == 22050) { rate22B.doClick(); } else if (rate == 44100) { rate44B.doClick(); } switch (format.getSampleSizeInBits()) { case 8: size8B.doClick(); break; case 16: size16B.doClick(); break; } if (format.isBigEndian()) { bigB.doClick(); } else { litB.doClick(); } if (format.getChannels() == 1) { monoB.doClick(); } else { sterB.doClick(); } } }