#include "chromeos/services/tts/tts_player.h"
#include "chromeos/services/tts/constants.h"
#include "chromeos/services/tts/tts_test_utils.h"
#include "media/base/audio_bus.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace chromeos {
namespace tts {
namespace {
class TtsPlayerTest : public TtsTestBase {
public:
TtsPlayerTest()
: tts_player_(audio_stream_factory_.BindNewPipeAndPassRemote(),
std::move(media::AudioParameters(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::ChannelLayoutConfig::Mono(),
kDefaultSampleRate,
kDefaultBufferSize))),
observer_(&backing_observer_) {}
TtsPlayerTest(const TtsPlayerTest&) = delete;
TtsPlayerTest& operator=(const TtsPlayerTest&) = delete;
~TtsPlayerTest() override = default;
protected:
void AddAudioBuffer(const std::vector<float>& frames,
int32_t char_index,
int32_t status) {
TtsPlayer::AudioBuffer buffer;
buffer.frames = frames;
buffer.char_index = char_index;
buffer.status = status;
tts_player_.AddAudioBuffer(std::move(buffer));
}
void SetUp() override {
tts_player_.Play(base::BindOnce(
[](mojo::Receiver<mojom::TtsEventObserver>* receiver,
mojo::PendingReceiver<mojom::TtsEventObserver> pending_receiver) {
receiver->Bind(std::move(pending_receiver));
},
&observer_));
}
TtsPlayer tts_player_;
MockTtsEventObserver backing_observer_;
mojo::Receiver<mojom::TtsEventObserver> observer_;
};
TEST_F(TtsPlayerTest, RenderNoFramesFromEmptyBuffer) {
auto bus = media::AudioBus::Create(1, 512);
tts_player_.Render(base::Seconds(0), base::TimeTicks::Now(),
{} , bus.get());
observer_.FlushForTesting();
EXPECT_EQ(0, backing_observer_.start_count);
EXPECT_TRUE(backing_observer_.char_indices.empty());
EXPECT_EQ(0, backing_observer_.end_count);
AddAudioBuffer(std::vector<float>(), 0 , 1 );
int frames_rendered =
tts_player_.Render(base::Seconds(0), base::TimeTicks::Now(),
{} , bus.get());
observer_.FlushForTesting();
EXPECT_EQ(0, backing_observer_.start_count);
ASSERT_EQ(1U, backing_observer_.char_indices.size());
EXPECT_EQ(0, backing_observer_.char_indices[0]);
EXPECT_EQ(0, backing_observer_.end_count);
EXPECT_EQ(0, frames_rendered);
}
TEST_F(TtsPlayerTest, RenderSingleFrame) {
auto bus = media::AudioBus::Create(1, 512);
tts_player_.Render(base::Seconds(0), base::TimeTicks::Now(),
{} , bus.get());
observer_.FlushForTesting();
EXPECT_EQ(0, backing_observer_.start_count);
EXPECT_TRUE(backing_observer_.char_indices.empty());
EXPECT_EQ(0, backing_observer_.end_count);
AddAudioBuffer(std::vector<float>({0.7}), 1 ,
0 );
int frames_rendered =
tts_player_.Render(base::Seconds(0), base::TimeTicks::Now(),
{} , bus.get());
observer_.FlushForTesting();
EXPECT_EQ(0, backing_observer_.start_count);
EXPECT_TRUE(backing_observer_.char_indices.empty());
EXPECT_EQ(1, backing_observer_.end_count);
EXPECT_EQ(1, frames_rendered);
auto actual = bus->channel_span(0).first<1u>();
constexpr std::array<float, 1> kExpected = {0.7};
EXPECT_EQ(actual, base::span(kExpected));
}
TEST_F(TtsPlayerTest, RenderFramesFromPartialBuffers) {
auto bus = media::AudioBus::Create(1, 5);
tts_player_.Render(base::Seconds(0), base::TimeTicks::Now(),
{} , bus.get());
observer_.FlushForTesting();
EXPECT_EQ(0, backing_observer_.start_count);
EXPECT_TRUE(backing_observer_.char_indices.empty());
EXPECT_EQ(0, backing_observer_.end_count);
AddAudioBuffer(std::vector<float>({0.1, 0.2, 0.3}), 1 ,
1 );
AddAudioBuffer(std::vector<float>({0.4, 0.5}), 2 ,
0 );
int frames_rendered =
tts_player_.Render(base::Seconds(0), base::TimeTicks::Now(),
{} , bus.get());
observer_.FlushForTesting();
EXPECT_EQ(0, backing_observer_.start_count);
ASSERT_EQ(1U, backing_observer_.char_indices.size());
EXPECT_EQ(1, backing_observer_.char_indices[0]);
EXPECT_EQ(1, backing_observer_.end_count);
EXPECT_EQ(5, frames_rendered);
auto actual = bus->channel_span(0).first<5u>();
constexpr std::array<float, 5> kExpected = {0.1, 0.2, 0.3, 0.4, 0.5};
EXPECT_EQ(actual, base::span(kExpected));
}
TEST_F(TtsPlayerTest, RenderBusWithFramesFromEmptyAndPartialBuffers) {
auto bus = media::AudioBus::Create(1, 5);
tts_player_.Render(base::Seconds(0), base::TimeTicks::Now(),
{} , bus.get());
observer_.FlushForTesting();
EXPECT_EQ(0, backing_observer_.start_count);
EXPECT_TRUE(backing_observer_.char_indices.empty());
EXPECT_EQ(0, backing_observer_.end_count);
AddAudioBuffer(std::vector<float>({}), 0 , 1 );
AddAudioBuffer(std::vector<float>({0.1, 0.2, 0.3}), 1 ,
1 );
AddAudioBuffer(std::vector<float>({0.4}), 2 , 1 );
AddAudioBuffer(std::vector<float>({}), 3 , 1 );
AddAudioBuffer(std::vector<float>({}), 4 , 1 );
AddAudioBuffer(std::vector<float>({0.5}), 5 , 1 );
AddAudioBuffer(std::vector<float>({}), 6 ,
0 );
int frames_rendered =
tts_player_.Render(base::Seconds(0), base::TimeTicks::Now(),
{} , bus.get());
observer_.FlushForTesting();
EXPECT_EQ(0, backing_observer_.start_count);
ASSERT_EQ(6U, backing_observer_.char_indices.size());
EXPECT_EQ(0, backing_observer_.char_indices[0]);
EXPECT_EQ(1, backing_observer_.char_indices[1]);
EXPECT_EQ(2, backing_observer_.char_indices[2]);
EXPECT_EQ(3, backing_observer_.char_indices[3]);
EXPECT_EQ(4, backing_observer_.char_indices[4]);
EXPECT_EQ(5, backing_observer_.char_indices[5]);
EXPECT_EQ(0, backing_observer_.end_count);
EXPECT_EQ(5, frames_rendered);
auto actual = bus->channel_span(0).first<5u>();
constexpr std::array<float, 5> kExpected = {0.1, 0.2, 0.3, 0.4, 0.5};
EXPECT_EQ(actual, base::span(kExpected));
}
TEST_F(TtsPlayerTest, RenderMultiBusFromMultiBuffers) {
auto first_bus = media::AudioBus::Create(1, 5);
tts_player_.Render(base::Seconds(0), base::TimeTicks::Now(),
{} , first_bus.get());
observer_.FlushForTesting();
EXPECT_EQ(0, backing_observer_.start_count);
EXPECT_TRUE(backing_observer_.char_indices.empty());
EXPECT_EQ(0, backing_observer_.end_count);
AddAudioBuffer(std::vector<float>({}), 0 , 1 );
AddAudioBuffer(std::vector<float>({0.1, 0.2, 0.3}), 1 ,
1 );
AddAudioBuffer(std::vector<float>({0.4, 0.5, 0.6, 0.7}), 2 ,
1 );
AddAudioBuffer(std::vector<float>({}), 3 ,
0 );
int frames_rendered =
tts_player_.Render(base::Seconds(0), base::TimeTicks::Now(),
{} , first_bus.get());
observer_.FlushForTesting();
EXPECT_EQ(0, backing_observer_.start_count);
ASSERT_EQ(2U, backing_observer_.char_indices.size());
EXPECT_EQ(0, backing_observer_.char_indices[0]);
EXPECT_EQ(1, backing_observer_.char_indices[1]);
EXPECT_EQ(0, backing_observer_.end_count);
EXPECT_EQ(5, frames_rendered);
auto first_actual = first_bus->channel_span(0).first<5u>();
constexpr std::array<float, 5> kFirstExpected = {0.1, 0.2, 0.3, 0.4, 0.5};
EXPECT_EQ(first_actual, base::span(kFirstExpected));
auto second_bus = media::AudioBus::Create(1, 5);
frames_rendered = tts_player_.Render(base::Seconds(0), base::TimeTicks::Now(),
{} , second_bus.get());
observer_.FlushForTesting();
EXPECT_EQ(0, backing_observer_.start_count);
ASSERT_EQ(3U, backing_observer_.char_indices.size());
EXPECT_EQ(0, backing_observer_.char_indices[0]);
EXPECT_EQ(1, backing_observer_.char_indices[1]);
EXPECT_EQ(2, backing_observer_.char_indices[2]);
EXPECT_EQ(1, backing_observer_.end_count);
EXPECT_EQ(2, frames_rendered);
auto second_actual = second_bus->channel_span(0).first<2u>();
constexpr std::array<float, 2> kSecondExpected = {0.6, 0.7};
EXPECT_THAT(second_actual, base::span(kSecondExpected));
}
}
}
}