Files
TiedUp-/src/main/java/com/tiedup/remake/dialogue/EmotionalContext.java
NotEvil f6466360b6 Clean repo for open source release
Remove build artifacts, dev tool configs, unused dependencies,
and third-party source dumps. Add proper README, update .gitignore,
clean up Makefile.
2026-04-12 00:51:22 +02:00

271 lines
7.8 KiB
Java

package com.tiedup.remake.dialogue;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Detects and applies emotional context to gagged speech.
*/
public class EmotionalContext {
/**
* Types of emotional expression that affect speech transformation.
*/
public enum EmotionType {
NORMAL,
SHOUTING,
WHISPERING,
QUESTIONING,
PLEADING,
DISTRESSED,
LAUGHING,
CRYING,
}
// Pattern for extended vowels (nooooo, heeelp, pleeease)
private static final Pattern EXTENDED_VOWELS = Pattern.compile(
"([aeiou])\\1{2,}",
Pattern.CASE_INSENSITIVE
);
// Pattern for laughing (haha, hehe, lol)
private static final Pattern LAUGHING_PATTERN = Pattern.compile(
"(ha){2,}|(he){2,}|(hi){2,}|lol|lmao|xd",
Pattern.CASE_INSENSITIVE
);
// Pattern for crying indicators
private static final Pattern CRYING_PATTERN = Pattern.compile(
"\\*(?:sob|cry|sniff|whimper)s?\\*|;-?;|T[-_]T|:'+\\(",
Pattern.CASE_INSENSITIVE
);
// Pleading keywords
private static final Set<String> PLEADING_WORDS = Set.of(
"please",
"help",
"stop",
"no",
"don't",
"dont",
"wait",
"s'il vous plait",
"svp",
"aide",
"aidez",
"arrete",
"arreter",
"non",
"mercy",
"spare",
"let me go",
"release"
);
// Whispering indicators
private static final Set<String> WHISPERING_INDICATORS = Set.of(
"*whisper*",
"*whispers*",
"*quietly*",
"*softly*",
"(whisper)",
"(quietly)"
);
/**
* Detect the emotional context of a message or word.
*
* @param text The text to analyze
* @return The detected emotion type
*/
public static EmotionType detectEmotion(String text) {
if (text == null || text.isEmpty()) {
return EmotionType.NORMAL;
}
String lower = text.toLowerCase();
// Check for explicit emotional markers first
if (CRYING_PATTERN.matcher(text).find()) {
return EmotionType.CRYING;
}
if (LAUGHING_PATTERN.matcher(text).find()) {
return EmotionType.LAUGHING;
}
// Check for whispering indicators
for (String indicator : WHISPERING_INDICATORS) {
if (lower.contains(indicator)) {
return EmotionType.WHISPERING;
}
}
// Check for shouting (ALL CAPS with 3+ letters, or multiple !)
String letters = text.replaceAll("[^a-zA-Z]", "");
if (letters.length() >= 3 && letters.equals(letters.toUpperCase())) {
return EmotionType.SHOUTING;
}
// Require at least 2 exclamation marks for shouting
if (text.contains("!!") || text.contains("!?") || text.contains("?!")) {
return EmotionType.SHOUTING;
}
// Check for questioning
if (text.endsWith("?") || text.endsWith("??")) {
return EmotionType.QUESTIONING;
}
// Check for distress (extended vowels: nooooo, heeelp)
if (EXTENDED_VOWELS.matcher(text).find()) {
return EmotionType.DISTRESSED;
}
// Check for pleading keywords
for (String word : PLEADING_WORDS) {
if (lower.contains(word)) {
return EmotionType.PLEADING;
}
}
return EmotionType.NORMAL;
}
/**
* Apply emotional modifiers to a muffled message.
*
* @param muffled The muffled text
* @param emotion The detected emotion type
* @return Modified text with emotional expression
*/
public static String applyEmotionalModifiers(
String muffled,
EmotionType emotion
) {
if (muffled == null || muffled.isEmpty()) {
return muffled;
}
switch (emotion) {
case SHOUTING:
// Convert to uppercase and emphasize
return (
muffled.toUpperCase() + (muffled.endsWith("!") ? "!" : "!!")
);
case WHISPERING:
// Softer, shorter sounds
return "*" + muffled.toLowerCase() + "*";
case QUESTIONING:
// Rising intonation
String question = muffled.endsWith("?")
? muffled
: muffled + "?";
return question.replace("mm", "mn").replace("nn", "nh");
case PLEADING:
// Add whimpering
return muffled + "-mm..";
case DISTRESSED:
// Extend the dominant sound
return extendDominantSound(muffled);
case LAUGHING:
// Muffled laughter
return muffled.replace("mm", "hm").replace("nn", "hn") + "-hm";
case CRYING:
// Add sobbing sounds
return "*hic* " + muffled + " *mm*";
case NORMAL:
default:
return muffled;
}
}
/**
* Extend the dominant/repeated sound in a muffled word for distress effect.
*/
private static String extendDominantSound(String text) {
if (text == null || text.length() < 2) {
return text;
}
StringBuilder result = new StringBuilder();
char prev = 0;
int repeatCount = 0;
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (c == prev && Character.isLetter(c)) {
repeatCount++;
// Extend repeated sounds
if (repeatCount <= 3) {
result.append(c);
}
} else {
result.append(c);
repeatCount = 1;
}
prev = c;
}
// If no extension happened, extend the last vowel-like sound
String str = result.toString();
if (str.equals(text)) {
// Find last 'm' or 'n' or vowel and extend it
int lastExtendable = -1;
for (int i = str.length() - 1; i >= 0; i--) {
char c = Character.toLowerCase(str.charAt(i));
if (c == 'm' || c == 'n' || c == 'a' || c == 'o' || c == 'u') {
lastExtendable = i;
break;
}
}
if (lastExtendable >= 0) {
char ext = str.charAt(lastExtendable);
return (
str.substring(0, lastExtendable + 1) +
ext +
ext +
str.substring(lastExtendable + 1)
);
}
}
return result.toString();
}
/**
* Get the intensity multiplier for an emotion.
* Higher intensity = more muffling effect.
*
* @param emotion The emotion type
* @return Intensity multiplier (1.0 = normal)
*/
public static float getIntensityMultiplier(EmotionType emotion) {
switch (emotion) {
case SHOUTING:
return 1.3f; // Harder to understand when shouting
case WHISPERING:
return 0.7f; // Easier (softer, clearer)
case DISTRESSED:
return 1.2f;
case CRYING:
return 1.4f;
case LAUGHING:
return 1.1f;
case PLEADING:
case QUESTIONING:
case NORMAL:
default:
return 1.0f;
}
}
/**
* Check if the emotion should preserve more of the original text.
* Some emotions (like whispering) are clearer.
*/
public static boolean shouldPreserveMore(EmotionType emotion) {
return emotion == EmotionType.WHISPERING;
}
}