Home | History | Annotate | Download | only in audio
      1 /*
      2  * Copyright (c) 2009-2010 jMonkeyEngine
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  * * Redistributions of source code must retain the above copyright
     10  *   notice, this list of conditions and the following disclaimer.
     11  *
     12  * * Redistributions in binary form must reproduce the above copyright
     13  *   notice, this list of conditions and the following disclaimer in the
     14  *   documentation and/or other materials provided with the distribution.
     15  *
     16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
     17  *   may be used to endorse or promote products derived from this software
     18  *   without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 package com.jme3.audio;
     34 
     35 import com.jme3.util.NativeObject;
     36 import java.io.Closeable;
     37 import java.io.IOException;
     38 import java.io.InputStream;
     39 import java.util.logging.Level;
     40 import java.util.logging.Logger;
     41 
     42 /**
     43  * <code>AudioStream</code> is an implementation of AudioData that
     44  * acquires the audio from an InputStream. Audio can be streamed
     45  * from network, hard drive etc. It is assumed the data coming
     46  * from the input stream is uncompressed.
     47  *
     48  * @author Kirill Vainer
     49  */
     50 public class AudioStream extends AudioData implements Closeable{
     51 
     52     private final static Logger logger = Logger.getLogger(AudioStream.class.getName());
     53     protected InputStream in;
     54     protected float duration = -1f;
     55     protected boolean open = false;
     56     protected int[] ids;
     57 
     58     public AudioStream(){
     59         super();
     60     }
     61 
     62     protected AudioStream(int[] ids){
     63         // Pass some dummy ID so handle
     64         // doesn't get created.
     65         super(-1);
     66         // This is what gets destroyed in reality
     67         this.ids = ids;
     68     }
     69 
     70     public void updateData(InputStream in, float duration){
     71         if (id != -1 || this.in != null)
     72             throw new IllegalStateException("Data already set!");
     73 
     74         this.in = in;
     75         this.duration = duration;
     76         open = true;
     77     }
     78 
     79     /**
     80      * Reads samples from the stream. The format of the data
     81      * depends on the getSampleRate(), getChannels(), getBitsPerSample()
     82      * values.
     83      *
     84      * @param buf Buffer where to read the samples
     85      * @param offset The offset in the buffer where to read samples
     86      * @param length The length inside the buffer where to read samples
     87      * @return number of bytes read.
     88      */
     89     public int readSamples(byte[] buf, int offset, int length){
     90         if (!open)
     91             return -1;
     92 
     93         try{
     94             return in.read(buf, offset, length);
     95         }catch (IOException ex){
     96             return -1;
     97         }
     98     }
     99 
    100     /**
    101      * Reads samples from the stream.
    102      *
    103      * @see AudioStream#readSamples(byte[], int, int)
    104      * @param buf Buffer where to read the samples
    105      * @return number of bytes read.
    106      */
    107     public int readSamples(byte[] buf){
    108         return readSamples(buf, 0, buf.length);
    109     }
    110 
    111     public float getDuration(){
    112         return duration;
    113     }
    114 
    115     @Override
    116     public int getId(){
    117         throw new RuntimeException("Don't use getId() on streams");
    118     }
    119 
    120     @Override
    121     public void setId(int id){
    122         throw new RuntimeException("Don't use setId() on streams");
    123     }
    124 
    125     public void initIds(int count){
    126         ids = new int[count];
    127     }
    128 
    129     public int getId(int index){
    130         return ids[index];
    131     }
    132 
    133     public void setId(int index, int id){
    134         ids[index] = id;
    135     }
    136 
    137     public int[] getIds(){
    138         return ids;
    139     }
    140 
    141     public void setIds(int[] ids){
    142         this.ids = ids;
    143     }
    144 
    145     @Override
    146     public DataType getDataType() {
    147         return DataType.Stream;
    148     }
    149 
    150     @Override
    151     public void resetObject() {
    152         id = -1;
    153         ids = null;
    154         setUpdateNeeded();
    155     }
    156 
    157     @Override
    158     public void deleteObject(Object rendererObject) {
    159         // It seems that the audio renderer is already doing a good
    160         // job at deleting audio streams when they finish playing.
    161 //        ((AudioRenderer)rendererObject).deleteAudioData(this);
    162     }
    163 
    164     @Override
    165     public NativeObject createDestructableClone() {
    166         return new AudioStream(ids);
    167     }
    168 
    169     /**
    170      * @return Whether the stream is open or not. Reading from a closed
    171      * stream will always return eof.
    172      */
    173     public boolean isOpen(){
    174         return open;
    175     }
    176 
    177     /**
    178      * Closes the stream, releasing all data relating to it. Reading
    179      * from the stream will return eof.
    180      * @throws IOException
    181      */
    182     public void close() {
    183         if (in != null && open){
    184             try{
    185                 in.close();
    186             }catch (IOException ex){
    187             }
    188             open = false;
    189         }else{
    190             throw new RuntimeException("AudioStream is already closed!");
    191         }
    192     }
    193 
    194 
    195     public void setTime(float time){
    196         if(in instanceof SeekableStream){
    197             ((SeekableStream)in).setTime(time);
    198         }else{
    199             logger.log(Level.WARNING,"Cannot use setTime on a stream that is not seekable. You must load the file with the streamCache option set to true");
    200         }
    201     }
    202 
    203 
    204 }
    205