OSDN Git Service

Add channel index mask audio data conversion
authorAndy Hung <hunga@google.com>
Mon, 2 Feb 2015 23:34:13 +0000 (15:34 -0800)
committerAndy Hung <hunga@google.com>
Fri, 27 Feb 2015 20:53:41 +0000 (12:53 -0800)
Adds memcpy_by_index_array_initialization_src_index which fills an
index array used by memcpy_by_index_array.

Change-Id: Id8823a11cad642688ecbc16d9f2d894845d6e9c0

audio_utils/include/audio_utils/primitives.h
audio_utils/primitives.c
audio_utils/tests/build_and_run_all_unit_tests.sh
audio_utils/tests/primitives_tests.cpp

index ac0c0a9..e852894 100644 (file)
@@ -390,6 +390,9 @@ void memcpy_by_index_array(void *dst, uint32_t dst_channels,
  * Channels present in the channel mask are represented by set bits in the
  * uint32_t value and are matched without further interpretation.
  *
+ * This function is typically used for converting audio data with different
+ * channel position masks.
+ *
  * Parameters:
  *  idxary      Updated array of indices of channels in the src frame for the dst frame
  *  idxcount    Number of caller allocated elements in idxary
@@ -399,6 +402,24 @@ void memcpy_by_index_array(void *dst, uint32_t dst_channels,
 size_t memcpy_by_index_array_initialization(int8_t *idxary, size_t idxcount,
         uint32_t dst_mask, uint32_t src_mask);
 
+/* Prepares an index array (idxary) from channel masks, which can be later
+ * used by memcpy_by_index_array(). Returns the number of array elements required.
+ *
+ * For a source channel index mask, the source channels will map to the destination
+ * channels as if counting the set bits in dst_mask in order from lsb to msb
+ * (zero bits are ignored). The ith bit of the src_mask corresponds to the
+ * ith SET bit of dst_mask and the ith destination channel.  Hence, a zero ith
+ * bit of the src_mask indicates that the ith destination channel plays silence.
+ *
+ * Parameters:
+ *  idxary      Updated array of indices of channels in the src frame for the dst frame
+ *  idxcount    Number of caller allocated elements in idxary
+ *  dst_mask    Bit mask corresponding to destination channels present
+ *  src_mask    Bit mask corresponding to source channels present
+ */
+size_t memcpy_by_index_array_initialization_src_index(int8_t *idxary, size_t idxcount,
+        uint32_t dst_mask, uint32_t src_mask);
+
 /**
  * Clamp (aka hard limit or clip) a signed 32-bit sample to 16-bit range.
  */
index ae9b28c..fb4df97 100644 (file)
@@ -423,3 +423,25 @@ size_t memcpy_by_index_array_initialization(int8_t *idxary, size_t idxcount,
     }
     return n + popcount(ormask & dst_mask);
 }
+
+size_t memcpy_by_index_array_initialization_src_index(int8_t *idxary, size_t idxcount,
+        uint32_t dst_mask, uint32_t src_mask) {
+    size_t dst_count = popcount(dst_mask);
+    if (idxcount == 0) {
+        return dst_count;
+    }
+    if (dst_count > idxcount) {
+        dst_count = idxcount;
+    }
+
+    size_t src_idx, dst_idx;
+    for (src_idx = 0, dst_idx = 0; dst_idx < dst_count; ++dst_idx) {
+        if (src_mask & 1) {
+            idxary[dst_idx] = src_idx++;
+        } else {
+            idxary[dst_idx] = -1;
+        }
+        src_mask >>= 1;
+    }
+    return dst_idx;
+}
index 633e22c..3656974 100755 (executable)
@@ -20,5 +20,5 @@ adb root && adb wait-for-device remount
 echo "========================================"
 echo "testing primitives"
 adb push $OUT/system/lib/libaudioutils.so /system/lib
-adb push $OUT/system/bin/primitives_tests /system/bin
+adb push $OUT/data/nativetest/primitives_tests /system/bin
 adb shell /system/bin/primitives_tests
index 54ce9df..86ba8ae 100644 (file)
@@ -445,6 +445,98 @@ TEST(audio_utils_primitives, memcpy_by_index_array) {
     delete[] u24ary;
 }
 
+void memcpy_by_channel_mask_src_index(void *dst, uint32_t dst_mask,
+        const void *src, uint32_t src_mask, size_t sample_size, size_t count)
+{
+    int8_t idxary[32];
+    uint32_t src_channels = popcount(src_mask);
+    uint32_t dst_channels =
+            memcpy_by_index_array_initialization_src_index(idxary, 32, dst_mask, src_mask);
+
+    memcpy_by_index_array(dst, dst_channels, src, src_channels, idxary, sample_size, count);
+}
+
+// a modified version of the memcpy_by_channel_mask test
+// but using 24 bit type and memcpy_by_index_array()
+TEST(audio_utils_primitives, memcpy_by_index_array_src_index) {
+    uint32_t dst_mask;
+    uint32_t src_mask;
+    typedef struct {uint8_t c[3];} __attribute__((__packed__)) uint8x3_t;
+    uint8x3_t *u24ref = new uint8x3_t[65536];
+    uint8x3_t *u24ary = new uint8x3_t[65536];
+    uint16_t *u16ref = new uint16_t[65536];
+    uint16_t *u16ary = new uint16_t[65536];
+
+    EXPECT_EQ((size_t)3, sizeof(uint8x3_t)); // 3 bytes per struct
+
+    // tests prepare_index_array_from_masks()
+    EXPECT_EQ((size_t)4, memcpy_by_index_array_initialization_src_index(NULL, 0, 0x8d, 0x8c));
+    EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization_src_index(NULL, 0, 0x8c, 0x8d));
+
+    for (size_t i = 0; i < 65536; ++i) {
+        u16ref[i] = i;
+    }
+    memcpy_to_p24_from_i16((uint8_t*)u24ref, (int16_t*)u16ref, 65536);
+
+    // Test when src mask is 0.  Everything copied is zero.
+    src_mask = 0;
+    dst_mask = 0x8d;
+    memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
+    memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
+            65536 / popcount(dst_mask));
+    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
+    EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
+
+    // Test when dst_mask is 0.  Nothing should be copied.
+    src_mask = 0;
+    dst_mask = 0;
+    memset(u24ary, 0, 65536 * sizeof(u24ary[0]));
+    memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
+            65536);
+    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
+    EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
+
+    // Test when source mask must copy to dst mask.  One to one copy.
+    src_mask = 0xf;
+    dst_mask = 0xf;
+    memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
+    memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
+    EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * popcount(dst_mask)));
+
+    // Test when source mask must copy to dst mask.  One to one copy.
+    src_mask = 0xf;
+    dst_mask = 0x8d;
+    memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
+    memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]), 555);
+    EXPECT_EQ(0, memcmp(u24ary, u24ref, 555 * sizeof(u24ref[0]) * popcount(dst_mask)));
+
+    // Test with a gap in source:
+    // Input 3 samples, output 4 samples, one zero inserted.
+    src_mask = 0x07;
+    dst_mask = 0x8d;
+    memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
+    memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
+            65536 / popcount(dst_mask));
+    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
+    checkMonotoneOrZero(u16ary, 65536);
+    EXPECT_EQ((size_t)(65536 * 3 / 4 - 1), nonZeroMono16((int16_t*)u16ary, 65536));
+
+    // Test with a gap in destination:
+    // Input 4 samples, output 3 samples, one deleted
+    src_mask = 0x0f;
+    dst_mask = 0x8c;
+    memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
+    memcpy_by_channel_mask_src_index(u24ary, dst_mask, u24ref, src_mask, sizeof(u24ref[0]),
+            65536 / popcount(src_mask));
+    memcpy_to_i16_from_p24((int16_t*)u16ary, (uint8_t*)u24ary, 65536);
+    checkMonotone(u16ary, 65536 * 3 / 4);
+
+    delete[] u16ref;
+    delete[] u16ary;
+    delete[] u24ref;
+    delete[] u24ary;
+}
+
 TEST(audio_utils_channels, adjust_channels) {
     uint16_t *u16ref = new uint16_t[65536];
     uint16_t *u16expand = new uint16_t[65536*2];