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;
034
035/**
036 *      This class encapsulates the information that determines the format
037 *      of audio data.
038 *
039 *      @author David Dupplaw (dpd@ecs.soton.ac.uk)
040 *  @created 8 Jun 2011
041 *      
042 */
043public class AudioFormat
044{
045        /** The number of channels for each sample */
046        private int nChannels = 0;
047        
048        /** The number of bits in each sample */
049        private int nBits = 0;
050        
051        /** The sample rate in KHz */
052        private double sampleRateKHz = 0;
053        
054        /** Whether the data is signed */
055        private boolean isSigned = true;
056        
057        /** Whether the data is big-endian */
058        private boolean isBigEndian = false;
059        
060        /**
061         *      Construct a new audio format object with the
062         *      given number of bits and sample rate.
063         * 
064         *      @param nBits The number of bits in each sample
065         *      @param sampleRate The sample rate in kilohertz
066         *      @param nChannels The number of channels
067         */
068        public AudioFormat( int nBits, double sampleRate, int nChannels )
069        {
070                this.nBits = nBits;
071                this.sampleRateKHz = sampleRate;
072                this.setNumChannels( nChannels );
073        }
074
075        /**
076         *      Get the number of bits in each sample. 
077         *      @return The number of bits in each sample.
078         */
079        public int getNBits()
080        {
081                return nBits;
082        }
083        
084        /**
085         *      Sets the number of bits in this audio format. This is expected to
086         *      be a multiple of 8, but can be -1 for a non-integer format.
087         * 
088         *      @param nBits The number of bits.
089         *      @return this audio format
090         */
091        public AudioFormat setNBits( int nBits )
092        {
093                this.nBits = nBits;
094                return this;
095        }
096
097        /**
098         *      Get the rate at which the audio should be replayed
099         *      @return The audio sample rate in kilohertz.
100         */
101        public double getSampleRateKHz()
102        {
103                return sampleRateKHz;
104        }
105        
106        /**
107         *      Set the sample rate at which the audio should be replayed
108         *      @param s The sample rate
109         *      @return this audio format
110         */
111        public AudioFormat setSampleRateKHz( double s )
112        {
113                this.sampleRateKHz = s;
114                return this;
115        }
116
117        /**
118         *      Set the number of channels in this format.
119         *      @param nChannels the number of channels
120         *      @return this audio format
121         */
122        public AudioFormat setNumChannels( int nChannels )
123        {
124                this.nChannels = nChannels;
125                return this;
126        }
127
128        /**
129         *      Get the number of channels in this format.
130         *      @return the number of channels
131         */
132        public int getNumChannels()
133        {
134                return nChannels;
135        }
136
137        /**
138         *      Set whether the data is signed or not.
139         *      @param isSigned Whether the data is signed.
140         *      @return this audio format
141         */
142        public AudioFormat setSigned( boolean isSigned )
143        {
144                this.isSigned = isSigned;
145                return this;
146        }
147
148        /**
149         *      Returns whether the data is signed or unsigned.
150         *      @return TRUE if the data is signed; FALSE otherwise;
151         */
152        public boolean isSigned()
153        {
154                return isSigned;
155        }
156
157        /**
158         *      Set whether the data is big-endian or not.
159         *      @param isBigEndian Whether the data is big-endian
160         *      @return this audio format
161         */
162        public AudioFormat setBigEndian( boolean isBigEndian )
163        {
164                this.isBigEndian = isBigEndian;
165                return this;
166        }
167
168        /**
169         *      Returns whether the data is big or little endian.
170         *      @return TRUE if the data is big-endian; FALSE if little-endian
171         */
172        public boolean isBigEndian()
173        {
174                return isBigEndian;
175        }
176        
177        /**
178         *      {@inheritDoc}
179         */
180        @Override
181        public String toString()
182        {
183                return "[Audio: "+getSampleRateKHz()+"KHz, "+getNBits()+"bit, "+
184                        getNumChannels()+" channel"+(getNumChannels()>1?"s":"")+
185                        ", "+(isSigned?"signed":"unsigned")+", "+
186                        (isBigEndian?"big-endian":"little-endian")+"]";
187        }
188
189        /**
190         *  {@inheritDoc}
191         *  @see java.lang.Object#equals(java.lang.Object)
192         */
193        @Override
194        public boolean equals( Object obj )
195        {
196                if( obj instanceof AudioFormat )
197                {
198                        AudioFormat af = (AudioFormat)obj;
199                        if( isBigEndian == af.isBigEndian &&
200                                isSigned == af.isSigned &&
201                                nChannels == af.nChannels &&
202                                nBits == af.nBits &&
203                                sampleRateKHz == af.sampleRateKHz )
204                                return true;
205                }
206                
207                return false;
208        }
209        
210        /**
211         *      {@inheritDoc}
212         */
213        @Override
214        public AudioFormat clone()
215        {
216                AudioFormat af = new AudioFormat( 
217                                getNBits(), getSampleRateKHz(), getNumChannels() );
218                af.setBigEndian( isBigEndian );
219                af.setSigned( isSigned );
220                return af;
221        }
222        
223        /**
224         *      Get a Java Sound API AudioFormat object using this object's
225         *      properties.
226         * 
227         *      @return The Java Sound API Audio Format object.
228         */
229        public javax.sound.sampled.AudioFormat getJavaAudioFormat()
230        {
231                // Convert the OpenIMAJ audio format to a Java Sound audio format object
232                return new javax.sound.sampled.AudioFormat(
233                        (int)this.getSampleRateKHz() * 1000, 
234                        this.getNBits(), this.getNumChannels(), 
235                        this.isSigned(), this.isBigEndian() );
236        }
237}