001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030/** 031 * 032 */ 033package org.openimaj.audio.util; 034 035import java.util.ArrayList; 036import java.util.List; 037 038import javax.sound.sampled.AudioSystem; 039import javax.sound.sampled.DataLine; 040import javax.sound.sampled.LineUnavailableException; 041import javax.sound.sampled.Mixer; 042import javax.sound.sampled.SourceDataLine; 043 044import org.openimaj.audio.AudioDevice; 045import org.openimaj.audio.AudioFormat; 046 047/** 048 * Various static methods for dealing with audio information and data. 049 * 050 * @author David Dupplaw (dpd@ecs.soton.ac.uk) 051 * 052 * @created 26 Nov 2011 053 */ 054public class AudioUtils 055{ 056 /** When looking for devices, these are the sample rates we'll try */ 057 static final double[] freqsToTry = new double[] 058 {11.025, 22.05, 44.1, 48, 96.1, 192}; 059 060 /** When looking for devices, these are the bits per sample we'll try */ 061 static final int[] bitsToTry = new int[] {8,16,24,32}; 062 063 /** When looking for devices, these are the number of channels we'll try */ 064 static final int[] chansToTry = new int[] {1,2,4,5,7,8}; 065 066 /** 067 * Returns a list of devices that are available on this system. 068 * @return The list of devices available on this system. 069 */ 070 static public List<AudioDevice> getDevices() 071 { 072 final List<AudioDevice> l = new ArrayList<AudioDevice>(); 073 final Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo(); 074 075 for(int i = 0; i < mixerInfo.length; i++) 076 { 077 l.add( new AudioDevice( mixerInfo[i].getName(), 078 mixerInfo[i].getDescription() ) ); 079 } 080 081 return l; 082 } 083 084 /** 085 * Returns a Java sound line for the given device name. Use 086 * {@link AudioDevice#deviceName} as input to this method. Use 087 * {@link AudioUtils#getDevices()} to get an {@link AudioDevice} object. 088 * 089 * @param deviceName The device name. 090 * @param af The format 091 * @return A Java sound line. 092 * @throws LineUnavailableException 093 */ 094 static public SourceDataLine getJavaOutputLine( final String deviceName, 095 final AudioFormat af ) 096 throws LineUnavailableException 097 { 098 final Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo(); 099 for( final Mixer.Info info: mixerInfo ) 100 { 101 if( info.getName().equals( deviceName ) ) 102 { 103 final Mixer m = AudioSystem.getMixer(info); 104 if( m.getSourceLineInfo().length > 0 ) 105 return (SourceDataLine)AudioSystem.getLine( 106 m.getSourceLineInfo()[0] ); 107 } 108 } 109 110 return null; 111 } 112 113 /** 114 * Gets a Java output line (SourceDataLine) that can play something with 115 * the given audio format. 116 * 117 * @param af The audio format. 118 * @return A SourceDataLine 119 * @throws LineUnavailableException 120 */ 121 static public SourceDataLine getAnyJavaOutputLine( final AudioFormat af ) 122 throws LineUnavailableException 123 { 124 // Convert the OpenIMAJ audio format to a Java Sound audio format object 125 final javax.sound.sampled.AudioFormat audioFormat = af.getJavaAudioFormat(); 126 127 // Create info to create an output data line 128 final DataLine.Info info = new DataLine.Info( 129 SourceDataLine.class, audioFormat ); 130 131 // Get the output line to write to using the given 132 // sample format we just created. 133 return (SourceDataLine) AudioSystem.getLine( info ); 134 } 135 136 /** 137 * Converts a frequency to an approximation of a Mel frequency. 138 * This formula gives a close approximation for frequencies less than 139 * 1000Hz. 140 * 141 * @param freq The frequency to convert 142 * @return The Mel frequency 143 */ 144 static public double frequencyToMelFrequency( final double freq ) 145 { 146 return (1127d * Math.log( 1 + freq/700d ) ); 147// return (2595d * Math.log10(1 + freq/700d) ); 148 } 149 150 /** 151 * Converts a Mel frequency back into an approximation of a frequency. 152 * 153 * @param melFreq The Mel frequency to convert 154 * @return The frequency 155 */ 156 static public double melFrequencyToFrequency( final double melFreq ) 157 { 158 return (700d * Math.exp( melFreq/1127d ) -700d ); 159// return (700d * (Math.pow(10, melFreq/2595d) - 1) ); 160 } 161 162 /** 163 * Converts a frequency to a Bark frequency 164 * 165 * @param freq The frequency to convert 166 * @return The Bark frequency 167 */ 168 static public double frequencyToBarkFrequency( final double freq ) 169 { 170 return 6*Math.log( (freq/600d) + Math.sqrt(Math.pow(freq/600d,2) + 1 ) ); 171 } 172 173 /** 174 * 175 * @param args 176 */ 177 public static void main( final String[] args ) 178 { 179 try 180 { 181 System.out.println( AudioUtils.getDevices() ); 182 System.out.println( AudioUtils.getJavaOutputLine( "Line 1/2 (M-Audio Delta 44)", 183 new AudioFormat( 16, 44.1, 2 ) ) ); 184 } 185 catch( final LineUnavailableException e ) 186 { 187 e.printStackTrace(); 188 } 189 } 190}