Anki-Android icon indicating copy to clipboard operation
Anki-Android copied to clipboard

TTS volume adjusting

Open John4650-hub opened this issue 1 year ago • 7 comments

INTRO

I don't know whether this has already been added but it hasn't then i wish you add it.

REASON

In my cards i usually add recorded audios explaining some concepts and the tone at which they are recorded is always low so i when am reviewing, i always adjust the volume to be able to listen clearly but a problem comes when the next card comes up, the volume used by the TTS engine is always very loud and kinda makes reviewing painful because now i have to re-adjust the volume. Thanks for the work you are doing.

John4650-hub avatar Jan 22 '24 06:01 John4650-hub

Hello! 👋 Thanks for logging this issue. Please remember we are all volunteers here, so some patience may be required before we can get to the issue. Also remember that the fastest way to get resolution on an issue is to propose a change directly, https://github.com/ankidroid/Anki-Android/wiki/Contributing

welcome[bot] avatar Jan 22 '24 06:01 welcome[bot]

How should this be implemented? E.g. with a volume slider in the settings, where you toggle TTS on and off? I might work on this.

elli-hae avatar Jan 30 '24 17:01 elli-hae

@elli-hae ,thanks for replying. I think their should be a slider somewhere in the settings , which can be used to set the TTS volume which should then be applied to all cards in a deck when TTS is enabled during reviewing. That way the general device volume remains unchanged. For audio recordings they can remain dependant on the system volume.

John4650-hub avatar Feb 04 '24 11:02 John4650-hub

Would adding an AnkiDroid Volume to the TTS tag resolve this issue?

{{tts en_GB ad_volume=20:Front}}

patch
Index: AnkiDroid/src/main/java/com/ichi2/anki/AndroidTtsPlayer.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AndroidTtsPlayer.kt b/AnkiDroid/src/main/java/com/ichi2/anki/AndroidTtsPlayer.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/AndroidTtsPlayer.kt	(revision 906dd02571179f3096af4cdf32a924385c2af4b2)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/AndroidTtsPlayer.kt	(date 1708285933163)
@@ -20,7 +20,9 @@
 import android.os.Bundle
 import android.speech.tts.TextToSpeech
 import android.speech.tts.TextToSpeech.ERROR
+import android.speech.tts.TextToSpeech.Engine.KEY_PARAM_VOLUME
 import androidx.annotation.CheckResult
+import androidx.core.os.bundleOf
 import com.ichi2.anki.AndroidTtsError.TtsErrorCode
 import com.ichi2.compat.UtteranceProgressListenerCompat
 import com.ichi2.libanki.TTSTag
@@ -117,7 +119,10 @@
                 currentUtterance = this
                 cancelledUtterances.remove(this)
             }
-            tts.speak(tag.fieldText, TextToSpeech.QUEUE_FLUSH, bundleFlyweight, utteranceId)
+            val bundle = tag.volume?.let {
+                bundleOf(KEY_PARAM_VOLUME to it / 100)
+            } ?: bundleFlyweight
+            tts.speak(tag.fieldText, TextToSpeech.QUEUE_FLUSH, bundle, utteranceId)
 
             continuation.invokeOnCancellation {
                 Timber.d("stopping tts due to cancellation")
@@ -223,3 +228,16 @@
     } else {
         this.toString()
     }
+
+/**
+ * Returns the custom `ad_volume=` parameter, from 0 to 100
+ *
+ * `{{tts en_GB ad_volume=30:Front}}`
+ */
+val TTSTag.volume: Float?
+    get() {
+        val volumeParam = this.otherArgs.firstOrNull { it.lowercase().startsWith("ad_volume=")} ?: return null
+        val volume = volumeParam.substring("ad_volume=".length).toFloatOrNull() ?: return null
+        if (volume < 0 || volume > 100) return null
+        return volume
+    }
\ No newline at end of file

david-allison avatar Feb 18 '24 19:02 david-allison

I think that's reasonable to try to get this in upstream first, so the TTS format is as much cross-platform as possible

BrayanDSO avatar Feb 18 '24 21:02 BrayanDSO

We don't want volume to be consistent across the platforms: each platform uses a different voice with different volume characteristics

david-allison avatar Feb 18 '24 23:02 david-allison

Very reasonable

BrayanDSO avatar Feb 19 '24 00:02 BrayanDSO

That approach makes a lot more sense! @John4650-hub are you satisfied with this fix then?

elli-hae avatar Feb 29 '24 16:02 elli-hae

Would adding an AnkiDroid Volume to the TTS tag resolve this issue?

{{tts en_GB ad_volume=20:Front}}

patch

Index: AnkiDroid/src/main/java/com/ichi2/anki/AndroidTtsPlayer.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AndroidTtsPlayer.kt b/AnkiDroid/src/main/java/com/ichi2/anki/AndroidTtsPlayer.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/AndroidTtsPlayer.kt	(revision 906dd02571179f3096af4cdf32a924385c2af4b2)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/AndroidTtsPlayer.kt	(date 1708285933163)
@@ -20,7 +20,9 @@
 import android.os.Bundle
 import android.speech.tts.TextToSpeech
 import android.speech.tts.TextToSpeech.ERROR
+import android.speech.tts.TextToSpeech.Engine.KEY_PARAM_VOLUME
 import androidx.annotation.CheckResult
+import androidx.core.os.bundleOf
 import com.ichi2.anki.AndroidTtsError.TtsErrorCode
 import com.ichi2.compat.UtteranceProgressListenerCompat
 import com.ichi2.libanki.TTSTag
@@ -117,7 +119,10 @@
                 currentUtterance = this
                 cancelledUtterances.remove(this)
             }
-            tts.speak(tag.fieldText, TextToSpeech.QUEUE_FLUSH, bundleFlyweight, utteranceId)
+            val bundle = tag.volume?.let {
+                bundleOf(KEY_PARAM_VOLUME to it / 100)
+            } ?: bundleFlyweight
+            tts.speak(tag.fieldText, TextToSpeech.QUEUE_FLUSH, bundle, utteranceId)
 
             continuation.invokeOnCancellation {
                 Timber.d("stopping tts due to cancellation")
@@ -223,3 +228,16 @@
     } else {
         this.toString()
     }
+
+/**
+ * Returns the custom `ad_volume=` parameter, from 0 to 100
+ *
+ * `{{tts en_GB ad_volume=30:Front}}`
+ */
+val TTSTag.volume: Float?
+    get() {
+        val volumeParam = this.otherArgs.firstOrNull { it.lowercase().startsWith("ad_volume=")} ?: return null
+        val volume = volumeParam.substring("ad_volume=".length).toFloatOrNull() ?: return null
+        if (volume < 0 || volume > 100) return null
+        return volume
+    }
\ No newline at end of file

Yes.

John4650-hub avatar Mar 02 '24 02:03 John4650-hub

Hello 👋, this issue has been opened for more than 3 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically

github-actions[bot] avatar May 31 '24 02:05 github-actions[bot]