1 /* 2 * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.sound.sampled; 27 28 import java.util.Collections; 29 import java.util.HashMap; 30 import java.util.Map; 31 32 /** 33 * An instance of the {@code AudioFileFormat} class describes an audio file, 34 * including the file type, the file's length in bytes, the length in sample 35 * frames of the audio data contained in the file, and the format of the audio 36 * data. 37 * <p> 38 * The {@link AudioSystem} class includes methods for determining the format of 39 * an audio file, obtaining an audio input stream from an audio file, and 40 * writing an audio file from an audio input stream. 41 * <p> 42 * An {@code AudioFileFormat} object can include a set of properties. A property 43 * is a pair of key and value: the key is of type {@code String}, the associated 44 * property value is an arbitrary object. Properties specify additional 45 * informational meta data (like a author, copyright, or file duration). 46 * Properties are optional information, and file reader and file writer 47 * implementations are not required to provide or recognize properties. 48 * <p> 49 * The following table lists some common properties that should be used in 50 * implementations: 51 * 52 * <table border=1> 53 * <caption>Audio File Format Properties</caption> 54 * <tr> 55 * <th>Property key</th> 56 * <th>Value type</th> 57 * <th>Description</th> 58 * </tr> 59 * <tr> 60 * <td>"duration"</td> 61 * <td>{@link java.lang.Long Long}</td> 62 * <td>playback duration of the file in microseconds</td> 63 * </tr> 64 * <tr> 65 * <td>"author"</td> 66 * <td>{@link java.lang.String String}</td> 67 * <td>name of the author of this file</td> 68 * </tr> 69 * <tr> 70 * <td>"title"</td> 71 * <td>{@link java.lang.String String}</td> 72 * <td>title of this file</td> 73 * </tr> 74 * <tr> 75 * <td>"copyright"</td> 76 * <td>{@link java.lang.String String}</td> 77 * <td>copyright message</td> 78 * </tr> 79 * <tr> 80 * <td>"date"</td> 81 * <td>{@link java.util.Date Date}</td> 82 * <td>date of the recording or release</td> 83 * </tr> 84 * <tr> 85 * <td>"comment"</td> 86 * <td>{@link java.lang.String String}</td> 87 * <td>an arbitrary text</td> 88 * </tr> 89 * </table> 90 * 91 * 92 * @author David Rivas 93 * @author Kara Kytle 94 * @author Florian Bomers 95 * @see AudioInputStream 96 * @since 1.3 97 */ 98 public class AudioFileFormat { 99 100 /** 101 * File type. 102 */ 103 private Type type; 104 105 /** 106 * File length in bytes. 107 */ 108 private int byteLength; 109 110 /** 111 * Format of the audio data contained in the file. 112 */ 113 private AudioFormat format; 114 115 /** 116 * Audio data length in sample frames. 117 */ 118 private int frameLength; 119 120 /** 121 * The set of properties. 122 */ 123 private HashMap<String, Object> properties; 124 125 /** 126 * Constructs an audio file format object. This protected constructor is 127 * intended for use by providers of file-reading services when returning 128 * information about an audio file or about supported audio file formats. 129 * 130 * @param type the type of the audio file 131 * @param byteLength the length of the file in bytes, or 132 * {@code AudioSystem.NOT_SPECIFIED} 133 * @param format the format of the audio data contained in the file 134 * @param frameLength the audio data length in sample frames, or 135 * {@code AudioSystem.NOT_SPECIFIED} 136 * @see #getType 137 */ 138 protected AudioFileFormat(Type type, int byteLength, AudioFormat format, int frameLength) { 139 140 this.type = type; 141 this.byteLength = byteLength; 142 this.format = format; 143 this.frameLength = frameLength; 144 this.properties = null; 145 } 146 147 /** 148 * Constructs an audio file format object. This public constructor may be 149 * used by applications to describe the properties of a requested audio 150 * file. 151 * 152 * @param type the type of the audio file 153 * @param format the format of the audio data contained in the file 154 * @param frameLength the audio data length in sample frames, or 155 * {@code AudioSystem.NOT_SPECIFIED} 156 */ 157 public AudioFileFormat(Type type, AudioFormat format, int frameLength) { 158 159 160 this(type,AudioSystem.NOT_SPECIFIED,format,frameLength); 161 } 162 163 /** 164 * Construct an audio file format object with a set of defined properties. 165 * This public constructor may be used by applications to describe the 166 * properties of a requested audio file. The properties map will be copied 167 * to prevent any changes to it. 168 * 169 * @param type the type of the audio file 170 * @param format the format of the audio data contained in the file 171 * @param frameLength the audio data length in sample frames, or 172 * {@code AudioSystem.NOT_SPECIFIED} 173 * @param properties a {@code Map<String, Object>} object with properties 174 * @since 1.5 175 */ 176 public AudioFileFormat(Type type, AudioFormat format, 177 int frameLength, Map<String, Object> properties) { 178 this(type,AudioSystem.NOT_SPECIFIED,format,frameLength); 179 this.properties = new HashMap<String, Object>(properties); 180 } 181 182 /** 183 * Obtains the audio file type, such as {@code WAVE} or {@code AU}. 184 * 185 * @return the audio file type 186 * @see Type#WAVE 187 * @see Type#AU 188 * @see Type#AIFF 189 * @see Type#AIFC 190 * @see Type#SND 191 */ 192 public Type getType() { 193 return type; 194 } 195 196 /** 197 * Obtains the size in bytes of the entire audio file (not just its audio 198 * data). 199 * 200 * @return the audio file length in bytes 201 * @see AudioSystem#NOT_SPECIFIED 202 */ 203 public int getByteLength() { 204 return byteLength; 205 } 206 207 /** 208 * Obtains the format of the audio data contained in the audio file. 209 * 210 * @return the audio data format 211 */ 212 public AudioFormat getFormat() { 213 return format; 214 } 215 216 /** 217 * Obtains the length of the audio data contained in the file, expressed in 218 * sample frames. 219 * 220 * @return the number of sample frames of audio data in the file 221 * @see AudioSystem#NOT_SPECIFIED 222 */ 223 public int getFrameLength() { 224 return frameLength; 225 } 226 227 /** 228 * Obtain an unmodifiable map of properties. The concept of properties is 229 * further explained in the {@link AudioFileFormat class description}. 230 * 231 * @return a {@code Map<String, Object>} object containing all properties. 232 * If no properties are recognized, an empty map is returned. 233 * @see #getProperty(String) 234 * @since 1.5 235 */ 236 @SuppressWarnings("unchecked") // Cast of result of clone 237 public Map<String, Object> properties() { 238 Map<String,Object> ret; 239 if (properties == null) { 240 ret = new HashMap<>(0); 241 } else { 242 ret = (Map<String,Object>) (properties.clone()); 243 } 244 return Collections.unmodifiableMap(ret); 245 } 246 247 /** 248 * Obtain the property value specified by the key. The concept of properties 249 * is further explained in the {@link AudioFileFormat class description}. 250 * <p> 251 * If the specified property is not defined for a particular file format, 252 * this method returns {@code null}. 253 * 254 * @param key the key of the desired property 255 * @return the value of the property with the specified key, or {@code null} 256 * if the property does not exist 257 * @see #properties() 258 * @since 1.5 259 */ 260 public Object getProperty(String key) { 261 if (properties == null) { 262 return null; 263 } 264 return properties.get(key); 265 } 266 267 /** 268 * Provides a string representation of the file format. 269 * 270 * @return the file format as a string 271 */ 272 @Override 273 public String toString() { 274 275 StringBuffer buf = new StringBuffer(); 276 277 //$$fb2002-11-01: fix for 4672864: AudioFileFormat.toString() throws unexpected NullPointerException 278 if (type != null) { 279 buf.append(type.toString() + " (." + type.getExtension() + ") file"); 280 } else { 281 buf.append("unknown file format"); 282 } 283 284 if (byteLength != AudioSystem.NOT_SPECIFIED) { 285 buf.append(", byte length: " + byteLength); 286 } 287 288 buf.append(", data format: " + format); 289 290 if (frameLength != AudioSystem.NOT_SPECIFIED) { 291 buf.append(", frame length: " + frameLength); 292 } 293 294 return new String(buf); 295 } 296 297 /** 298 * An instance of the {@code Type} class represents one of the standard 299 * types of audio file. Static instances are provided for the common types. 300 */ 301 public static class Type { 302 303 // FILE FORMAT TYPE DEFINES 304 305 /** 306 * Specifies a WAVE file. 307 */ 308 public static final Type WAVE = new Type("WAVE", "wav"); 309 310 /** 311 * Specifies an AU file. 312 */ 313 public static final Type AU = new Type("AU", "au"); 314 315 /** 316 * Specifies an AIFF file. 317 */ 318 public static final Type AIFF = new Type("AIFF", "aif"); 319 320 /** 321 * Specifies an AIFF-C file. 322 */ 323 public static final Type AIFC = new Type("AIFF-C", "aifc"); 324 325 /** 326 * Specifies a SND file. 327 */ 328 public static final Type SND = new Type("SND", "snd"); 329 330 /** 331 * File type name. 332 */ 333 private final String name; 334 335 /** 336 * File type extension. 337 */ 338 private final String extension; 339 340 /** 341 * Constructs a file type. 342 * 343 * @param name the string that names the file type 344 * @param extension the string that commonly marks the file type 345 * without leading dot 346 */ 347 public Type(String name, String extension) { 348 this.name = name; 349 this.extension = extension; 350 } 351 352 /** 353 * Finalizes the equals method. 354 */ 355 @Override 356 public final boolean equals(Object obj) { 357 if (toString() == null) { 358 return (obj != null) && (obj.toString() == null); 359 } 360 if (obj instanceof Type) { 361 return toString().equals(obj.toString()); 362 } 363 return false; 364 } 365 366 /** 367 * Finalizes the hashCode method. 368 */ 369 @Override 370 public final int hashCode() { 371 if (toString() == null) { 372 return 0; 373 } 374 return toString().hashCode(); 375 } 376 377 /** 378 * Provides the file type's name as the {@code String} representation of 379 * the file type. 380 * 381 * @return the file type's name 382 */ 383 @Override 384 public final String toString() { 385 return name; 386 } 387 388 /** 389 * Obtains the common file name extension for this file type. 390 * 391 * @return file type extension 392 */ 393 public String getExtension() { 394 return extension; 395 } 396 } 397 }