| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.media.cts; |
| |
| import android.media.AudioFormat; |
| import android.os.Parcel; |
| |
| import com.android.compatibility.common.util.CtsAndroidTestCase; |
| |
| @NonMediaMainlineTest |
| public class AudioFormatTest extends CtsAndroidTestCase { |
| |
| // ----------------------------------------------------------------- |
| // AUDIOFORMAT TESTS: |
| // ---------------------------------- |
| |
| // ----------------------------------------------------------------- |
| // Builder tests |
| // ---------------------------------- |
| |
| // Test case 1: Use Builder to duplicate an AudioFormat with all fields supplied |
| public void testBuilderForCopy() throws Exception { |
| final int TEST_ENCODING = AudioFormat.ENCODING_PCM_16BIT; |
| final int TEST_SR = 48000; |
| final int TEST_CONF_POS = AudioFormat.CHANNEL_OUT_5POINT1; |
| // 6ch, like in 5.1 above offset by a randomly chosen number |
| final int TEST_CONF_IDX = 0x3F << 3; |
| |
| final AudioFormat formatToCopy = new AudioFormat.Builder() |
| .setEncoding(TEST_ENCODING).setSampleRate(TEST_SR) |
| .setChannelMask(TEST_CONF_POS).setChannelIndexMask(TEST_CONF_IDX).build(); |
| assertNotNull("Failure to create the AudioFormat to copy", formatToCopy); |
| |
| final AudioFormat copiedFormat = new AudioFormat.Builder(formatToCopy).build(); |
| assertNotNull("Failure to create AudioFormat copy with Builder", copiedFormat); |
| assertEquals("New AudioFormat has wrong sample rate", |
| TEST_SR, copiedFormat.getSampleRate()); |
| assertEquals("New AudioFormat has wrong encoding", |
| TEST_ENCODING, copiedFormat.getEncoding()); |
| assertEquals("New AudioFormat has wrong channel mask", |
| TEST_CONF_POS, copiedFormat.getChannelMask()); |
| assertEquals("New AudioFormat has wrong channel index mask", |
| TEST_CONF_IDX, copiedFormat.getChannelIndexMask()); |
| assertEquals("New AudioFormat has wrong channel count", |
| 6, copiedFormat.getChannelCount()); |
| assertEquals("New AudioFormat has the wrong frame size", |
| 6 /* channels */ * 2 /* bytes per sample */, copiedFormat.getFrameSizeInBytes()); |
| } |
| |
| // Test case 2: Use Builder to duplicate an AudioFormat with only encoding supplied |
| public void testPartialFormatBuilderForCopyEncoding() throws Exception { |
| final int TEST_ENCODING = AudioFormat.ENCODING_PCM_16BIT; |
| |
| final AudioFormat formatToCopy = new AudioFormat.Builder() |
| .setEncoding(TEST_ENCODING).build(); |
| assertNotNull("Failure to create the AudioFormat to copy", formatToCopy); |
| |
| final AudioFormat copiedFormat = new AudioFormat.Builder(formatToCopy).build(); |
| assertNotNull("Failure to create AudioFormat copy with Builder", copiedFormat); |
| assertEquals("New AudioFormat has wrong encoding", |
| TEST_ENCODING, copiedFormat.getEncoding()); |
| // test expected values when none has been set |
| assertEquals("New AudioFormat doesn't report expected sample rate", |
| 0, copiedFormat.getSampleRate()); |
| assertEquals("New AudioFormat doesn't report expected channel mask", |
| AudioFormat.CHANNEL_INVALID, copiedFormat.getChannelMask()); |
| assertEquals("New AudioFormat doesn't report expected channel index mask", |
| AudioFormat.CHANNEL_INVALID, copiedFormat.getChannelIndexMask()); |
| } |
| |
| // Test case 3: Use Builder to duplicate an AudioFormat with only sample rate supplied |
| public void testPartialFormatBuilderForCopyRate() throws Exception { |
| final int TEST_SR = 48000; |
| |
| final AudioFormat formatToCopy = new AudioFormat.Builder() |
| .setSampleRate(TEST_SR).build(); |
| assertNotNull("Failure to create the AudioFormat to copy", formatToCopy); |
| |
| final AudioFormat copiedFormat = new AudioFormat.Builder(formatToCopy).build(); |
| assertNotNull("Failure to create AudioFormat copy with Builder", copiedFormat); |
| assertEquals("New AudioFormat has wrong sample rate", |
| TEST_SR, copiedFormat.getSampleRate()); |
| // test expected values when none has been set |
| assertEquals("New AudioFormat doesn't report expected encoding", |
| AudioFormat.ENCODING_INVALID, copiedFormat.getEncoding()); |
| assertEquals("New AudioFormat doesn't report expected channel mask", |
| AudioFormat.CHANNEL_INVALID, copiedFormat.getChannelMask()); |
| assertEquals("New AudioFormat doesn't report expected channel index mask", |
| AudioFormat.CHANNEL_INVALID, copiedFormat.getChannelIndexMask()); |
| } |
| |
| // Test case 4: Use Builder to duplicate an AudioFormat with only channel mask supplied |
| public void testPartialFormatBuilderForCopyChanMask() throws Exception { |
| final int TEST_CONF_POS = AudioFormat.CHANNEL_OUT_5POINT1; |
| |
| final AudioFormat formatToCopy = new AudioFormat.Builder() |
| .setChannelMask(TEST_CONF_POS).build(); |
| assertNotNull("Failure to create the AudioFormat to copy", formatToCopy); |
| |
| final AudioFormat copiedFormat = new AudioFormat.Builder(formatToCopy).build(); |
| assertNotNull("Failure to create AudioFormat copy with Builder", copiedFormat); |
| assertEquals("New AudioFormat has wrong channel mask", |
| TEST_CONF_POS, copiedFormat.getChannelMask()); |
| // test expected values when none has been set |
| assertEquals("New AudioFormat doesn't report expected encoding", |
| AudioFormat.ENCODING_INVALID, copiedFormat.getEncoding()); |
| assertEquals("New AudioFormat doesn't report expected sample rate", |
| 0, copiedFormat.getSampleRate()); |
| assertEquals("New AudioFormat doesn't report expected channel index mask", |
| AudioFormat.CHANNEL_INVALID, copiedFormat.getChannelIndexMask()); |
| } |
| |
| |
| // Test case 5: Use Builder to duplicate an AudioFormat with only channel index mask supplied |
| public void testPartialFormatBuilderForCopyChanIdxMask() throws Exception { |
| final int TEST_CONF_IDX = 0x30; |
| |
| final AudioFormat formatToCopy = new AudioFormat.Builder() |
| .setChannelIndexMask(TEST_CONF_IDX).build(); |
| assertNotNull("Failure to create the AudioFormat to copy", formatToCopy); |
| |
| final AudioFormat copiedFormat = new AudioFormat.Builder(formatToCopy).build(); |
| assertNotNull("Failure to create AudioFormat copy with Builder", copiedFormat); |
| assertEquals("New AudioFormat has wrong channel mask", |
| TEST_CONF_IDX, copiedFormat.getChannelIndexMask()); |
| // test expected values when none has been set |
| assertEquals("New AudioFormat doesn't report expected encoding", |
| AudioFormat.ENCODING_INVALID, copiedFormat.getEncoding()); |
| assertEquals("New AudioFormat doesn't report expected sample rate", |
| 0, copiedFormat.getSampleRate()); |
| assertEquals("New AudioFormat doesn't report expected channel mask", |
| AudioFormat.CHANNEL_INVALID, copiedFormat.getChannelMask()); |
| } |
| |
| // Test case 6: create an instance, marshall it and create a new instance, |
| // check for equality |
| public void testParcel() throws Exception { |
| final int TEST_ENCODING = AudioFormat.ENCODING_PCM_16BIT; |
| final int TEST_SR = 48000; |
| final int TEST_CONF_POS = AudioFormat.CHANNEL_OUT_5POINT1; |
| // 6ch, like in 5.1 above offset by a randomly chosen number |
| final int TEST_CONF_IDX = 0x3F << 3; |
| |
| final AudioFormat formatToMarshall = new AudioFormat.Builder() |
| .setEncoding(TEST_ENCODING).setSampleRate(TEST_SR) |
| .setChannelMask(TEST_CONF_POS).setChannelIndexMask(TEST_CONF_IDX).build(); |
| assertNotNull("Failure to create the AudioFormat to marshall", formatToMarshall); |
| assertEquals(0, formatToMarshall.describeContents()); |
| |
| final Parcel srcParcel = Parcel.obtain(); |
| final Parcel dstParcel = Parcel.obtain(); |
| |
| formatToMarshall.writeToParcel(srcParcel, 0 /*no public flags for marshalling*/); |
| final byte[] mbytes = srcParcel.marshall(); |
| dstParcel.unmarshall(mbytes, 0, mbytes.length); |
| dstParcel.setDataPosition(0); |
| final AudioFormat unmarshalledFormat = AudioFormat.CREATOR.createFromParcel(dstParcel); |
| |
| assertNotNull("Failure to unmarshall AudioFormat", unmarshalledFormat); |
| assertEquals("Source and destination AudioFormat not equal", |
| formatToMarshall, unmarshalledFormat); |
| } |
| |
| // Test case 7: Check frame size for compressed, float formats. |
| public void testFrameSize() throws Exception { |
| int[] encodings = { |
| AudioFormat.ENCODING_MP3, |
| AudioFormat.ENCODING_AAC_LC, |
| AudioFormat.ENCODING_AAC_HE_V1, |
| AudioFormat.ENCODING_AAC_HE_V2, |
| AudioFormat.ENCODING_OPUS, |
| AudioFormat.ENCODING_MPEGH_BL_L3, |
| AudioFormat.ENCODING_MPEGH_BL_L4, |
| AudioFormat.ENCODING_MPEGH_LC_L3, |
| AudioFormat.ENCODING_MPEGH_LC_L4, |
| AudioFormat.ENCODING_DTS_UHD, |
| AudioFormat.ENCODING_DRA, |
| }; |
| for (int encoding : encodings) { |
| final AudioFormat format = new AudioFormat.Builder() |
| .setEncoding(encoding) |
| .setSampleRate(44100) |
| .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO) |
| .build(); |
| |
| assertEquals("AudioFormat with encoding " + encoding + " has the wrong frame size", |
| 1, format.getFrameSizeInBytes()); |
| } |
| |
| final AudioFormat formatPcmFloat = new AudioFormat.Builder() |
| .setEncoding(AudioFormat.ENCODING_PCM_FLOAT) |
| .setSampleRate(192000) |
| .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO) |
| .build(); |
| |
| assertEquals("Float AudioFormat has the wrong frame size", |
| 2 /* channels */ * 4 /* bytes per sample */, formatPcmFloat.getFrameSizeInBytes()); |
| } |
| |
| /** |
| * Check whether the bits in a are all present in b. |
| * |
| * Used for channel position mask verification. |
| */ |
| private boolean subsetOf(int a, int b) { |
| return Integer.bitCount(a ^ b) == Integer.bitCount(b) - Integer.bitCount(a); |
| } |
| |
| /** |
| * Test case 8: Check validity of channel masks |
| */ |
| public void testChannelMasks() throws Exception { |
| // Channel count check. |
| int[][] maskCount = new int[][] { |
| {AudioFormat.CHANNEL_OUT_MONO, 1}, |
| {AudioFormat.CHANNEL_OUT_STEREO, 2}, |
| {AudioFormat.CHANNEL_OUT_QUAD, 4}, |
| {AudioFormat.CHANNEL_OUT_SURROUND, 4}, |
| {AudioFormat.CHANNEL_OUT_5POINT1, 6}, |
| {AudioFormat.CHANNEL_OUT_5POINT1POINT2, 8}, |
| {AudioFormat.CHANNEL_OUT_7POINT1_SURROUND, 8}, |
| {AudioFormat.CHANNEL_OUT_7POINT1POINT2, 10}, |
| {AudioFormat.CHANNEL_OUT_5POINT1POINT4, 10}, |
| {AudioFormat.CHANNEL_OUT_7POINT1POINT2, 10}, |
| {AudioFormat.CHANNEL_OUT_7POINT1POINT4, 12}, |
| {AudioFormat.CHANNEL_OUT_9POINT1POINT4, 14}, |
| {AudioFormat.CHANNEL_OUT_13POINT_360RA, 13}, |
| {AudioFormat.CHANNEL_OUT_9POINT1POINT6, 16}, |
| {AudioFormat.CHANNEL_OUT_22POINT2, 24}, |
| }; |
| for (int[] pair : maskCount) { |
| assertEquals("Mask " + Integer.toHexString(pair[0]) |
| + " should have " + pair[1] + " bits set#", |
| /*expected*/ pair[1], /*actual*/ Integer.bitCount(pair[0])); |
| } |
| |
| // Check channel position masks that are a subset of other masks. |
| assertTrue(subsetOf(AudioFormat.CHANNEL_OUT_MONO, |
| AudioFormat.CHANNEL_OUT_STEREO)); |
| assertTrue(subsetOf(AudioFormat.CHANNEL_OUT_STEREO, |
| AudioFormat.CHANNEL_OUT_QUAD)); |
| assertTrue(subsetOf(AudioFormat.CHANNEL_OUT_STEREO, |
| AudioFormat.CHANNEL_OUT_SURROUND)); |
| assertTrue(subsetOf(AudioFormat.CHANNEL_OUT_QUAD, |
| AudioFormat.CHANNEL_OUT_5POINT1)); |
| assertTrue(subsetOf(AudioFormat.CHANNEL_OUT_5POINT1, |
| AudioFormat.CHANNEL_OUT_5POINT1POINT2)); |
| assertTrue(subsetOf(AudioFormat.CHANNEL_OUT_5POINT1, |
| AudioFormat.CHANNEL_OUT_5POINT1POINT4)); |
| // Note CHANNEL_OUT_5POINT1POINT2 not a subset of CHANNEL_OUT_5POINT1POINT4 |
| assertTrue(subsetOf(AudioFormat.CHANNEL_OUT_7POINT1_SURROUND, |
| AudioFormat.CHANNEL_OUT_7POINT1POINT2)); |
| assertTrue(subsetOf(AudioFormat.CHANNEL_OUT_7POINT1_SURROUND, |
| AudioFormat.CHANNEL_OUT_7POINT1POINT4)); |
| // Note CHANNEL_OUT_7POINT1POINT2 not a subset of CHANNEL_OUT_7POINT1POINT4 |
| assertTrue(subsetOf(AudioFormat.CHANNEL_OUT_5POINT1POINT4, |
| AudioFormat.CHANNEL_OUT_7POINT1POINT4)); |
| assertTrue(subsetOf(AudioFormat.CHANNEL_OUT_7POINT1POINT4, |
| AudioFormat.CHANNEL_OUT_22POINT2)); |
| assertTrue(subsetOf(AudioFormat.CHANNEL_OUT_7POINT1POINT4, |
| AudioFormat.CHANNEL_OUT_9POINT1POINT4)); |
| assertTrue(subsetOf(AudioFormat.CHANNEL_OUT_9POINT1POINT4, |
| AudioFormat.CHANNEL_OUT_9POINT1POINT6)); |
| assertTrue(subsetOf(AudioFormat.CHANNEL_OUT_13POINT_360RA, |
| AudioFormat.CHANNEL_OUT_22POINT2)); |
| } |
| } |