src/media/audio/audio_core/mixer/test/mixer_resampling_tests.cc
// Test LinearSampler interpolation accuracy, given fractional position.
// Inputs trigger various +/- values that should be rounded each direction.
//
// With these six precise spot checks, we verify interpolation accuracy to the
// fullest extent possible with 32-bit float and 13-bit subframe timestamps.
Test LinearSampler interpolation accuracy, given fractional position.
Inputs trigger various +/- values that should be rounded each direction.

With these six precise spot checks, we verify interpolation accuracy to the
fullest extent possible with 32-bit float and 13-bit subframe timestamps.
Test LinearSampler interpolation accuracy given fractional position . Inputs trigger various + / - values that should be rounded each direction . With these six precise spot checks we verify interpolation accuracy to the fullest extent possible with 32 - bit float and 13 - bit subframe timestamps .
void TestLinearInterpolation(uint32_t source_frames_per_second, uint32_t dest_frames_per_second) {
  auto mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1, source_frames_per_second, 1,
                           dest_frames_per_second, Resampler::LinearInterpolation);
   Base check: interpolated value is exactly calculated, no rounding.
   src offset 0.5, should mix 50/50
  float source1[] = {-1.0f, -0.999999880790710f};   BF800000, BF7FFFFE
  float expect1 = -0.999999940395355f;              BF7FFFFF
  uint32_t frac_src_frames = (std::size(source1)) << kPtsFractionalBits;
  int32_t frac_src_offset = 1 << (kPtsFractionalBits - 1);   0x1000 (2000==1)
  uint32_t dest_offset = 0;
  float accum_result = 0xCAFE;   value will be overwritten
  auto& info = mixer->bookkeeping();
  info.step_size = (static_cast<uint64_t>(source_frames_per_second) << kPtsFractionalBits) /
                   dest_frames_per_second;
  int32_t expected_src_offset = frac_src_offset + info.step_size;
  mixer->Mix(&accum_result, 1, &dest_offset, source1, frac_src_frames, &frac_src_offset, false);
  EXPECT_EQ(dest_offset, 1u);
  EXPECT_EQ(frac_src_offset, expected_src_offset);
  EXPECT_FLOAT_EQ(accum_result, expect1);
   Additional check: interpolated result is negative and should round out.
   src offset of 0.25 should lead us to mix the two src samples 75/25, which
   results in a value -0.999999970197678 that in IEEE-754 format is exactly
   halfway between the least-significant bit of floating-point precision
   BF7FFFFF.8). Here, we should round "out" so that this last bit is 0 (the
   'round even' convention), so we expect BF800000, which is -1.0.
  expect1 = -1.0f;
  frac_src_offset = 1 << (kPtsFractionalBits - 2);   0x0800 (2000==1.0)
  expected_src_offset = frac_src_offset + info.step_size;
  dest_offset = 0;
  accum_result = 0xCAFE;   Value will be overwritten.
  mixer->Mix(&accum_result, 1, &dest_offset, source1, frac_src_frames, &frac_src_offset, false);
  EXPECT_EQ(dest_offset, 1u);
  EXPECT_EQ(frac_src_offset, expected_src_offset);
  EXPECT_FLOAT_EQ(accum_result, expect1);
   Base check: interpolated value is exactly calculated, no rounding.
   src offset 0.5, should mix 50/50
  float source2[] = {0.999999880790710f, 1.0f};   3F7FFFFE, 3F800000
  float expect2 = 0.999999940395355f;             3F7FFFFF
  frac_src_frames = (std::size(source2)) << kPtsFractionalBits;
  frac_src_offset = 1 << (kPtsFractionalBits - 1);   0x1000 (2000==1.0)
  expected_src_offset = frac_src_offset + info.step_size;
  dest_offset = 0;
  accum_result = 0xCAFE;   Value will be overwritten.
  mixer->Mix(&accum_result, 1, &dest_offset, source2, frac_src_frames, &frac_src_offset, false);
  EXPECT_EQ(dest_offset, 1u);
  EXPECT_EQ(frac_src_offset, expected_src_offset);
  EXPECT_FLOAT_EQ(accum_result, expect2);
   Additional check: interpolated result is positive and should round out.
   src offset of 0x1800 should lead us to mix the two src samples 25/75, which
   results in a value 0.999999970197678 that in IEEE-754 format is exactly
   halfway between the least-significant bit of floating-point precision
   3F7FFFFF.8). Here, we should round "out" so that this last bit is 0 (the
   'round even' convention), so we expect 3F800000, which is +1.0.
  expect2 = 1.0f;
  frac_src_offset = 3 << (kPtsFractionalBits - 2);   0x1800 (0x2000==1.0)
  expected_src_offset = frac_src_offset + info.step_size;
  dest_offset = 0;
  accum_result = 0xCAFE;   Value will be overwritten.
  mixer->Mix(&accum_result, 1, &dest_offset, source2, frac_src_frames, &frac_src_offset, false);
  EXPECT_EQ(dest_offset, 1u);
  EXPECT_EQ(frac_src_offset, expected_src_offset);
  EXPECT_FLOAT_EQ(accum_result, expect2);
   Check: interpolated result is positive and should round in.
   src offset 0x17FF (0x2000 is 1.0) should mix just less than 25/75, which
   results in an interpolated value 0.749694854021072 that in IEEE-754 format
   is exactly halfway between the least-significant bit of floating-point
   precision 3F3FEC00.8). Here, we should round "in" so that the LSB is 0 (the
   'round even' convention), so we expect 3F3FEC00, which is 0.74969482421875.
  float source3[] = {0.0f, 0.999755859375f};
  float expect3 = 0.74969482421875f;
  frac_src_frames = (std::size(source3)) << kPtsFractionalBits;
  frac_src_offset = (3 << (kPtsFractionalBits - 2)) - 1;   0x17FF (2000==1.0)
  expected_src_offset = frac_src_offset + info.step_size;
  dest_offset = 0;
  accum_result = 0xCAFE;   Value will be overwritten.
  mixer->Mix(&accum_result, 1, &dest_offset, source3, frac_src_frames, &frac_src_offset, false);
  EXPECT_EQ(dest_offset, 1u);
  EXPECT_EQ(frac_src_offset, expected_src_offset);
  EXPECT_FLOAT_EQ(accum_result, expect3);
   Check: interpolated result is negative and should round in.
   src offset of 0x0801, which should mix just less than 75/25, resulting in
   an interpolated value of -0.749694854021072 that in IEEE-754 format is
   precisely halfway between the least-significant bit of floating-point
   precision BF3FEC00.8). Here, we should round "in" so that the LSB is 0 (the
   'round even' convention), so we expect BF3FEC00: -0.74969482421875.
  float source4[] = {-0.999755859375f, 0.0f};
  float expect4 = -0.74969482421875f;
  frac_src_frames = (std::size(source4)) << kPtsFractionalBits;
  frac_src_offset = (1 << (kPtsFractionalBits - 2)) + 1;   0x0801 (2000==1.0)
  expected_src_offset = frac_src_offset + info.step_size;
  dest_offset = 0;
  accum_result = 0xCAFE;   Value will be overwritten.
  mixer->Mix(&accum_result, 1, &dest_offset, source4, frac_src_frames, &frac_src_offset, false);
  EXPECT_EQ(dest_offset, 1u);
  EXPECT_EQ(frac_src_offset, expected_src_offset);
  EXPECT_FLOAT_EQ(accum_result, expect4);
}
void TestLinearInterpolation ( uint32_t source_frames_per_second , uint32_t dest_frames_per_second ) { auto mixer = SelectMixer ( fuchsia :: media :: AudioSampleFormat :: FLOAT , 1 , source_frames_per_second , 1 , dest_frames_per_second , Resampler :: LinearInterpolation ) ; float source1 [ ] = { -1.0f , -0.999999880790710f } ; float expect1 = -0.999999940395355f ; uint32_t frac_src_frames = ( std :: size ( source1 ) ) << kPtsFractionalBits ; int32_t frac_src_offset = 1 << ( kPtsFractionalBits - 1 ) ; uint32_t dest_offset = 0 ; float accum_result = 0xCAFE ; auto & info = mixer -> bookkeeping ( ) ; info . step_size = ( static_cast < uint64_t > ( source_frames_per_second ) << kPtsFractionalBits ) / dest_frames_per_second ; int32_t expected_src_offset = frac_src_offset + info . step_size ; mixer -> Mix ( & accum_result , 1 , & dest_offset , source1 , frac_src_frames , & frac_src_offset , false ) ; EXPECT_EQ ( dest_offset , 1u ) ; EXPECT_EQ ( frac_src_offset , expected_src_offset ) ; EXPECT_FLOAT_EQ ( accum_result , expect1 ) ; expect1 = -1.0f ; frac_src_offset = 1 << ( kPtsFractionalBits - 2 ) ; expected_src_offset = frac_src_offset + info . step_size ; dest_offset = 0 ; accum_result = 0xCAFE ; mixer -> Mix ( & accum_result , 1 , & dest_offset , source1 , frac_src_frames , & frac_src_offset , false ) ; EXPECT_EQ ( dest_offset , 1u ) ; EXPECT_EQ ( frac_src_offset , expected_src_offset ) ; EXPECT_FLOAT_EQ ( accum_result , expect1 ) ; float source2 [ ] = { 0.999999880790710f , 1.0f } ; float expect2 = 0.999999940395355f ; frac_src_frames = ( std :: size ( source2 ) ) << kPtsFractionalBits ; frac_src_offset = 1 << ( kPtsFractionalBits - 1 ) ; expected_src_offset = frac_src_offset + info . step_size ; dest_offset = 0 ; accum_result = 0xCAFE ; mixer -> Mix ( & accum_result , 1 , & dest_offset , source2 , frac_src_frames , & frac_src_offset , false ) ; EXPECT_EQ ( dest_offset , 1u ) ; EXPECT_EQ ( frac_src_offset , expected_src_offset ) ; EXPECT_FLOAT_EQ ( accum_result , expect2 ) ; expect2 = 1.0f ; frac_src_offset = 3 << ( kPtsFractionalBits - 2 ) ; expected_src_offset = frac_src_offset + info . step_size ; dest_offset = 0 ; accum_result = 0xCAFE ; mixer -> Mix ( & accum_result , 1 , & dest_offset , source2 , frac_src_frames , & frac_src_offset , false ) ; EXPECT_EQ ( dest_offset , 1u ) ; EXPECT_EQ ( frac_src_offset , expected_src_offset ) ; EXPECT_FLOAT_EQ ( accum_result , expect2 ) ; float source3 [ ] = { 0.0f , 0.999755859375f } ; float expect3 = 0.74969482421875f ; frac_src_frames = ( std :: size ( source3 ) ) << kPtsFractionalBits ; frac_src_offset = ( 3 << ( kPtsFractionalBits - 2 ) ) - 1 ; expected_src_offset = frac_src_offset + info . step_size ; dest_offset = 0 ; accum_result = 0xCAFE ; mixer -> Mix ( & accum_result , 1 , & dest_offset , source3 , frac_src_frames , & frac_src_offset , false ) ; EXPECT_EQ ( dest_offset , 1u ) ; EXPECT_EQ ( frac_src_offset , expected_src_offset ) ; EXPECT_FLOAT_EQ ( accum_result , expect3 ) ; float source4 [ ] = { -0.999755859375f , 0.0f } ; float expect4 = -0.74969482421875f ; frac_src_frames = ( std :: size ( source4 ) ) << kPtsFractionalBits ; frac_src_offset = ( 1 << ( kPtsFractionalBits - 2 ) ) + 1 ; expected_src_offset = frac_src_offset + info . step_size ; dest_offset = 0 ; accum_result = 0xCAFE ; mixer -> Mix ( & accum_result , 1 , & dest_offset , source4 , frac_src_frames , & frac_src_offset , false ) ; EXPECT_EQ ( dest_offset , 1u ) ; EXPECT_EQ ( frac_src_offset , expected_src_offset ) ; EXPECT_FLOAT_EQ ( accum_result , expect4 ) ; }
Test LinearSampler interpolation accuracy, given fractional position.
Test LinearSampler interpolation accuracy given fractional position .
// // Base check: interpolated value is exactly calculated, no rounding. // src offset 0.5, should mix 50/50 // BF800000, BF7FFFFE // BF7FFFFF // 0x1000 (2000==1) // value will be overwritten // // Additional check: interpolated result is negative and should round out. // src offset of 0.25 should lead us to mix the two src samples 75/25, which // results in a value -0.999999970197678 that in IEEE-754 format is exactly // halfway between the least-significant bit of floating-point precision // BF7FFFFF.8). Here, we should round "out" so that this last bit is 0 (the // 'round even' convention), so we expect BF800000, which is -1.0. // 0x0800 (2000==1.0) // Value will be overwritten. // // Base check: interpolated value is exactly calculated, no rounding. // src offset 0.5, should mix 50/50 // 3F7FFFFE, 3F800000 // 3F7FFFFF // 0x1000 (2000==1.0) // Value will be overwritten. // // Additional check: interpolated result is positive and should round out. // src offset of 0x1800 should lead us to mix the two src samples 25/75, which // results in a value 0.999999970197678 that in IEEE-754 format is exactly // halfway between the least-significant bit of floating-point precision // 3F7FFFFF.8). Here, we should round "out" so that this last bit is 0 (the // 'round even' convention), so we expect 3F800000, which is +1.0. // 0x1800 (0x2000==1.0) // Value will be overwritten. // // Check: interpolated result is positive and should round in. // src offset 0x17FF (0x2000 is 1.0) should mix just less than 25/75, which // results in an interpolated value 0.749694854021072 that in IEEE-754 format // is exactly halfway between the least-significant bit of floating-point // precision 3F3FEC00.8). Here, we should round "in" so that the LSB is 0 (the // 'round even' convention), so we expect 3F3FEC00, which is 0.74969482421875. // 0x17FF (2000==1.0) // Value will be overwritten. // // Check: interpolated result is negative and should round in. // src offset of 0x0801, which should mix just less than 75/25, resulting in // an interpolated value of -0.749694854021072 that in IEEE-754 format is // precisely halfway between the least-significant bit of floating-point // precision BF3FEC00.8). Here, we should round "in" so that the LSB is 0 (the // 'round even' convention), so we expect BF3FEC00: -0.74969482421875. // 0x0801 (2000==1.0) // Value will be overwritten.