karashiiro / TextToTalk

Chat TTS plugin for Dalamud. Has support for triggers/exclusions, several TTS providers, and more!
MIT License
46 stars 30 forks source link

Add configuration option to disable stutter remover #118

Closed ryankhart closed 2 years ago

ryankhart commented 2 years ago

I'm not proud of the way I did the config.RemoveStutterEnabled conditional. I couldn't figure out an elegant way to use lamda or a += syntax with the way it's currently set up. I also tried and failed to read from the PluginConfiguration from inside the TalkUtils.cs but couldn't because its a static class. I'm interested to see if there's a better way to do this.

This PR is an attempt to provide contributors a testing tool for improving the stutter remover and to provide users a workaround for issues like this one: https://github.com/karashiiro/TextToTalk/issues/86

ryankhart commented 2 years ago

Ok, I just found out that was I was trying to do was apparently impossible according to this answer: https://stackoverflow.com/a/16677508/717674

I think that just leaves putting the conditional inside the TalkUtils class, but I'm not sure how to set that up since it is a static class and without access to a PluginConfiguration object to read from.

karashiiro commented 2 years ago

Off the top of my head, here are two ways of doing it cleanly:

  1. Create a middleware like the rate limiter, and have a callback control what happens according to the config.
  2. Use a lambda that just has t => this.config.DisableStutters ? t : RemoveStutters(t). If you wanted to make this cleaner, you could just extract it out to a separate function.
karashiiro commented 2 years ago

So long as your lambda takes a string and returns a string, it should work fine.

ryankhart commented 2 years ago

Wow, I guess I still struggle to understand exactly how lambdas work, but I tried option 2, and it worked.

I'm still a little confused about how Pipe works, more specifically, how Aggegate works. It seems to take the textValue and pass it as a param to all the Pipe params, which are funcs. And those funcs take the textValue as their own param. And when a lambda is used, the variable to the left of => is the value of textValue after it's been modified by all the previous param funcs?

karashiiro commented 2 years ago

That's correct, it's basically just a forced implementation of a pipe operator to save having to write textValue = Fn(textValue); a half-dozen times. You could also imagine it as aggregating some transformations F1, F2, F3 together with a parameter t into the (messy) composition F3(F2(F1(t)));

karashiiro commented 2 years ago

It's definitely not idiomatic C#, but I didn't feel like writing out either of the "standard" patterns for what I wanted to do.

ryankhart commented 2 years ago

Sweet, I'm learning all sorts of things!