普通文本  |  1338行  |  42.02 KB

// 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 <gtest/gtest.h>
#include <sys/param.h>

extern "C" {
#include "cras_fmt_conv.h"
#include "cras_types.h"
}

static int mono_channel_layout[CRAS_CH_MAX] =
  {-1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1};
static int stereo_channel_layout[CRAS_CH_MAX] =
  {0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
static int surround_channel_layout[CRAS_CH_MAX] =
	{0, 1, 2, 3, 4, 5, -1, -1, -1, -1, -1};
static int linear_resampler_needed_val;
static double linear_resampler_ratio = 1.0;

void ResetStub() {
  linear_resampler_needed_val = 0;
  linear_resampler_ratio = 1.0;
}

// Like malloc or calloc, but fill the memory with random bytes.
static void *ralloc(size_t size) {
  unsigned char *buf = (unsigned char *)malloc(size);
  while (size--)
    buf[size] = rand() & 0xff;
  return buf;
}

static void swap_channel_layout(int8_t *layout,
                                CRAS_CHANNEL a,
				CRAS_CHANNEL b) {
	int8_t tmp = layout[a];
	layout[a] = layout[b];
	layout[b] = tmp;
}

// Only support LE, BE should fail.
TEST(FormatConverterTest,  InvalidParamsOnlyLE) {
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;
  struct cras_fmt_conv *c;

  ResetStub();
  in_fmt.format = out_fmt.format = SND_PCM_FORMAT_S32_BE;
  in_fmt.num_channels = out_fmt.num_channels = 2;
  c = cras_fmt_conv_create(&in_fmt, &out_fmt, 4096, 0);
  EXPECT_EQ(NULL, c);
}

// Test Mono to Stereo mix.
TEST(FormatConverterTest, MonoToStereo) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int16_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S16_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 1;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_out_frames_to_in(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  in_buff = (int16_t *)ralloc(buf_size * 2 * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size * 2 * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (size_t i = 0; i < buf_size; i++) {
    if (in_buff[i] != out_buff[i*2] ||
        in_buff[i] != out_buff[i*2 + 1]) {
      EXPECT_TRUE(false);
      break;
    }
  }

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test Stereo to Mono mix.
TEST(FormatConverterTest, StereoToMono) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int16_t *in_buff;
  int16_t *out_buff;
  unsigned int i;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S16_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 2;
  out_fmt.num_channels = 1;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_out_frames_to_in(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  in_buff = (int16_t *)malloc(buf_size * 2 * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)malloc(buf_size * cras_get_format_bytes(&out_fmt));
  for (i = 0; i < buf_size; i++) {
    in_buff[i * 2] = 13450;
    in_buff[i * 2 + 1] = -13449;
  }
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (i = 0; i < buf_size; i++) {
    EXPECT_EQ(1, out_buff[i]);
  }

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test Stereo to Mono mix 24 and 32 bit.
TEST(FormatConverterTest, StereoToMono24bit) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int32_t *in_buff;
  int32_t *out_buff;
  unsigned int i;
  const size_t buf_size = 100;
  unsigned int in_buf_size = 100;
  unsigned int test;

  for (test = 0; test < 2; test++) {
    ResetStub();
    if (test == 0) {
      in_fmt.format = SND_PCM_FORMAT_S24_LE;
      out_fmt.format = SND_PCM_FORMAT_S24_LE;
    } else {
      in_fmt.format = SND_PCM_FORMAT_S32_LE;
      out_fmt.format = SND_PCM_FORMAT_S32_LE;
    }
    in_fmt.num_channels = 2;
    out_fmt.num_channels = 1;
    in_fmt.frame_rate = 48000;
    out_fmt.frame_rate = 48000;

    c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
    ASSERT_NE(c, (void *)NULL);

    out_frames = cras_fmt_conv_out_frames_to_in(c, buf_size);
    EXPECT_EQ(buf_size, out_frames);

    out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
    EXPECT_EQ(buf_size, out_frames);

    in_buff = (int32_t *)malloc(buf_size * cras_get_format_bytes(&in_fmt));
    out_buff = (int32_t *)malloc(buf_size * cras_get_format_bytes(&out_fmt));
    // TODO(dgreid) - s/0x10000/1/ once it stays full bits the whole way.
    for (i = 0; i < buf_size; i++) {
	    in_buff[i * 2] = 13450 << 16;
	    in_buff[i * 2 + 1] = -in_buff[i * 2] + 0x10000;
    }
    out_frames = cras_fmt_conv_convert_frames(c,
		    (uint8_t *)in_buff,
		    (uint8_t *)out_buff,
		    &in_buf_size,
		    buf_size);
    EXPECT_EQ(buf_size, out_frames);
    for (i = 0; i < buf_size; i++) {
	    EXPECT_EQ(0x10000, out_buff[i]);
    }

    cras_fmt_conv_destroy(c);
    free(in_buff);
    free(out_buff);
  }
}

// Test 5.1 to Stereo mix.
TEST(FormatConverterTest, SurroundToStereo) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int16_t *in_buff;
  int16_t *out_buff;
  unsigned int i;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S16_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 6;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;
  for (i = 0; i < CRAS_CH_MAX; i++)
    in_fmt.channel_layout[i] = surround_channel_layout[i];

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_out_frames_to_in(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  in_buff = (int16_t *)malloc(buf_size * 2 * cras_get_format_bytes(&in_fmt));

  /* Swap channel to FL = 13450, RL = -100.
   * Assert right channel is silent.
   */
  for (i = 0; i < buf_size; i++) {
    in_buff[i * 6] = 13450;
    in_buff[i * 6 + 1] = 0;
    in_buff[i * 6 + 2] = -100;
    in_buff[i * 6 + 3] = 0;
    in_buff[i * 6 + 4] = 0;
    in_buff[i * 6 + 5] = 0;
  }
  out_buff = (int16_t *)malloc(buf_size * 2 * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (i = 0; i < buf_size; i++)
    EXPECT_LT(0, out_buff[i * 2]);

  /* Swap channel to FR = 13450, RR = -100.
   * Assert left channel is silent.
   */
  swap_channel_layout(in_fmt.channel_layout, CRAS_CH_FL, CRAS_CH_FR);
  swap_channel_layout(in_fmt.channel_layout, CRAS_CH_RL, CRAS_CH_RR);
  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (i = 0; i < buf_size; i++)
    EXPECT_LT(0, out_buff[i * 2 + 1]);

  /* Swap channel to FC = 13450, LFE = -100.
   * Assert output left and right has equal magnitude.
   */
  swap_channel_layout(in_fmt.channel_layout, CRAS_CH_FR, CRAS_CH_FC);
  swap_channel_layout(in_fmt.channel_layout, CRAS_CH_RR, CRAS_CH_LFE);
  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (i = 0; i < buf_size; i++) {
    EXPECT_NE(0, out_buff[i * 2]);
    EXPECT_EQ(out_buff[i * 2], out_buff[i * 2 + 1]);
  }

  /* Swap channel to FR = 13450, FL = -100.
   * Assert output left is positive and right is negative. */
  swap_channel_layout(in_fmt.channel_layout, CRAS_CH_LFE, CRAS_CH_FR);
  swap_channel_layout(in_fmt.channel_layout, CRAS_CH_FC, CRAS_CH_FL);
  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (i = 0; i < buf_size; i++) {
    EXPECT_LT(0, out_buff[i * 2]);
    EXPECT_GT(0, out_buff[i * 2 + 1]);
  }

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 2 to 1 SRC.
TEST(FormatConverterTest,  Convert2To1) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int16_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;

  ResetStub();
  in_fmt.format = out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = out_fmt.num_channels = 2;
  in_fmt.frame_rate = 96000;
  out_fmt.frame_rate = 48000;

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size/2, out_frames);

  in_buff = (int16_t *)ralloc(buf_size * 2 * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size/2 * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size / 2);
  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 1 to 2 SRC.
TEST(FormatConverterTest,  Convert1To2) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;
  size_t out_frames;
  int16_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;

  ResetStub();
  in_fmt.format = out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = out_fmt.num_channels = 2;
  in_fmt.frame_rate = 22050;
  out_fmt.frame_rate = 44100;

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size*2, out_frames);

  in_buff = (int16_t *)ralloc(buf_size * 2 * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size*2 * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size * 2);
  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 1 to 2 SRC with mono to stereo conversion.
TEST(FormatConverterTest,  Convert1To2MonoToStereo) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;
  size_t out_frames;
  int16_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;

  ResetStub();
  in_fmt.format = out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 1;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 22050;
  out_fmt.frame_rate = 44100;

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_out_frames_to_in(c, buf_size);
  EXPECT_EQ(buf_size / 2, out_frames);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size * 2, out_frames);

  in_buff = (int16_t *)ralloc(buf_size * 2 * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size * 2 * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size * 2);
  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 32 to 16 bit conversion.
TEST(FormatConverterTest, ConvertS32LEToS16LE) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int32_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S32_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = out_fmt.num_channels = 2;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  in_buff = (int32_t *)ralloc(buf_size * 2 * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (unsigned int i = 0; i < buf_size; i++)
    EXPECT_EQ((int16_t)(in_buff[i] >> 16), out_buff[i]);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 24 to 16 bit conversion.
TEST(FormatConverterTest, ConvertS24LEToS16LE) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int32_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S24_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = out_fmt.num_channels = 2;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  in_buff = (int32_t *)ralloc(buf_size * 2 * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (unsigned int i = 0; i < buf_size; i++)
    EXPECT_EQ((int16_t)(in_buff[i] >> 8), out_buff[i]);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 8 to 16 bit conversion.
TEST(FormatConverterTest, ConvertU8LEToS16LE) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  uint8_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_U8;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 2;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  in_buff = (uint8_t *)ralloc(buf_size * 2 * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (unsigned int i = 0; i < buf_size; i++)
    EXPECT_EQ(((int16_t)(in_buff[i] - 128) << 8), out_buff[i]);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 16 to 32 bit conversion.
TEST(FormatConverterTest, ConvertS16LEToS32LE) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int16_t *in_buff;
  int32_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S16_LE;
  out_fmt.format = SND_PCM_FORMAT_S32_LE;
  in_fmt.num_channels = out_fmt.num_channels = 2;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  in_buff = (int16_t *)ralloc(buf_size * cras_get_format_bytes(&in_fmt));
  out_buff = (int32_t *)ralloc(buf_size * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (unsigned int i = 0; i < buf_size; i++)
    EXPECT_EQ(((int32_t)in_buff[i] << 16), out_buff[i]);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 16 to 24 bit conversion.
TEST(FormatConverterTest, ConvertS16LEToS24LE) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int16_t *in_buff;
  int32_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S16_LE;
  out_fmt.format = SND_PCM_FORMAT_S24_LE;
  in_fmt.num_channels = out_fmt.num_channels = 2;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  in_buff = (int16_t *)ralloc(buf_size * cras_get_format_bytes(&in_fmt));
  out_buff = (int32_t *)ralloc(buf_size * 2 * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (unsigned int i = 0; i < buf_size; i++)
    EXPECT_EQ(((int32_t)in_buff[i] << 8), out_buff[i]);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 16 to 8 bit conversion.
TEST(FormatConverterTest, ConvertS16LEToU8) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int16_t *in_buff;
  uint8_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S16_LE;
  out_fmt.format = SND_PCM_FORMAT_U8;
  in_fmt.num_channels = 2;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  in_buff = (int16_t *)ralloc(buf_size * cras_get_format_bytes(&in_fmt));
  out_buff = (uint8_t *)ralloc(buf_size * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (unsigned int i = 0; i < buf_size; i++)
    EXPECT_EQ((in_buff[i] >> 8) + 128, out_buff[i]);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 32 bit 5.1 to 16 bit stereo conversion.
TEST(FormatConverterTest, ConvertS32LEToS16LEDownmix51ToStereo) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int32_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;
  int i;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S32_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 6;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;
  for (i = 0; i < CRAS_CH_MAX; i++)
    in_fmt.channel_layout[i] = surround_channel_layout[i];

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  in_buff = (int32_t *)ralloc(buf_size * 2 * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 16 bit stereo to 5.1 conversion.
TEST(FormatConverterTest, ConvertS16LEToS16LEStereoTo51) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int16_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;
  int i;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S16_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 2;
  out_fmt.num_channels = 6;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;
  for (i = 0; i < CRAS_CH_MAX; i++)
    out_fmt.channel_layout[i] = surround_channel_layout[i];

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  in_buff = (int16_t *)ralloc(buf_size * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (unsigned int i = 0; i < buf_size; i++) {
    /* Check mono be converted to CRAS_CH_FL and CRAS_CH_FR */
    EXPECT_EQ(in_buff[2 * i], out_buff[6 * i]);
    EXPECT_EQ(in_buff[2 * i + 1], out_buff[6 * i + 1]);
    EXPECT_EQ(0, out_buff[6 * i + 2]);
    EXPECT_EQ(0, out_buff[6 * i + 3]);
    EXPECT_EQ(0, out_buff[6 * i + 4]);
    EXPECT_EQ(0, out_buff[6 * i + 5]);
  }

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 16 bit mono to 5.1 conversion.
TEST(FormatConverterTest, ConvertS16LEToS16LEMonoTo51) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int16_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;
  int i;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S16_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 1;
  out_fmt.num_channels = 6;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;
  for (i = 0; i < CRAS_CH_MAX; i++)
    out_fmt.channel_layout[i] = surround_channel_layout[i];

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size, out_frames);

  in_buff = (int16_t *)ralloc(buf_size * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(buf_size, out_frames);
  for (unsigned int i = 0; i < buf_size; i++) {
    /* Check mono be converted to CRAS_CH_FC */
    EXPECT_EQ(in_buff[i], out_buff[6 * i + 4]);
    EXPECT_EQ(0, out_buff[6 * i + 0]);
    EXPECT_EQ(0, out_buff[6 * i + 1]);
    EXPECT_EQ(0, out_buff[6 * i + 2]);
    EXPECT_EQ(0, out_buff[6 * i + 3]);
    EXPECT_EQ(0, out_buff[6 * i + 5]);
  }

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 32 bit 5.1 to 16 bit stereo conversion with SRC 1 to 2.
TEST(FormatConverterTest, ConvertS32LEToS16LEDownmix51ToStereo48To96) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int32_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;
  int i;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S32_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 6;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 96000;
  for (i = 0; i < CRAS_CH_MAX; i++)
    in_fmt.channel_layout[i] = surround_channel_layout[i];

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size * 2, out_frames);

  in_buff = (int32_t *)ralloc(buf_size * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size * 2 * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size * 2);
  EXPECT_EQ(buf_size * 2, out_frames);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 32 bit 5.1 to 16 bit stereo conversion with SRC 2 to 1.
TEST(FormatConverterTest, ConvertS32LEToS16LEDownmix51ToStereo96To48) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int32_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;
  int i;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S32_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 6;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 96000;
  out_fmt.frame_rate = 48000;
  for (i = 0; i < CRAS_CH_MAX; i++)
    in_fmt.channel_layout[i] = surround_channel_layout[i];

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size / 2, out_frames);

  in_buff = (int32_t *)ralloc(buf_size * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size / 2 * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size / 2);
  EXPECT_EQ(buf_size / 2, out_frames);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 32 bit 5.1 to 16 bit stereo conversion with SRC 48 to 44.1.
TEST(FormatConverterTest, ConvertS32LEToS16LEDownmix51ToStereo48To441) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  size_t ret_frames;
  int32_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;
  int i;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S32_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 6;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 44100;
  for (i = 0; i < CRAS_CH_MAX; i++)
    in_fmt.channel_layout[i] = surround_channel_layout[i];

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_LT(out_frames, buf_size);

  in_buff = (int32_t *)ralloc(buf_size * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(out_frames * cras_get_format_bytes(&out_fmt));
  ret_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            out_frames);
  EXPECT_EQ(out_frames, ret_frames);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test 32 bit 5.1 to 16 bit stereo conversion with SRC 441 to 48.
TEST(FormatConverterTest, ConvertS32LEToS16LEDownmix51ToStereo441To48) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  size_t ret_frames;
  int32_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;
  int i;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S32_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 6;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 44100;
  out_fmt.frame_rate = 48000;
  for (i = 0; i < CRAS_CH_MAX; i++)
    in_fmt.channel_layout[i] = surround_channel_layout[i];

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_GT(out_frames, buf_size);

  in_buff = (int32_t *)ralloc(buf_size * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc((out_frames - 1) *
                               cras_get_format_bytes(&out_fmt));
  ret_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            out_frames - 1);
  EXPECT_EQ(out_frames - 1, ret_frames);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test Invalid buffer length just truncates.
TEST(FormatConverterTest, ConvertS32LEToS16LEDownmix51ToStereo96To48Short) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  size_t ret_frames;
  int32_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;
  int i;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S32_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 6;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 96000;
  out_fmt.frame_rate = 48000;
  for (i = 0; i < CRAS_CH_MAX; i++)
    in_fmt.channel_layout[i] = surround_channel_layout[i];

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size, 0);
  ASSERT_NE(c, (void *)NULL);

  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(buf_size / 2, out_frames);

  in_buff = (int32_t *)ralloc(buf_size * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc((out_frames - 2) *
                               cras_get_format_bytes(&out_fmt));
  ret_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            out_frames - 2);
  EXPECT_EQ(out_frames - 2, ret_frames);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test format convert pre linear resample and then follows SRC from 96 to 48.
TEST(FormatConverterTest, Convert96to48PreLinearResample) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int32_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;
  unsigned int expected_fr;
  int i;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S16_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 2;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 96000;
  out_fmt.frame_rate = 48000;
  for (i = 0; i < CRAS_CH_MAX; i++) {
    in_fmt.channel_layout[i] = surround_channel_layout[i];
    out_fmt.channel_layout[i] = surround_channel_layout[i];
  }

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size * 2, 1);
  ASSERT_NE(c, (void *)NULL);

  linear_resampler_needed_val = 1;
  linear_resampler_ratio = 1.01;
  expected_fr = buf_size / 2 * linear_resampler_ratio;
  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(expected_fr, out_frames);

  in_buff = (int32_t *)ralloc(buf_size * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            out_frames);
  EXPECT_EQ(expected_fr, out_frames);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test format convert SRC from 96 to 48 and then post linear resample.
TEST(FormatConverterTest, Convert96to48PostLinearResample) {
  struct cras_fmt_conv *c;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  size_t out_frames;
  int32_t *in_buff;
  int16_t *out_buff;
  const size_t buf_size = 4096;
  unsigned int in_buf_size = 4096;
  unsigned int expected_fr;
  int i;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S16_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 2;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 96000;
  out_fmt.frame_rate = 48000;
  for (i = 0; i < CRAS_CH_MAX; i++) {
    in_fmt.channel_layout[i] = surround_channel_layout[i];
    out_fmt.channel_layout[i] = surround_channel_layout[i];
  }

  c = cras_fmt_conv_create(&in_fmt, &out_fmt, buf_size * 2, 0);
  ASSERT_NE(c, (void *)NULL);

  linear_resampler_needed_val = 1;
  linear_resampler_ratio = 0.99;
  expected_fr = buf_size / 2 * linear_resampler_ratio;
  out_frames = cras_fmt_conv_in_frames_to_out(c, buf_size);
  EXPECT_EQ(expected_fr, out_frames);

  in_buff = (int32_t *)ralloc(buf_size * cras_get_format_bytes(&in_fmt));
  out_buff = (int16_t *)ralloc(buf_size * cras_get_format_bytes(&out_fmt));
  out_frames = cras_fmt_conv_convert_frames(c,
                                            (uint8_t *)in_buff,
                                            (uint8_t *)out_buff,
                                            &in_buf_size,
                                            buf_size);
  EXPECT_EQ(expected_fr, out_frames);

  cras_fmt_conv_destroy(c);
  free(in_buff);
  free(out_buff);
}

// Test format converter created in config_format_converter
TEST(FormatConverterTest, ConfigConverter) {
  int i;
  struct cras_fmt_conv *c = NULL;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S16_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 1;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 96000;
  out_fmt.frame_rate = 48000;
  for (i = 0; i < CRAS_CH_MAX; i++) {
    in_fmt.channel_layout[i] = mono_channel_layout[i];
    out_fmt.channel_layout[i] = stereo_channel_layout[i];
  }

  config_format_converter(&c, CRAS_STREAM_OUTPUT, &in_fmt, &out_fmt, 4096);
  ASSERT_NE(c, (void *)NULL);

  cras_fmt_conv_destroy(c);
}

// Test format converter not created when in/out format conversion is not
// needed.
TEST(FormatConverterTest, ConfigConverterNoNeed) {
  int i;
  struct cras_fmt_conv *c = NULL;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S16_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 2;
  out_fmt.num_channels = 2;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;
  for (i = 0; i < CRAS_CH_MAX; i++) {
    in_fmt.channel_layout[i] = stereo_channel_layout[i];
    out_fmt.channel_layout[i] = stereo_channel_layout[i];
  }

  config_format_converter(&c, CRAS_STREAM_OUTPUT, &in_fmt, &out_fmt, 4096);
  EXPECT_NE(c, (void *)NULL);
  EXPECT_EQ(0, cras_fmt_conversion_needed(c));
}

// Test format converter not created for input when in/out format differs
// at channel count or layout.
TEST(FormatConverterTest, ConfigConverterNoNeedForInput) {
  static int kmic_channel_layout[CRAS_CH_MAX] =
    {0, 1, -1, -1, 2, -1, -1, -1, -1, -1, -1};
  int i;
  struct cras_fmt_conv *c = NULL;
  struct cras_audio_format in_fmt;
  struct cras_audio_format out_fmt;

  ResetStub();
  in_fmt.format = SND_PCM_FORMAT_S16_LE;
  out_fmt.format = SND_PCM_FORMAT_S16_LE;
  in_fmt.num_channels = 2;
  out_fmt.num_channels = 3;
  in_fmt.frame_rate = 48000;
  out_fmt.frame_rate = 48000;
  for (i = 0; i < CRAS_CH_MAX; i++) {
    in_fmt.channel_layout[i] = stereo_channel_layout[i];
    out_fmt.channel_layout[i] = kmic_channel_layout[i];
  }

  config_format_converter(&c, CRAS_STREAM_INPUT, &in_fmt, &out_fmt, 4096);
  EXPECT_NE(c, (void *)NULL);
  EXPECT_EQ(0, cras_fmt_conversion_needed(c));
}

TEST(ChannelRemixTest, ChannelRemixAppliedOrNot) {
  float coeff[4] = {0.5, 0.5, 0.26, 0.73};
  struct cras_fmt_conv *conv;
  struct cras_audio_format fmt;
  int16_t *buf, *res;
  unsigned i;

  fmt.num_channels = 2;
  conv = cras_channel_remix_conv_create(2, coeff);

  buf = (int16_t *)ralloc(50 * 4);
  res = (int16_t *)malloc(50 * 4);

  for (i = 0; i < 100; i += 2) {
    res[i] = coeff[0] * buf[i];
    res[i] += coeff[1] * buf[i + 1];
    res[i + 1] = coeff[2] * buf[i];
    res[i + 1] += coeff[3] * buf[i + 1];
  }

  cras_channel_remix_convert(conv, &fmt, (uint8_t *)buf, 50);
  for (i = 0; i < 100; i++)
    EXPECT_EQ(res[i],  buf[i]);

  /* If num_channels not match, remix conversion will not apply. */
  fmt.num_channels = 6;
  cras_channel_remix_convert(conv, &fmt, (uint8_t *)buf, 50);
  for (i = 0; i < 100; i++)
    EXPECT_EQ(res[i],  buf[i]);

  cras_fmt_conv_destroy(conv);
}

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

extern "C" {
float** cras_channel_conv_matrix_alloc(size_t in_ch, size_t out_ch)
{
  int i;
  float** conv_mtx;
  conv_mtx = (float **)calloc(CRAS_CH_MAX, sizeof(*conv_mtx));
  for (i = 0; i < CRAS_CH_MAX; i++)
    conv_mtx[i] = (float *)calloc(CRAS_CH_MAX, sizeof(*conv_mtx[i]));
  return conv_mtx;
}
void cras_channel_conv_matrix_destroy(float **mtx, size_t out_ch)
{
  int i;
  for (i = 0; i < CRAS_CH_MAX; i++)
    free(mtx[i]);
  free(mtx);
}
float **cras_channel_conv_matrix_create(const struct cras_audio_format *in,
					const struct cras_audio_format *out)
{
  return cras_channel_conv_matrix_alloc(in->num_channels,
					out->num_channels);
}
struct linear_resampler *linear_resampler_create(unsigned int num_channels,
             unsigned int format_bytes,
             float src_rate,
             float dst_rate)
{
  return reinterpret_cast<struct linear_resampler*>(0x33);;
}

int linear_resampler_needed(struct linear_resampler *lr)
{
  return linear_resampler_needed_val;
}

void linear_resampler_set_rates(struct linear_resampler *lr,
                                unsigned int from,
                                unsigned int to)
{
}

unsigned int linear_resampler_out_frames_to_in(struct linear_resampler *lr,
                                               unsigned int frames)
{
  return (double)frames / linear_resampler_ratio;
}

/* Converts the frames count from input rate to output rate. */
unsigned int linear_resampler_in_frames_to_out(struct linear_resampler *lr,
                                               unsigned int frames)
{
  return (double)frames * linear_resampler_ratio;
}

unsigned int linear_resampler_resample(struct linear_resampler *lr,
           uint8_t *src,
           unsigned int *src_frames,
           uint8_t *dst,
           unsigned dst_frames)
{
  unsigned int resampled_fr = *src_frames * linear_resampler_ratio;

  if (resampled_fr > dst_frames) {
    resampled_fr = dst_frames;
    *src_frames = dst_frames / linear_resampler_ratio;
  }

  return resampled_fr;
}

void linear_resampler_destroy(struct linear_resampler *lr)
{
}
} // extern "C"