Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.media;
     18 
     19 import android.annotation.IntDef;
     20 
     21 import java.lang.annotation.Retention;
     22 import java.lang.annotation.RetentionPolicy;
     23 
     24 /**
     25  * The AudioFormat class is used to access a number of audio format and
     26  * channel configuration constants. They are for instance used
     27  * in {@link AudioTrack} and {@link AudioRecord}.
     28  *
     29  */
     30 public class AudioFormat {
     31 
     32     //---------------------------------------------------------
     33     // Constants
     34     //--------------------
     35     /** Invalid audio data format */
     36     public static final int ENCODING_INVALID = 0;
     37     /** Default audio data format */
     38     public static final int ENCODING_DEFAULT = 1;
     39 
     40     // These values must be kept in sync with core/jni/android_media_AudioFormat.h
     41     /** Audio data format: PCM 16 bit per sample. Guaranteed to be supported by devices. */
     42     public static final int ENCODING_PCM_16BIT = 2;
     43     /** Audio data format: PCM 8 bit per sample. Not guaranteed to be supported by devices. */
     44     public static final int ENCODING_PCM_8BIT = 3;
     45     /** Audio data format: single-precision floating-point per sample */
     46     public static final int ENCODING_PCM_FLOAT = 4;
     47     /** Audio data format: AC-3 compressed */
     48     public static final int ENCODING_AC3 = 5;
     49     /** Audio data format: E-AC-3 compressed */
     50     public static final int ENCODING_E_AC3 = 6;
     51 
     52     /** Invalid audio channel configuration */
     53     /** @deprecated use CHANNEL_INVALID instead  */
     54     @Deprecated    public static final int CHANNEL_CONFIGURATION_INVALID   = 0;
     55     /** Default audio channel configuration */
     56     /** @deprecated use CHANNEL_OUT_DEFAULT or CHANNEL_IN_DEFAULT instead  */
     57     @Deprecated    public static final int CHANNEL_CONFIGURATION_DEFAULT   = 1;
     58     /** Mono audio configuration */
     59     /** @deprecated use CHANNEL_OUT_MONO or CHANNEL_IN_MONO instead  */
     60     @Deprecated    public static final int CHANNEL_CONFIGURATION_MONO      = 2;
     61     /** Stereo (2 channel) audio configuration */
     62     /** @deprecated use CHANNEL_OUT_STEREO or CHANNEL_IN_STEREO instead  */
     63     @Deprecated    public static final int CHANNEL_CONFIGURATION_STEREO    = 3;
     64 
     65     /** Invalid audio channel mask */
     66     public static final int CHANNEL_INVALID = 0;
     67     /** Default audio channel mask */
     68     public static final int CHANNEL_OUT_DEFAULT = 1;
     69 
     70     // Output channel mask definitions below are translated to the native values defined in
     71     //  in /system/core/include/system/audio.h in the JNI code of AudioTrack
     72     public static final int CHANNEL_OUT_FRONT_LEFT = 0x4;
     73     public static final int CHANNEL_OUT_FRONT_RIGHT = 0x8;
     74     public static final int CHANNEL_OUT_FRONT_CENTER = 0x10;
     75     public static final int CHANNEL_OUT_LOW_FREQUENCY = 0x20;
     76     public static final int CHANNEL_OUT_BACK_LEFT = 0x40;
     77     public static final int CHANNEL_OUT_BACK_RIGHT = 0x80;
     78     public static final int CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x100;
     79     public static final int CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x200;
     80     public static final int CHANNEL_OUT_BACK_CENTER = 0x400;
     81     public static final int CHANNEL_OUT_SIDE_LEFT =         0x800;
     82     public static final int CHANNEL_OUT_SIDE_RIGHT =       0x1000;
     83     /** @hide */
     84     public static final int CHANNEL_OUT_TOP_CENTER =       0x2000;
     85     /** @hide */
     86     public static final int CHANNEL_OUT_TOP_FRONT_LEFT =   0x4000;
     87     /** @hide */
     88     public static final int CHANNEL_OUT_TOP_FRONT_CENTER = 0x8000;
     89     /** @hide */
     90     public static final int CHANNEL_OUT_TOP_FRONT_RIGHT = 0x10000;
     91     /** @hide */
     92     public static final int CHANNEL_OUT_TOP_BACK_LEFT =   0x20000;
     93     /** @hide */
     94     public static final int CHANNEL_OUT_TOP_BACK_CENTER = 0x40000;
     95     /** @hide */
     96     public static final int CHANNEL_OUT_TOP_BACK_RIGHT =  0x80000;
     97 
     98     public static final int CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT;
     99     public static final int CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT);
    100     // aka QUAD_BACK
    101     public static final int CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
    102             CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT);
    103     /** @hide */
    104     public static final int CHANNEL_OUT_QUAD_SIDE = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
    105             CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT);
    106     public static final int CHANNEL_OUT_SURROUND = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
    107             CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER);
    108     // aka 5POINT1_BACK
    109     public static final int CHANNEL_OUT_5POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
    110             CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT);
    111     /** @hide */
    112     public static final int CHANNEL_OUT_5POINT1_SIDE = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
    113             CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY |
    114             CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT);
    115     // TODO does this need an @deprecated ?
    116     // different from AUDIO_CHANNEL_OUT_7POINT1
    117     public static final int CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
    118             CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
    119             CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER);
    120     /** @hide */
    121     // matches AUDIO_CHANNEL_OUT_7POINT1
    122     public static final int CHANNEL_OUT_7POINT1_SURROUND = (
    123             CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_FRONT_RIGHT |
    124             CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT |
    125             CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
    126             CHANNEL_OUT_LOW_FREQUENCY);
    127     // CHANNEL_OUT_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_OUT_ALL
    128 
    129     /**
    130      * @hide
    131      * Return the input channel mask corresponding to an output channel mask.
    132      * This can be used for submix rerouting for the mask of the recorder to map to that of the mix.
    133      * @param outMask a combination of the CHANNEL_OUT_* definitions, but not CHANNEL_OUT_DEFAULT
    134      * @return a combination of CHANNEL_IN_* definitions matching an output channel mask
    135      * @throws IllegalArgumentException
    136      */
    137     public static int inChannelMaskFromOutChannelMask(int outMask) throws IllegalArgumentException {
    138         if (outMask == CHANNEL_OUT_DEFAULT) {
    139             throw new IllegalArgumentException(
    140                     "Illegal CHANNEL_OUT_DEFAULT channel mask for input.");
    141         }
    142         switch (channelCountFromOutChannelMask(outMask)) {
    143             case 1:
    144                 return CHANNEL_IN_MONO;
    145             case 2:
    146                 return CHANNEL_IN_STEREO;
    147             default:
    148                 throw new IllegalArgumentException("Unsupported channel configuration for input.");
    149         }
    150     }
    151 
    152     /**
    153      * @hide
    154      * Return the number of channels from an input channel mask
    155      * @param mask a combination of the CHANNEL_IN_* definitions, even CHANNEL_IN_DEFAULT
    156      * @return number of channels for the mask
    157      */
    158     public static int channelCountFromInChannelMask(int mask) {
    159         return Integer.bitCount(mask);
    160     }
    161     /**
    162      * @hide
    163      * Return the number of channels from an output channel mask
    164      * @param mask a combination of the CHANNEL_OUT_* definitions, but not CHANNEL_OUT_DEFAULT
    165      * @return number of channels for the mask
    166      */
    167     public static int channelCountFromOutChannelMask(int mask) {
    168         return Integer.bitCount(mask);
    169     }
    170     /**
    171      * @hide
    172      * Return a channel mask ready to be used by native code
    173      * @param mask a combination of the CHANNEL_OUT_* definitions, but not CHANNEL_OUT_DEFAULT
    174      * @return a native channel mask
    175      */
    176     public static int convertChannelOutMaskToNativeMask(int javaMask) {
    177         return (javaMask >> 2);
    178     }
    179 
    180     /**
    181      * @hide
    182      * Return a java output channel mask
    183      * @param mask a native channel mask
    184      * @return a combination of the CHANNEL_OUT_* definitions
    185      */
    186     public static int convertNativeChannelMaskToOutMask(int nativeMask) {
    187         return (nativeMask << 2);
    188     }
    189 
    190     public static final int CHANNEL_IN_DEFAULT = 1;
    191     // These directly match native
    192     public static final int CHANNEL_IN_LEFT = 0x4;
    193     public static final int CHANNEL_IN_RIGHT = 0x8;
    194     public static final int CHANNEL_IN_FRONT = 0x10;
    195     public static final int CHANNEL_IN_BACK = 0x20;
    196     public static final int CHANNEL_IN_LEFT_PROCESSED = 0x40;
    197     public static final int CHANNEL_IN_RIGHT_PROCESSED = 0x80;
    198     public static final int CHANNEL_IN_FRONT_PROCESSED = 0x100;
    199     public static final int CHANNEL_IN_BACK_PROCESSED = 0x200;
    200     public static final int CHANNEL_IN_PRESSURE = 0x400;
    201     public static final int CHANNEL_IN_X_AXIS = 0x800;
    202     public static final int CHANNEL_IN_Y_AXIS = 0x1000;
    203     public static final int CHANNEL_IN_Z_AXIS = 0x2000;
    204     public static final int CHANNEL_IN_VOICE_UPLINK = 0x4000;
    205     public static final int CHANNEL_IN_VOICE_DNLINK = 0x8000;
    206     public static final int CHANNEL_IN_MONO = CHANNEL_IN_FRONT;
    207     public static final int CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT);
    208     /** @hide */
    209     public static final int CHANNEL_IN_FRONT_BACK = CHANNEL_IN_FRONT | CHANNEL_IN_BACK;
    210     // CHANNEL_IN_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_IN_ALL
    211 
    212     /** @hide */
    213     public static int getBytesPerSample(int audioFormat)
    214     {
    215         switch (audioFormat) {
    216         case ENCODING_PCM_8BIT:
    217             return 1;
    218         case ENCODING_PCM_16BIT:
    219         case ENCODING_DEFAULT:
    220             return 2;
    221         case ENCODING_PCM_FLOAT:
    222             return 4;
    223         case ENCODING_INVALID:
    224         default:
    225             throw new IllegalArgumentException("Bad audio format " + audioFormat);
    226         }
    227     }
    228 
    229     /** @hide */
    230     public static boolean isValidEncoding(int audioFormat)
    231     {
    232         switch (audioFormat) {
    233         case ENCODING_PCM_8BIT:
    234         case ENCODING_PCM_16BIT:
    235         case ENCODING_PCM_FLOAT:
    236         case ENCODING_AC3:
    237         case ENCODING_E_AC3:
    238             return true;
    239         default:
    240             return false;
    241         }
    242     }
    243 
    244     /** @hide */
    245     public static boolean isEncodingLinearPcm(int audioFormat)
    246     {
    247         switch (audioFormat) {
    248         case ENCODING_PCM_8BIT:
    249         case ENCODING_PCM_16BIT:
    250         case ENCODING_PCM_FLOAT:
    251         case ENCODING_DEFAULT:
    252             return true;
    253         case ENCODING_AC3:
    254         case ENCODING_E_AC3:
    255             return false;
    256         case ENCODING_INVALID:
    257         default:
    258             throw new IllegalArgumentException("Bad audio format " + audioFormat);
    259         }
    260     }
    261 
    262     /** @removed */
    263     public AudioFormat()
    264     {
    265         throw new UnsupportedOperationException("There is no valid usage of this constructor");
    266     }
    267 
    268     /**
    269      * Private constructor with an ignored argument to differentiate from the removed default ctor
    270      * @param ignoredArgument
    271      */
    272     private AudioFormat(int ignoredArgument) {
    273     }
    274 
    275     /**
    276      * Constructor used by the JNI
    277      */
    278     // Update sound trigger JNI in core/jni/android_hardware_SoundTrigger.cpp when modifying this
    279     // constructor
    280     private AudioFormat(int encoding, int sampleRate, int channelMask) {
    281         mEncoding = encoding;
    282         mSampleRate = sampleRate;
    283         mChannelMask = channelMask;
    284         mPropertySetMask = AUDIO_FORMAT_HAS_PROPERTY_ENCODING |
    285                 AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE |
    286                 AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK;
    287     }
    288 
    289     /** @hide */
    290     public final static int AUDIO_FORMAT_HAS_PROPERTY_NONE = 0x0;
    291     /** @hide */
    292     public final static int AUDIO_FORMAT_HAS_PROPERTY_ENCODING = 0x1 << 0;
    293     /** @hide */
    294     public final static int AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE = 0x1 << 1;
    295     /** @hide */
    296     public final static int AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK = 0x1 << 2;
    297 
    298     private int mEncoding;
    299     private int mSampleRate;
    300     private int mChannelMask;
    301     private int mPropertySetMask;
    302 
    303     /**
    304      * Return the encoding.
    305      * @return one of the values that can be set in {@link Builder#setEncoding(int)} or
    306      * {@link AudioFormat#ENCODING_INVALID} if not set.
    307      */
    308     public int getEncoding() {
    309         if ((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_ENCODING) == 0) {
    310             return ENCODING_INVALID;
    311         }
    312         return mEncoding;
    313     }
    314 
    315     /**
    316      * Return the sample rate.
    317      * @return one of the values that can be set in {@link Builder#setSampleRate(int)} or
    318      * 0 if not set.
    319      */
    320     public int getSampleRate() {
    321         if ((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE) == 0) {
    322             return 0;
    323         }
    324         return mSampleRate;
    325     }
    326 
    327     /**
    328      * Return the channel mask.
    329      * @return one of the values that can be set in {@link Builder#setChannelMask(int)} or
    330      * {@link AudioFormat#CHANNEL_INVALID} if not set.
    331      */
    332     public int getChannelMask() {
    333         if ((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK) == 0) {
    334             return CHANNEL_INVALID;
    335         }
    336         return mChannelMask;
    337     }
    338 
    339     /** @hide */
    340     public int getPropertySetMask() {
    341         return mPropertySetMask;
    342     }
    343 
    344     /**
    345      * Builder class for {@link AudioFormat} objects.
    346      * Use this class to configure and create an AudioFormat instance. By setting format
    347      * characteristics such as audio encoding, channel mask or sample rate, you indicate which
    348      * of those are to vary from the default behavior on this device wherever this audio format
    349      * is used.
    350      * <p>{@link AudioFormat} is for instance used in
    351      * {@link AudioTrack#AudioTrack(AudioAttributes, AudioFormat, int, int, int)}. In this
    352      * constructor, every format characteristic set on the <code>Builder</code> (e.g. with
    353      * {@link #setSampleRate(int)}) will alter the default values used by an
    354      * <code>AudioTrack</code>. In this case for audio playback with <code>AudioTrack</code>, the
    355      * sample rate set in the <code>Builder</code> would override the platform output sample rate
    356      * which would otherwise be selected by default.
    357      */
    358     public static class Builder {
    359         private int mEncoding = ENCODING_INVALID;
    360         private int mSampleRate = 0;
    361         private int mChannelMask = CHANNEL_INVALID;
    362         private int mPropertySetMask = AUDIO_FORMAT_HAS_PROPERTY_NONE;
    363 
    364         /**
    365          * Constructs a new Builder with none of the format characteristics set.
    366          */
    367         public Builder() {
    368         }
    369 
    370         /**
    371          * Constructs a new Builder from a given {@link AudioFormat}.
    372          * @param af the {@link AudioFormat} object whose data will be reused in the new Builder.
    373          */
    374         public Builder(AudioFormat af) {
    375             mEncoding = af.mEncoding;
    376             mSampleRate = af.mSampleRate;
    377             mChannelMask = af.mChannelMask;
    378             mPropertySetMask = af.mPropertySetMask;
    379         }
    380 
    381         /**
    382          * Combines all of the format characteristics that have been set and return a new
    383          * {@link AudioFormat} object.
    384          * @return a new {@link AudioFormat} object
    385          */
    386         public AudioFormat build() {
    387             AudioFormat af = new AudioFormat(1980/*ignored*/);
    388             af.mEncoding = mEncoding;
    389             af.mSampleRate = mSampleRate;
    390             af.mChannelMask = mChannelMask;
    391             af.mPropertySetMask = mPropertySetMask;
    392             return af;
    393         }
    394 
    395         /**
    396          * Sets the data encoding format.
    397          * @param encoding one of {@link AudioFormat#ENCODING_DEFAULT},
    398          *     {@link AudioFormat#ENCODING_PCM_8BIT},
    399          *     {@link AudioFormat#ENCODING_PCM_16BIT},
    400          *     {@link AudioFormat#ENCODING_PCM_FLOAT},
    401          *     {@link AudioFormat#ENCODING_AC3},
    402          *     {@link AudioFormat#ENCODING_E_AC3}.
    403          * @return the same Builder instance.
    404          * @throws java.lang.IllegalArgumentException
    405          */
    406         public Builder setEncoding(@Encoding int encoding) throws IllegalArgumentException {
    407             switch (encoding) {
    408                 case ENCODING_DEFAULT:
    409                     mEncoding = ENCODING_PCM_16BIT;
    410                     break;
    411                 case ENCODING_PCM_8BIT:
    412                 case ENCODING_PCM_16BIT:
    413                 case ENCODING_PCM_FLOAT:
    414                 case ENCODING_AC3:
    415                 case ENCODING_E_AC3:
    416                     mEncoding = encoding;
    417                     break;
    418                 case ENCODING_INVALID:
    419                 default:
    420                     throw new IllegalArgumentException("Invalid encoding " + encoding);
    421             }
    422             mPropertySetMask |= AUDIO_FORMAT_HAS_PROPERTY_ENCODING;
    423             return this;
    424         }
    425 
    426         /**
    427          * Sets the channel mask.
    428          * @param channelMask describes the configuration of the audio channels.
    429          *    <p>For output, the mask should be a combination of
    430          *    {@link AudioFormat#CHANNEL_OUT_FRONT_LEFT},
    431          *    {@link AudioFormat#CHANNEL_OUT_FRONT_CENTER},
    432          *    {@link AudioFormat#CHANNEL_OUT_FRONT_RIGHT},
    433          *    {@link AudioFormat#CHANNEL_OUT_SIDE_LEFT},
    434          *    {@link AudioFormat#CHANNEL_OUT_SIDE_RIGHT},
    435          *    {@link AudioFormat#CHANNEL_OUT_BACK_LEFT},
    436          *    {@link AudioFormat#CHANNEL_OUT_BACK_RIGHT}.
    437          *    <p>for input, the mask should be {@link AudioFormat#CHANNEL_IN_MONO} or
    438          *    {@link AudioFormat#CHANNEL_IN_STEREO}.  {@link AudioFormat#CHANNEL_IN_MONO} is
    439          *    guaranteed to work on all devices.
    440          * @return the same Builder instance.
    441          */
    442         public Builder setChannelMask(int channelMask) {
    443             // only validated when used, with input or output context
    444             mChannelMask = channelMask;
    445             mPropertySetMask |= AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK;
    446             return this;
    447         }
    448 
    449         /**
    450          * Sets the sample rate.
    451          * @param sampleRate the sample rate expressed in Hz
    452          * @return the same Builder instance.
    453          * @throws java.lang.IllegalArgumentException
    454          */
    455         public Builder setSampleRate(int sampleRate) throws IllegalArgumentException {
    456             if ((sampleRate <= 0) || (sampleRate > 192000)) {
    457                 throw new IllegalArgumentException("Invalid sample rate " + sampleRate);
    458             }
    459             mSampleRate = sampleRate;
    460             mPropertySetMask |= AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE;
    461             return this;
    462         }
    463     }
    464 
    465     @Override
    466     public String toString () {
    467         return new String("AudioFormat:"
    468                 + " props=" + mPropertySetMask
    469                 + " enc=" + mEncoding
    470                 + " chan=0x" + Integer.toHexString(mChannelMask)
    471                 + " rate=" + mSampleRate);
    472     }
    473 
    474     /** @hide */
    475     @IntDef({
    476         ENCODING_DEFAULT,
    477         ENCODING_PCM_8BIT,
    478         ENCODING_PCM_16BIT,
    479         ENCODING_PCM_FLOAT,
    480         ENCODING_AC3,
    481         ENCODING_E_AC3
    482     })
    483     @Retention(RetentionPolicy.SOURCE)
    484     public @interface Encoding {}
    485 
    486 }
    487