// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include extern "C" { #include "cras_mix.h" #include "cras_shm.h" #include "cras_types.h" } namespace { static const size_t kBufferFrames = 8192; static const size_t kNumChannels = 2; static const size_t kNumSamples = kBufferFrames * kNumChannels; static const float kMaxVolumeToScale = 0.9999999; static const float kMinVolumeToScale = 0.0000001; static inline int need_to_scale(float scaler) { return (scaler < 0.99 || scaler > 1.01); } class MixTestSuiteS16_LE : public testing::Test { protected: virtual void SetUp() { fmt_ = SND_PCM_FORMAT_S16_LE; mix_buffer_ = (int16_t*)malloc(kBufferFrames * 4); src_buffer_ = static_cast( calloc(1, kBufferFrames * 4 + sizeof(cras_audio_shm_header))); for (size_t i = 0; i < kBufferFrames * 2; i++) { src_buffer_[i] = i; mix_buffer_[i] = -i; } compare_buffer_ = (int16_t*)malloc(kBufferFrames * 4); } virtual void TearDown() { free(mix_buffer_); free(compare_buffer_); free(src_buffer_); } void _SetupBuffer() { for (size_t i = 0; i < kBufferFrames; i++) { src_buffer_[i] = i + (INT16_MAX >> 2); mix_buffer_[i] = i + (INT16_MAX >> 2); compare_buffer_[i] = mix_buffer_[i]; } for (size_t i = kBufferFrames; i < kBufferFrames * 2; i++) { src_buffer_[i] = i - (INT16_MAX >> 2); mix_buffer_[i] = i - (INT16_MAX >> 2); compare_buffer_[i] = mix_buffer_[i]; } } void TestScaleStride(float scaler) { _SetupBuffer(); for (size_t i = 0; i < kBufferFrames * 2; i += 2) { int32_t tmp; if (need_to_scale(scaler)) tmp = mix_buffer_[i] + src_buffer_[i / 2] * scaler; else tmp = mix_buffer_[i] + src_buffer_[i / 2]; if (tmp > INT16_MAX) tmp = INT16_MAX; else if (tmp < INT16_MIN) tmp = INT16_MIN; compare_buffer_[i] = tmp; } cras_mix_add_scale_stride(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kBufferFrames, 4, 2, scaler); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } void ScaleIncrement(float start_scaler, float increment, float target) { float scaler = start_scaler; for (size_t i = 0; i < kBufferFrames * 2; i++) { float applied_scaler = scaler; if ((applied_scaler > target && increment > 0) || (applied_scaler < target && increment < 0)) applied_scaler = target; if (applied_scaler > kMaxVolumeToScale) { } else if (applied_scaler < kMinVolumeToScale) { compare_buffer_[i] = 0; } else { compare_buffer_[i] = mix_buffer_[i] * applied_scaler; } if (i % 2 == 1) scaler += increment; } } int16_t* mix_buffer_; int16_t* src_buffer_; int16_t* compare_buffer_; snd_pcm_format_t fmt_; }; TEST_F(MixTestSuiteS16_LE, MixFirst) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); EXPECT_EQ(0, memcmp(mix_buffer_, src_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, MixTwo) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 1, 0, 1.0); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = src_buffer_[i] * 2; EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, MixTwoClip) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); for (size_t i = 0; i < kBufferFrames * 2; i++) src_buffer_[i] = INT16_MAX; cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 1, 0, 1.0); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = INT16_MAX; EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, MixFirstMuted) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 1, 1.0); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = 0; EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, MixFirstZeroVolume) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 0.0); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = 0; EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, MixFirstHalfVolume) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 0.5); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = src_buffer_[i] * 0.5; EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, MixTwoSecondHalfVolume) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 1, 0, 0.5); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = src_buffer_[i] + (int16_t)(src_buffer_[i] * 0.5); EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, ScaleFullVolumeIncrement) { float increment = 0.01; int step = 2; float start_scaler = 0.999999999; float target = 1.0; _SetupBuffer(); // Scale full volume with positive increment will not change buffer. memcpy(compare_buffer_, src_buffer_, kBufferFrames * 4); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, ScaleMinVolumeIncrement) { float increment = -0.01; int step = 2; float start_scaler = 0.000000001; float target = 0.0; _SetupBuffer(); // Scale min volume with negative increment will change buffer to zeros. memset(compare_buffer_, 0, kBufferFrames * 4); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, ScaleVolumePositiveIncrement) { float increment = 0.0001; int step = 2; float start_scaler = 0.1; float target = 1.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, ScaleVolumeNegativeIncrement) { float increment = -0.0001; int step = 2; float start_scaler = 0.8; float target = 0.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, ScaleVolumeStartFullNegativeIncrement) { float increment = -0.0001; int step = 2; float start_scaler = 1.0; float target = 0.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, ScaleVolumeStartZeroPositiveIncrement) { float increment = 0.0001; int step = 2; float start_scaler = 0.0; float target = 1.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, ScaleVolumePositiveIncrementCappedByTarget) { float increment = 0.0001; int step = 2; float start_scaler = 0.1; float target = 0.5; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, ScaleVolumeNegativeIncrementCappedByTarget) { float increment = -0.01; int step = 2; float start_scaler = 0.8; float target = 0.5; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, ScaleFullVolume) { memcpy(compare_buffer_, src_buffer_, kBufferFrames * 4); cras_scale_buffer(fmt_, (uint8_t*)mix_buffer_, kNumSamples, 0.999999999); EXPECT_EQ(0, memcmp(compare_buffer_, src_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, ScaleMinVolume) { memset(compare_buffer_, 0, kBufferFrames * 4); cras_scale_buffer(fmt_, (uint8_t*)src_buffer_, kNumSamples, 0.0000000001); EXPECT_EQ(0, memcmp(compare_buffer_, src_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, ScaleHalfVolume) { for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = src_buffer_[i] * 0.5; cras_scale_buffer(fmt_, (uint8_t*)src_buffer_, kNumSamples, 0.5); EXPECT_EQ(0, memcmp(compare_buffer_, src_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS16_LE, StrideCopy) { TestScaleStride(1.0); TestScaleStride(100); TestScaleStride(0.5); } class MixTestSuiteS24_LE : public testing::Test { protected: virtual void SetUp() { fmt_ = SND_PCM_FORMAT_S24_LE; fr_bytes_ = 4 * kNumChannels; mix_buffer_ = (int32_t*)malloc(kBufferFrames * fr_bytes_); src_buffer_ = static_cast( calloc(1, kBufferFrames * fr_bytes_ + sizeof(cras_audio_shm_header))); for (size_t i = 0; i < kBufferFrames * 2; i++) { src_buffer_[i] = i; mix_buffer_[i] = -i; } compare_buffer_ = (int32_t*)malloc(kBufferFrames * fr_bytes_); } virtual void TearDown() { free(mix_buffer_); free(compare_buffer_); free(src_buffer_); } void _SetupBuffer() { for (size_t i = 0; i < kBufferFrames; i++) { src_buffer_[i] = i + (0x007fffff >> 2); mix_buffer_[i] = i + (0x007fffff >> 2); compare_buffer_[i] = mix_buffer_[i]; } for (size_t i = kBufferFrames; i < kBufferFrames * 2; i++) { src_buffer_[i] = -i - (0x007fffff >> 2); mix_buffer_[i] = -i - (0x007fffff >> 2); compare_buffer_[i] = mix_buffer_[i]; } } void TestScaleStride(float scaler) { _SetupBuffer(); for (size_t i = 0; i < kBufferFrames * 2; i += 2) { int32_t tmp; if (need_to_scale(scaler)) tmp = mix_buffer_[i] + Scale(src_buffer_[i / 2], scaler); else tmp = mix_buffer_[i] + src_buffer_[i / 2]; if (tmp > 0x007fffff) tmp = 0x007fffff; else if (tmp < (int32_t)0xff800000) tmp = (int32_t)0xff800000; compare_buffer_[i] = tmp; } cras_mix_add_scale_stride(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kBufferFrames, 8, 4, scaler); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 8)); } void ScaleIncrement(float start_scaler, float increment, float target) { float scaler = start_scaler; for (size_t i = 0; i < kBufferFrames * 2; i++) { float applied_scaler = scaler; if ((applied_scaler > target && increment > 0) || (applied_scaler < target && increment < 0)) applied_scaler = target; if (applied_scaler > kMaxVolumeToScale) { } else if (applied_scaler < kMinVolumeToScale) { compare_buffer_[i] = 0; } else { compare_buffer_[i] = Scale(mix_buffer_[i], applied_scaler); } if (i % 2 == 1) scaler += increment; } } int32_t Scale(int32_t value, float scaler) { value = ((uint32_t)(value & 0x00ffffff)) << 8; value *= scaler; return (value >> 8) & 0x00ffffff; } int32_t* mix_buffer_; int32_t* src_buffer_; int32_t* compare_buffer_; snd_pcm_format_t fmt_; unsigned int fr_bytes_; }; TEST_F(MixTestSuiteS24_LE, MixFirst) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); EXPECT_EQ(0, memcmp(mix_buffer_, src_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, MixTwo) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 1, 0, 1.0); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = Scale(src_buffer_[i], 2); EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, MixTwoClip) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); for (size_t i = 0; i < kBufferFrames * 2; i++) src_buffer_[i] = 0x007fffff; cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 1, 0, 1.0); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = 0x007fffff; EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, MixFirstMuted) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 1, 1.0); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = 0; EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, MixFirstZeroVolume) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 0.0); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = 0; EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, MixFirstHalfVolume) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 0.5); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = Scale(src_buffer_[i], 0.5); EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, MixTwoSecondHalfVolume) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 1, 0, 0.5); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = src_buffer_[i] + Scale(src_buffer_[i], 0.5); EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, ScaleFullVolumeIncrement) { float increment = 0.01; int step = 2; float start_scaler = 0.999999999; float target = 1.0; _SetupBuffer(); // Scale full volume with positive increment will not change buffer. memcpy(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, ScaleMinVolumeIncrement) { float increment = -0.01; int step = 2; float start_scaler = 0.000000001; float target = 0.0; _SetupBuffer(); // Scale min volume with negative increment will change buffer to zeros. memset(compare_buffer_, 0, kBufferFrames * fr_bytes_); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, ScaleVolumePositiveIncrement) { float increment = 0.0001; int step = 2; float start_scaler = 0.1; float target = 1.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, ScaleVolumeNegativeIncrement) { float increment = -0.0001; int step = 2; float start_scaler = 0.8; float target = 0.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, ScaleVolumeStartFullNegativeIncrement) { float increment = -0.0001; int step = 2; float start_scaler = 1.0; float target = 0.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS24_LE, ScaleVolumeStartZeroPositiveIncrement) { float increment = 0.0001; int step = 2; float start_scaler = 0.0; float target = 1.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS24_LE, ScaleVolumePositiveIncrementCappedByTarget) { float increment = 0.0001; int step = 2; float start_scaler = 0.1; float target = 0.5; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, ScaleVolumeNegativeIncrementCappedByTarget) { float increment = -0.01; int step = 2; float start_scaler = 0.8; float target = 0.5; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, ScaleFullVolume) { memcpy(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_); cras_scale_buffer(fmt_, (uint8_t*)mix_buffer_, kNumSamples, 0.999999999); EXPECT_EQ(0, memcmp(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, ScaleMinVolume) { memset(compare_buffer_, 0, kBufferFrames * fr_bytes_); cras_scale_buffer(fmt_, (uint8_t*)src_buffer_, kNumSamples, 0.0000000001); EXPECT_EQ(0, memcmp(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, ScaleHalfVolume) { for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = Scale(src_buffer_[i], 0.5); cras_scale_buffer(fmt_, (uint8_t*)src_buffer_, kNumSamples, 0.5); EXPECT_EQ(0, memcmp(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_LE, StrideCopy) { TestScaleStride(1.0); TestScaleStride(100); TestScaleStride(0.1); } class MixTestSuiteS32_LE : public testing::Test { protected: virtual void SetUp() { fmt_ = SND_PCM_FORMAT_S32_LE; fr_bytes_ = 4 * kNumChannels; mix_buffer_ = (int32_t*)malloc(kBufferFrames * fr_bytes_); src_buffer_ = static_cast( calloc(1, kBufferFrames * fr_bytes_ + sizeof(cras_audio_shm_header))); for (size_t i = 0; i < kBufferFrames * 2; i++) { src_buffer_[i] = i; mix_buffer_[i] = -i; } compare_buffer_ = (int32_t*)malloc(kBufferFrames * fr_bytes_); } virtual void TearDown() { free(mix_buffer_); free(compare_buffer_); free(src_buffer_); } void _SetupBuffer() { for (size_t i = 0; i < kBufferFrames; i++) { src_buffer_[i] = i + (INT32_MAX >> 2); mix_buffer_[i] = i + (INT32_MAX >> 2); compare_buffer_[i] = mix_buffer_[i]; } for (size_t i = kBufferFrames; i < kBufferFrames * 2; i++) { src_buffer_[i] = i - (INT32_MAX >> 2); mix_buffer_[i] = i - (INT32_MAX >> 2); compare_buffer_[i] = mix_buffer_[i]; } } void TestScaleStride(float scaler) { _SetupBuffer(); for (size_t i = 0; i < kBufferFrames * 2; i += 2) { int64_t tmp; if (need_to_scale(scaler)) tmp = mix_buffer_[i] + src_buffer_[i / 2] * scaler; else tmp = mix_buffer_[i] + src_buffer_[i / 2]; if (tmp > INT32_MAX) tmp = INT32_MAX; else if (tmp < INT32_MIN) tmp = INT32_MIN; compare_buffer_[i] = tmp; } cras_mix_add_scale_stride(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kBufferFrames, 8, 4, scaler); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 8)); } void ScaleIncrement(float start_scaler, float increment, float target) { float scaler = start_scaler; for (size_t i = 0; i < kBufferFrames * 2; i++) { float applied_scaler = scaler; if ((applied_scaler > target && increment > 0) || (applied_scaler < target && increment < 0)) applied_scaler = target; if (applied_scaler > kMaxVolumeToScale) { } else if (applied_scaler < kMinVolumeToScale) { compare_buffer_[i] = 0; } else { compare_buffer_[i] = mix_buffer_[i] * applied_scaler; } if (i % 2 == 1) scaler += increment; } } int32_t* mix_buffer_; int32_t* src_buffer_; int32_t* compare_buffer_; snd_pcm_format_t fmt_; unsigned int fr_bytes_; }; TEST_F(MixTestSuiteS32_LE, MixFirst) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); EXPECT_EQ(0, memcmp(mix_buffer_, src_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, MixTwo) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 1, 0, 1.0); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = src_buffer_[i] * 2; EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, MixTwoClip) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); for (size_t i = 0; i < kBufferFrames * 2; i++) src_buffer_[i] = INT32_MAX; cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 1, 0, 1.0); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = INT32_MAX; EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, MixFirstMuted) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 1, 1.0); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = 0; EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, MixFirstZeroVolume) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 0.0); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = 0; EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, MixFirstHalfVolume) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 0.5); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = src_buffer_[i] * 0.5; EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, MixTwoSecondHalfVolume) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 1, 0, 0.5); for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = src_buffer_[i] + (int32_t)(src_buffer_[i] * 0.5); EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, ScaleFullVolumeIncrement) { float increment = 0.01; int step = 2; float start_scaler = 0.999999999; float target = 1.0; _SetupBuffer(); // Scale full volume with positive increment will not change buffer. memcpy(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, ScaleMinVolumeIncrement) { float increment = -0.01; int step = 2; float start_scaler = 0.000000001; float target = 0.0; _SetupBuffer(); // Scale min volume with negative increment will change buffer to zeros. memset(compare_buffer_, 0, kBufferFrames * fr_bytes_); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, ScaleVolumePositiveIncrement) { float increment = 0.0001; int step = 2; float start_scaler = 0.1; float target = 1.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, ScaleVolumeNegativeIncrement) { float increment = -0.0001; int step = 2; float start_scaler = 0.8; float target = 0.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, ScaleVolumeStartFullNegativeIncrement) { float increment = -0.0001; int step = 2; float start_scaler = 1.0; float target = 0.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS32_LE, ScaleVolumeStartZeroPositiveIncrement) { float increment = 0.0001; int step = 2; float start_scaler = 0.0; float target = 1.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS32_LE, ScaleVolumePositiveIncrementCappedByTarget) { float increment = 0.0001; int step = 2; float start_scaler = 0.1; float target = 0.5; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, ScaleVolumeNegativeIncrementCappedByTarget) { float increment = -0.01; int step = 2; float start_scaler = 0.8; float target = 0.5; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, ScaleFullVolume) { memcpy(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_); cras_scale_buffer(fmt_, (uint8_t*)mix_buffer_, kNumSamples, 0.999999999); EXPECT_EQ(0, memcmp(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, ScaleMinVolume) { memset(compare_buffer_, 0, kBufferFrames * fr_bytes_); cras_scale_buffer(fmt_, (uint8_t*)src_buffer_, kNumSamples, 0.0000000001); EXPECT_EQ(0, memcmp(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, ScaleHalfVolume) { for (size_t i = 0; i < kBufferFrames * 2; i++) compare_buffer_[i] = src_buffer_[i] * 0.5; cras_scale_buffer(fmt_, (uint8_t*)src_buffer_, kNumSamples, 0.5); EXPECT_EQ(0, memcmp(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS32_LE, StrideCopy) { TestScaleStride(1.0); TestScaleStride(100); TestScaleStride(0.1); } class MixTestSuiteS24_3LE : public testing::Test { protected: virtual void SetUp() { fmt_ = SND_PCM_FORMAT_S24_3LE; fr_bytes_ = 3 * kNumChannels; mix_buffer_ = (uint8_t*)malloc(kBufferFrames * fr_bytes_); src_buffer_ = static_cast( calloc(1, kBufferFrames * fr_bytes_ + sizeof(cras_audio_shm_header))); for (size_t i = 0; i < kBufferFrames * kNumChannels; i++) { memcpy(src_buffer_ + 3 * i, &i, 3); int32_t tmp = -i * 256; memcpy(mix_buffer_ + 3 * i, (uint8_t*)&tmp + 1, 3); } compare_buffer_ = (uint8_t*)malloc(kBufferFrames * fr_bytes_); } virtual void TearDown() { free(mix_buffer_); free(compare_buffer_); free(src_buffer_); } void _SetupBuffer() { memset(compare_buffer_, 0, kBufferFrames * fr_bytes_); for (size_t i = 0; i < kBufferFrames; i++) { int32_t tmp = (i << 8) + (INT32_MAX >> 2); memcpy(src_buffer_ + 3 * i, (uint8_t*)&tmp + 1, 3); memcpy(mix_buffer_ + 3 * i, (uint8_t*)&tmp + 1, 3); memcpy(compare_buffer_ + 3 * i, (uint8_t*)&tmp + 1, 3); } for (size_t i = kBufferFrames; i < kBufferFrames * 2; i++) { int32_t tmp = (i << 8) - (INT32_MAX >> 2); memcpy(src_buffer_ + 3 * i, (uint8_t*)&tmp + 1, 3); memcpy(mix_buffer_ + 3 * i, (uint8_t*)&tmp + 1, 3); memcpy(compare_buffer_ + 3 * i, (uint8_t*)&tmp + 1, 3); } } void TestScaleStride(float scaler) { _SetupBuffer(); for (size_t i = 0; i < kBufferFrames * kNumChannels; i += 2) { int64_t tmp; int32_t src_frame = 0; int32_t dst_frame = 0; memcpy((uint8_t*)&src_frame + 1, src_buffer_ + 3 * i / 2, 3); memcpy((uint8_t*)&dst_frame + 1, mix_buffer_ + 3 * i, 3); if (need_to_scale(scaler)) tmp = (int64_t)dst_frame + (int64_t)src_frame * scaler; else tmp = (int64_t)dst_frame + (int64_t)src_frame; if (tmp > INT32_MAX) tmp = INT32_MAX; else if (tmp < INT32_MIN) tmp = INT32_MIN; dst_frame = (int32_t)tmp; memcpy(compare_buffer_ + 3 * i, (uint8_t*)&dst_frame + 1, 3); } cras_mix_add_scale_stride(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kBufferFrames, 6, 3, scaler); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 6)); } void ScaleIncrement(float start_scaler, float increment, float target) { float scaler = start_scaler; for (size_t i = 0; i < kBufferFrames * kNumChannels; i++) { float applied_scaler = scaler; int32_t tmp = 0; memcpy((uint8_t*)&tmp + 1, src_buffer_ + 3 * i, 3); if ((applied_scaler > target && increment > 0) || (applied_scaler < target && increment < 0)) applied_scaler = target; if (applied_scaler > kMaxVolumeToScale) { } else if (applied_scaler < kMinVolumeToScale) { tmp = 0; } else { tmp *= applied_scaler; } memcpy(compare_buffer_ + 3 * i, (uint8_t*)&tmp + 1, 3); if (i % 2 == 1) scaler += increment; } } uint8_t* mix_buffer_; uint8_t* src_buffer_; uint8_t* compare_buffer_; snd_pcm_format_t fmt_; unsigned int fr_bytes_; }; TEST_F(MixTestSuiteS24_3LE, MixFirst) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); EXPECT_EQ(0, memcmp(mix_buffer_, src_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, MixTwo) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 1, 0, 1.0); for (size_t i = 0; i < kBufferFrames * kNumChannels; i++) { int32_t tmp = 0; memcpy((uint8_t*)&tmp + 1, src_buffer_ + 3 * i, 3); tmp *= 2; memcpy(compare_buffer_ + 3 * i, (uint8_t*)&tmp + 1, 3); } EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, MixTwoClip) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); for (size_t i = 0; i < kBufferFrames * kNumChannels; i++) { int32_t tmp = INT32_MAX; memcpy(src_buffer_ + 3 * i, (uint8_t*)&tmp + 1, 3); } cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 1, 0, 1.0); for (size_t i = 0; i < kBufferFrames * kNumChannels; i++) { int32_t tmp = INT32_MAX; memcpy(compare_buffer_ + 3 * i, (uint8_t*)&tmp + 1, 3); } EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, MixFirstMuted) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 1, 1.0); for (size_t i = 0; i < kBufferFrames * kNumChannels; i++) memset(compare_buffer_ + 3 * i, 0, 3); EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, MixFirstZeroVolume) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 0.0); for (size_t i = 0; i < kBufferFrames * kNumChannels; i++) memset(compare_buffer_ + 3 * i, 0, 3); EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, MixFirstHalfVolume) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 0.5); for (size_t i = 0; i < kBufferFrames * kNumChannels; i++) { int32_t tmp = 0; memcpy((uint8_t*)&tmp + 1, src_buffer_ + 3 * i, 3); tmp *= 0.5; memcpy(compare_buffer_ + 3 * i, (uint8_t*)&tmp + 1, 3); } EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, MixTwoSecondHalfVolume) { cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 0, 0, 1.0); cras_mix_add(fmt_, (uint8_t*)mix_buffer_, (uint8_t*)src_buffer_, kNumSamples, 1, 0, 0.5); for (size_t i = 0; i < kBufferFrames * kNumChannels; i++) { int32_t tmp1 = 0, tmp2 = 0; memcpy((uint8_t*)&tmp1 + 1, src_buffer_ + 3 * i, 3); memcpy((uint8_t*)&tmp2 + 1, src_buffer_ + 3 * i, 3); tmp1 = tmp1 + (int32_t)(tmp2 * 0.5); memcpy(compare_buffer_ + 3 * i, (uint8_t*)&tmp1 + 1, 3); } EXPECT_EQ(0, memcmp(mix_buffer_, compare_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, ScaleFullVolumeIncrement) { float increment = 0.01; int step = 2; float start_scaler = 0.999999999; float target = 1.0; _SetupBuffer(); // Scale full volume with positive increment will not change buffer. memcpy(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, ScaleMinVolumeIncrement) { float increment = -0.01; int step = 2; float start_scaler = 0.000000001; float target = 0.0; _SetupBuffer(); // Scale min volume with negative increment will change buffer to zeros. memset(compare_buffer_, 0, kBufferFrames * fr_bytes_); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, ScaleVolumePositiveIncrement) { float increment = 0.0001; int step = 2; float start_scaler = 0.1; float target = 1.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, ScaleVolumeNegativeIncrement) { float increment = -0.0001; int step = 2; float start_scaler = 0.8; float target = 0.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, ScaleVolumeStartFullNegativeIncrement) { float increment = -0.0001; int step = 2; float start_scaler = 1.0; float target = 0.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS24_3LE, ScaleVolumeStartZeroPositiveIncrement) { float increment = 0.0001; int step = 2; float start_scaler = 0.0; float target = 1.0; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * 4)); } TEST_F(MixTestSuiteS24_3LE, ScaleVolumePositiveIncrementCappedByTarget) { float increment = 0.0001; int step = 2; float start_scaler = 0.1; float target = 0.5; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, ScaleVolumeNegativeIncrementCappedByTarget) { float increment = -0.01; int step = 2; float start_scaler = 0.8; float target = 0.5; _SetupBuffer(); ScaleIncrement(start_scaler, increment, target); cras_scale_buffer_increment(fmt_, (uint8_t*)mix_buffer_, kBufferFrames, start_scaler, increment, target, step); EXPECT_EQ(0, memcmp(compare_buffer_, mix_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, ScaleFullVolume) { memcpy(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_); cras_scale_buffer(fmt_, (uint8_t*)mix_buffer_, kNumSamples, 0.999999999); EXPECT_EQ(0, memcmp(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, ScaleMinVolume) { memset(compare_buffer_, 0, kBufferFrames * fr_bytes_); cras_scale_buffer(fmt_, (uint8_t*)src_buffer_, kNumSamples, 0.0000000001); EXPECT_EQ(0, memcmp(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, ScaleHalfVolume) { for (size_t i = 0; i < kBufferFrames * kNumChannels; i++) { int32_t tmp = 0; memcpy((uint8_t*)&tmp + 1, src_buffer_ + 3 * i, 3); tmp *= 0.5; memcpy(compare_buffer_ + 3 * i, (uint8_t*)&tmp + 1, 3); } cras_scale_buffer(fmt_, (uint8_t*)src_buffer_, kNumSamples, 0.5); EXPECT_EQ(0, memcmp(compare_buffer_, src_buffer_, kBufferFrames * fr_bytes_)); } TEST_F(MixTestSuiteS24_3LE, StrideCopy) { TestScaleStride(1.0); TestScaleStride(100); TestScaleStride(0.1); } /* Stubs */ extern "C" {} // extern "C" } // namespace int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }