/* * Copyright 2018 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_format_tests" #include #include #include /** returns true if the format is a common source or destination format. memcpy_by_audio_format() allows interchange between any PCM format and the "common" PCM 16 bit and PCM float formats. */ static bool is_common_src_format(audio_format_t format) { return format == AUDIO_FORMAT_PCM_16_BIT || format == AUDIO_FORMAT_PCM_FLOAT; } static bool is_common_dst_format(audio_format_t format) { return format == AUDIO_FORMAT_PCM_8_BIT // Allowed for HAL to AudioRecord conversion. || format == AUDIO_FORMAT_PCM_16_BIT || format == AUDIO_FORMAT_PCM_FLOAT; } // Initialize PCM 16 bit ramp for basic data validation (generated from PCM 8 bit data). // TODO: consider creating fillPseudoRandomValue(). template static void fillRamp(int16_t(&buffer)[size]) { // Create PCM 16 bit data based on PCM 8 bit format because PCM 8 bit is convertible // to all other audio formats without loss; hence, round trip conversion preserves equality. uint8_t bytes[size]; for (size_t i = 0; i < size; ++i) { bytes[i] = i; } // convert to PCM 16 bit memcpy_by_audio_format( buffer, AUDIO_FORMAT_PCM_16_BIT, bytes, AUDIO_FORMAT_PCM_8_BIT, size); uint8_t check[size]; memcpy_by_audio_format( check, AUDIO_FORMAT_PCM_8_BIT, buffer, AUDIO_FORMAT_PCM_16_BIT, size); EXPECT_EQ(0, memcmp(check, bytes, size)); } class FormatTest : public testing::TestWithParam> { }; TEST_P(FormatTest, memcpy_by_audio_format) { // fetch parameters const auto param = GetParam(); const audio_format_t src_encoding = std::get<0>(param); const audio_format_t dst_encoding = std::get<1>(param); // either source or destination (or both) need to be a common format if (!is_common_src_format(src_encoding) && !is_common_dst_format(dst_encoding)) { printf("skip conversion src:%#x dst:%#x\n", src_encoding, dst_encoding); return; } constexpr size_t SAMPLES = UINT8_MAX; constexpr audio_format_t orig_encoding = AUDIO_FORMAT_PCM_16_BIT; int16_t orig_data[SAMPLES]; fillRamp(orig_data); // data buffer for in-place conversion (uint32_t is maximum sample size of 4 bytes) uint32_t data[SAMPLES]; // check buffer is used to compare out-of-place vs in-place conversion. uint32_t check[SAMPLES]; printf("trying conversion src:%#x dst:%#x\n", src_encoding, dst_encoding); fflush(stdout); // Copy original data to data buffer at src_encoding. memcpy_by_audio_format( data, src_encoding, orig_data, orig_encoding, SAMPLES); // Convert from src encoding to dst encoding. memcpy_by_audio_format( check, dst_encoding, data, src_encoding, SAMPLES); // Check in-place is same as out-of-place conversion. memcpy_by_audio_format( data, dst_encoding, data, src_encoding, SAMPLES); EXPECT_EQ(0, memcmp(check, data, SAMPLES * audio_bytes_per_sample(dst_encoding))); // Go back to the original data encoding for comparison. memcpy_by_audio_format( data, orig_encoding, data, dst_encoding, SAMPLES); // Raw byte compare at the original encoding must succeed - our conversions // must be lossless for PCM 8 bit representation which orig_data was constructed from. EXPECT_EQ(0, memcmp(data, orig_data, SAMPLES * audio_bytes_per_sample(orig_encoding))); } INSTANTIATE_TEST_CASE_P(FormatVariations, FormatTest, ::testing::Combine( ::testing::Values( AUDIO_FORMAT_PCM_8_BIT, AUDIO_FORMAT_PCM_16_BIT, AUDIO_FORMAT_PCM_FLOAT, AUDIO_FORMAT_PCM_24_BIT_PACKED, AUDIO_FORMAT_PCM_32_BIT, AUDIO_FORMAT_PCM_8_24_BIT ), ::testing::Values( AUDIO_FORMAT_PCM_8_BIT, AUDIO_FORMAT_PCM_16_BIT, AUDIO_FORMAT_PCM_FLOAT, AUDIO_FORMAT_PCM_24_BIT_PACKED, AUDIO_FORMAT_PCM_32_BIT, AUDIO_FORMAT_PCM_8_24_BIT )));