upload android base code part6
This commit is contained in:
parent
421e214c7d
commit
4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions
172
android/system/media/audio_utils/tests/Android.bp
Normal file
172
android/system/media/audio_utils/tests/Android.bp
Normal file
|
@ -0,0 +1,172 @@
|
|||
// Build the unit tests for audio_utils
|
||||
|
||||
cc_test {
|
||||
name: "primitives_tests",
|
||||
host_supported: true,
|
||||
|
||||
shared_libs: [
|
||||
"liblog",
|
||||
"libcutils",
|
||||
],
|
||||
srcs: ["primitives_tests.cpp"],
|
||||
cflags: [
|
||||
"-Werror",
|
||||
"-Wall",
|
||||
],
|
||||
target: {
|
||||
android: {
|
||||
shared_libs: ["libaudioutils"],
|
||||
},
|
||||
host: {
|
||||
static_libs: ["libaudioutils"],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "fifo_tests",
|
||||
host_supported: true,
|
||||
srcs: ["fifo_tests.cpp"],
|
||||
shared_libs: ["libaudioutils"],
|
||||
static_libs: ["libsndfile"],
|
||||
cflags: [
|
||||
"-Werror",
|
||||
"-Wall",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "fifo_multiprocess",
|
||||
host_supported: false,
|
||||
srcs: ["fifo_multiprocess.cpp"],
|
||||
shared_libs: ["libaudioutils", "libcutils"],
|
||||
static_libs: ["libsndfile"],
|
||||
cflags: [
|
||||
"-Werror",
|
||||
"-Wall",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary_host {
|
||||
name: "fifo_threads",
|
||||
// TODO move getch.c and .h to a utility library
|
||||
srcs: [
|
||||
"fifo_threads.cpp",
|
||||
"getch.c",
|
||||
],
|
||||
static_libs: [
|
||||
"libaudioutils",
|
||||
"liblog",
|
||||
],
|
||||
cflags: [
|
||||
"-Werror",
|
||||
"-Wall",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary_host {
|
||||
name: "limiter_tests",
|
||||
srcs: ["limiter_tests.c"],
|
||||
static_libs: ["libaudioutils"],
|
||||
cflags: [
|
||||
"-Werror",
|
||||
"-Wall",
|
||||
"-UNDEBUG",
|
||||
],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "power_tests",
|
||||
host_supported: true,
|
||||
|
||||
shared_libs: [
|
||||
"libcutils",
|
||||
"liblog",
|
||||
],
|
||||
srcs: ["power_tests.cpp"],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-Wextra",
|
||||
],
|
||||
target: {
|
||||
android: {
|
||||
shared_libs: ["libaudioutils"],
|
||||
},
|
||||
host: {
|
||||
static_libs: ["libaudioutils"],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "errorlog_tests",
|
||||
host_supported: false,
|
||||
|
||||
shared_libs: [
|
||||
"libcutils",
|
||||
"liblog",
|
||||
],
|
||||
srcs: ["errorlog_tests.cpp"],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-Wextra",
|
||||
],
|
||||
target: {
|
||||
android: {
|
||||
shared_libs: ["libaudioutils"],
|
||||
},
|
||||
host: {
|
||||
static_libs: ["libaudioutils"],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "powerlog_tests",
|
||||
host_supported: false,
|
||||
|
||||
shared_libs: [
|
||||
"libcutils",
|
||||
"liblog",
|
||||
],
|
||||
srcs: ["powerlog_tests.cpp"],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-Wextra",
|
||||
],
|
||||
target: {
|
||||
android: {
|
||||
shared_libs: ["libaudioutils"],
|
||||
},
|
||||
host: {
|
||||
static_libs: ["libaudioutils"],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "simplelog_tests",
|
||||
host_supported: false,
|
||||
|
||||
shared_libs: [
|
||||
"libcutils",
|
||||
"liblog",
|
||||
],
|
||||
srcs: ["simplelog_tests.cpp"],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-Wextra",
|
||||
],
|
||||
target: {
|
||||
android: {
|
||||
shared_libs: ["libaudioutils"],
|
||||
},
|
||||
host: {
|
||||
static_libs: ["libaudioutils"],
|
||||
},
|
||||
}
|
||||
}
|
5
android/system/media/audio_utils/tests/README.md
Normal file
5
android/system/media/audio_utils/tests/README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
primitive\_tests uses gtest framework
|
||||
|
||||
fifo\_tests does not run under gtest
|
||||
|
||||
FIXME: getch.[ch] are copied from ../../../../frameworks/wilhelm/tests/sandbox/
|
28
android/system/media/audio_utils/tests/build_and_run_all_unit_tests.sh
Executable file
28
android/system/media/audio_utils/tests/build_and_run_all_unit_tests.sh
Executable file
|
@ -0,0 +1,28 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Run tests in this directory.
|
||||
#
|
||||
|
||||
if [ -z "$ANDROID_BUILD_TOP" ]; then
|
||||
echo "Android build environment not set"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
# ensure we have mm
|
||||
. $ANDROID_BUILD_TOP/build/envsetup.sh
|
||||
|
||||
mm
|
||||
|
||||
echo "waiting for device"
|
||||
|
||||
adb root && adb wait-for-device remount
|
||||
|
||||
echo "========================================"
|
||||
echo "testing primitives"
|
||||
adb push $OUT/system/lib/libaudioutils.so /system/lib
|
||||
adb push $OUT/data/nativetest/primitives_tests/primitives_tests /system/bin
|
||||
adb shell /system/bin/primitives_tests
|
||||
|
||||
echo "testing power"
|
||||
adb push $OUT/data/nativetest/power_tests/power_tests /system/bin
|
||||
adb shell /system/bin/power_tests
|
104
android/system/media/audio_utils/tests/errorlog_tests.cpp
Normal file
104
android/system/media/audio_utils/tests/errorlog_tests.cpp
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "audio_utils_errorlog_tests"
|
||||
|
||||
#include <audio_utils/ErrorLog.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
#include <log/log.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
static size_t countNewLines(const std::string &s) {
|
||||
return std::count(s.begin(), s.end(), '\n');
|
||||
}
|
||||
|
||||
TEST(audio_utils_errorlog, basic) {
|
||||
auto elog = std::make_unique<ErrorLog<int32_t>>(100 /* lines */);
|
||||
const int64_t oneSecond = 1000000000;
|
||||
|
||||
EXPECT_EQ((size_t)1, countNewLines(elog->dumpToString()));
|
||||
|
||||
elog->log(1 /* code */, 0 /* nowNs */);
|
||||
elog->log(2 /* code */, 1 /* nowNs */);
|
||||
|
||||
// two separate errors (4 lines including 2 header lines)
|
||||
EXPECT_EQ((size_t)4, countNewLines(elog->dumpToString()));
|
||||
|
||||
// aggregation at (oneSecond - 1)
|
||||
elog->log(2 /* code */, oneSecond /* nowNs */);
|
||||
EXPECT_EQ((size_t)4, countNewLines(elog->dumpToString()));
|
||||
|
||||
// no aggregation if spaced exactly one second apart
|
||||
elog->log(2 /* code */, oneSecond * 2 /* nowNs */);
|
||||
EXPECT_EQ((size_t)5, countNewLines(elog->dumpToString()));
|
||||
|
||||
// Check log:
|
||||
// truncate on lines
|
||||
EXPECT_EQ((size_t)3, countNewLines(elog->dumpToString("" /* prefix */, 3 /* lines */)));
|
||||
|
||||
// truncate on time
|
||||
EXPECT_EQ((size_t)4, countNewLines(
|
||||
elog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond - 1 /* limitNs */)));
|
||||
|
||||
// truncate on time
|
||||
EXPECT_EQ((size_t)4, countNewLines(
|
||||
elog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond /* limitNs */)));
|
||||
|
||||
// truncate on time (more)
|
||||
EXPECT_EQ((size_t)3, countNewLines(
|
||||
elog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond + 1 /* limitNs */)));
|
||||
|
||||
// truncate on time
|
||||
EXPECT_EQ((size_t)3, countNewLines(
|
||||
elog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond * 2 /* limitNs */)));
|
||||
|
||||
// truncate on time (to first header line)
|
||||
EXPECT_EQ((size_t)1, countNewLines(
|
||||
elog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond * 2 + 1/* limitNs */)));
|
||||
|
||||
elog->dump(0 /* fd (stdout) */);
|
||||
|
||||
// The output below depends on the local time zone.
|
||||
// The indentation below is exact, check alignment.
|
||||
/*
|
||||
Errors: 4
|
||||
Code Freq First time Last time
|
||||
1 1 12-31 16:00:00.000 12-31 16:00:00.000
|
||||
2 2 12-31 16:00:00.000 12-31 16:00:01.000
|
||||
2 1 12-31 16:00:02.000 12-31 16:00:02.000
|
||||
*/
|
||||
}
|
||||
|
||||
TEST(audio_utils_errorlog, c) {
|
||||
error_log_t *error_log =
|
||||
error_log_create(100 /* lines */, 1000000000 /* one second aggregation */);
|
||||
|
||||
// just a sanity test
|
||||
error_log_log(error_log, 2 /* code */, 1 /* now_ns */);
|
||||
error_log_dump(error_log, 0 /* fd */, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
|
||||
error_log_destroy(error_log);
|
||||
|
||||
// This has a 2 character prefix offset from the previous test when dumping.
|
||||
// The indentation below is exact, check alignment.
|
||||
/*
|
||||
Errors: 1
|
||||
Code Freq First time Last time
|
||||
2 1 12-31 16:00:00.000 12-31 16:00:00.000
|
||||
*/
|
||||
}
|
224
android/system/media/audio_utils/tests/fifo_multiprocess.cpp
Normal file
224
android/system/media/audio_utils/tests/fifo_multiprocess.cpp
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <audio_utils/fifo.h>
|
||||
#include <cutils/ashmem.h>
|
||||
|
||||
#define FRAME_COUNT 2048
|
||||
#define FRAME_SIZE sizeof(int16_t)
|
||||
#define BUFFER_SIZE (FRAME_COUNT * FRAME_SIZE)
|
||||
|
||||
int main(int argc __unused, char **argv __unused)
|
||||
{
|
||||
// TODO Add error checking for ashmem_create_region and mmap
|
||||
|
||||
const int frontFd = ashmem_create_region("front", sizeof(audio_utils_fifo_index));
|
||||
printf("frontFd=%d\n", frontFd);
|
||||
|
||||
const int rearFd = ashmem_create_region("rear", sizeof(audio_utils_fifo_index));
|
||||
printf("rearFd=%d\n", rearFd);
|
||||
|
||||
const int dataFd = ashmem_create_region("buffer", BUFFER_SIZE);
|
||||
printf("dataFd=%d\n", dataFd);
|
||||
|
||||
// next two index constructors must execute exactly once, so we do it in the parent
|
||||
|
||||
audio_utils_fifo_index *frontIndex = (audio_utils_fifo_index *) mmap(NULL,
|
||||
sizeof(audio_utils_fifo_index), PROT_READ | PROT_WRITE, MAP_SHARED, frontFd, (off_t) 0);
|
||||
printf("parent frontIndex=%p\n", frontIndex);
|
||||
(void) new(frontIndex) audio_utils_fifo_index();
|
||||
|
||||
audio_utils_fifo_index *rearIndex = (audio_utils_fifo_index *) mmap(NULL,
|
||||
sizeof(audio_utils_fifo_index), PROT_READ | PROT_WRITE, MAP_SHARED, rearFd, (off_t) 0);
|
||||
printf("parent rearIndex=%p\n", rearIndex);
|
||||
(void) new(rearIndex) audio_utils_fifo_index();
|
||||
|
||||
int16_t *data = (int16_t *) mmap(NULL, sizeof(audio_utils_fifo_index), PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, dataFd, (off_t) 0);
|
||||
printf("parent data=%p\n", data);
|
||||
memset(data, 0, BUFFER_SIZE);
|
||||
|
||||
const int pageSize = getpagesize();
|
||||
printf("page size=%d\n", pageSize);
|
||||
|
||||
// create writer
|
||||
|
||||
printf("fork writer:\n");
|
||||
const pid_t pidWriter = fork();
|
||||
// TODO check if pidWriter < 0
|
||||
if (!pidWriter) {
|
||||
|
||||
// Child inherits the parent's read/write mapping of front index.
|
||||
// To confirm that there are no attempts to write to the front index,
|
||||
// unmap it and then re-map it as read-only.
|
||||
int ok = munmap(frontIndex, sizeof(audio_utils_fifo_index));
|
||||
printf("writer unmap front ok=%d\n", ok);
|
||||
ok = ashmem_set_prot_region(frontFd, PROT_READ);
|
||||
printf("writer prot read front ok=%d\n", ok);
|
||||
// The pagesize * 4 offset confirms that we don't assume identical mapping in both processes
|
||||
frontIndex = (audio_utils_fifo_index *) mmap((char *) frontIndex + pageSize * 4,
|
||||
sizeof(audio_utils_fifo_index), PROT_READ, MAP_SHARED | MAP_FIXED, frontFd,
|
||||
(off_t) 0);
|
||||
printf("writer frontIndex=%p\n", frontIndex);
|
||||
|
||||
// Retain our read/write mapping of rear index and data
|
||||
audio_utils_fifo fifo(FRAME_COUNT, FRAME_SIZE, data, *rearIndex, frontIndex);
|
||||
audio_utils_fifo_writer writer(fifo);
|
||||
|
||||
sleep(2);
|
||||
|
||||
for (int16_t value = 1; value <= 20; value++) {
|
||||
printf("writing %d\n", value);
|
||||
const ssize_t actual = writer.write(&value, 1);
|
||||
if (actual != 1) {
|
||||
printf("wrote unexpected actual = %zd\n", actual);
|
||||
break;
|
||||
}
|
||||
// TODO needs a lot of work
|
||||
switch (value) {
|
||||
case 10:
|
||||
sleep(2);
|
||||
break;
|
||||
case 14:
|
||||
sleep(4);
|
||||
break;
|
||||
default:
|
||||
usleep(500000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
(void) close(frontFd);
|
||||
(void) close(rearFd);
|
||||
(void) close(dataFd);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// The sleep(2) above and sleep(1) here ensure that the order is:
|
||||
// a. writer initializes
|
||||
// b. reader initializes
|
||||
// c. reader starts the read loop
|
||||
// d. writer starts the write loop
|
||||
// Actually, as long as (a) precedes (d) and (b) precedes (c), the order does not matter.
|
||||
// TODO test all valid sequences.
|
||||
sleep(1);
|
||||
|
||||
// create reader
|
||||
|
||||
printf("fork reader:\n");
|
||||
const pid_t pidReader = fork();
|
||||
// TODO check if pidReader < 0
|
||||
if (!pidReader) {
|
||||
|
||||
// Child inherits the parent's read/write mapping of rear index.
|
||||
// To confirm that there are no attempts to write to the rear index,
|
||||
// unmap it and then re-map it as read-only.
|
||||
int ok = munmap(rearIndex, sizeof(audio_utils_fifo_index));
|
||||
printf("reader unmap rear ok=%d\n", ok);
|
||||
ok = ashmem_set_prot_region(rearFd, PROT_READ);
|
||||
printf("reader prot read rear ok=%d\n", ok);
|
||||
// The pagesize * 4 offset confirms that we don't assume identical mapping in both processes
|
||||
rearIndex = (audio_utils_fifo_index *) mmap((char *) rearIndex + pageSize * 4,
|
||||
sizeof(audio_utils_fifo_index), PROT_READ, MAP_SHARED | MAP_FIXED, rearFd,
|
||||
(off_t) 0);
|
||||
printf("reader rearIndex=%p\n", rearIndex);
|
||||
|
||||
// Similarly for the data
|
||||
ok = munmap(data, BUFFER_SIZE);
|
||||
printf("reader unmap data ok=%d\n", ok);
|
||||
ok = ashmem_set_prot_region(dataFd, PROT_READ);
|
||||
printf("reader prot read data ok=%d\n", ok);
|
||||
// The pagesize * 8 offset confirms that we don't assume identical mapping in both processes
|
||||
data = (int16_t *) mmap((char *) data + pageSize * 8, BUFFER_SIZE, PROT_READ,
|
||||
MAP_SHARED | MAP_FIXED, dataFd, (off_t) 0);
|
||||
printf("reader data=%p\n", data);
|
||||
|
||||
// Retain our read/write mapping of front index
|
||||
audio_utils_fifo fifo(FRAME_COUNT, FRAME_SIZE, data, *rearIndex, frontIndex);
|
||||
audio_utils_fifo_reader reader(fifo);
|
||||
|
||||
for (;;) {
|
||||
int16_t value;
|
||||
struct timespec timeout = {
|
||||
.tv_sec = 1,
|
||||
.tv_nsec = 0
|
||||
};
|
||||
const ssize_t actual = reader.read(&value, 1, &timeout);
|
||||
switch (actual) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
printf("read %d\n", value);
|
||||
if (value == 20) {
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case -ETIMEDOUT:
|
||||
printf("read timed out\n");
|
||||
break;
|
||||
default:
|
||||
printf("read unexpected actual = %zd\n", actual);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
out:
|
||||
|
||||
(void) close(frontFd);
|
||||
(void) close(rearFd);
|
||||
(void) close(dataFd);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int status;
|
||||
pid_t pid = waitpid(pidWriter, &status, 0);
|
||||
if (pid == pidWriter) {
|
||||
printf("writer exited with status %d\n", status);
|
||||
} else {
|
||||
printf("waitpid on writer = %d\n", pid);
|
||||
}
|
||||
pid = waitpid(pidReader, &status, 0);
|
||||
if (pid == pidReader) {
|
||||
printf("reader exited with status %d\n", status);
|
||||
} else {
|
||||
printf("waitpid on reader = %d\n", pid);
|
||||
}
|
||||
|
||||
// next two index destructors must execute exactly once, so we do it in the parent
|
||||
frontIndex->~audio_utils_fifo_index();
|
||||
rearIndex->~audio_utils_fifo_index();
|
||||
|
||||
int ok = munmap(frontIndex, sizeof(audio_utils_fifo_index));
|
||||
printf("parent unmap front ok=%d\n", ok);
|
||||
ok = munmap(rearIndex, sizeof(audio_utils_fifo_index));
|
||||
printf("parent unmap rear ok=%d\n", ok);
|
||||
ok = munmap(data, BUFFER_SIZE);
|
||||
printf("parent unmap data ok=%d\n", ok);
|
||||
|
||||
(void) close(frontFd);
|
||||
(void) close(rearFd);
|
||||
(void) close(dataFd);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
245
android/system/media/audio_utils/tests/fifo_tests.cpp
Normal file
245
android/system/media/audio_utils/tests/fifo_tests.cpp
Normal file
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Test program for audio_utils FIFO library.
|
||||
// This only tests the single-threaded aspects, not the barriers.
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <audio_utils/fifo.h>
|
||||
#include <audio_utils/sndfile.h>
|
||||
|
||||
#ifndef min
|
||||
#define min(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
size_t frameCount = 0;
|
||||
size_t maxFramesPerRead = 0;
|
||||
size_t maxFramesPerWrite = 0;
|
||||
bool readerThrottlesWriter = true;
|
||||
bool verbose = false;
|
||||
int i;
|
||||
for (i = 1; i < argc; i++) {
|
||||
char *arg = argv[i];
|
||||
if (arg[0] != '-')
|
||||
break;
|
||||
switch (arg[1]) {
|
||||
case 'f': // FIFO frame count
|
||||
frameCount = atoi(&arg[2]);
|
||||
break;
|
||||
case 'r': // maximum frame count per read from FIFO
|
||||
maxFramesPerRead = atoi(&arg[2]);
|
||||
break;
|
||||
case 't': // disable throttling of writer by reader
|
||||
readerThrottlesWriter = false;
|
||||
break;
|
||||
case 'v': // enable verbose logging
|
||||
verbose = true;
|
||||
break;
|
||||
case 'w': // maximum frame count per write to FIFO
|
||||
maxFramesPerWrite = atoi(&arg[2]);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: unknown option %s\n", argv[0], arg);
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if (frameCount == 0) {
|
||||
frameCount = 256;
|
||||
}
|
||||
if (maxFramesPerRead == 0) {
|
||||
maxFramesPerRead = frameCount;
|
||||
}
|
||||
if (maxFramesPerWrite == 0) {
|
||||
maxFramesPerWrite = frameCount;
|
||||
}
|
||||
|
||||
if (argc - i != 2) {
|
||||
usage:
|
||||
fprintf(stderr, "usage: %s [-f#] [-r#] [-t] [-v] [-w#] in.wav out.wav\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
char *inputFile = argv[i];
|
||||
char *outputFile = argv[i+1];
|
||||
|
||||
SF_INFO sfinfoin;
|
||||
memset(&sfinfoin, 0, sizeof(sfinfoin));
|
||||
SNDFILE *sfin = sf_open(inputFile, SFM_READ, &sfinfoin);
|
||||
if (sfin == NULL) {
|
||||
perror(inputFile);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
switch (sfinfoin.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) {
|
||||
case SF_FORMAT_WAV | SF_FORMAT_PCM_16:
|
||||
case SF_FORMAT_WAV | SF_FORMAT_PCM_U8:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: unsupported format\n", inputFile);
|
||||
sf_close(sfin);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
size_t frameSize = sizeof(int16_t) * sfinfoin.channels;
|
||||
int16_t *inputBuffer = new int16_t[sfinfoin.frames * sfinfoin.channels];
|
||||
sf_count_t actualRead = sf_readf_short(sfin, inputBuffer, sfinfoin.frames);
|
||||
if (actualRead != sfinfoin.frames) {
|
||||
fprintf(stderr, "%s: unexpected EOF or error\n", inputFile);
|
||||
sf_close(sfin);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
sf_close(sfin);
|
||||
|
||||
int16_t *outputBuffer = new int16_t[sfinfoin.frames * sfinfoin.channels];
|
||||
size_t framesWritten = 0;
|
||||
size_t framesRead = 0;
|
||||
int16_t *fifoBuffer = new int16_t[frameCount * sfinfoin.channels];
|
||||
audio_utils_fifo fifo(frameCount, frameSize, fifoBuffer, readerThrottlesWriter);
|
||||
audio_utils_fifo_writer fifoWriter(fifo);
|
||||
audio_utils_fifo_reader fifoReader(fifo, readerThrottlesWriter);
|
||||
int fifoWriteCount = 0, fifoReadCount = 0;
|
||||
int fifoFillLevel = 0, minFillLevel = INT_MAX, maxFillLevel = INT_MIN;
|
||||
for (;;) {
|
||||
size_t framesToWrite = sfinfoin.frames - framesWritten;
|
||||
size_t framesToRead = sfinfoin.frames - framesRead;
|
||||
if (framesToWrite == 0 && (framesToRead == 0 || !readerThrottlesWriter)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (framesToWrite > maxFramesPerWrite) {
|
||||
framesToWrite = maxFramesPerWrite;
|
||||
}
|
||||
framesToWrite = rand() % (framesToWrite + 1);
|
||||
ssize_t actualWritten = fifoWriter.write(
|
||||
&inputBuffer[framesWritten * sfinfoin.channels], framesToWrite);
|
||||
if (verbose) {
|
||||
printf("wrote %d out of %d\n", (int) actualWritten, (int) framesToWrite);
|
||||
}
|
||||
if (actualWritten < 0 || (size_t) actualWritten > framesToWrite) {
|
||||
fprintf(stderr, "write to FIFO failed\n");
|
||||
break;
|
||||
}
|
||||
if (actualWritten < min((int) frameCount - fifoFillLevel, (int) framesToWrite)) {
|
||||
fprintf(stderr, "only wrote %d when should have written min(%d, %d)\n",
|
||||
(int) actualWritten, (int) frameCount - fifoFillLevel, (int) framesToWrite);
|
||||
}
|
||||
framesWritten += actualWritten;
|
||||
if (actualWritten > 0) {
|
||||
fifoWriteCount++;
|
||||
}
|
||||
fifoFillLevel += actualWritten;
|
||||
if (verbose) {
|
||||
printf("fill level after write %d\n", fifoFillLevel);
|
||||
}
|
||||
if (fifoFillLevel > maxFillLevel) {
|
||||
maxFillLevel = fifoFillLevel;
|
||||
if (maxFillLevel > (int) frameCount) {
|
||||
if (readerThrottlesWriter) {
|
||||
printf("maxFillLevel=%d > frameCount=%d\n", maxFillLevel, (int) frameCount);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (framesToRead > maxFramesPerRead) {
|
||||
framesToRead = maxFramesPerRead;
|
||||
}
|
||||
framesToRead = rand() % (framesToRead + 1);
|
||||
ssize_t actualRead = fifoReader.read(
|
||||
&outputBuffer[framesRead * sfinfoin.channels], framesToRead);
|
||||
if (verbose) {
|
||||
printf("read %d out of %d\n", (int) actualRead, (int) framesToRead);
|
||||
}
|
||||
if (actualRead < 0 || (size_t) actualRead > framesToRead) {
|
||||
switch (actualRead) {
|
||||
case -EIO:
|
||||
fprintf(stderr, "read from FIFO failed: corrupted indices\n");
|
||||
abort();
|
||||
break;
|
||||
case -EOVERFLOW:
|
||||
if (readerThrottlesWriter) {
|
||||
fprintf(stderr, "read from FIFO failed: unexpected overflow\n");
|
||||
abort();
|
||||
}
|
||||
printf("warning: reader lost frames\n");
|
||||
actualRead = 0;
|
||||
break;
|
||||
default:
|
||||
if (actualRead < 0) {
|
||||
fprintf(stderr, "read from FIFO failed: unexpected error code %d\n",
|
||||
(int) actualRead);
|
||||
} else {
|
||||
fprintf(stderr, "read from FIFO failed: actualRead=%d > framesToRead=%d\n",
|
||||
(int) actualRead, (int) framesToRead);
|
||||
}
|
||||
abort();
|
||||
}
|
||||
}
|
||||
if (actualRead < min(fifoFillLevel, (int) framesToRead)) {
|
||||
//fprintf(stderr, "only read %d when should have read min(%d, %d)\n",
|
||||
// (int) actualRead, fifoFillLevel, (int) framesToRead);
|
||||
}
|
||||
framesRead += actualRead;
|
||||
if (actualRead > 0) {
|
||||
fifoReadCount++;
|
||||
}
|
||||
fifoFillLevel -= actualRead;
|
||||
if (verbose) {
|
||||
printf("fill level after read %d\n", fifoFillLevel);
|
||||
}
|
||||
if (fifoFillLevel < minFillLevel) {
|
||||
minFillLevel = fifoFillLevel;
|
||||
if (minFillLevel < 0) {
|
||||
printf("minFillLevel=%d < 0\n", minFillLevel);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] inputBuffer;
|
||||
inputBuffer = NULL;
|
||||
delete[] fifoBuffer;
|
||||
fifoBuffer = NULL;
|
||||
|
||||
printf("FIFO non-empty writes: %d, non-empty reads: %d\n", fifoWriteCount, fifoReadCount);
|
||||
printf("fill=%d, min=%d, max=%d\n", fifoFillLevel, minFillLevel, maxFillLevel);
|
||||
|
||||
printf("writing output\n");
|
||||
SF_INFO sfinfoout;
|
||||
memset(&sfinfoout, 0, sizeof(sfinfoout));
|
||||
sfinfoout.samplerate = sfinfoin.samplerate;
|
||||
sfinfoout.channels = sfinfoin.channels;
|
||||
sfinfoout.format = sfinfoin.format;
|
||||
SNDFILE *sfout = sf_open(outputFile, SFM_WRITE, &sfinfoout);
|
||||
if (sfout == NULL) {
|
||||
perror(outputFile);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
sf_count_t actualWritten = sf_writef_short(sfout, outputBuffer, framesRead);
|
||||
delete[] outputBuffer;
|
||||
outputBuffer = NULL;
|
||||
|
||||
if (actualWritten != (sf_count_t) framesRead) {
|
||||
fprintf(stderr, "%s: unexpected error\n", outputFile);
|
||||
sf_close(sfout);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
sf_close(sfout);
|
||||
printf("done\n");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
166
android/system/media/audio_utils/tests/fifo_threads.cpp
Normal file
166
android/system/media/audio_utils/tests/fifo_threads.cpp
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <audio_utils/fifo.h>
|
||||
extern "C" {
|
||||
#include "getch.h"
|
||||
}
|
||||
|
||||
struct Context {
|
||||
audio_utils_fifo_writer *mInputWriter;
|
||||
audio_utils_fifo_reader *mInputReader;
|
||||
audio_utils_fifo_writer *mTransferWriter;
|
||||
audio_utils_fifo_reader *mTransferReader;
|
||||
audio_utils_fifo_writer *mOutputWriter;
|
||||
audio_utils_fifo_reader *mOutputReader;
|
||||
};
|
||||
|
||||
void *input_routine(void *arg)
|
||||
{
|
||||
Context *context = (Context *) arg;
|
||||
for (;;) {
|
||||
struct timespec timeout;
|
||||
timeout.tv_sec = 30;
|
||||
timeout.tv_nsec = 0;
|
||||
char buffer[4];
|
||||
ssize_t actual = context->mInputReader->read(buffer, sizeof(buffer), &timeout);
|
||||
// TODO this test is unreadable
|
||||
if (actual > 0) {
|
||||
if ((size_t) actual > sizeof(buffer)) {
|
||||
printf("input.read actual = %d\n", (int) actual);
|
||||
abort();
|
||||
}
|
||||
ssize_t actual2 = context->mTransferWriter->write(buffer, actual, &timeout);
|
||||
if (actual2 != actual) {
|
||||
printf("transfer.write(%d) = %d\n", (int) actual, (int) actual2);
|
||||
}
|
||||
//sleep(10);
|
||||
} else if (actual == -ETIMEDOUT) {
|
||||
(void) write(1, "t", 1);
|
||||
} else {
|
||||
printf("input.read actual = %d\n", (int) actual);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
volatile bool outputPaused = false;
|
||||
|
||||
void *output_routine(void *arg)
|
||||
{
|
||||
Context *context = (Context *) arg;
|
||||
for (;;) {
|
||||
if (outputPaused) {
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
struct timespec timeout;
|
||||
timeout.tv_sec = 60;
|
||||
timeout.tv_nsec = 0;
|
||||
char buffer[4];
|
||||
ssize_t actual = context->mTransferReader->read(buffer, sizeof(buffer), &timeout);
|
||||
if (actual > 0) {
|
||||
if ((size_t) actual > sizeof(buffer)) {
|
||||
printf("transfer.read actual = %d\n", (int) actual);
|
||||
abort();
|
||||
}
|
||||
ssize_t actual2 = context->mOutputWriter->write(buffer, actual, NULL /*timeout*/);
|
||||
if (actual2 != actual) {
|
||||
printf("output.write(%d) = %d\n", (int) actual, (int) actual2);
|
||||
}
|
||||
} else if (actual == -ETIMEDOUT) {
|
||||
(void) write(1, "T", 1);
|
||||
} else {
|
||||
printf("transfer.read actual = %d\n", (int) actual);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
set_conio_terminal_mode();
|
||||
argc = argc + 0;
|
||||
argv = &argv[0];
|
||||
|
||||
char inputBuffer[16];
|
||||
audio_utils_fifo inputFifo(sizeof(inputBuffer) /*frameCount*/, 1 /*frameSize*/, inputBuffer,
|
||||
true /*throttlesWriter*/);
|
||||
audio_utils_fifo_writer inputWriter(inputFifo);
|
||||
audio_utils_fifo_reader inputReader(inputFifo, true /*throttlesWriter*/);
|
||||
//inputWriter.setHysteresis(sizeof(inputBuffer) * 1/4, sizeof(inputBuffer) * 3/4);
|
||||
|
||||
char transferBuffer[64];
|
||||
audio_utils_fifo transferFifo(sizeof(transferBuffer) /*frameCount*/, 1 /*frameSize*/,
|
||||
transferBuffer, true /*throttlesWriter*/);
|
||||
audio_utils_fifo_writer transferWriter(transferFifo);
|
||||
audio_utils_fifo_reader transferReader(transferFifo, true /*throttlesWriter*/);
|
||||
transferReader.setHysteresis(sizeof(transferBuffer) * 3/4, sizeof(transferBuffer) * 1/4);
|
||||
//transferWriter.setEffective(8);
|
||||
|
||||
char outputBuffer[64];
|
||||
audio_utils_fifo outputFifo(sizeof(outputBuffer) /*frameCount*/, 1 /*frameSize*/, outputBuffer,
|
||||
true /*throttlesWriter*/);
|
||||
audio_utils_fifo_writer outputWriter(outputFifo);
|
||||
audio_utils_fifo_reader outputReader(outputFifo, true /*readerThrottlesWriter*/);
|
||||
|
||||
Context context;
|
||||
context.mInputWriter = &inputWriter;
|
||||
context.mInputReader = &inputReader;
|
||||
context.mTransferWriter = &transferWriter;
|
||||
context.mTransferReader = &transferReader;
|
||||
context.mOutputWriter = &outputWriter;
|
||||
context.mOutputReader = &outputReader;
|
||||
|
||||
pthread_t input_thread;
|
||||
int ok = pthread_create(&input_thread, (const pthread_attr_t *) NULL, input_routine,
|
||||
(void *) &context);
|
||||
pthread_t output_thread;
|
||||
ok = pthread_create(&output_thread, (const pthread_attr_t *) NULL, output_routine,
|
||||
(void *) &context);
|
||||
ok = ok + 0;
|
||||
|
||||
for (;;) {
|
||||
char buffer[4];
|
||||
ssize_t actual = outputReader.read(buffer, sizeof(buffer), NULL /*timeout*/);
|
||||
if (actual > 0) {
|
||||
printf("%.*s", (int) actual, buffer);
|
||||
fflush(stdout);
|
||||
} else if (actual != 0) {
|
||||
printf("outputReader.read actual = %d\n", (int) actual);
|
||||
}
|
||||
if (kbhit()) {
|
||||
int ch = getch();
|
||||
if (ch <= 0 || ch == '\003' /*control-C*/) {
|
||||
break;
|
||||
}
|
||||
if (ch == 'p')
|
||||
outputPaused = true;
|
||||
else if (ch == 'p')
|
||||
outputPaused = false;
|
||||
buffer[0] = ch;
|
||||
actual = inputWriter.write(buffer, 1, NULL /*timeout*/);
|
||||
if (actual != 1) {
|
||||
printf("inputWriter.write actual = %d\n", (int) actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
reset_terminal_mode();
|
||||
}
|
65
android/system/media/audio_utils/tests/getch.c
Normal file
65
android/system/media/audio_utils/tests/getch.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
C non-blocking keyboard input
|
||||
http://stackoverflow.com/questions/448944/c-non-blocking-keyboard-input
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include "getch.h"
|
||||
|
||||
struct termios orig_termios;
|
||||
|
||||
void reset_terminal_mode()
|
||||
{
|
||||
tcsetattr(0, TCSANOW, &orig_termios);
|
||||
}
|
||||
|
||||
void set_conio_terminal_mode()
|
||||
{
|
||||
struct termios new_termios;
|
||||
|
||||
/* take two copies - one for now, one for later */
|
||||
tcgetattr(0, &orig_termios);
|
||||
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
|
||||
|
||||
/* register cleanup handler, and set the new terminal mode */
|
||||
atexit(reset_terminal_mode);
|
||||
cfmakeraw(&new_termios);
|
||||
new_termios.c_oflag |= OPOST;
|
||||
tcsetattr(0, TCSANOW, &new_termios);
|
||||
}
|
||||
|
||||
int kbhit()
|
||||
{
|
||||
struct timeval tv = { 0L, 0L };
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds); // not in original posting to stackoverflow
|
||||
FD_SET(0, &fds);
|
||||
return select(1, &fds, NULL, NULL, &tv);
|
||||
}
|
||||
|
||||
int getch()
|
||||
{
|
||||
int r;
|
||||
unsigned char c;
|
||||
if ((r = read(0, &c, sizeof(c))) < 0) {
|
||||
return r;
|
||||
} else {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
set_conio_terminal_mode();
|
||||
|
||||
while (!kbhit()) {
|
||||
/* do some work */
|
||||
}
|
||||
(void)getch(); /* consume the character */
|
||||
}
|
||||
#endif
|
20
android/system/media/audio_utils/tests/getch.h
Normal file
20
android/system/media/audio_utils/tests/getch.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (C) 2011 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.
|
||||
*/
|
||||
|
||||
extern int kbhit();
|
||||
extern int getch(void);
|
||||
extern void set_conio_terminal_mode(void);
|
||||
extern void reset_terminal_mode(void);
|
42
android/system/media/audio_utils/tests/limiter_tests.c
Normal file
42
android/system/media/audio_utils/tests/limiter_tests.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <audio_utils/limiter.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
if (argc > 1) {
|
||||
for (i = 1; i < argc; i++) {
|
||||
float x = atof(argv[i]);
|
||||
printf("limit(%g)=%g\n", x, limiter(x));
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i <= 150; i++) {
|
||||
float in = (float) ((double) i * 0.01);
|
||||
float out = limiter(in);
|
||||
printf("%g,%g\n", in, out);
|
||||
if (i != 0) {
|
||||
out = limiter(-in);
|
||||
printf("%g,%g\n", -in, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
173
android/system/media/audio_utils/tests/power_tests.cpp
Normal file
173
android/system/media/audio_utils/tests/power_tests.cpp
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "audio_utils_power_tests"
|
||||
|
||||
#include <cmath>
|
||||
#include <math.h>
|
||||
|
||||
#include <audio_utils/power.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <log/log.h>
|
||||
|
||||
typedef struct { uint8_t c[3]; } __attribute__((__packed__)) uint8x3_t;
|
||||
|
||||
void testFloatValue(float f_value, size_t length) {
|
||||
const float power = audio_utils_power_from_amplitude(f_value);
|
||||
float f_ary[length];
|
||||
uint8_t u8_ary[length];
|
||||
int16_t i16_ary[length];
|
||||
int32_t i32_ary[length];
|
||||
int32_t q8_23_ary[length];
|
||||
uint8x3_t p24_ary[length];
|
||||
|
||||
// magic formulas to convert floating point to fixed point representations.
|
||||
// we negate the floating point value to ensure full integer range for 1.f.
|
||||
const uint8_t u8_value((1.f - f_value) * 128);
|
||||
const int16_t i16_value(f_value * INT16_MIN);
|
||||
const int32_t i32_value (f_value * INT32_MIN);
|
||||
const int32_t q8_23_value(f_value * -(1 << 23));
|
||||
|
||||
// PCM_24_BIT_PACKED is native endian.
|
||||
#if HAVE_BIG_ENDIAN
|
||||
const uint8x3_t p24_value{{
|
||||
uint8_t(q8_23_value >> 16),
|
||||
uint8_t(q8_23_value >> 8),
|
||||
uint8_t(q8_23_value),
|
||||
}};
|
||||
#else
|
||||
const uint8x3_t p24_value{{
|
||||
uint8_t(q8_23_value),
|
||||
uint8_t(q8_23_value >> 8),
|
||||
uint8_t(q8_23_value >> 16),
|
||||
}};
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
f_ary[i] = f_value;
|
||||
u8_ary[i] = u8_value;
|
||||
i16_ary[i] = i16_value;
|
||||
i32_ary[i] = i32_value;
|
||||
q8_23_ary[i] = q8_23_value;
|
||||
p24_ary[i] = p24_value;
|
||||
}
|
||||
|
||||
// check offset by 1, 2, 3 elements for unaligned NEON vector handling.
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
if (i >= length) break;
|
||||
EXPECT_EQ(power,
|
||||
audio_utils_compute_power_mono(f_ary + i, AUDIO_FORMAT_PCM_FLOAT, length - i));
|
||||
EXPECT_EQ(power,
|
||||
audio_utils_compute_power_mono(u8_ary + i, AUDIO_FORMAT_PCM_8_BIT, length - i));
|
||||
EXPECT_EQ(power,
|
||||
audio_utils_compute_power_mono(i16_ary + i, AUDIO_FORMAT_PCM_16_BIT, length - i));
|
||||
EXPECT_EQ(power,
|
||||
audio_utils_compute_power_mono(i32_ary + i, AUDIO_FORMAT_PCM_32_BIT, length - i));
|
||||
EXPECT_EQ(power,
|
||||
audio_utils_compute_power_mono(
|
||||
q8_23_ary + i, AUDIO_FORMAT_PCM_8_24_BIT, length - i));
|
||||
EXPECT_EQ(power,
|
||||
audio_utils_compute_power_mono(
|
||||
p24_ary + i, AUDIO_FORMAT_PCM_24_BIT_PACKED, length - i));
|
||||
}
|
||||
}
|
||||
|
||||
void testFloatRamp(size_t length) {
|
||||
float f_ary[length];
|
||||
uint8_t u8_ary[length];
|
||||
int16_t i16_ary[length];
|
||||
int32_t i32_ary[length];
|
||||
int32_t q8_23_ary[length];
|
||||
uint8x3_t p24_ary[length];
|
||||
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
// must be expressed cleanly in uint8_t
|
||||
const float f_value = (int(length & 0xff) - 128) / 128.f;
|
||||
|
||||
// magic formulas to convert floating point to fixed point representations.
|
||||
// we negate the floating point value to ensure full integer range for 1.f.
|
||||
const uint8_t u8_value((1.f - f_value) * 128);
|
||||
const int16_t i16_value(f_value * INT16_MIN);
|
||||
const int32_t i32_value (f_value * INT32_MIN);
|
||||
const int32_t q8_23_value(f_value * -(1 << 23));
|
||||
|
||||
// PCM_24_BIT_PACKED is native endian.
|
||||
#if HAVE_BIG_ENDIAN
|
||||
const uint8x3_t p24_value{{
|
||||
uint8_t(q8_23_value >> 16),
|
||||
uint8_t(q8_23_value >> 8),
|
||||
uint8_t(q8_23_value),
|
||||
}};
|
||||
#else
|
||||
const uint8x3_t p24_value{{
|
||||
uint8_t(q8_23_value),
|
||||
uint8_t(q8_23_value >> 8),
|
||||
uint8_t(q8_23_value >> 16),
|
||||
}};
|
||||
#endif
|
||||
|
||||
f_ary[i] = f_value;
|
||||
u8_ary[i] = u8_value;
|
||||
i16_ary[i] = i16_value;
|
||||
i32_ary[i] = i32_value;
|
||||
q8_23_ary[i] = q8_23_value;
|
||||
p24_ary[i] = p24_value;
|
||||
}
|
||||
|
||||
const float power8 = audio_utils_compute_power_mono(u8_ary, AUDIO_FORMAT_PCM_8_BIT, length);
|
||||
|
||||
EXPECT_EQ(power8,
|
||||
audio_utils_compute_power_mono(f_ary, AUDIO_FORMAT_PCM_FLOAT, length));
|
||||
EXPECT_EQ(power8,
|
||||
audio_utils_compute_power_mono(i16_ary, AUDIO_FORMAT_PCM_16_BIT, length));
|
||||
EXPECT_EQ(power8,
|
||||
audio_utils_compute_power_mono(i32_ary, AUDIO_FORMAT_PCM_32_BIT, length));
|
||||
EXPECT_EQ(power8,
|
||||
audio_utils_compute_power_mono(q8_23_ary, AUDIO_FORMAT_PCM_8_24_BIT, length));
|
||||
EXPECT_EQ(power8,
|
||||
audio_utils_compute_power_mono(p24_ary, AUDIO_FORMAT_PCM_24_BIT_PACKED, length));
|
||||
}
|
||||
|
||||
// power_mono implicitly tests energy_mono
|
||||
TEST(audio_utils_power, power_mono) {
|
||||
// f_values should have limited mantissa
|
||||
for (float f_value : { 0.f, 0.25f, 0.5f, 0.75f, 1.f }) {
|
||||
const float power = audio_utils_power_from_amplitude(f_value);
|
||||
printf("power_mono: amplitude: %f power: %f\n", f_value, power);
|
||||
|
||||
for (size_t length : { 1, 3, 5, 7, 16, 21, 32, 37 }) {
|
||||
testFloatValue(f_value, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// power_mono implicitly tests energy_mono
|
||||
TEST(audio_utils_power, power_mono_ramp) {
|
||||
for (size_t length : { 1, 3, 5, 7, 16, 21, 32, 37, 297 }) {
|
||||
testFloatRamp(length);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(audio_utils_power, power_from) {
|
||||
EXPECT_EQ(0.f, audio_utils_power_from_amplitude(1.f));
|
||||
EXPECT_EQ(-INFINITY, audio_utils_power_from_amplitude(0.f));
|
||||
EXPECT_EQ(0.f, audio_utils_power_from_amplitude(-1.f));
|
||||
|
||||
EXPECT_EQ(0.f, audio_utils_power_from_energy(1.f));
|
||||
EXPECT_EQ(-INFINITY, audio_utils_power_from_energy(0.f));
|
||||
EXPECT_TRUE(std::isnan(audio_utils_power_from_energy(-1.f)));
|
||||
}
|
103
android/system/media/audio_utils/tests/powerlog_tests.cpp
Normal file
103
android/system/media/audio_utils/tests/powerlog_tests.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "audio_utils_powerlog_tests"
|
||||
|
||||
#include <audio_utils/PowerLog.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
#include <log/log.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
static size_t countNewLines(const std::string &s) {
|
||||
return std::count(s.begin(), s.end(), '\n');
|
||||
}
|
||||
|
||||
TEST(audio_utils_powerlog, basic) {
|
||||
auto plog = std::make_unique<PowerLog>(
|
||||
48000 /* sampleRate */,
|
||||
1 /* channelCount */,
|
||||
AUDIO_FORMAT_PCM_16_BIT,
|
||||
100 /* entries */,
|
||||
1 /* framesPerEntry */);
|
||||
|
||||
// header
|
||||
EXPECT_EQ((size_t)1, countNewLines(plog->dumpToString()));
|
||||
|
||||
const int16_t zero = 0;
|
||||
const int16_t half = 0x4000;
|
||||
|
||||
plog->log(&half, 1 /* frame */, 0 /* nowNs */);
|
||||
plog->log(&half, 1 /* frame */, 1 /* nowNs */);
|
||||
plog->log(&half, 1 /* frame */, 2 /* nowNs */);
|
||||
|
||||
// one line / signal
|
||||
EXPECT_EQ((size_t)2, countNewLines(plog->dumpToString()));
|
||||
|
||||
plog->log(&zero, 1 /* frame */, 3 /* nowNs */);
|
||||
// zero termination doesn't change this.
|
||||
EXPECT_EQ((size_t)2, countNewLines(plog->dumpToString()));
|
||||
|
||||
// but adding next line does.
|
||||
plog->log(&half, 1 /* frame */, 4 /* nowNs */);
|
||||
EXPECT_EQ((size_t)3, countNewLines(plog->dumpToString()));
|
||||
|
||||
// truncating on lines
|
||||
EXPECT_EQ((size_t)2, countNewLines(plog->dumpToString(
|
||||
"" /* prefix */, 2 /* lines */)));
|
||||
|
||||
// truncating on time
|
||||
EXPECT_EQ((size_t)3, countNewLines(plog->dumpToString(
|
||||
"" /* prefix */, 0 /* lines */, 2 /* limitNs */)));
|
||||
EXPECT_EQ((size_t)2, countNewLines(plog->dumpToString(
|
||||
"" /* prefix */, 0 /* lines */, 3 /* limitNs */)));
|
||||
plog->dump(0 /* fd (stdout) */);
|
||||
|
||||
// The output below depends on the local time zone.
|
||||
// The indentation below is exact, check alignment.
|
||||
/*
|
||||
Signal power history:
|
||||
12-31 16:00:00.000: [ -6.0 -6.0 -6.0 ] sum(-1.2)
|
||||
12-31 16:00:00.000: [ -6.0
|
||||
*/
|
||||
}
|
||||
|
||||
TEST(audio_utils_powerlog, c) {
|
||||
power_log_t *power_log = power_log_create(
|
||||
48000 /* sample_rate */,
|
||||
1 /* channel_count */,
|
||||
AUDIO_FORMAT_PCM_16_BIT,
|
||||
100 /* entries */,
|
||||
1 /* frames_per_entry */);
|
||||
|
||||
// sanity test
|
||||
const int16_t zero = 0;
|
||||
const int16_t quarter = 0x2000;
|
||||
|
||||
power_log_log(power_log, &quarter, 1 /* frame */, 0 /* now_ns */);
|
||||
power_log_log(power_log, &zero, 1 /* frame */, 1 /* now_ns */);
|
||||
power_log_dump(power_log, 0 /* fd */, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
|
||||
power_log_destroy(power_log);
|
||||
|
||||
// This has a 2 character prefix offset from the previous test when dumping.
|
||||
// The indentation below is exact, check alignment.
|
||||
/*
|
||||
Signal power history:
|
||||
12-31 16:00:00.000: [ -12.0 ] sum(-12.0)
|
||||
*/
|
||||
}
|
691
android/system/media/audio_utils/tests/primitives_tests.cpp
Normal file
691
android/system/media/audio_utils/tests/primitives_tests.cpp
Normal file
|
@ -0,0 +1,691 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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.
|
||||
*/
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "audio_utils_primitives_tests"
|
||||
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <log/log.h>
|
||||
|
||||
#include <audio_utils/primitives.h>
|
||||
#include <audio_utils/format.h>
|
||||
#include <audio_utils/channels.h>
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
static const int32_t lim8pos = 255;
|
||||
static const int32_t lim8neg = 0;
|
||||
static const int32_t lim16pos = (1 << 15) - 1;
|
||||
static const int32_t lim16neg = -(1 << 15);
|
||||
static const int32_t lim24pos = (1 << 23) - 1;
|
||||
static const int32_t lim24neg = -(1 << 23);
|
||||
|
||||
inline void testClamp8(float f)
|
||||
{
|
||||
// f is in native u8 scaling to test rounding
|
||||
uint8_t uval = clamp8_from_float((f - 128) / (1 << 7));
|
||||
|
||||
// test clamping
|
||||
ALOGV("clamp8_from_float(%f) = %u\n", f, uval);
|
||||
if (f > lim8pos) {
|
||||
EXPECT_EQ(lim8pos, uval);
|
||||
} else if (f < lim8neg) {
|
||||
EXPECT_EQ(lim8neg, uval);
|
||||
}
|
||||
|
||||
// if in range, make sure round trip clamp and conversion is correct.
|
||||
if (f < lim8pos - 1. && f > lim8neg + 1.) {
|
||||
uint8_t uval2 = clamp8_from_float(float_from_u8(uval));
|
||||
int diff = abs(uval - uval2);
|
||||
EXPECT_LE(diff, 1);
|
||||
}
|
||||
}
|
||||
|
||||
inline void testClamp16(float f)
|
||||
{
|
||||
int16_t ival = clamp16_from_float(f / (1 << 15));
|
||||
|
||||
// test clamping
|
||||
ALOGV("clamp16_from_float(%f) = %d\n", f, ival);
|
||||
if (f > lim16pos) {
|
||||
EXPECT_EQ(lim16pos, ival);
|
||||
} else if (f < lim16neg) {
|
||||
EXPECT_EQ(lim16neg, ival);
|
||||
}
|
||||
|
||||
// if in range, make sure round trip clamp and conversion is correct.
|
||||
if (f < lim16pos - 1. && f > lim16neg + 1.) {
|
||||
int ival2 = clamp16_from_float(float_from_i16(ival));
|
||||
int diff = abs(ival - ival2);
|
||||
EXPECT_LE(diff, 1);
|
||||
}
|
||||
}
|
||||
|
||||
inline void testClamp24(float f)
|
||||
{
|
||||
int32_t ival = clamp24_from_float(f / (1 << 23));
|
||||
|
||||
// test clamping
|
||||
ALOGV("clamp24_from_float(%f) = %d\n", f, ival);
|
||||
if (f > lim24pos) {
|
||||
EXPECT_EQ(lim24pos, ival);
|
||||
} else if (f < lim24neg) {
|
||||
EXPECT_EQ(lim24neg, ival);
|
||||
}
|
||||
|
||||
// if in range, make sure round trip clamp and conversion is correct.
|
||||
if (f < lim24pos - 1. && f > lim24neg + 1.) {
|
||||
int ival2 = clamp24_from_float(float_from_q8_23(ival));
|
||||
int diff = abs(ival - ival2);
|
||||
EXPECT_LE(diff, 1);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void checkMonotone(const T *ary, size_t size)
|
||||
{
|
||||
for (size_t i = 1; i < size; ++i) {
|
||||
EXPECT_LT(ary[i-1], ary[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void checkMonotonep24(uint8_t * pary, size_t size)
|
||||
{
|
||||
size_t frames = size/3;
|
||||
for (size_t i = 1; i < frames; ++i) {
|
||||
EXPECT_LT(i32_from_p24(pary + 3*(i-1)), i32_from_p24(pary + 3*i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(audio_utils_primitives, clamp_to_int) {
|
||||
static const float testArray[] = {
|
||||
-NAN, -INFINITY,
|
||||
-1.e20, -32768., 63.9,
|
||||
-3.5, -3.4, -2.5, 2.4, -1.5, -1.4, -0.5, -0.2, 0., 0.2, 0.5, 0.8,
|
||||
1.4, 1.5, 1.8, 2.4, 2.5, 2.6, 3.4, 3.5,
|
||||
32767., 32768., 1.e20,
|
||||
INFINITY, NAN };
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
|
||||
testClamp8(testArray[i]);
|
||||
}
|
||||
for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
|
||||
testClamp16(testArray[i]);
|
||||
}
|
||||
for (size_t i = 0; i < ARRAY_SIZE(testArray); ++i) {
|
||||
testClamp24(testArray[i]);
|
||||
}
|
||||
|
||||
// used for ULP testing (tweaking the lsb of the float)
|
||||
union {
|
||||
int32_t i;
|
||||
float f;
|
||||
} val;
|
||||
int32_t res;
|
||||
|
||||
// check clampq4_27_from_float()
|
||||
val.f = 16.;
|
||||
res = clampq4_27_from_float(val.f);
|
||||
EXPECT_EQ(0x7fffffff, res);
|
||||
val.i--;
|
||||
res = clampq4_27_from_float(val.f);
|
||||
EXPECT_LE(res, 0x7fffffff);
|
||||
EXPECT_GE(res, 0x7fff0000);
|
||||
val.f = -16.;
|
||||
res = clampq4_27_from_float(val.f);
|
||||
EXPECT_EQ((int32_t)0x80000000, res); // negative
|
||||
val.i++;
|
||||
res = clampq4_27_from_float(val.f);
|
||||
EXPECT_GE(res, (int32_t)0x80000000); // negative
|
||||
EXPECT_LE(res, (int32_t)0x80008000); // negative
|
||||
|
||||
// check u4_28_from_float and u4_12_from_float
|
||||
uint32_t ures;
|
||||
uint16_t ures16;
|
||||
val.f = 16.;
|
||||
ures = u4_28_from_float(val.f);
|
||||
EXPECT_EQ(0xffffffff, ures);
|
||||
ures16 = u4_12_from_float(val.f);
|
||||
EXPECT_EQ(0xffff, ures16);
|
||||
|
||||
val.f = -1.;
|
||||
ures = u4_28_from_float(val.f);
|
||||
EXPECT_EQ((uint32_t)0, ures);
|
||||
ures16 = u4_12_from_float(val.f);
|
||||
EXPECT_EQ(0, ures16);
|
||||
|
||||
// check float_from_u4_28 and float_from_u4_12 (roundtrip)
|
||||
for (uint32_t v = 0x100000; v <= 0xff000000; v += 0x100000) {
|
||||
ures = u4_28_from_float(float_from_u4_28(v));
|
||||
EXPECT_EQ(ures, v);
|
||||
}
|
||||
for (uint32_t v = 0; v <= 0xffff; ++v) { // uint32_t prevents overflow
|
||||
ures16 = u4_12_from_float(float_from_u4_12(v));
|
||||
EXPECT_EQ(ures16, v);
|
||||
}
|
||||
|
||||
// check infinity
|
||||
EXPECT_EQ(0, clamp8_from_float(-INFINITY));
|
||||
EXPECT_EQ(255, clamp8_from_float(INFINITY));
|
||||
}
|
||||
|
||||
TEST(audio_utils_primitives, memcpy) {
|
||||
// test round-trip.
|
||||
int16_t *i16ref = new int16_t[65536];
|
||||
int16_t *i16ary = new int16_t[65536];
|
||||
int32_t *i32ary = new int32_t[65536];
|
||||
float *fary = new float[65536];
|
||||
uint8_t *pary = new uint8_t[65536*3];
|
||||
|
||||
for (size_t i = 0; i < 65536; ++i) {
|
||||
i16ref[i] = i16ary[i] = i - 32768;
|
||||
}
|
||||
|
||||
// do round-trip testing i16 and float
|
||||
memcpy_to_float_from_i16(fary, i16ary, 65536);
|
||||
memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
|
||||
checkMonotone(fary, 65536);
|
||||
|
||||
memcpy_to_i16_from_float(i16ary, fary, 65536);
|
||||
memset(fary, 0, 65536 * sizeof(fary[0]));
|
||||
checkMonotone(i16ary, 65536);
|
||||
|
||||
// TODO make a template case for the following?
|
||||
|
||||
// do round-trip testing p24 to i16 and float
|
||||
memcpy_to_p24_from_i16(pary, i16ary, 65536);
|
||||
memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
|
||||
|
||||
// check an intermediate format at a position(???)
|
||||
#if 0
|
||||
printf("pary[%d].0 = %u pary[%d].1 = %u pary[%d].2 = %u\n",
|
||||
1025, (unsigned) pary[1025*3],
|
||||
1025, (unsigned) pary[1025*3+1],
|
||||
1025, (unsigned) pary[1025*3+2]
|
||||
);
|
||||
#endif
|
||||
|
||||
memcpy_to_float_from_p24(fary, pary, 65536);
|
||||
memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
|
||||
checkMonotone(fary, 65536);
|
||||
|
||||
memcpy_to_p24_from_float(pary, fary, 65536);
|
||||
memset(fary, 0, 65536 * sizeof(fary[0]));
|
||||
|
||||
memcpy_to_i16_from_p24(i16ary, pary, 65536);
|
||||
memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
|
||||
checkMonotone(i16ary, 65536);
|
||||
|
||||
// do round-trip testing q8_23 to i16 and float
|
||||
memcpy_to_q8_23_from_i16(i32ary, i16ary, 65536);
|
||||
memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
|
||||
checkMonotone(i32ary, 65536);
|
||||
|
||||
memcpy_to_float_from_q8_23(fary, i32ary, 65536);
|
||||
memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
|
||||
checkMonotone(fary, 65536);
|
||||
|
||||
memcpy_to_q8_23_from_float_with_clamp(i32ary, fary, 65536);
|
||||
memset(fary, 0, 65536 * sizeof(fary[0]));
|
||||
checkMonotone(i32ary, 65536);
|
||||
|
||||
memcpy_to_i16_from_q8_23(i16ary, i32ary, 65536);
|
||||
memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
|
||||
checkMonotone(i16ary, 65536);
|
||||
|
||||
// do round-trip testing i32 to i16 and float
|
||||
memcpy_to_i32_from_i16(i32ary, i16ary, 65536);
|
||||
memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
|
||||
checkMonotone(i32ary, 65536);
|
||||
|
||||
memcpy_to_float_from_i32(fary, i32ary, 65536);
|
||||
memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
|
||||
checkMonotone(fary, 65536);
|
||||
|
||||
memcpy_to_i32_from_float(i32ary, fary, 65536);
|
||||
memset(fary, 0, 65536 * sizeof(fary[0]));
|
||||
checkMonotone(i32ary, 65536);
|
||||
|
||||
memcpy_to_i16_from_i32(i16ary, i32ary, 65536);
|
||||
memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
|
||||
checkMonotone(i16ary, 65536);
|
||||
|
||||
// do round-trip test i16 -> p24 -> i32 -> p24 -> q8_23 -> p24 -> i16
|
||||
memcpy_to_p24_from_i16(pary, i16ary, 65536);
|
||||
memset(i16ary, 0, 65536 * sizeof(i16ary[0]));
|
||||
checkMonotonep24(pary, 65536 * 3);
|
||||
|
||||
memcpy_to_i32_from_p24(i32ary, pary, 65536);
|
||||
memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
|
||||
checkMonotone(i32ary, 65536);
|
||||
|
||||
memcpy_to_p24_from_i32(pary, i32ary, 65536);
|
||||
memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
|
||||
checkMonotonep24(pary, 65536 * 3);
|
||||
|
||||
memcpy_to_q8_23_from_p24(i32ary, pary, 65536);
|
||||
memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
|
||||
checkMonotone(i32ary, 65536);
|
||||
|
||||
memcpy_to_p24_from_q8_23(pary, i32ary, 65536);
|
||||
memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
|
||||
checkMonotonep24(pary, 65536 * 3);
|
||||
|
||||
memcpy_to_i16_from_p24(i16ary, pary, 65536);
|
||||
memset(pary, 0, 65536 * 3 * sizeof(pary[0]));
|
||||
checkMonotone(i16ary, 65536);
|
||||
|
||||
// do partial round-trip testing q4_27 to i16 and float
|
||||
memcpy_to_float_from_i16(fary, i16ary, 65536);
|
||||
//memset(i16ary, 0, 65536 * sizeof(i16ary[0])); // not cleared: we don't do full roundtrip
|
||||
|
||||
memcpy_to_q4_27_from_float(i32ary, fary, 65536);
|
||||
memset(fary, 0, 65536 * sizeof(fary[0]));
|
||||
checkMonotone(i32ary, 65536);
|
||||
|
||||
memcpy_to_float_from_q4_27(fary, i32ary, 65536);
|
||||
memset(i32ary, 0, 65536 * sizeof(i32ary[0]));
|
||||
checkMonotone(fary, 65536);
|
||||
|
||||
// at the end, our i16ary must be the same. (Monotone should be equivalent to this)
|
||||
EXPECT_EQ(0, memcmp(i16ary, i16ref, 65536*sizeof(i16ary[0])));
|
||||
|
||||
// test round-trip for u8 and float.
|
||||
uint8_t *u8ref = new uint8_t[256];
|
||||
uint8_t *u8ary = new uint8_t[256];
|
||||
|
||||
for (unsigned i = 0; i < 256; ++i) {
|
||||
u8ref[i] = i;
|
||||
}
|
||||
|
||||
memcpy_to_float_from_u8(fary, u8ref, 256);
|
||||
memcpy_to_u8_from_float(u8ary, fary, 256);
|
||||
|
||||
EXPECT_EQ(0, memcmp(u8ary, u8ref, 256 * sizeof(u8ary[0])));
|
||||
|
||||
delete[] u8ref;
|
||||
delete[] u8ary;
|
||||
delete[] i16ref;
|
||||
delete[] i16ary;
|
||||
delete[] i32ary;
|
||||
delete[] fary;
|
||||
delete[] pary;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void checkMonotoneOrZero(const T *ary, size_t size)
|
||||
{
|
||||
T least = 0;
|
||||
|
||||
for (size_t i = 1; i < size; ++i) {
|
||||
if (ary[i]) {
|
||||
EXPECT_LT(least, ary[i]);
|
||||
least = ary[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(audio_utils_primitives, memcpy_by_channel_mask) {
|
||||
uint32_t dst_mask;
|
||||
uint32_t src_mask;
|
||||
uint16_t *u16ref = new uint16_t[65536];
|
||||
uint16_t *u16ary = new uint16_t[65536];
|
||||
|
||||
for (size_t i = 0; i < 65536; ++i) {
|
||||
u16ref[i] = i;
|
||||
}
|
||||
|
||||
// Test when src mask is 0. Everything copied is zero.
|
||||
src_mask = 0;
|
||||
dst_mask = 0x8d;
|
||||
memset(u16ary, 0x99, 65536 * sizeof(u16ref[0]));
|
||||
memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
|
||||
65536 / popcount(dst_mask));
|
||||
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(u16ary, 0, 65536 * sizeof(u16ref[0]));
|
||||
memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
|
||||
65536);
|
||||
EXPECT_EQ((size_t)0, nonZeroMono16((int16_t*)u16ary, 65530));
|
||||
|
||||
// Test when masks are the same. One to one copy.
|
||||
src_mask = dst_mask = 0x8d;
|
||||
memset(u16ary, 0x99, 65536 * sizeof(u16ref[0]));
|
||||
memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]), 555);
|
||||
EXPECT_EQ(0, memcmp(u16ary, u16ref, 555 * sizeof(u16ref[0]) * popcount(dst_mask)));
|
||||
|
||||
// Test with a gap in source:
|
||||
// Input 3 samples, output 4 samples, one zero inserted.
|
||||
src_mask = 0x8c;
|
||||
dst_mask = 0x8d;
|
||||
memset(u16ary, 0x9, 65536 * sizeof(u16ary[0]));
|
||||
memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
|
||||
65536 / popcount(dst_mask));
|
||||
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 = 0x8d;
|
||||
dst_mask = 0x8c;
|
||||
memset(u16ary, 0x9, 65536 * sizeof(u16ary[0]));
|
||||
memcpy_by_channel_mask(u16ary, dst_mask, u16ref, src_mask, sizeof(u16ref[0]),
|
||||
65536 / popcount(src_mask));
|
||||
checkMonotone(u16ary, 65536 * 3 / 4);
|
||||
|
||||
delete[] u16ref;
|
||||
delete[] u16ary;
|
||||
}
|
||||
|
||||
void memcpy_by_channel_mask2(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(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) {
|
||||
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(NULL, 0, 0x8d, 0x8c));
|
||||
EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization(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_mask2(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_mask2(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 masks are the same. One to one copy.
|
||||
src_mask = dst_mask = 0x8d;
|
||||
memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
|
||||
memcpy_by_channel_mask2(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 = 0x8c;
|
||||
dst_mask = 0x8d;
|
||||
memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
|
||||
memcpy_by_channel_mask2(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 = 0x8d;
|
||||
dst_mask = 0x8c;
|
||||
memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
|
||||
memcpy_by_channel_mask2(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;
|
||||
}
|
||||
|
||||
void memcpy_by_channel_mask_dst_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_dst_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_dst_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_dst_index(NULL, 0, 0x8d, 0x8c));
|
||||
EXPECT_EQ((size_t)3, memcpy_by_index_array_initialization_dst_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_dst_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_dst_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 dst mask equals source count size. One to one copy.
|
||||
src_mask = 0x8d;
|
||||
dst_mask = 0x0f;
|
||||
memset(u24ary, 0x99, 65536 * sizeof(u24ary[0]));
|
||||
memcpy_by_channel_mask_dst_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 = 0x8c;
|
||||
dst_mask = 0x0f;
|
||||
memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
|
||||
memcpy_by_channel_mask_dst_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 = 0x8d;
|
||||
dst_mask = 0x07;
|
||||
memset(u24ary, 0x9, 65536 * sizeof(u24ary[0]));
|
||||
memcpy_by_channel_mask_dst_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;
|
||||
}
|
||||
|
||||
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];
|
||||
uint16_t *u16ary = new uint16_t[65536];
|
||||
|
||||
// reference buffer always increases
|
||||
for (size_t i = 0; i < 65536; ++i) {
|
||||
u16ref[i] = i;
|
||||
}
|
||||
|
||||
// expand channels from stereo to quad.
|
||||
adjust_channels(u16ref /*in_buff*/, 2 /*in_channels*/,
|
||||
u16expand /*out_buff*/, 4 /*out_channels*/,
|
||||
sizeof(u16ref[0]) /*sample_size_in_bytes*/,
|
||||
sizeof(u16ref[0])*65536 /*num_in_bytes*/);
|
||||
|
||||
// expanded buffer must increase (or be zero)
|
||||
checkMonotoneOrZero(u16expand, 65536*2);
|
||||
|
||||
// contract channels back to stereo.
|
||||
adjust_channels(u16expand /*in_buff*/, 4 /*in_channels*/,
|
||||
u16ary /*out_buff*/, 2 /*out_channels*/,
|
||||
sizeof(u16expand[0]) /*sample_size_in_bytes*/,
|
||||
sizeof(u16expand[0])*65536*2 /*num_in_bytes*/);
|
||||
|
||||
// must be identical to original.
|
||||
EXPECT_EQ(0, memcmp(u16ary, u16ref, sizeof(u16ref[0])*65536));
|
||||
|
||||
delete[] u16ref;
|
||||
delete[] u16expand;
|
||||
delete[] u16ary;
|
||||
}
|
81
android/system/media/audio_utils/tests/simplelog_tests.cpp
Normal file
81
android/system/media/audio_utils/tests/simplelog_tests.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright 2017 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.
|
||||
*/
|
||||
|
||||
//#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "audio_utils_errorlog_tests"
|
||||
|
||||
#include <audio_utils/SimpleLog.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
#include <log/log.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
static size_t countNewLines(const std::string &s) {
|
||||
return std::count(s.begin(), s.end(), '\n');
|
||||
}
|
||||
|
||||
TEST(audio_utils_simplelog, basic) {
|
||||
auto slog = std::make_unique<SimpleLog>();
|
||||
const int64_t oneSecond = 1000000000;
|
||||
|
||||
EXPECT_EQ((size_t)0, countNewLines(slog->dumpToString()));
|
||||
|
||||
const int nine = 9;
|
||||
slog->log("Hello %d", nine);
|
||||
slog->log("World");
|
||||
|
||||
// two lines (no header)
|
||||
EXPECT_EQ((size_t)2, countNewLines(slog->dumpToString()));
|
||||
|
||||
// another two lines (this is out of time order, but the log doesn't care)
|
||||
slog->log(oneSecond /* nowNs */, "Hello World %d", 10);
|
||||
slog->log(oneSecond * 2 /* nowNs */, "%s", "Goodbye");
|
||||
|
||||
EXPECT_EQ((size_t)4, countNewLines(slog->dumpToString()));
|
||||
|
||||
// truncate on lines
|
||||
EXPECT_EQ((size_t)1, countNewLines(slog->dumpToString("" /* prefix */, 1 /* lines */)));
|
||||
|
||||
// truncate on time
|
||||
EXPECT_EQ((size_t)4, countNewLines(
|
||||
slog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond /* limitNs */)));
|
||||
|
||||
// truncate on time (more)
|
||||
EXPECT_EQ((size_t)3, countNewLines(
|
||||
slog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond * 2 /* limitNs */)));
|
||||
|
||||
// truncate on time (more)
|
||||
EXPECT_EQ((size_t)2, countNewLines(
|
||||
slog->dumpToString("" /* prefix */, 0 /* lines */, oneSecond * 2 + 1 /* limitNs */)));
|
||||
|
||||
std::cout << slog->dumpToString() << std::flush;
|
||||
|
||||
slog->dump(0 /* fd (stdout) */, " "); // add a prefix
|
||||
|
||||
// The output below depends on the local time zone and current time.
|
||||
// The indentation below is exact, check alignment.
|
||||
/*
|
||||
03-27 14:47:43.567 Hello 9
|
||||
03-27 14:47:43.567 World
|
||||
12-31 16:00:01.000 Hello World 10
|
||||
12-31 16:00:02.000 Goodbye
|
||||
03-27 14:47:43.567 Hello 9
|
||||
03-27 14:47:43.567 World
|
||||
12-31 16:00:01.000 Hello World 10
|
||||
12-31 16:00:02.000 Goodbye
|
||||
*/
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue