Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  TestDynamicResampler.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "gtest/gtest.h"

#include "DynamicResampler.h"

using namespace mozilla;

TEST(TestDynamicResampler, SameRates_Float1)
{
  const uint32_t in_frames = 100;
  const uint32_t out_frames = 100;
  uint32_t channels = 2;
  uint32_t in_rate = 44100;
  uint32_t out_rate = 44100;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_FLOAT32);
  EXPECT_EQ(dr.GetInRate(), in_rate);
  EXPECT_EQ(dr.GetChannels(), channels);

  // float in_ch1[] = {.1, .2, .3, .4, .5, .6, .7, .8, .9, 1.0};
  // float in_ch2[] = {.1, .2, .3, .4, .5, .6, .7, .8, .9, 1.0};
  float in_ch1[in_frames] = {};
  float in_ch2[in_frames] = {};
  AutoTArray<const float*, 2> in_buffer;
  in_buffer.AppendElements(channels);
  in_buffer[0] = in_ch1;
  in_buffer[1] = in_ch2;

  float out_ch1[out_frames] = {};
  float out_ch2[out_frames] = {};

  // Warm up with zeros
  dr.AppendInput(in_buffer, in_frames);
  bool hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  for (uint32_t i = 0; i < out_frames; ++i) {
    EXPECT_FLOAT_EQ(in_ch1[i], out_ch1[i]);
    EXPECT_FLOAT_EQ(in_ch2[i], out_ch2[i]);
  }

  // Continue with non zero
  for (uint32_t i = 0; i < in_frames; ++i) {
    in_ch1[i] = in_ch2[i] = 0.01f * i;
  }
  dr.AppendInput(in_buffer, in_frames);
  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  for (uint32_t i = 0; i < out_frames; ++i) {
    EXPECT_FLOAT_EQ(in_ch1[i], out_ch1[i]);
    EXPECT_FLOAT_EQ(in_ch2[i], out_ch2[i]);
  }

  // No more frames in the input buffer
  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_TRUE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_TRUE(hasUnderrun);
}

TEST(TestDynamicResampler, SameRates_Short1)
{
  uint32_t in_frames = 2;
  uint32_t out_frames = 2;
  uint32_t channels = 2;
  uint32_t in_rate = 44100;
  uint32_t out_rate = 44100;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_S16);
  EXPECT_EQ(dr.GetInRate(), in_rate);
  EXPECT_EQ(dr.GetChannels(), channels);

  short in_ch1[] = {1, 2, 3};
  short in_ch2[] = {4, 5, 6};
  AutoTArray<const short*, 2> in_buffer;
  in_buffer.AppendElements(channels);
  in_buffer[0] = in_ch1;
  in_buffer[1] = in_ch2;

  short out_ch1[3] = {};
  short out_ch2[3] = {};

  dr.AppendInput(in_buffer, in_frames);
  bool hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  for (uint32_t i = 0; i < out_frames; ++i) {
    EXPECT_EQ(in_ch1[i], out_ch1[i]);
    EXPECT_EQ(in_ch2[i], out_ch2[i]);
  }

  // No more frames in the input buffer
  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_TRUE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_TRUE(hasUnderrun);
}

TEST(TestDynamicResampler, SameRates_Float2)
{
  uint32_t in_frames = 3;
  uint32_t out_frames = 2;
  uint32_t channels = 2;
  uint32_t in_rate = 44100;
  uint32_t out_rate = 44100;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  float in_ch1[] = {0.1, 0.2, 0.3};
  float in_ch2[] = {0.4, 0.5, 0.6};
  AutoTArray<const float*, 2> in_buffer;
  in_buffer.AppendElements(channels);
  in_buffer[0] = in_ch1;
  in_buffer[1] = in_ch2;

  float out_ch1[3] = {};
  float out_ch2[3] = {};

  dr.AppendInput(in_buffer, in_frames);
  bool hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  for (uint32_t i = 0; i < out_frames; ++i) {
    EXPECT_FLOAT_EQ(in_ch1[i], out_ch1[i]);
    EXPECT_FLOAT_EQ(in_ch2[i], out_ch2[i]);
  }

  out_frames = 1;
  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  for (uint32_t i = 0; i < out_frames; ++i) {
    EXPECT_FLOAT_EQ(in_ch1[i + 2], out_ch1[i]);
    EXPECT_FLOAT_EQ(in_ch2[i + 2], out_ch2[i]);
  }

  // No more frames, the input buffer has drained
  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_TRUE(hasUnderrun);
  dr.Resample(out_ch2, out_frames, 1);
  EXPECT_TRUE(hasUnderrun);
}

TEST(TestDynamicResampler, SameRates_Short2)
{
  uint32_t in_frames = 3;
  uint32_t out_frames = 2;
  uint32_t channels = 2;
  uint32_t in_rate = 44100;
  uint32_t out_rate = 44100;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_S16);

  short in_ch1[] = {1, 2, 3};
  short in_ch2[] = {4, 5, 6};
  AutoTArray<const short*, 2> in_buffer;
  in_buffer.AppendElements(channels);
  in_buffer[0] = in_ch1;
  in_buffer[1] = in_ch2;

  short out_ch1[3] = {};
  short out_ch2[3] = {};

  dr.AppendInput(in_buffer, in_frames);
  bool hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  for (uint32_t i = 0; i < out_frames; ++i) {
    EXPECT_EQ(in_ch1[i], out_ch1[i]);
    EXPECT_EQ(in_ch2[i], out_ch2[i]);
  }

  out_frames = 1;
  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  for (uint32_t i = 0; i < out_frames; ++i) {
    EXPECT_EQ(in_ch1[i + 2], out_ch1[i]);
    EXPECT_EQ(in_ch2[i + 2], out_ch2[i]);
  }

  // No more frames, the input buffer has drained
  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_TRUE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_TRUE(hasUnderrun);
}

TEST(TestDynamicResampler, SameRates_Float3)
{
  uint32_t in_frames = 2;
  uint32_t out_frames = 3;
  uint32_t channels = 2;
  uint32_t in_rate = 44100;
  uint32_t out_rate = 44100;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  float in_ch1[] = {0.1, 0.2, 0.3};
  float in_ch2[] = {0.4, 0.5, 0.6};
  AutoTArray<const float*, 2> in_buffer;
  in_buffer.AppendElements(channels);
  in_buffer[0] = in_ch1;
  in_buffer[1] = in_ch2;

  float out_ch1[3] = {};
  float out_ch2[3] = {};

  // Not enough frames in the input buffer
  dr.AppendInput(in_buffer, in_frames);
  bool hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_TRUE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_TRUE(hasUnderrun);

  // Add one frame
  in_buffer[0] = in_ch1 + 2;
  in_buffer[1] = in_ch2 + 2;
  dr.AppendInput(in_buffer, 1);
  out_frames = 1;
  hasUnderrun = dr.Resample(out_ch1 + 2, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2 + 2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  for (uint32_t i = 0; i < 3; ++i) {
    EXPECT_FLOAT_EQ(in_ch1[i], out_ch1[i]);
    EXPECT_FLOAT_EQ(in_ch2[i], out_ch2[i]);
  }
}

TEST(TestDynamicResampler, SameRates_Short3)
{
  uint32_t in_frames = 2;
  uint32_t out_frames = 3;
  uint32_t channels = 2;
  uint32_t in_rate = 44100;
  uint32_t out_rate = 44100;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_S16);

  short in_ch1[] = {1, 2, 3};
  short in_ch2[] = {4, 5, 6};
  AutoTArray<const short*, 2> in_buffer;
  in_buffer.AppendElements(channels);
  in_buffer[0] = in_ch1;
  in_buffer[1] = in_ch2;

  short out_ch1[3] = {};
  short out_ch2[3] = {};

  // Not enough frames in the input buffer
  dr.AppendInput(in_buffer, in_frames);
  bool hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_TRUE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_TRUE(hasUnderrun);

  // Add one frame
  in_buffer[0] = in_ch1 + 2;
  in_buffer[1] = in_ch2 + 2;
  dr.AppendInput(in_buffer, 1);
  out_frames = 1;
  hasUnderrun = dr.Resample(out_ch1 + 2, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2 + 2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  for (uint32_t i = 0; i < 3; ++i) {
    EXPECT_EQ(in_ch1[i], out_ch1[i]);
    EXPECT_EQ(in_ch2[i], out_ch2[i]);
  }
}

TEST(TestDynamicResampler, UpdateOutRate_Float)
{
  uint32_t in_frames = 10;
  uint32_t out_frames = 40;
  uint32_t channels = 2;
  uint32_t in_rate = 24000;
  uint32_t out_rate = 48000;

  uint32_t pre_buffer = 20;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_FLOAT32);
  EXPECT_EQ(dr.GetInRate(), in_rate);
  EXPECT_EQ(dr.GetChannels(), channels);

  float in_ch1[10] = {};
  float in_ch2[10] = {};
  for (uint32_t i = 0; i < in_frames; ++i) {
    in_ch1[i] = in_ch2[i] = 0.01f * i;
  }
  AutoTArray<const float*, 2> in_buffer;
  in_buffer.AppendElements(channels);
  in_buffer[0] = in_ch1;
  in_buffer[1] = in_ch2;

  float out_ch1[40] = {};
  float out_ch2[40] = {};

  dr.AppendInputSilence(pre_buffer - in_frames);
  dr.AppendInput(in_buffer, in_frames);
  out_frames = 20u;
  bool hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  for (uint32_t i = 0; i < out_frames; ++i) {
    // Half the input pre-buffer (10) is silence, and half the output (20).
    EXPECT_FLOAT_EQ(out_ch1[i], 0.0);
    EXPECT_FLOAT_EQ(out_ch2[i], 0.0);
  }

  // Update in rate
  in_rate = 26122;
  dr.UpdateResampler(in_rate, channels);
  EXPECT_EQ(dr.GetInRate(), in_rate);
  EXPECT_EQ(dr.GetChannels(), channels);
  out_frames = in_frames * out_rate / in_rate;
  EXPECT_EQ(out_frames, 18u);
  // Even if we provide no input if we have enough buffered input, we can create
  // output
  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
}

TEST(TestDynamicResampler, UpdateOutRate_Short)
{
  uint32_t in_frames = 10;
  uint32_t out_frames = 40;
  uint32_t channels = 2;
  uint32_t in_rate = 24000;
  uint32_t out_rate = 48000;

  uint32_t pre_buffer = 20;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_S16);
  EXPECT_EQ(dr.GetInRate(), in_rate);
  EXPECT_EQ(dr.GetChannels(), channels);

  short in_ch1[10] = {};
  short in_ch2[10] = {};
  for (uint32_t i = 0; i < in_frames; ++i) {
    in_ch1[i] = in_ch2[i] = i;
  }
  AutoTArray<const short*, 2> in_buffer;
  in_buffer.AppendElements(channels);
  in_buffer[0] = in_ch1;
  in_buffer[1] = in_ch2;

  short out_ch1[40] = {};
  short out_ch2[40] = {};

  dr.AppendInputSilence(pre_buffer - in_frames);
  dr.AppendInput(in_buffer, in_frames);
  out_frames = 20u;
  bool hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  for (uint32_t i = 0; i < out_frames; ++i) {
    // Half the input pre-buffer (10) is silence, and half the output (20).
    EXPECT_EQ(out_ch1[i], 0.0);
    EXPECT_EQ(out_ch2[i], 0.0);
  }

  // Update in rate
  in_rate = 26122;
  dr.UpdateResampler(in_rate, channels);
  EXPECT_EQ(dr.GetInRate(), in_rate);
  EXPECT_EQ(dr.GetChannels(), channels);
  out_frames = in_frames * out_rate / in_rate;
  EXPECT_EQ(out_frames, 18u);
  // Even if we provide no input if we have enough buffered input, we can create
  // output
  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
}

TEST(TestDynamicResampler, BigRangeInRates_Float)
{
  uint32_t in_frames = 10;
  uint32_t out_frames = 10;
  uint32_t channels = 2;
  uint32_t in_rate = 44100;
  uint32_t out_rate = 44100;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  const uint32_t in_capacity = 40;
  float in_ch1[in_capacity] = {};
  float in_ch2[in_capacity] = {};
  for (uint32_t i = 0; i < in_capacity; ++i) {
    in_ch1[i] = in_ch2[i] = 0.01f * i;
  }
  AutoTArray<const float*, 2> in_buffer;
  in_buffer.AppendElements(channels);
  in_buffer[0] = in_ch1;
  in_buffer[1] = in_ch2;

  const uint32_t out_capacity = 1000;
  float out_ch1[out_capacity] = {};
  float out_ch2[out_capacity] = {};

  // Downsampling at a high enough ratio happens to have enough excess
  // in_frames from rounding in the out_frames calculation to cover the
  // skipped input latency when switching from zero-latency 44100->44100 to a
  // non-1:1 ratio.
  for (uint32_t rate = 100000; rate >= 10000; rate -= 2) {
    in_rate = rate;
    dr.UpdateResampler(in_rate, channels);
    EXPECT_EQ(dr.GetInRate(), in_rate);
    EXPECT_EQ(dr.GetChannels(), channels);
    in_frames = 20;  // more than we need
    out_frames = in_frames * out_rate / in_rate;
    for (uint32_t y = 0; y < 2; ++y) {
      dr.AppendInput(in_buffer, in_frames);
      bool hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
      EXPECT_FALSE(hasUnderrun);
      hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
      EXPECT_FALSE(hasUnderrun);
    }
  }
}

TEST(TestDynamicResampler, DownsamplingToCopying)
{
  uint32_t channel_count = 1;
  // Start with downsampling
  uint32_t in_rate = 48001;
  uint32_t out_rate = 48000;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_FLOAT32);
  dr.UpdateResampler(in_rate, channel_count);

  const uint32_t in_frame_count = 100;
  float in_frames[in_frame_count];
  float increment = 1.f / in_frame_count;
  for (uint32_t i = 0; i < in_frame_count; ++i) {
    in_frames[i] = static_cast<float>(i) * increment;
  }
  const float* in_channels[] = {in_frames};
  dr.AppendInput(in_channels, in_frame_count);

  const uint32_t block_size = 30;
  const uint32_t out_frame_count = 2 * block_size;
  float out_frames[out_frame_count];
  bool hasUnderrun = dr.Resample(out_frames, block_size, 0);
  EXPECT_FALSE(hasUnderrun);
  // Use out_rate for the input rate so that the DynamicResampler switches
  // from resampling to copying of frames.
  dr.UpdateResampler(out_rate, channel_count);
  hasUnderrun = dr.Resample(out_frames + block_size, block_size, 0);
  EXPECT_FALSE(hasUnderrun);

  // The abrupt change in slope from zero to increment is resampled to some
  // oscillations around the point of change.
  constexpr float tolerance = 0.1f;
  bool latencyHasPassed = false;
  EXPECT_NEAR(out_frames[0], 0.f, tolerance);
  for (uint32_t i = 1; i < out_frame_count; ++i) {
    if (!latencyHasPassed) {
      // Before the latency passes, samples may be approximately zero.
      EXPECT_GT(out_frames[i], -tolerance) << "for i=" << i;
      if (out_frames[i] > tolerance) {
        latencyHasPassed = true;
        EXPECT_LT(out_frames[i], increment + tolerance) << "for i=" << i;
      }
      continue;
    }
    EXPECT_NEAR(out_frames[i], out_frames[i - 1] + increment, tolerance);
  }
}

TEST(TestDynamicResampler, BigRangeInRates_Short)
{
  uint32_t in_frames = 10;
  uint32_t out_frames = 10;
  uint32_t channels = 2;
  uint32_t in_rate = 44100;
  uint32_t out_rate = 44100;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_S16);

  const uint32_t in_capacity = 40;
  short in_ch1[in_capacity] = {};
  short in_ch2[in_capacity] = {};
  for (uint32_t i = 0; i < in_capacity; ++i) {
    in_ch1[i] = in_ch2[i] = i;
  }
  AutoTArray<const short*, 2> in_buffer;
  in_buffer.AppendElements(channels);
  in_buffer[0] = in_ch1;
  in_buffer[1] = in_ch2;

  const uint32_t out_capacity = 1000;
  short out_ch1[out_capacity] = {};
  short out_ch2[out_capacity] = {};

  for (uint32_t rate = 100000; rate >= 10000; rate -= 2) {
    in_rate = rate;
    dr.UpdateResampler(in_rate, channels);
    in_frames = 20;  // more than we need
    out_frames = in_frames * out_rate / in_rate;
    for (uint32_t y = 0; y < 2; ++y) {
      dr.AppendInput(in_buffer, in_frames);
      bool hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
      EXPECT_FALSE(hasUnderrun);
      hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
      EXPECT_FALSE(hasUnderrun);
    }
  }
}

TEST(TestDynamicResampler, UpdateChannels_Float)
{
  uint32_t in_frames = 10;
  uint32_t out_frames = 10;
  uint32_t channels = 2;
  uint32_t in_rate = 44100;
  uint32_t out_rate = 48000;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_FLOAT32);

  float in_ch1[10] = {};
  float in_ch2[10] = {};
  for (uint32_t i = 0; i < in_frames; ++i) {
    in_ch1[i] = in_ch2[i] = 0.01f * i;
  }
  AutoTArray<const float*, 2> in_buffer;
  in_buffer.AppendElements(channels);
  in_buffer[0] = in_ch1;
  in_buffer[1] = in_ch2;

  float out_ch1[10] = {};
  float out_ch2[10] = {};

  dr.AppendInput(in_buffer, in_frames);
  bool hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);

  // Add 3rd channel
  dr.UpdateResampler(in_rate, 3);
  EXPECT_EQ(dr.GetInRate(), in_rate);
  EXPECT_EQ(dr.GetChannels(), 3u);

  float in_ch3[10] = {};
  for (uint32_t i = 0; i < in_frames; ++i) {
    in_ch3[i] = 0.01f * i;
  }
  in_buffer.AppendElement();
  in_buffer[2] = in_ch3;
  float out_ch3[10] = {};

  dr.AppendInput(in_buffer, in_frames);

  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch3, out_frames, 2);
  EXPECT_FALSE(hasUnderrun);

  float in_ch4[10] = {};
  for (uint32_t i = 0; i < in_frames; ++i) {
    in_ch3[i] = 0.01f * i;
  }
  in_buffer.AppendElement();
  in_buffer[3] = in_ch4;
  float out_ch4[10] = {};

  dr.UpdateResampler(in_rate, 4);
  EXPECT_EQ(dr.GetInRate(), in_rate);
  EXPECT_EQ(dr.GetChannels(), 4u);
  dr.AppendInput(in_buffer, in_frames);

  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch3, out_frames, 2);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch4, out_frames, 3);
  EXPECT_FALSE(hasUnderrun);
}

TEST(TestDynamicResampler, UpdateChannels_Short)
{
  uint32_t in_frames = 10;
  uint32_t out_frames = 10;
  uint32_t channels = 2;
  uint32_t in_rate = 44100;
  uint32_t out_rate = 48000;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_S16);

  short in_ch1[10] = {};
  short in_ch2[10] = {};
  for (uint32_t i = 0; i < in_frames; ++i) {
    in_ch1[i] = in_ch2[i] = i;
  }
  AutoTArray<const short*, 2> in_buffer;
  in_buffer.AppendElements(channels);
  in_buffer[0] = in_ch1;
  in_buffer[1] = in_ch2;

  short out_ch1[10] = {};
  short out_ch2[10] = {};

  dr.AppendInput(in_buffer, in_frames);
  bool hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);

  // Add 3rd channel
  dr.UpdateResampler(in_rate, 3);
  EXPECT_EQ(dr.GetInRate(), in_rate);
  EXPECT_EQ(dr.GetChannels(), 3u);

  short in_ch3[10] = {};
  for (uint32_t i = 0; i < in_frames; ++i) {
    in_ch3[i] = i;
  }
  in_buffer.AppendElement();
  in_buffer[2] = in_ch3;
  short out_ch3[10] = {};

  dr.AppendInput(in_buffer, in_frames);

  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch3, out_frames, 2);
  EXPECT_FALSE(hasUnderrun);

  // Check update with AudioSegment
  short in_ch4[10] = {};
  for (uint32_t i = 0; i < in_frames; ++i) {
    in_ch3[i] = i;
  }
  in_buffer.AppendElement();
  in_buffer[3] = in_ch4;
  short out_ch4[10] = {};

  dr.UpdateResampler(in_rate, 4);
  EXPECT_EQ(dr.GetInRate(), in_rate);
  EXPECT_EQ(dr.GetChannels(), 4u);
  dr.AppendInput(in_buffer, in_frames);

  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch3, out_frames, 2);
  EXPECT_FALSE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch4, out_frames, 3);
  EXPECT_FALSE(hasUnderrun);
}

TEST(TestDynamicResampler, Underrun)
{
  const uint32_t in_frames = 100;
  const uint32_t out_frames = 200;
  uint32_t channels = 2;
  uint32_t in_rate = 48000;
  uint32_t out_rate = 48000;

  DynamicResampler dr(in_rate, out_rate);
  dr.SetSampleFormat(AUDIO_FORMAT_FLOAT32);
  EXPECT_EQ(dr.GetInRate(), in_rate);
  EXPECT_EQ(dr.GetChannels(), channels);

  float in_ch1[in_frames] = {};
  float in_ch2[in_frames] = {};
  AutoTArray<const float*, 2> in_buffer;
  in_buffer.AppendElements(channels);
  in_buffer[0] = in_ch1;
  in_buffer[1] = in_ch2;

  float out_ch1[out_frames] = {};
  float out_ch2[out_frames] = {};

  for (uint32_t i = 0; i < in_frames; ++i) {
    in_ch1[i] = 0.01f * i;
    in_ch2[i] = -0.01f * i;
  }
  dr.AppendInput(in_buffer, in_frames);
  bool hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_TRUE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_TRUE(hasUnderrun);
  for (uint32_t i = 0; i < in_frames; ++i) {
    EXPECT_EQ(out_ch1[i], in_ch1[i]);
    EXPECT_EQ(out_ch2[i], in_ch2[i]);
  }
  for (uint32_t i = in_frames; i < out_frames; ++i) {
    EXPECT_EQ(out_ch1[i], 0.0f) << "for i=" << i;
    EXPECT_EQ(out_ch2[i], 0.0f) << "for i=" << i;
  }

  // No more frames in the input buffer
  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_TRUE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_TRUE(hasUnderrun);
  for (uint32_t i = 0; i < out_frames; ++i) {
    EXPECT_EQ(out_ch1[i], 0.0f) << "for i=" << i;
    EXPECT_EQ(out_ch2[i], 0.0f) << "for i=" << i;
  }

  // Now try with resampling.
  dr.UpdateResampler(in_rate * 2, channels);
  dr.AppendInput(in_buffer, in_frames);
  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_TRUE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_TRUE(hasUnderrun);
  // There is some buffering in the resampler, which is why the below is not
  // exact.
  for (uint32_t i = 0; i < 50; ++i) {
    EXPECT_GT(out_ch1[i], 0.0f) << "for i=" << i;
    EXPECT_LT(out_ch2[i], 0.0f) << "for i=" << i;
  }
  for (uint32_t i = 50; i < 54; ++i) {
    EXPECT_NE(out_ch1[i], 0.0f) << "for i=" << i;
    EXPECT_NE(out_ch2[i], 0.0f) << "for i=" << i;
  }
  for (uint32_t i = 54; i < out_frames; ++i) {
    EXPECT_EQ(out_ch1[i], 0.0f) << "for i=" << i;
    EXPECT_EQ(out_ch2[i], 0.0f) << "for i=" << i;
  }

  // No more frames in the input buffer
  hasUnderrun = dr.Resample(out_ch1, out_frames, 0);
  EXPECT_TRUE(hasUnderrun);
  hasUnderrun = dr.Resample(out_ch2, out_frames, 1);
  EXPECT_TRUE(hasUnderrun);
  for (uint32_t i = 0; i < out_frames; ++i) {
    EXPECT_EQ(out_ch1[i], 0.0f) << "for i=" << i;
    EXPECT_EQ(out_ch2[i], 0.0f) << "for i=" << i;
  }
}

Messung V0.5
C=95 H=56 G=77

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge