少し前にバズっていた以下の記事があまりに面白かったので
この絶頂度計算なるものを誰か編み出してくれないかなーと思っていたのですが誰もやってくれないので自分で考えてみました。
結論としてあまり良い結果は得られませんでしたが、firebaseで公開しましたのでよかったら遊んでみてください。
記事内容からの仕様読み取り
「あえぎエディタ.xls」と題されたエクセルファイルは、前任者が残したあえぎ声専用のマクロ
Excelのマクロ(VBA)で作成されている。この場合、分かち書きなどはできないはずなので、特定の発言をしていればポイントを高くするなどの文章解析処理にあたるものは行なっていない可能性が高い。
縦に並んだセルにセリフを一つずつ入力していくと、各セリフに含まれる母音・子音等の音声的要素が自動で数値化される。
さらに、その数値を足し引き計算することで、「絶頂度」と呼ばれる値が算出される仕組み
母音・子音に分解し、数値を足し引き計算しているだけで算出している。
あえぎ声を入力するセルには、理論上どんな文章も入れることができる。
つまり、あえぎ声以外のテキストでも、その「絶頂度」を算出できるのだ。
この絶頂度計算の仕組みは本来あえぎ声を計算することだけを想定したものであり、作者は通常の文章までカバーすることまでは想定していなかったはず。
さらに、テキストの長さを調整することも重要だ。
短すぎると気持ちいい感じが伝わらないのだが、かといって長すぎるとボイスが冗長になる。
文章の長さが重要。短すぎるのも長すぎるのもダメ。
「私はその人を常に先生と呼んでいた。」は12、「親譲りの無鉄砲で小供の時から損ばかりしている。」は30という具合だ。
とくに顕著なのは芥川で、「下人の行方は、誰も知らない。」など絶頂度367だ。
薬漬けになった人妻が白目を剥いて失神するシーンでもせいぜい330程度
大学名によっても異なるが、概して「卒業」よりも「中退」のほうが絶頂度は高くなる。
計算結果の大小は上記を満たしているべき。
↑この一文の絶頂度は290だ。
かなり高まってきているので、この辺りで文章を終わりにしたい。
んほぉぉぉぉ! あああぁぁん!!
最後の一文「んほぉぉぉぉ! あああぁぁん!!」の絶頂度は290よりも高いはず。
ここまでの話でそれが出ている例は「下人の行方は、誰も知らない。」以外には"薬漬けになった人妻が白目を剥いて失神するシーン"のあえぎ声。
「んほぉぉぉぉ! あああぁぁん!!」="薬漬けになった人妻が白目を剥いて失神するシーン"のあえぎ声、か?
その場合「んほぉぉぉぉ! あああぁぁん!!」の絶頂度はかなり高いが「下人の行方は、誰も知らない。」よりは低いものと推察される。
読み取った内容からの考察と実装内容
- 文章の各文字の音声要素(母音・子音)ごとに「恍惚ポイント」というものを設定し、その四則演算から値を算出した。
- 恍惚ポイントはその発音をするために「口元にどれだけ複雑な操作が必要か」「全身が緊張状態の時に発音しやすいか」という2つの基準から、主観的に判断して決定。なお、口元の操作が複雑であるほど恍惚ポイントは低く、緊張状態のときに発音しやすいほど恍惚ポイントは高い。
- 母音の恍惚ポイント×子音の恍惚ポイントを、文章中でその文字が持つ恍惚ポイントと定義。その文字ごとの恍惚ポイントおよび前の文字からの恍惚の変化量(※1)を合算した値を基本の値とした。
- ※1:つまり、恍惚ポイントが高い発音から低い発音への移行が多い場合は全体としての恍惚ポイントは低めになる補正がかかり、低い恍惚ポイントから高い恍惚ポイントへ移行する発音が多い場合は高めになる補正がかかる
- 読点や感嘆符など、実際に発声する際には息継ぎが発声すると思われる文字が現れた場合、そこで息継ぎが発声したものとみなし、そこまでの文章を「単呼吸内の発声」として扱う。
- 恍惚ポイントの移行計算は息継ぎが発生した時点でリセットする
- 単呼吸内で発声した文字数が適切であるほど絶頂度が高いとみなし、その基準を8文字と設定した。8文字ちょうどの場合にもっとも評価が高く、8文字から乖離するほど評価が低くなる。
- 読点や感嘆符も込みで1つの文章(あえぎ声)全体の長さが16文字以内であることを制限とした。制限文字数内では文字数が多いほどエロさが高いとして絶頂度が高くなる。いっぽう制限文字数を超えたものは冗長であるとしてとたんに評価が下がる。
- なお、「音声的要素」と言っているので、前の文字による発音の変化も考慮に入れたが、音素ごとのポイント評価が途中で面倒くさくなって似たような発音をするものには結局同じポイントを振っていったので、あまり意味はなかったかもしれない
- 音韻についてはwikipediaを参考にした
- https://ja.wikipedia.org/wiki/日本語の音韻
- https://ja.wikibooks.org/wiki/日本語/非母語話者むけ/五十音図
- 計算結果として記事に記載されている絶頂度の値そのものを目指すのは困難であることが予想されたため、例にあげられている文章と相対的な高低関係がある程度あっていればよいものとした。
- 漢字込みの文章がコピペで入力された場合に、その読み方を正確に特定できる機能を実装することは難しかったため、漢字込みの文章は対応せず、ひらがなもしくはカタカナのみの入力を許容することとした。
- Excelの場合は、Excel上で入力した文章であれば読み仮名を特定してくれる機能があるらしい。(参考: https://getnavi.jp/business/64775/ )
そしてできたものがこれ
URL
画面
絶頂度算出のコード
const pronunciateVariationN = (prevPronunciation, nextPronunciation) => {
// 語末では通常は口蓋垂鼻音 [ɴ]、たまに軟口蓋鼻音 [ŋ] になる。歌手の多くは両唇鼻音 [m]を語末の「ん」として使う。
if (nextPronunciation == null) return "ɴ";
if (nextPronunciation["consonant"].length == 0) {
const firstConsonant = nextPronunciation["consonant"].slice(0, 1);
// [n]・[t]・[d] の前では歯茎鼻音 [n] になる。
if (["n", "t", "d"].includes(firstConsonant)) return "n";
// [m]・[p]・[b] の前では両唇鼻音 [m] になる。
if (["m", "p", "b"].includes(firstConsonant)) return "m";
// [k]・[g] の前では軟口蓋鼻音 [ŋ] になる。
if (["k", "g"].includes(firstConsonant)) return "ŋ";
// 母音、半母音、摩擦音または、はじき音の前のときは鼻母音になる。
if (["s", "h"].includes(firstConsonant)) return " ̃";
// 撥音 /N/ は、後ろが子音が続くときはその子音と同じ調音位置になる。
return "ɴ";
}
// 母音、半母音、摩擦音または、はじき音の前のときは鼻母音になる。
return " ̃";
};
const pronunciateVariationQ = (prevPronunciation, nextPronunciation) => {
/**
* 語末では声門閉鎖音 [ʔ] になる
*/
if (nextPronunciation == null) return "ʔ";
if (nextPronunciation["consonant"].length > 0) {
const firstConsonant = nextPronunciation["consonant"].slice(0, 1);
/**
* 破裂音の前ではその破裂音の内破音である。
/p/ の前では [p̚] になる。
例 葉っぱ [hap̚pa]
/t/ の前では [t̚] になる。
例 打った [ut̚ta]
/k/ の前では [k̚] になる。
例 作家 [sak̚ka]
*/
if (["p"].includes(firstConsonant)) return "p̚";
if (["t"].includes(firstConsonant) && nextPronunciation["vowel"] != "a") return "t̚";
if (["k"].includes(firstConsonant)) return "k̚";
/**
* 破擦音の前では内破音の[t]になる。
例 一致 [it̚tɕi]
例 ブリッジ [buɽit̚dʑi]
例 グッズ [gut̚dzu]
例 三つ [mit̚tsu]
*/
if (["t", "d", "z"].includes(firstConsonant)) return "t̚";
/**
* 摩擦音の前ではその摩擦音を伸ばす。
例 あっさり [assaɾʲi]
例 一緒 [iɕɕo]
例 バッハ [bahha]
例 ビュッフェ [bjuɸɸe]
例 ワッフル [waɸɸuɽu]
*/
if (["s", "h"].includes(firstConsonant)) return firstConsonant;
if (firstConsonant in ["s", "h"]) return firstConsonant;
}
return "";
}
const pronunciateVariationR = (prevPronunciation, nextPronunciation) => {
if (prevPronunciation["vowel"].length > 0) {
return prevPronunciation["vowel"];
}
return "";
}
const pronunciations = {
"あ": {"full": "a", "consonant": "", "vowel": "a"},
"ア": {"full": "a", "consonant": "", "vowel": "a"},
"い": {"full": "i", "consonant": "", "vowel": "i"},
"イ": {"full": "i", "consonant": "", "vowel": "i"},
"う": {"full": "u", "consonant": "", "vowel": "u"},
"ウ": {"full": "ɯ", "consonant": "", "vowel": "ɯ"},
"え": {"full": "e", "consonant": "", "vowel": "e"},
"エ": {"full": "e", "consonant": "", "vowel": "e"},
"お": {"full": "o", "consonant": "", "vowel": "o"},
"オ": {"full": "o", "consonant": "", "vowel": "o"},
"か": {"full": "ka", "consonant": "k", "vowel": "a"},
"カ": {"full": "ka", "consonant": "k", "vowel": "a"},
"が": {"full": "ga", "consonant": "g", "vowel": "a"},
"ガ": {"full": "ɡa", "consonant": "ɡ", "vowel": "a"},
"き": {"full": "ki", "consonant": "k", "vowel": "i"},
"キ": {"full": "kʲi", "consonant": "kʲ", "vowel": "i"},
"ぎ": {"full": "gi", "consonant": "g", "vowel": "i"},
"ギ": {"full": "ɡʲi", "consonant": "ɡʲ", "vowel": "i"},
"きゃ": {"full": "kya", "consonant": "ky", "vowel": "a"},
"キャ": {"full": "kʲa", "consonant": "kʲ", "vowel": "a"},
"ぎゃ": {"full": "gya", "consonant": "gy", "vowel": "a"},
"ギャ": {"full": "ɡʲa", "consonant": "ɡʲ", "vowel": "a"},
"きゅ": {"full": "kyu", "consonant": "ky", "vowel": "u"},
"キュ": {"full": "kʲɯ", "consonant": "kʲ", "vowel": "ɯ"},
"ぎゅ": {"full": "gyu", "consonant": "gy", "vowel": "u"},
"ギュ": {"full": "ɡʲɯ", "consonant": "ɡʲ", "vowel": "ɯ"},
"きょ": {"full": "kyo", "consonant": "ky", "vowel": "o"},
"キョ": {"full": "kʲo", "consonant": "kʲ", "vowel": "o"},
"ぎょ": {"full": "gyo", "consonant": "gy", "vowel": "o"},
"ギョ": {"full": "ɡʲo", "consonant": "ɡʲ", "vowel": "o"},
"く": {"full": "ku", "consonant": "k", "vowel": "u"},
"ク": {"full": "kɯ", "consonant": "k", "vowel": "ɯ"},
"ぐ": {"full": "gu", "consonant": "g", "vowel": "u"},
"グ": {"full": "ɡɯ", "consonant": "ɡ", "vowel": "ɯ"},
"け": {"full": "ke", "consonant": "k", "vowel": "e"},
"ケ": {"full": "ke", "consonant": "k", "vowel": "e"},
"げ": {"full": "ge", "consonant": "g", "vowel": "e"},
"ゲ": {"full": "ɡe", "consonant": "ɡ", "vowel": "e"},
"こ": {"full": "ko", "consonant": "k", "vowel": "o"},
"コ": {"full": "ko", "consonant": "k", "vowel": "o"},
"ご": {"full": "go", "consonant": "g", "vowel": "o"},
"ゴ": {"full": "ɡo", "consonant": "ɡ", "vowel": "o"},
"さ": {"full": "sa", "consonant": "s", "vowel": "a"},
"サ": {"full": "sa", "consonant": "s", "vowel": "a"},
"ざ": {"full": "za", "consonant": "z", "vowel": "a"},
"ザ": {"full": "dza", "consonant": "dz", "vowel": "a"},
"し": {"full": "si", "consonant": "s", "vowel": "i"},
"シ": {"full": "ʃi", "consonant": "ʃ", "vowel": "i"},
"じ": {"full": "zi", "consonant": "z", "vowel": "i"},
"ジ": {"full": "ʤi", "consonant": "ʤ", "vowel": "i"},
"しゃ": {"full": "sya", "consonant": "sy", "vowel": "a"},
"シャ": {"full": "ʃa", "consonant": "ʃ", "vowel": "a"},
"じゃ": {"full": "zya", "consonant": "zy", "vowel": "a"},
"ジャ": {"full": "ʤa", "consonant": "ʤ", "vowel": "a"},
"しゅ": {"full": "syu", "consonant": "sy", "vowel": "u"},
"シュ": {"full": "ʃɯ", "consonant": "ʃ", "vowel": "ɯ"},
"じゅ": {"full": "zyu", "consonant": "zy", "vowel": "u"},
"ジュ": {"full": "ʤɯ", "consonant": "ʤ", "vowel": "ɯ"},
"しょ": {"full": "syo", "consonant": "sy", "vowel": "o"},
"ショ": {"full": "ʃo", "consonant": "ʃ", "vowel": "o"},
"じょ": {"full": "zyo", "consonant": "zy", "vowel": "o"},
"ジョ": {"full": "ʤo", "consonant": "ʤ", "vowel": "o"},
"す": {"full": "su", "consonant": "s", "vowel": "u"},
"ス": {"full": "sɯ", "consonant": "s", "vowel": "ɯ"},
"ず": {"full": "zu", "consonant": "z", "vowel": "u"},
"ズ": {"full": "dzɯ", "consonant": "dz", "vowel": "ɯ"},
"せ": {"full": "se", "consonant": "s", "vowel": "e"},
"セ": {"full": "se", "consonant": "s", "vowel": "e"},
"ぜ": {"full": "ze", "consonant": "z", "vowel": "e"},
"ゼ": {"full": "dze", "consonant": "dz", "vowel": "e"},
"そ": {"full": "so", "consonant": "s", "vowel": "o"},
"ソ": {"full": "so", "consonant": "s", "vowel": "o"},
"ぞ": {"full": "zo", "consonant": "z", "vowel": "o"},
"ゾ": {"full": "dzo", "consonant": "dz", "vowel": "o"},
"た": {"full": "ta", "consonant": "t", "vowel": "a"},
"タ": {"full": "ta", "consonant": "t", "vowel": "a"},
"だ": {"full": "da", "consonant": "d", "vowel": "a"},
"ダ": {"full": "da", "consonant": "d", "vowel": "a"},
"ち": {"full": "ti", "consonant": "t", "vowel": "i"},
"チ": {"full": "tʃi", "consonant": "tʃ", "vowel": "i"},
"ぢ": {"full": "di", "consonant": "d", "vowel": "i"},
"ヂ": {"full": "ʤi", "consonant": "ʤ", "vowel": "i"},
"ちゃ": {"full": "tya", "consonant": "ty", "vowel": "a"},
"チャ": {"full": "tʃa", "consonant": "tʃ", "vowel": "a"},
"ぢゃ": {"full": "dya", "consonant": "dy", "vowel": "a"},
"ヂャ": {"full": "ʤa", "consonant": "ʤ", "vowel": "a"},
"ちゅ": {"full": "tyu", "consonant": "ty", "vowel": "u"},
"チュ": {"full": "tʃɯ", "consonant": "tʃ", "vowel": "ɯ"},
"ぢゅ": {"full": "dyu", "consonant": "dy", "vowel": "u"},
"ヂュ": {"full": "ʤɯ", "consonant": "ʤ", "vowel": "ɯ"},
"ちょ": {"full": "tyo", "consonant": "ty", "vowel": "o"},
"チョ": {"full": "tʃo", "consonant": "tʃ", "vowel": "o"},
"ぢょ": {"full": "dyo", "consonant": "dy", "vowel": "o"},
"ヂョ": {"full": "ʤo", "consonant": "ʤ", "vowel": "o"},
"つ": {"full": "tu", "consonant": "t", "vowel": "u"},
"ツ": {"full": "tsɯ", "consonant": "ts", "vowel": "ɯ"},
"づ": {"full": "du", "consonant": "d", "vowel": "u"},
"ヅ": {"full": "dzɯ", "consonant": "dz", "vowel": "ɯ"},
"て": {"full": "te", "consonant": "t", "vowel": "e"},
"テ": {"full": "te", "consonant": "t", "vowel": "e"},
"で": {"full": "de", "consonant": "d", "vowel": "e"},
"デ": {"full": "de", "consonant": "d", "vowel": "e"},
"と": {"full": "to", "consonant": "t", "vowel": "o"},
"ト": {"full": "to", "consonant": "t", "vowel": "o"},
"ど": {"full": "do", "consonant": "d", "vowel": "o"},
"ド": {"full": "do", "consonant": "d", "vowel": "o"},
"な": {"full": "na", "consonant": "n", "vowel": "a"},
"ナ": {"full": "na", "consonant": "n", "vowel": "a"},
"に": {"full": "ni", "consonant": "n", "vowel": "i"},
"ニ": {"full": "ɲi", "consonant": "ɲ", "vowel": "i"},
"にゃ": {"full": "nya", "consonant": "ny", "vowel": "a"},
"ニャ": {"full": "ɲa", "consonant": "ɲ", "vowel": "a"},
"にゅ": {"full": "nyu", "consonant": "ny", "vowel": "u"},
"ニュ": {"full": "ɲɯ", "consonant": "ɲ", "vowel": "ɯ"},
"にょ": {"full": "nyo", "consonant": "ny", "vowel": "o"},
"ニョ": {"full": "ɲo", "consonant": "ɲ", "vowel": "o"},
"ぬ": {"full": "nu", "consonant": "n", "vowel": "u"},
"ヌ": {"full": "nɯ", "consonant": "n", "vowel": "ɯ"},
"ね": {"full": "ne", "consonant": "n", "vowel": "e"},
"ネ": {"full": "ne", "consonant": "n", "vowel": "e"},
"の": {"full": "no", "consonant": "n", "vowel": "o"},
"ノ": {"full": "no", "consonant": "n", "vowel": "o"},
"は": {"full": "ha", "consonant": "h", "vowel": "a"},
"ハ": {"full": "ha", "consonant": "h", "vowel": "a"},
"ば": {"full": "ba", "consonant": "b", "vowel": "a"},
"バ": {"full": "ba", "consonant": "b", "vowel": "a"},
"ぱ": {"full": "pa", "consonant": "p", "vowel": "a"},
"パ": {"full": "pa", "consonant": "p", "vowel": "a"},
"ひ": {"full": "hi", "consonant": "h", "vowel": "i"},
"ヒ": {"full": "çʲi", "consonant": "çʲ", "vowel": "i"},
"び": {"full": "bi", "consonant": "b", "vowel": "i"},
"ビ": {"full": "bʲi", "consonant": "bʲ", "vowel": "i"},
"ぴ": {"full": "pi", "consonant": "p", "vowel": "i"},
"ピ": {"full": "pʲi", "consonant": "pʲ", "vowel": "i"},
"ひゃ": {"full": "hya", "consonant": "hy", "vowel": "a"},
"ヒャ": {"full": "ça", "consonant": "ç", "vowel": "a"},
"びゃ": {"full": "bya", "consonant": "by", "vowel": "a"},
"ビャ": {"full": "bʲa", "consonant": "bʲ", "vowel": "a"},
"ぴゃ": {"full": "pya", "consonant": "py", "vowel": "a"},
"ピャ": {"full": "pʲa", "consonant": "pʲ", "vowel": "a"},
"ひゅ": {"full": "hyu", "consonant": "hy", "vowel": "u"},
"ヒュ": {"full": "çɯ", "consonant": "ç", "vowel": "ɯ"},
"びゅ": {"full": "byu", "consonant": "by", "vowel": "u"},
"ビュ": {"full": "bʲɯ", "consonant": "bʲ", "vowel": "ɯ"},
"ぴゅ": {"full": "pyu", "consonant": "py", "vowel": "u"},
"ピュ": {"full": "pʲɯ", "consonant": "pʲ", "vowel": "ɯ"},
"ひょ": {"full": "hyo", "consonant": "hy", "vowel": "o"},
"ヒョ": {"full": "ço", "consonant": "ç", "vowel": "o"},
"びょ": {"full": "byo", "consonant": "by", "vowel": "o"},
"ビョ": {"full": "bʲo", "consonant": "bʲ", "vowel": "o"},
"ぴょ": {"full": "pyo", "consonant": "py", "vowel": "o"},
"ピョ": {"full": "pʲo", "consonant": "pʲ", "vowel": "o"},
"ふ": {"full": "hu", "consonant": "h", "vowel": "u"},
"フ": {"full": "ɸɯ", "consonant": "ɸ", "vowel": "ɯ"},
"ぶ": {"full": "bu", "consonant": "b", "vowel": "u"},
"ブ": {"full": "bɯ", "consonant": "b", "vowel": "ɯ"},
"ぷ": {"full": "pu", "consonant": "p", "vowel": "u"},
"プ": {"full": "pɯ", "consonant": "p", "vowel": "ɯ"},
"へ": {"full": "he", "consonant": "h", "vowel": "e"},
"ヘ": {"full": "he", "consonant": "h", "vowel": "e"},
"べ": {"full": "be", "consonant": "b", "vowel": "e"},
"ベ": {"full": "be", "consonant": "b", "vowel": "e"},
"ぺ": {"full": "pe", "consonant": "p", "vowel": "e"},
"ペ": {"full": "pe", "consonant": "p", "vowel": "e"},
"ほ": {"full": "ho", "consonant": "h", "vowel": "o"},
"ホ": {"full": "ho", "consonant": "h", "vowel": "o"},
"ぼ": {"full": "bo", "consonant": "b", "vowel": "o"},
"ボ": {"full": "bo", "consonant": "b", "vowel": "o"},
"ぽ": {"full": "po", "consonant": "p", "vowel": "o"},
"ポ": {"full": "po", "consonant": "p", "vowel": "o"},
"ま": {"full": "ma", "consonant": "m", "vowel": "a"},
"マ": {"full": "ma", "consonant": "m", "vowel": "a"},
"み": {"full": "mi", "consonant": "m", "vowel": "i"},
"ミ": {"full": "mʲi", "consonant": "mʲ", "vowel": "i"},
"みゃ": {"full": "mya", "consonant": "my", "vowel": "a"},
"ミャ": {"full": "mʲa", "consonant": "mʲ", "vowel": "a"},
"みゅ": {"full": "myu", "consonant": "my", "vowel": "u"},
"ミュ": {"full": "mʲɯ", "consonant": "mʲ", "vowel": "ɯ"},
"みょ": {"full": "myo", "consonant": "my", "vowel": "o"},
"ミョ": {"full": "mʲo", "consonant": "mʲ", "vowel": "o"},
"む": {"full": "mu", "consonant": "m", "vowel": "u"},
"ム": {"full": "mɯ", "consonant": "m", "vowel": "ɯ"},
"め": {"full": "me", "consonant": "m", "vowel": "e"},
"メ": {"full": "me", "consonant": "m", "vowel": "e"},
"も": {"full": "mo", "consonant": "m", "vowel": "o"},
"モ": {"full": "mo", "consonant": "m", "vowel": "o"},
"ゃ": {"full": "ya", "consonant": "y", "vowel": "a"},
"ャ": {"full": "ja", "consonant": "j", "vowel": "a"},
"や": {"full": "ya", "consonant": "y", "vowel": "a"},
"ヤ": {"full": "ja", "consonant": "j", "vowel": "a"},
"ゅ": {"full": "yu", "consonant": "y", "vowel": "u"},
"ュ": {"full": "jɯ", "consonant": "j", "vowel": "ɯ"},
"ゆ": {"full": "yu", "consonant": "y", "vowel": "u"},
"ユ": {"full": "jɯ", "consonant": "j", "vowel": "ɯ"},
"ょ": {"full": "yo", "consonant": "y", "vowel": "o"},
"ョ": {"full": "jo", "consonant": "j", "vowel": "o"},
"よ": {"full": "yo", "consonant": "y", "vowel": "o"},
"ヨ": {"full": "jo", "consonant": "j", "vowel": "o"},
"ら": {"full": "ra", "consonant": "r", "vowel": "a"},
"ラ": {"full": "ɾa", "consonant": "ɾ", "vowel": "a"},
"り": {"full": "ri", "consonant": "r", "vowel": "i"},
"リ": {"full": "ɾʲi", "consonant": "ɾʲ", "vowel": "i"},
"りゃ": {"full": "rya", "consonant": "ry", "vowel": "a"},
"リャ": {"full": "ɾʲa", "consonant": "ɾʲ", "vowel": "a"},
"りゅ": {"full": "ryu", "consonant": "ry", "vowel": "u"},
"リュ": {"full": "ɾʲɯ", "consonant": "ɾʲ", "vowel": "ɯ"},
"りょ": {"full": "ryo", "consonant": "ry", "vowel": "o"},
"リョ": {"full": "ɾʲo", "consonant": "ɾʲ", "vowel": "o"},
"る": {"full": "ru", "consonant": "r", "vowel": "u"},
"ル": {"full": "ɾɯ", "consonant": "ɾ", "vowel": "ɯ"},
"れ": {"full": "re", "consonant": "r", "vowel": "e"},
"レ": {"full": "ɾe", "consonant": "ɾ", "vowel": "e"},
"ろ": {"full": "ro", "consonant": "r", "vowel": "o"},
"ロ": {"full": "ɾo", "consonant": "ɾ", "vowel": "o"},
"わ": {"full": "wa", "consonant": "w", "vowel": "a"},
"ワ": {"full": "ɰa", "consonant": "ɰ", "vowel": "a"},
"ゐ": {"full": "i", "consonant": "", "vowel": "i"},
"ヰ": {"full": "i", "consonant": "", "vowel": "i"},
"ゑ": {"full": "e", "consonant": "", "vowel": "e"},
"ヱ": {"full": "e", "consonant": "", "vowel": "e"},
"を": {"full": "o", "consonant": "", "vowel": "o"},
"ヲ": {"full": "o", "consonant": "", "vowel": "o"},
"ん": {"full": "n", "consonant": "", "vowel": "n"},
"ン": { "full": "/N/", "consonant": "", "vowel": pronunciateVariationN},
"っ": {"full": "/Q/", "consonant": "", "vowel": pronunciateVariationQ},
"ー": {"full": "/R/", "consonant": "", "vowel": pronunciateVariationR},
"ぁ": {"full": "a", "consonant": "", "vowel": "a"},
"ぃ": {"full": "i", "consonant": "", "vowel": "i"},
"ぅ": {"full": "u", "consonant": "", "vowel": "u"},
"ぇ": {"full": "e", "consonant": "", "vowel": "e"},
"ぉ": { "full": "o", "consonant": "", "vowel": "o" },
"ァ": {"full": "a", "consonant": "", "vowel": "a"},
"ィ": {"full": "i", "consonant": "", "vowel": "i"},
"ゥ": {"full": "u", "consonant": "", "vowel": "u"},
"ェ": {"full": "e", "consonant": "", "vowel": "e"},
"ォ": { "full": "o", "consonant": "", "vowel": "o" },
};
const vowelPointMapping = {
"": 0,
"n": 1,
"m": 2,
"ɴ": 1,
"ŋ": 1,
" ̃": 1,
"p̚": 2,
"t̚": 2,
"k̚": 2,
"s": 2,
"h": 2,
"ʔ": 10,
"i": 5,
"u": 5,
"ɯ": 5,
"e": 4,
"o": 8,
"a": 10,
};
const consonantPointMapping = {
"": 10,
"k": 1,
"g": 7,
"ɡ": 7,
"kʲ": 1,
"ɡʲ": 7,
"ky": 1,
"gy": 7,
"s": 1,
"z": 7,
"dz": 7,
"ʃ": 4,
"ʤ": 7,
"sy": 2,
"zy": 7,
"t": 1,
"d": 4,
"tʃ": 1,
"ty": 2,
"dy": 4,
"ts": 1,
"n": 3,
"ɲ": 3,
"ny": 4,
"h": 1,
"b": 6,
"p": 6,
"çʲ": 7,
"bʲ": 7,
"pʲ": 8,
"hy": 3,
"ç": 2,
"by": 7,
"py": 7,
"ɸ": 3,
"m": 4,
"mʲ": 4,
"my": 3,
"y": 2,
"j": 7,
"r": 3,
"ɾ": 3,
"ɾʲ": 3,
"ry": 2,
"w": 2,
"ɰ": 2,
};
const stopLetterMappings = {
"、": 1,
"!": 2,
"?": 1,
"…": 1,
" ": 1,
};
const BREATHING_BEST_LENGTH = 8;
const TEXT_BEST_LENGTH = 16;
const calcurate = (texts) => {
const textArray = texts.split(/[\n|。]/).reverse();
const ret = [];
for (const text of textArray) {
if (text.length == 0) continue;
let point = null;
try {
point = _calcurate(text);
ret.push([text, point]);
} catch (error) {
console.log(error);
ret.push([text, null]);
}
}
return ret;
}
const _getBestLengthCorrectionValue = (val, best) => {
const tmpVal = Math.abs(best - val);
return ((tmpVal > best ? best : tmpVal) + 1)
}
const _evalSentenceCrimaxPoint = (breathingCrimaxPoint, breathingLength) => {
breathingCrimaxPoint /= _getBestLengthCorrectionValue(breathingLength, BREATHING_BEST_LENGTH);
return breathingCrimaxPoint;
}
const _calcurate = (text) => {
const splited = text.split("");
const textArray = [];
for (const letter of splited) {
if (["ゃ", "ゅ", "ょ"].includes(letter)) {
textArray[textArray.length - 1] += letter;
} else {
textArray.push(letter);
}
}
const extacyDegreeArray = [];
for (let i = 0; i < textArray.length; i++) {
const letter = textArray[i];
let extacyPoint = null;
if (!Object.keys(stopLetterMappings).includes(letter)) {
const pronunciation = pronunciations[letter];
const prevPronunciation = i == 0 ? null : pronunciations[textArray[i - 1]];
const nextPronunciation = i + 1 == textArray.length ? null : pronunciations[textArray[i + 1]];
const consonantPoint = consonantPointMapping[pronunciation["consonant"]];
const vowel = typeof pronunciation["vowel"] == "function" ?
pronunciation["vowel"](prevPronunciation, nextPronunciation)
: pronunciation["vowel"];
const vowelPoint = vowelPointMapping[vowel];
extacyPoint = consonantPoint * vowelPoint;
}
extacyDegreeArray.push({ "letter": letter, "point": extacyPoint });
}
let preExtacyDegree = null;
let crimaxPoint = 0;
let breathingCrimaxPoint = 0;
let breathingLength = 0;
for (let i = 0; i < extacyDegreeArray.length; i++) {
const extacyDegree = extacyDegreeArray[i];
if (preExtacyDegree == null) {
preExtacyDegree = extacyDegree;
breathingCrimaxPoint += extacyDegree["point"];
continue;
}
if (Object.keys(stopLetterMappings).includes(extacyDegree["letter"])) {
if (preExtacyDegree != null) {
breathingCrimaxPoint += preExtacyDegree["point"] * stopLetterMappings[extacyDegree["letter"]];
}
crimaxPoint += _evalSentenceCrimaxPoint(breathingCrimaxPoint, breathingLength)
preExtacyDegree = null;
breathingCrimaxPoint = 0
breathingLength = 0
} else {
breathingCrimaxPoint +=
(extacyDegree["point"] - preExtacyDegree["point"]) +
+ ((extacyDegree["point"]) * (i + 1) / extacyDegreeArray.length);
preExtacyDegree = extacyDegree;
breathingLength += 1;
}
}
if (breathingLength > 0) {
crimaxPoint += _evalSentenceCrimaxPoint(breathingCrimaxPoint, BREATHING_BEST_LENGTH)
}
if (text.length <= TEXT_BEST_LENGTH) {
crimaxPoint /= TEXT_BEST_LENGTH - text.length + 1
} else {
crimaxPoint /= TEXT_BEST_LENGTH
}
return Math.round(crimaxPoint);
};
反省および所感
- すでに書いたが、発音の変化をできる限り実装したり、五十音の発音を単純なローマ字表記の母音子音よりも細かく分けた割には使いこなせなかった。
- 「下人の行方は、誰も知らない」のポイントが非常に高いが、そうなるようにルールを定めていったのだから当然の結果である。それ以外はまあまあ微妙な数値になった。
- お気づきの方もいるかもしれないが、元記事ではかなり高スコアであるとされている「さて、お気づきの方もいるかもしれないが、この文章もここまで少しずつ絶頂度を高めるように書いてきた」の値が、実はめちゃくちゃ低く出てしまう。(もう見なかったことにした)
- とはいえ、ルールとして定めたように、適度な長さに区切られていて発音しやすい音韻で組まれた文章が、人を心地よくさせる、というのは、実際ない話ではなさそう、と思った。
- んほぉぉぉぉ! あああぁぁん!!