#include "chromeos/services/tts/tts_service.h"
#include "chromeos/services/tts/public/mojom/tts_service.mojom.h"
#include "chromeos/services/tts/tts_test_utils.h"
#include "media/base/audio_bus.h"
namespace chromeos {
namespace tts {
namespace {
class TtsServiceTest : public TtsTestBase {
public:
TtsServiceTest() : service_(remote_service_.BindNewPipeAndPassReceiver()) {}
TtsServiceTest(const TtsServiceTest&) = delete;
TtsServiceTest& operator=(const TtsServiceTest&) = delete;
~TtsServiceTest() override = default;
protected:
void InitPlaybackTtsStream(mojo::Remote<mojom::PlaybackTtsStream>* stream) {
if (audio_stream_factory_.is_bound())
audio_stream_factory_.reset();
auto callback = base::BindOnce([](mojom::AudioParametersPtr) {
});
mojom::AudioParametersPtr desired_audio_parameters =
mojom::AudioParameters::New(20000 ,
128 );
remote_service_->BindPlaybackTtsStream(
stream->BindNewPipeAndPassReceiver(),
audio_stream_factory_.BindNewPipeAndPassRemote(),
std::move(desired_audio_parameters), std::move(callback));
remote_service_.FlushForTesting();
}
void SetUp() override { service_.set_keep_process_alive_for_testing(true); }
mojo::Remote<mojom::TtsService> remote_service_;
TtsService service_;
};
TEST_F(TtsServiceTest, DisconnectPlaybackStream) {
mojo::Remote<mojom::PlaybackTtsStream> stream1;
InitPlaybackTtsStream(&stream1);
EXPECT_TRUE(service_.receiver_for_testing()->is_bound());
stream1.reset();
service_.playback_tts_stream_for_testing()->FlushForTesting();
EXPECT_FALSE(service_.receiver_for_testing()->is_bound());
}
TEST_F(TtsServiceTest, BasicAudioBuffering) {
mojo::Remote<mojom::PlaybackTtsStream> playback_tts_stream;
InitPlaybackTtsStream(&playback_tts_stream);
MockTtsEventObserver backing_observer;
mojo::Receiver<mojom::TtsEventObserver> observer(&backing_observer);
playback_tts_stream->Play(base::BindOnce(
[](mojo::Receiver<mojom::TtsEventObserver>* receiver,
mojo::PendingReceiver<mojom::TtsEventObserver> pending_receiver) {
receiver->Bind(std::move(pending_receiver));
},
&observer));
playback_tts_stream.FlushForTesting();
service_.playback_tts_stream_for_testing()->FlushForTesting();
auto bus = media::AudioBus::Create(1 , 512 );
service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render(
base::Seconds(0), base::TimeTicks::Now(), {} ,
bus.get());
observer.FlushForTesting();
EXPECT_EQ(1, backing_observer.start_count);
EXPECT_TRUE(backing_observer.char_indices.empty());
EXPECT_EQ(0, backing_observer.end_count);
playback_tts_stream->SendAudioBuffer(
std::vector<float>(), 100 , false );
playback_tts_stream.FlushForTesting();
service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render(
base::Seconds(0), base::TimeTicks::Now(), {} ,
bus.get());
observer.FlushForTesting();
EXPECT_EQ(1, backing_observer.start_count);
EXPECT_EQ(1U, backing_observer.char_indices.size());
EXPECT_EQ(100, backing_observer.char_indices[0]);
EXPECT_EQ(0, backing_observer.end_count);
playback_tts_stream->SendAudioBuffer(
std::vector<float>(), 9999 , true );
playback_tts_stream.FlushForTesting();
service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render(
base::Seconds(0), base::TimeTicks::Now(), {} ,
bus.get());
observer.FlushForTesting();
EXPECT_EQ(1, backing_observer.start_count);
EXPECT_EQ(1U, backing_observer.char_indices.size());
EXPECT_EQ(1, backing_observer.end_count);
}
TEST_F(TtsServiceTest, ExplicitAudioTimepointing) {
mojo::Remote<mojom::PlaybackTtsStream> playback_tts_stream;
InitPlaybackTtsStream(&playback_tts_stream);
MockTtsEventObserver backing_observer;
mojo::Receiver<mojom::TtsEventObserver> observer(&backing_observer);
playback_tts_stream->Play(base::BindOnce(
[](mojo::Receiver<mojom::TtsEventObserver>* receiver,
mojo::PendingReceiver<mojom::TtsEventObserver> pending_receiver) {
receiver->Bind(std::move(pending_receiver));
},
&observer));
playback_tts_stream.FlushForTesting();
auto bus = media::AudioBus::Create(1 , 512 );
service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render(
base::Seconds(0), base::TimeTicks::Now(), {} ,
bus.get());
observer.FlushForTesting();
EXPECT_EQ(1, backing_observer.start_count);
EXPECT_TRUE(backing_observer.char_indices.empty());
EXPECT_EQ(0, backing_observer.end_count);
playback_tts_stream->SendAudioBuffer(
std::vector<float>(), -1 , false );
playback_tts_stream.FlushForTesting();
service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render(
base::Seconds(0), base::TimeTicks::Now(), {} ,
bus.get());
observer.FlushForTesting();
EXPECT_EQ(1, backing_observer.start_count);
EXPECT_TRUE(backing_observer.char_indices.empty());
EXPECT_EQ(0, backing_observer.end_count);
playback_tts_stream->SendAudioBuffer(
std::vector<float>(), -1 , false );
service_.playback_tts_stream_for_testing()
->tts_player_for_testing()
->AddExplicitTimepoint(100, base::Seconds(0));
service_.playback_tts_stream_for_testing()
->tts_player_for_testing()
->AddExplicitTimepoint(200, base::Seconds(0));
service_.playback_tts_stream_for_testing()
->tts_player_for_testing()
->AddExplicitTimepoint(300, base::Seconds(0));
playback_tts_stream.FlushForTesting();
service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render(
base::Seconds(0), base::TimeTicks::Now(), {} ,
bus.get());
observer.FlushForTesting();
EXPECT_EQ(1, backing_observer.start_count);
EXPECT_EQ(3U, backing_observer.char_indices.size());
EXPECT_EQ(100, backing_observer.char_indices[0]);
EXPECT_EQ(200, backing_observer.char_indices[1]);
EXPECT_EQ(300, backing_observer.char_indices[2]);
EXPECT_EQ(0, backing_observer.end_count);
playback_tts_stream->SendAudioBuffer(
std::vector<float>(), 9999 , true );
playback_tts_stream.FlushForTesting();
service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render(
base::Seconds(0), base::TimeTicks::Now(), {} ,
bus.get());
observer.FlushForTesting();
EXPECT_EQ(1, backing_observer.start_count);
EXPECT_EQ(3U, backing_observer.char_indices.size());
EXPECT_EQ(1, backing_observer.end_count);
}
}
}
}