Loading system/audio_a2dp_hw/Android.bp +30 −9 Original line number Diff line number Diff line cc_defaults { name: "audio_a2dp_hw_defaults", defaults: ["fluoride_defaults"], include_dirs: [ "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/audio_a2dp_hw/include", ] } // Audio A2DP shared library for target // ======================================================== cc_library_shared { cc_library { name: "audio.a2dp.default", defaults: ["fluoride_defaults"], defaults: ["audio_a2dp_hw_defaults"], relative_install_path: "hw", srcs: [ "audio_a2dp_hw.cc", "audio_a2dp_hw_utils.cc", ], include_dirs: [ "packages/modules/Bluetooth/system", "src/audio_a2dp_hw.cc", "src/audio_a2dp_hw_utils.cc", ], shared_libs: [ "liblog", Loading @@ -19,8 +25,23 @@ cc_library_shared { cc_library_static { name: "libaudio-a2dp-hw-utils", defaults: ["fluoride_defaults"], defaults: ["audio_a2dp_hw_defaults"], srcs: [ "audio_a2dp_hw_utils.cc", "src/audio_a2dp_hw_utils.cc", ], } // Audio A2DP library unit tests for target and host // ======================================================== cc_test { name: "net_test_audio_a2dp_hw", test_suites: ["device-tests"], defaults: ["audio_a2dp_hw_defaults"], srcs: [ "test/audio_a2dp_hw_test.cc", ], shared_libs: [ "liblog", ], static_libs: ["audio.a2dp.default"], } system/audio_a2dp_hw/audio_a2dp_hw.h→system/audio_a2dp_hw/include/audio_a2dp_hw.h +33 −3 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ #include <stdint.h> #include <hardware/bt_av.h> /***************************************************************************** * Constants & Macros *****************************************************************************/ Loading @@ -41,9 +43,6 @@ // If one assumes the write buffer is always full during normal BT playback, // then increasing this value increases our playback latency. // // FIXME: AUDIO_STREAM_OUTPUT_BUFFER_SZ should be controlled by the actual audio // sample rate rather than being constant. // // FIXME: The BT HAL should consume data at a constant rate. // AudioFlinger assumes that the HAL draws data at a constant rate, which is // true for most audio devices; however, the BT engine reads data at a variable Loading Loading @@ -115,6 +114,37 @@ typedef uint8_t tA2DP_BITS_PER_SAMPLE; * Functions *****************************************************************************/ // Computes the Audio A2DP HAL output buffer size. // |codec_sample_rate| is the sample rate of the output stream. // |codec_bits_per_sample| is the number of bits per sample of the output // stream. // |codec_channel_mode| is the channel mode of the output stream. // // The buffer size is computed by using the following formula: // // AUDIO_STREAM_OUTPUT_BUFFER_SIZE = // (TIME_PERIOD_MS * AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * // SAMPLE_RATE_HZ * NUMBER_OF_CHANNELS * (BITS_PER_SAMPLE / 8)) / 1000 // // AUDIO_STREAM_OUTPUT_BUFFER_PERIODS controls how the socket buffer is // divided for AudioFlinger data delivery. The AudioFlinger mixer delivers // data in chunks of // (AUDIO_STREAM_OUTPUT_BUFFER_SIZE / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS) . // If the number of periods is 2, the socket buffer represents "double // buffering" of the AudioFlinger mixer buffer. // // Furthermore, the AudioFlinger expects the buffer size to be a multiple // of 16 frames. // // NOTE: Currently, the computation uses the conservative 20ms time period. // // Returns the computed buffer size. If any of the input parameters is // invalid, the return value is the default |AUDIO_STREAM_OUTPUT_BUFFER_SZ|. extern size_t audio_a2dp_hw_stream_compute_buffer_size( btav_a2dp_codec_sample_rate_t codec_sample_rate, btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample, btav_a2dp_codec_channel_mode_t codec_channel_mode); // Returns a string representation of |event|. extern const char* audio_a2dp_hw_dump_ctrl_event(tA2DP_CTRL_CMD event); Loading system/audio_a2dp_hw/audio_a2dp_hw.cc→system/audio_a2dp_hw/src/audio_a2dp_hw.cc +3 −13 Original line number Diff line number Diff line Loading @@ -40,7 +40,6 @@ #include <mutex> #include <hardware/audio.h> #include <hardware/bt_av.h> #include <hardware/hardware.h> #include <system/audio.h> Loading Loading @@ -150,10 +149,6 @@ struct a2dp_stream_in { *****************************************************************************/ static size_t out_get_buffer_size(const struct audio_stream* stream); static size_t audio_stream_compute_buffer_size( btav_a2dp_codec_sample_rate_t codec_sample_rate, btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample, btav_a2dp_codec_channel_mode_t codec_channel_mode); /***************************************************************************** * Externs Loading Loading @@ -611,7 +606,7 @@ static int a2dp_read_output_audio_config( common->cfg.rate = stream_config.rate; common->cfg.channel_mask = stream_config.channel_mask; common->cfg.format = stream_config.format; common->buffer_sz = audio_stream_compute_buffer_size( common->buffer_sz = audio_a2dp_hw_stream_compute_buffer_size( codec_config->sample_rate, codec_config->bits_per_sample, codec_config->channel_mode); } Loading Loading @@ -922,24 +917,19 @@ static size_t out_get_buffer_size(const struct audio_stream* stream) { // period_size is the AudioFlinger mixer buffer size. const size_t period_size = out->common.buffer_sz / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS; const size_t mixer_unit_size = 16 /* frames */ * 4 /* framesize */; DEBUG("socket buffer size: %zu period size: %zu", out->common.buffer_sz, period_size); if (period_size % mixer_unit_size != 0) { ERROR("period size %zu not a multiple of %zu", period_size, mixer_unit_size); } return period_size; } static size_t audio_stream_compute_buffer_size( size_t audio_a2dp_hw_stream_compute_buffer_size( btav_a2dp_codec_sample_rate_t codec_sample_rate, btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample, btav_a2dp_codec_channel_mode_t codec_channel_mode) { size_t buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ; // Default value const uint32_t time_period_ms = 20; // Conservative 20ms const uint64_t time_period_ms = 20; // Conservative 20ms uint32_t sample_rate; uint32_t bits_per_sample; uint32_t number_of_channels; Loading system/audio_a2dp_hw/audio_a2dp_hw_utils.cc→system/audio_a2dp_hw/src/audio_a2dp_hw_utils.cc +0 −0 File moved. View file system/audio_a2dp_hw/test/audio_a2dp_hw_test.cc 0 → 100644 +142 −0 Original line number Diff line number Diff line /****************************************************************************** * * Copyright (C) 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. * ******************************************************************************/ #include <gtest/gtest.h> #include "audio_a2dp_hw/include/audio_a2dp_hw.h" namespace { static uint32_t codec_sample_rate2value( btav_a2dp_codec_sample_rate_t codec_sample_rate) { switch (codec_sample_rate) { case BTAV_A2DP_CODEC_SAMPLE_RATE_44100: return 44100; case BTAV_A2DP_CODEC_SAMPLE_RATE_48000: return 48000; case BTAV_A2DP_CODEC_SAMPLE_RATE_88200: return 88200; case BTAV_A2DP_CODEC_SAMPLE_RATE_96000: return 96000; case BTAV_A2DP_CODEC_SAMPLE_RATE_176400: return 176400; case BTAV_A2DP_CODEC_SAMPLE_RATE_192000: return 192000; case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE: break; } return 0; } static uint32_t codec_bits_per_sample2value( btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample) { switch (codec_bits_per_sample) { case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16: return 16; case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24: return 24; case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32: return 32; case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE: break; } return 0; } static uint32_t codec_channel_mode2value( btav_a2dp_codec_channel_mode_t codec_channel_mode) { switch (codec_channel_mode) { case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO: return 1; case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO: return 2; case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE: break; } return 0; } } // namespace class AudioA2dpHwTest : public ::testing::Test { protected: AudioA2dpHwTest() {} private: }; TEST_F(AudioA2dpHwTest, test_compute_buffer_size) { const btav_a2dp_codec_sample_rate_t codec_sample_rate_array[] = { BTAV_A2DP_CODEC_SAMPLE_RATE_NONE, BTAV_A2DP_CODEC_SAMPLE_RATE_44100, BTAV_A2DP_CODEC_SAMPLE_RATE_48000, BTAV_A2DP_CODEC_SAMPLE_RATE_88200, BTAV_A2DP_CODEC_SAMPLE_RATE_96000, BTAV_A2DP_CODEC_SAMPLE_RATE_176400, BTAV_A2DP_CODEC_SAMPLE_RATE_192000}; const btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample_array[] = { BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE, BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16, BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24, BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32}; const btav_a2dp_codec_channel_mode_t codec_channel_mode_array[] = { BTAV_A2DP_CODEC_CHANNEL_MODE_NONE, BTAV_A2DP_CODEC_CHANNEL_MODE_MONO, BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO}; for (const auto codec_sample_rate : codec_sample_rate_array) { for (const auto codec_bits_per_sample : codec_bits_per_sample_array) { for (const auto codec_channel_mode : codec_channel_mode_array) { size_t buffer_size = audio_a2dp_hw_stream_compute_buffer_size( codec_sample_rate, codec_bits_per_sample, codec_channel_mode); // Check for invalid input if ((codec_sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) || (codec_bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) || (codec_channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE)) { EXPECT_EQ(buffer_size, static_cast<size_t>(AUDIO_STREAM_OUTPUT_BUFFER_SZ)); continue; } uint32_t sample_rate = codec_sample_rate2value(codec_sample_rate); EXPECT_TRUE(sample_rate != 0); uint32_t bits_per_sample = codec_bits_per_sample2value(codec_bits_per_sample); EXPECT_TRUE(bits_per_sample != 0); uint32_t number_of_channels = codec_channel_mode2value(codec_channel_mode); EXPECT_TRUE(number_of_channels != 0); const uint64_t time_period_ms = 20; // TODO: Must be a parameter size_t expected_buffer_size = (time_period_ms * AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * sample_rate * number_of_channels * (bits_per_sample / 8)) / 1000; // Compute the divisor and adjust the buffer size const size_t divisor = (AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * 16 * number_of_channels * bits_per_sample) / 8; const size_t remainder = expected_buffer_size % divisor; if (remainder != 0) { expected_buffer_size += divisor - remainder; } EXPECT_EQ(buffer_size, expected_buffer_size); } } } } Loading
system/audio_a2dp_hw/Android.bp +30 −9 Original line number Diff line number Diff line cc_defaults { name: "audio_a2dp_hw_defaults", defaults: ["fluoride_defaults"], include_dirs: [ "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/audio_a2dp_hw/include", ] } // Audio A2DP shared library for target // ======================================================== cc_library_shared { cc_library { name: "audio.a2dp.default", defaults: ["fluoride_defaults"], defaults: ["audio_a2dp_hw_defaults"], relative_install_path: "hw", srcs: [ "audio_a2dp_hw.cc", "audio_a2dp_hw_utils.cc", ], include_dirs: [ "packages/modules/Bluetooth/system", "src/audio_a2dp_hw.cc", "src/audio_a2dp_hw_utils.cc", ], shared_libs: [ "liblog", Loading @@ -19,8 +25,23 @@ cc_library_shared { cc_library_static { name: "libaudio-a2dp-hw-utils", defaults: ["fluoride_defaults"], defaults: ["audio_a2dp_hw_defaults"], srcs: [ "audio_a2dp_hw_utils.cc", "src/audio_a2dp_hw_utils.cc", ], } // Audio A2DP library unit tests for target and host // ======================================================== cc_test { name: "net_test_audio_a2dp_hw", test_suites: ["device-tests"], defaults: ["audio_a2dp_hw_defaults"], srcs: [ "test/audio_a2dp_hw_test.cc", ], shared_libs: [ "liblog", ], static_libs: ["audio.a2dp.default"], }
system/audio_a2dp_hw/audio_a2dp_hw.h→system/audio_a2dp_hw/include/audio_a2dp_hw.h +33 −3 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ #include <stdint.h> #include <hardware/bt_av.h> /***************************************************************************** * Constants & Macros *****************************************************************************/ Loading @@ -41,9 +43,6 @@ // If one assumes the write buffer is always full during normal BT playback, // then increasing this value increases our playback latency. // // FIXME: AUDIO_STREAM_OUTPUT_BUFFER_SZ should be controlled by the actual audio // sample rate rather than being constant. // // FIXME: The BT HAL should consume data at a constant rate. // AudioFlinger assumes that the HAL draws data at a constant rate, which is // true for most audio devices; however, the BT engine reads data at a variable Loading Loading @@ -115,6 +114,37 @@ typedef uint8_t tA2DP_BITS_PER_SAMPLE; * Functions *****************************************************************************/ // Computes the Audio A2DP HAL output buffer size. // |codec_sample_rate| is the sample rate of the output stream. // |codec_bits_per_sample| is the number of bits per sample of the output // stream. // |codec_channel_mode| is the channel mode of the output stream. // // The buffer size is computed by using the following formula: // // AUDIO_STREAM_OUTPUT_BUFFER_SIZE = // (TIME_PERIOD_MS * AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * // SAMPLE_RATE_HZ * NUMBER_OF_CHANNELS * (BITS_PER_SAMPLE / 8)) / 1000 // // AUDIO_STREAM_OUTPUT_BUFFER_PERIODS controls how the socket buffer is // divided for AudioFlinger data delivery. The AudioFlinger mixer delivers // data in chunks of // (AUDIO_STREAM_OUTPUT_BUFFER_SIZE / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS) . // If the number of periods is 2, the socket buffer represents "double // buffering" of the AudioFlinger mixer buffer. // // Furthermore, the AudioFlinger expects the buffer size to be a multiple // of 16 frames. // // NOTE: Currently, the computation uses the conservative 20ms time period. // // Returns the computed buffer size. If any of the input parameters is // invalid, the return value is the default |AUDIO_STREAM_OUTPUT_BUFFER_SZ|. extern size_t audio_a2dp_hw_stream_compute_buffer_size( btav_a2dp_codec_sample_rate_t codec_sample_rate, btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample, btav_a2dp_codec_channel_mode_t codec_channel_mode); // Returns a string representation of |event|. extern const char* audio_a2dp_hw_dump_ctrl_event(tA2DP_CTRL_CMD event); Loading
system/audio_a2dp_hw/audio_a2dp_hw.cc→system/audio_a2dp_hw/src/audio_a2dp_hw.cc +3 −13 Original line number Diff line number Diff line Loading @@ -40,7 +40,6 @@ #include <mutex> #include <hardware/audio.h> #include <hardware/bt_av.h> #include <hardware/hardware.h> #include <system/audio.h> Loading Loading @@ -150,10 +149,6 @@ struct a2dp_stream_in { *****************************************************************************/ static size_t out_get_buffer_size(const struct audio_stream* stream); static size_t audio_stream_compute_buffer_size( btav_a2dp_codec_sample_rate_t codec_sample_rate, btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample, btav_a2dp_codec_channel_mode_t codec_channel_mode); /***************************************************************************** * Externs Loading Loading @@ -611,7 +606,7 @@ static int a2dp_read_output_audio_config( common->cfg.rate = stream_config.rate; common->cfg.channel_mask = stream_config.channel_mask; common->cfg.format = stream_config.format; common->buffer_sz = audio_stream_compute_buffer_size( common->buffer_sz = audio_a2dp_hw_stream_compute_buffer_size( codec_config->sample_rate, codec_config->bits_per_sample, codec_config->channel_mode); } Loading Loading @@ -922,24 +917,19 @@ static size_t out_get_buffer_size(const struct audio_stream* stream) { // period_size is the AudioFlinger mixer buffer size. const size_t period_size = out->common.buffer_sz / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS; const size_t mixer_unit_size = 16 /* frames */ * 4 /* framesize */; DEBUG("socket buffer size: %zu period size: %zu", out->common.buffer_sz, period_size); if (period_size % mixer_unit_size != 0) { ERROR("period size %zu not a multiple of %zu", period_size, mixer_unit_size); } return period_size; } static size_t audio_stream_compute_buffer_size( size_t audio_a2dp_hw_stream_compute_buffer_size( btav_a2dp_codec_sample_rate_t codec_sample_rate, btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample, btav_a2dp_codec_channel_mode_t codec_channel_mode) { size_t buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ; // Default value const uint32_t time_period_ms = 20; // Conservative 20ms const uint64_t time_period_ms = 20; // Conservative 20ms uint32_t sample_rate; uint32_t bits_per_sample; uint32_t number_of_channels; Loading
system/audio_a2dp_hw/audio_a2dp_hw_utils.cc→system/audio_a2dp_hw/src/audio_a2dp_hw_utils.cc +0 −0 File moved. View file
system/audio_a2dp_hw/test/audio_a2dp_hw_test.cc 0 → 100644 +142 −0 Original line number Diff line number Diff line /****************************************************************************** * * Copyright (C) 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. * ******************************************************************************/ #include <gtest/gtest.h> #include "audio_a2dp_hw/include/audio_a2dp_hw.h" namespace { static uint32_t codec_sample_rate2value( btav_a2dp_codec_sample_rate_t codec_sample_rate) { switch (codec_sample_rate) { case BTAV_A2DP_CODEC_SAMPLE_RATE_44100: return 44100; case BTAV_A2DP_CODEC_SAMPLE_RATE_48000: return 48000; case BTAV_A2DP_CODEC_SAMPLE_RATE_88200: return 88200; case BTAV_A2DP_CODEC_SAMPLE_RATE_96000: return 96000; case BTAV_A2DP_CODEC_SAMPLE_RATE_176400: return 176400; case BTAV_A2DP_CODEC_SAMPLE_RATE_192000: return 192000; case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE: break; } return 0; } static uint32_t codec_bits_per_sample2value( btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample) { switch (codec_bits_per_sample) { case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16: return 16; case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24: return 24; case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32: return 32; case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE: break; } return 0; } static uint32_t codec_channel_mode2value( btav_a2dp_codec_channel_mode_t codec_channel_mode) { switch (codec_channel_mode) { case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO: return 1; case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO: return 2; case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE: break; } return 0; } } // namespace class AudioA2dpHwTest : public ::testing::Test { protected: AudioA2dpHwTest() {} private: }; TEST_F(AudioA2dpHwTest, test_compute_buffer_size) { const btav_a2dp_codec_sample_rate_t codec_sample_rate_array[] = { BTAV_A2DP_CODEC_SAMPLE_RATE_NONE, BTAV_A2DP_CODEC_SAMPLE_RATE_44100, BTAV_A2DP_CODEC_SAMPLE_RATE_48000, BTAV_A2DP_CODEC_SAMPLE_RATE_88200, BTAV_A2DP_CODEC_SAMPLE_RATE_96000, BTAV_A2DP_CODEC_SAMPLE_RATE_176400, BTAV_A2DP_CODEC_SAMPLE_RATE_192000}; const btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample_array[] = { BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE, BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16, BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24, BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32}; const btav_a2dp_codec_channel_mode_t codec_channel_mode_array[] = { BTAV_A2DP_CODEC_CHANNEL_MODE_NONE, BTAV_A2DP_CODEC_CHANNEL_MODE_MONO, BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO}; for (const auto codec_sample_rate : codec_sample_rate_array) { for (const auto codec_bits_per_sample : codec_bits_per_sample_array) { for (const auto codec_channel_mode : codec_channel_mode_array) { size_t buffer_size = audio_a2dp_hw_stream_compute_buffer_size( codec_sample_rate, codec_bits_per_sample, codec_channel_mode); // Check for invalid input if ((codec_sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) || (codec_bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) || (codec_channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE)) { EXPECT_EQ(buffer_size, static_cast<size_t>(AUDIO_STREAM_OUTPUT_BUFFER_SZ)); continue; } uint32_t sample_rate = codec_sample_rate2value(codec_sample_rate); EXPECT_TRUE(sample_rate != 0); uint32_t bits_per_sample = codec_bits_per_sample2value(codec_bits_per_sample); EXPECT_TRUE(bits_per_sample != 0); uint32_t number_of_channels = codec_channel_mode2value(codec_channel_mode); EXPECT_TRUE(number_of_channels != 0); const uint64_t time_period_ms = 20; // TODO: Must be a parameter size_t expected_buffer_size = (time_period_ms * AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * sample_rate * number_of_channels * (bits_per_sample / 8)) / 1000; // Compute the divisor and adjust the buffer size const size_t divisor = (AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * 16 * number_of_channels * bits_per_sample) / 8; const size_t remainder = expected_buffer_size % divisor; if (remainder != 0) { expected_buffer_size += divisor - remainder; } EXPECT_EQ(buffer_size, expected_buffer_size); } } } }