Frames | No Frames |
1: /* An audio format 2: Copyright (C) 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.sound.sampled; 40: 41: import gnu.java.lang.CPStringBuilder; 42: 43: import java.util.Collections; 44: import java.util.HashMap; 45: import java.util.Map; 46: 47: /** 48: * This class describes an audio format, including its encoding, 49: * the number of channels, its frame rate, etc. 50: * @since 1.3 51: */ 52: public class AudioFormat 53: { 54: /** 55: * This describes a given audio format encoding. 56: * @since 1.3 57: */ 58: public static class Encoding 59: { 60: /** The ALAW encoding. */ 61: public static final Encoding ALAW = new Encoding("alaw"); 62: 63: /** The signed PCM encoding. */ 64: public static final Encoding PCM_SIGNED = new Encoding("pcm_signed"); 65: 66: /** The unsigned PCM encoding. */ 67: public static final Encoding PCM_UNSIGNED = new Encoding("pcm_unsigned"); 68: 69: /** The ULAW encoding. */ 70: public static final Encoding ULAW = new Encoding("ulaw"); 71: 72: private String name; 73: 74: /** 75: * Create a new encoding descriptor, given its name. 76: * @param name the name 77: */ 78: public Encoding(String name) 79: { 80: this.name = name; 81: } 82: 83: public final boolean equals(Object o) 84: { 85: return super.equals(o); 86: } 87: 88: public final int hashCode() 89: { 90: return super.hashCode(); 91: } 92: 93: /** 94: * Return the name of this encoding. 95: */ 96: public final String toString() 97: { 98: return name; 99: } 100: } 101: 102: /** 103: * True if the audio data is stored big-endian. 104: */ 105: protected boolean bigEndian; 106: 107: /** 108: * The number of channels of data in this format. 109: */ 110: protected int channels; 111: 112: /** 113: * The encoding of this format. 114: */ 115: protected Encoding encoding; 116: 117: /** 118: * The frame rate of this format. This is the number of frames 119: * per second. 120: */ 121: protected float frameRate; 122: 123: /** 124: * The number of bytes per frame in this format. 125: */ 126: protected int frameSize; 127: 128: /** 129: * The number of samples per second. 130: */ 131: protected float sampleRate; 132: 133: /** 134: * The number of bits in each sample. 135: */ 136: protected int sampleSizeInBits; 137: 138: private Map<String, Object> properties; 139: 140: /** 141: * Create a new audio format, given various attributes of it. 142: * The properties map for this format will be empty. 143: * 144: * @param encoding the encoding for this format 145: * @param sampleRate the sample rate 146: * @param sampleSizeInBits the sample size, in bits 147: * @param channels the number of channels 148: * @param frameSize the frame size, in bytes 149: * @param frameRate the frame rate, in frames per second 150: * @param bigEndian true if the data is stored big-endian 151: */ 152: public AudioFormat(Encoding encoding, float sampleRate, int sampleSizeInBits, 153: int channels, int frameSize, float frameRate, 154: boolean bigEndian) 155: { 156: this.encoding = encoding; 157: this.sampleRate = sampleRate; 158: this.sampleSizeInBits = sampleSizeInBits; 159: this.channels = channels; 160: this.frameSize = frameSize; 161: this.frameRate = frameRate; 162: this.bigEndian = bigEndian; 163: this.properties = Collections.<String, Object> emptyMap(); 164: } 165: 166: /** 167: * Create a new audio format, given various attributes of it. 168: * The properties map is copied by this constructor, so changes 169: * to the argument Map will not affect the new object. 170: * 171: * @param encoding the encoding for this format 172: * @param sampleRate the sample rate 173: * @param sampleSizeInBits the sample size, in bits 174: * @param channels the number of channels 175: * @param frameSize the frame size, in bytes 176: * @param frameRate the frame rate, in frames per second 177: * @param bigEndian true if the data is stored big-endian 178: * @param properties a map describing properties of this format 179: */ 180: public AudioFormat(Encoding encoding, float sampleRate, int sampleSizeInBits, 181: int channels, int frameSize, float frameRate, 182: boolean bigEndian, Map<String, Object> properties) 183: { 184: this.encoding = encoding; 185: this.sampleRate = sampleRate; 186: this.sampleSizeInBits = sampleSizeInBits; 187: this.channels = channels; 188: this.frameSize = frameSize; 189: this.frameRate = frameRate; 190: this.bigEndian = bigEndian; 191: this.properties = Collections.unmodifiableMap(new HashMap<String, Object>(properties)); 192: } 193: 194: /** 195: * Create a new PCM-based audio format, given various attributes of it. 196: * The encoding will either be Encoding#PCM_SIGNED or Encoding#PCM_UNSIGNED. 197: * The frame size for this format will be derived from the sample size in 198: * bits and the number of channels, unless one of those is 199: * AudioSystem#NOT_SPECIFIED. The frame rate will be the same as the sample 200: * rate, and the properties map will be empty. 201: * 202: * @param sampleRate the sample rate 203: * @param sampleSizeInBits the sample size, in bits 204: * @param channels the number of channels 205: * @param signed true if this is a signed encoding 206: * @param bigEndian true if the data is stored big-endian 207: */ 208: public AudioFormat(float sampleRate, int sampleSizeInBits, 209: int channels, boolean signed, boolean bigEndian) 210: { 211: this.encoding = signed ? Encoding.PCM_SIGNED : Encoding.PCM_UNSIGNED; 212: this.sampleRate = sampleRate; 213: this.sampleSizeInBits = sampleSizeInBits; 214: this.channels = channels; 215: // It isn't clear whether channels can be NOT_SPECIFIED. 216: if (sampleSizeInBits == AudioSystem.NOT_SPECIFIED 217: || channels == AudioSystem.NOT_SPECIFIED) 218: this.frameSize = AudioSystem.NOT_SPECIFIED; 219: else 220: this.frameSize = (sampleSizeInBits + 7) / 8 * channels; 221: this.frameRate = sampleRate; 222: this.bigEndian = bigEndian; 223: this.properties = Collections.<String, Object> emptyMap(); 224: } 225: 226: /** 227: * Return the number of channels in this format. 228: */ 229: public int getChannels() 230: { 231: return channels; 232: } 233: 234: /** 235: * Return the encoding of this format. 236: */ 237: public Encoding getEncoding() 238: { 239: return encoding; 240: } 241: 242: /** 243: * Return the frame rate of this format. 244: */ 245: public float getFrameRate() 246: { 247: return frameRate; 248: } 249: 250: /** 251: * Return the frame size of this format. 252: */ 253: public int getFrameSize() 254: { 255: return frameSize; 256: } 257: 258: /** 259: * Given a key, return a property associated with this format; 260: * or null if this property is not set. 261: * @param key the name of the property 262: * @return the value of the property, or null if the property is not set 263: */ 264: public Object getProperty(String key) 265: { 266: return properties.get(key); 267: } 268: 269: /** 270: * Return the sample rate of this format. 271: */ 272: public float getSampleRate() 273: { 274: return sampleRate; 275: } 276: 277: /** 278: * Return the sample size of this format, in bits. 279: */ 280: public int getSampleSizeInBits() 281: { 282: return sampleSizeInBits; 283: } 284: 285: /** 286: * Return true if this format is big endian, false otherwise. 287: * This only matters for formats whose sample size is greater than 288: * one byte. 289: */ 290: public boolean isBigEndian() 291: { 292: return bigEndian; 293: } 294: 295: /** 296: * Return true if this audio format matches another. 297: * @param fmt the format to match against 298: * @return true if they match, false otherwise 299: */ 300: public boolean matches(AudioFormat fmt) 301: { 302: if (! encoding.equals(fmt.encoding) 303: || channels != fmt.channels 304: || sampleSizeInBits != fmt.sampleSizeInBits 305: || frameSize != fmt.frameSize) 306: return false; 307: if (sampleRate != AudioSystem.NOT_SPECIFIED 308: && fmt.sampleRate != AudioSystem.NOT_SPECIFIED 309: && sampleRate != fmt.sampleRate) 310: return false; 311: if (frameRate != AudioSystem.NOT_SPECIFIED 312: && fmt.frameRate != AudioSystem.NOT_SPECIFIED 313: && frameRate != fmt.frameRate) 314: return false; 315: if (sampleSizeInBits > 8) 316: return bigEndian == fmt.bigEndian; 317: return true; 318: } 319: 320: /** 321: * Return a read-only Map holding the properties associated with 322: * this format. 323: */ 324: public Map<String, Object> properties() 325: { 326: return properties; 327: } 328: 329: /** 330: * Return a description of this format. 331: */ 332: public String toString() 333: { 334: CPStringBuilder result = new CPStringBuilder(); 335: 336: // usually at least encoding should be somewhat specified 337: result.append(encoding); 338: 339: if (sampleRate != AudioSystem.NOT_SPECIFIED) 340: { 341: result.append(" "); 342: result.append(sampleRate); 343: result.append(" Hz"); 344: } 345: 346: if (sampleSizeInBits != AudioSystem.NOT_SPECIFIED) 347: { 348: result.append(" "); 349: result.append(sampleSizeInBits); 350: result.append(" bits"); 351: } 352: 353: if (channels != AudioSystem.NOT_SPECIFIED) 354: { 355: result.append(" "); 356: result.append(channels); 357: result.append(" channel"); 358: if (channels > 1) result.append("s"); 359: } 360: 361: if (sampleSizeInBits > 8) 362: result.append(bigEndian ? " big endian" : " little endian"); 363: 364: return result.toString(); 365: } 366: }