Skip to content

Commit

Permalink
Update chiangxhua and zhongyuan
Browse files Browse the repository at this point in the history
Update chiangxhua: write medials as semivowels; ɨ > ə
Update zhongyuan: add `齊微韻洪音韻尾`
  • Loading branch information
untunt committed Nov 10, 2023
1 parent f44157f commit 14ce9b4
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 66 deletions.
134 changes: 76 additions & 58 deletions chiangxhua.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* 推導《聲音唱和圖》擬音
*
* https://zhuanlan.zhihu.com/p/498778513
*
* 《聲音唱和圖》分析並記錄了一個較保守版本的北宋共通語音系,對該圖的解析與擬音詳見:https://zhuanlan.zhihu.com/p/498778513
*
* 默認顯示音值,採用北宋早期音系通常拼寫風格
*
* 代碼注釋中的等均指韻圖等(聲音唱和圖等),而不是切韻等
Expand All @@ -14,38 +14,43 @@ const when = (...x) => 音韻地位.判斷(...x);
const is音值 = 選項.顯示 !== '音位';

const 知照組符號字典 = {
'tɹ tʃ': 'ʃʒɹ',
'tɹ tɕ': 'ɕʑɹ',
'tɻ tʂ': 'ʂʐɻ',
// '二等 tɻ tʂ,三等 tɹ tɕ': 'ʂʐɻ|ɕʑɹ',
'知tɹ 莊章tʃ': 'ʃʒɹ',
'知tɹ 莊章tɕ': 'ɕʑɹ',
'知tɻ 莊章tʂ': 'ʂʐɻ',
};
if (is音值) {
知照組符號字典['知tɹ 莊tʂ 章tɕ'] = 'ʂʐɹ|ɕʑɹ';
知照組符號字典['知tɻ 莊tʂ 章tɕ'] = 'ʂʐɻ|ɕʑɻ';
}

if (!音韻地位) return [
['顯示', [2,
'音位',
'音值',
]],
'標音風格',
['知照組', [1].concat(Object.keys(知照組符號字典))],
['知照組', [is音值 ? 4 : 1].concat(Object.keys(知照組符號字典))],
['入聲尾', is音值 ? [1,
// 'ʋ ɹ ɣ',
'β ɾ ɣ',
'p t k', // 符合通常習慣
'b d ɡ',
'p t k',
'β ɾ ɣ', // 接近實際音值
// 'ʋ ɹ ɰ',
] : [2,
'ˀ ʋˀ jˀ wˀ', // 僅作爲原圖的音位轉寫,不推薦
'p t k ',
]],
['聲調', [1, '附加符號', '調類數字', '省略']],
['省略二等介音', is音值 ? true : null],
['全濁平省略送氣', false],
['次濁上省略喉化', false],
// ['山攝二等脣音歸合口', false], // (僅作爲原圖轉寫)圖中“八”在合口,但二等不應該在合口。《韻鏡》《七音略》脣音刪舒、山入在合口,刪入、山舒在開口
['洪音高元音', [1, 'ɨ', 'ə']],
['止蟹攝三四等合口韻尾', is音值 ? [1, 'j', 'i'] : null],
// ['山攝三等一律寫前元音', is音值 ? false : null],
'演變規則',
['部分蟹攝二等入假攝', true],
['部分流攝脣音入遇攝', true],
['全濁上歸去', true], // 圖中未體現全濁上字的聲調,按口語則已歸去聲,按《蒙古字韻》風格則仍算上聲
['影喻上聲合併', false], // 圖中無影喻上聲對立的空間,可能口語已合併,但同期反切沒有相混的情況
// ['影喻上聲合併', false], // 圖中無影喻上聲對立的空間,可能口語已合併,但同期反切沒有相混的情況
];

function 調整音韻地位() {
Expand All @@ -64,9 +69,9 @@ function 調整音韻地位() {
function get聲母() {
return when([
['云母 通攝 平聲', 'ɣ'], // 云母“雄”在二音
['匣母 肴韻 平聲', ''], // 匣母“爻”在三音,但一等無字,說明“完”不是零聲母
['匣母 肴韻 平聲', 'ɰ'], // 匣母“爻”在三音,但一等無字,說明“完”不是零聲母
['崇母 止攝 仄聲', 'ʑ'], // 崇母“士”在十音。另船母船小韻和繩小韻中“乘”聲符字今讀塞擦音,但圖中未體現,這裏不考慮
[選項.影喻上聲合併 && '云以母 上聲', 'ʔ'], // 可能的情況
[選項.影喻上聲合併 === true && '云以母 上聲', 'ʔ'], // 可能的情況
// 以上爲特例

['東鍾微虞廢文元歌陽尤凡韻 三等 非 重紐A類', [ // “非 重紐A類”用於過濾𩦠小韻,“歌韻”用於包含縛小韻
Expand All @@ -84,7 +89,7 @@ function get聲母() {
['莊章母', 'tɕ'], ['崇母 仄聲', 'dʑ'], ['初昌母', 'tɕʰ'], ['崇常母', 'dʑʰ'], // 十一音

['泥孃母 上聲', 'ˀn'], ['泥孃母', 'n'], ['來母 上聲', 'ˀl'], ['來母', 'l'], // 七音
['影母', 'ʔ'], ['云以母', is`上聲` ? 'ˀ' : ''], ['明母 上聲', 'ˀm'], ['明母', 'm'], // 三音
['影母', 'ʔ'], ['云以母', is`上聲` ? 'ˀɰ' : 'ɰ'], ['明母 上聲', 'ˀm'], ['明母', 'm'], // 三音
], '無聲母規則', true);
}

Expand All @@ -97,7 +102,7 @@ function get等() {
['東鍾虞文歌陽尤韻', '一'],
]],
['銳音', [
['精組 止攝 開口', '一'], // 中唐發生 /siə/ > /sə/,變一等
['精組 止攝 開口', '一'], // 中唐 /sjɨ/ > /sɨ/ 變一等
['莊組', '二'],
['四等', '三'], // 圖中銳音一律無四等
['蟹山咸攝 一等 開口 非 (泥母 蟹攝)', '二'], // 圖中這類韻列在二等,但“乃”(泥開一咍上)仍在一等
Expand All @@ -122,36 +127,36 @@ function get開合() {

function get介音(, 開合) {
return {
: { : '', : 'u' },
: { : 'ʕ', : 'ʕu' },
: { : 'i', : 'iu' },
: { : 'ʲi', : 'ʲiu' },
: { : '', : 'w' },
: { : 'ʕ', : 'ʕw' },
: { : 'j', : 'jw' },
: { : 'ʲj', : 'ʲjw' },
}[][開合];
}

function get韻基() {
return when([
['蟹攝 (一二等 或 莊組)', 'aj'], // 一聲下(僅舒聲)

['止蟹攝 合口 非 莊組', 'əj'], // 五聲下(舒)
['曾梗攝', is`入聲` ? 'əɣ' : 'əŋ'], // 五聲下(入) & 二聲下
['止蟹攝 合口 非 莊組', 'ɨj'], // 五聲下(舒)
['曾梗攝', is`入聲` ? 'ɨk' : 'ɨŋ'], // 五聲下(入) & 二聲下

['止蟹攝', 'ə'], // 五聲上(舒)
['臻攝 非 元韻', is`入聲` ? 'əɾ' : 'ən'], // 五聲上(入) & 三聲下
['止蟹攝', 'ɨ'], // 五聲上(舒)
['臻攝 非 元韻', is`入聲` ? 'ɨt' : 'ɨn'], // 五聲上(入) & 三聲下

['果假攝', 'a'], // 一聲上(舒)
['山攝 或 元韻', is`入聲` ? '' : 'an'],// 一聲上(入) & 三聲上
['山攝 或 元韻', is`入聲` ? 'at' : 'an'],// 一聲上(入) & 三聲上

['遇攝', 'ɯ'], // 六聲下(僅舒聲)

['流攝', 'əw'], // 四聲下(舒)
['通攝', is`入聲` ? 'əwɣ' : 'əwŋ'], // 四聲下(入) & 六聲上
['流攝', 'ɨw'], // 四聲下(舒)
['通攝', is`入聲` ? 'ɨwk' : 'ɨwŋ'], // 四聲下(入) & 六聲上

['效攝', 'aw'], // 四聲上(舒)
['宕江攝', is`入聲` ? '' : ''], // 四聲上(入) & 二聲上
['宕江攝', is`入聲` ? 'awk' : 'awŋ'], // 四聲上(入) & 二聲上

['深攝', is`入聲` ? 'əβ' : 'əm'], // 七聲上
['咸攝', is`入聲` ? '' : 'am'], // 七聲下
['深攝', is`入聲` ? 'ɨp' : 'ɨm'], // 七聲上
['咸攝', is`入聲` ? 'ap' : 'am'], // 七聲下
], '無韻基規則');
}

Expand All @@ -168,62 +173,75 @@ function get聲調() {
function 音位to音值(音節) {
function 替換韻核(from, tos, condition = true) {
if (!condition) return;
音節.韻核 = 音節.韻核.replace(from, 音節.介音.includes('u') ? tos.pop() : tos[0]);
音節.韻核 = 音節.韻核.replace(from, 音節.介音.includes('w') ? tos.pop() : tos[0]);
}

const is收ŋ韻 = ['ŋ', 'ɣ'].includes(音節.韻尾);
const is曾梗攝 = ['ŋ', 'k'].includes(音節.韻尾);
替換韻核('a', ['ɑ']); // 先把 /a/ 重置成一等的音值 [ɑ]
if (音節.介音.includes('ʕ')) {
// 二等
替換韻核('ɯ', ['ɯ', '']);
替換韻核('ə', ['ɛ'], is收ŋ韻);
替換韻核('ɯ', ['ɯ', 'u']);
替換韻核('ɨ', ['e'], is曾梗攝);
替換韻核('ɑ', ['a']);
} else if (音節.介音.includes('i')) {
} else if (音節.介音.includes('j')) {
// 三四等
替換韻核('ɯ', ['ɯ', 'u']);
替換韻核('ə', ['']); // 韻核和介音相同,省略韻核
替換韻核('ɑ', ['æ', 'ɐ'], !音節.韻尾); // 北宋時麻二麻三未有明確分開的跡象,暫擬作 [iæ]
替換韻核('ɑ', ['ɛ', 'ɜ'], !is收ŋ韻); // 宕三保留在 [ɑ]
替換韻核('ɨ', ['i', 'y']); // 韻核和介音相同,省略韻核
替換韻核('ɑ', ['æ', 'ɐ'], !音節.韻尾); // 北宋時麻二麻三未有明確分開的跡象,暫擬作 [jæ]
替換韻核('ɑ', ['ɛ', 'ɔ'], !選項.山攝三等一律寫前元音 && is`鈍音` && !音節.介音.includes('ʲ'));
替換韻核('ɑ', ['ɛ']);
} else {
// 一等
替換韻核('ɯ', ['ɯ', '']);
替換韻核('ə', ['ə', ''], !is收ŋ韻); // [uəŋ] 不寫作 [uŋ],以免與通攝混淆
替換韻核('ɯ', ['ɯ', 'u']);
替換韻核('ɨ', ['ɨ', 'u'], !is曾梗攝); // /wɨŋ/ 不寫作 [uŋ],以免與通攝混淆
替換韻核('ɑ', ['ʌ', 'ɔ'], !音節.韻尾);
替換韻核('ɑ', ['ɑ', 'ɔ'], !is收ŋ韻);
替換韻核('ɔ', ['o'], 音節.韻尾 === 'j'); // /uɑj/ 離 [i] 更近
替換韻核('ɑ', ['ɑ', 'ɔ']);
替換韻核('ɔ', ['o'], 音節.韻尾 === 'j'); // /wɑj/ 離 [i] 更近
}
if (is`精莊章組` && 音節.韻核 === 'ə' && !音節.韻尾) {
// 噝音後的開音節 /ə/ 變 [ɹ̩](實際僅精組開口和莊組有字)
音節.介音.includes('u') ? 音節.韻尾 = 'ɹ' : 音節.韻核 = 'ɹ̩';
if (['wŋ', 'wk'].includes(音節.韻尾)) {
替換韻核(/[iɨ]/, ['u']);
替換韻核('y', ['o']);
替換韻核(/[ɛɔ]/, ['ɑ']);
音節.韻尾 = 音節.韻尾.replace('w', '');
}
音節.介音 = 音節.介音.replace('iu', 'ʉ');
if (!音節.韻核) 音節.韻尾 = 音節.韻尾.replace('j', 'i'); // /iuəj/ 實際上是 [i] 的合口
音節.韻尾 = 音節.韻尾.replace('wŋ', 'uŋ');
音節.韻尾 = 音節.韻尾.replace('wɣ', 'uɣ');
音節.介音 = 音節.介音.replace('jw', 'ɥ');
if (['ji', 'ɥy', 'wu'].includes(音節.介音.slice(-1) + 音節.韻核)) 音節.介音 = 音節.介音.slice(0, -1);

// /jwɨj/ 相當於 [i] 的合口
if (音節.韻核 === 'y' && 音節.韻尾 === 'j') 音節.韻尾 = 選項.止蟹攝三四等合口韻尾;
}

function 後處理(音節) {
let 知照組符號 = 知照組符號字典[選項.知照組];
if (!音節.介音.includes('ʕ')) 知照組符號 = 知照組符號.slice(-3); // 二等取開頭 3 個符號,三等取最後 3 個符號
[...'ɕʑɹ'].forEach((e, i) => { 音節.聲母 = 音節.聲母.replace(e, 知照組符號[i]); });
if (知照組符號.includes('ɻ')) {
音節.韻核 = 音節.韻核.replace('ɹ̩', 'ɻ̍');
音節.韻尾 = 音節.韻尾.replace('ɹ', 'ɻ');
if (is音值) {
音節.介音 = 音節.介音.replace('ʕ', '');
if (音節.韻核 === 'ɨ' && 選項.洪音高元音 !== 'ɨ' && !音節.韻尾) {
// “空韻”作成音節近音(實際僅精組開口和莊組)
音節.韻核 = 知照組符號.includes('ʂ') ? 'ɻ̍' : 'ɹ̩';
}
}
if (選項.省略二等介音) 音節.介音 = 音節.介音.replace('ʕ', '');
if (音節.韻核 === 'ɨ') 音節.韻核 = 選項.洪音高元音;

if (音節.介音.includes('ʲ')) {
音節.聲母 += ['', 'ˀ'].includes(音節.聲母) ? 'j' : 'ʲ';
音節.聲母 += 'ʲ';
音節.聲母 = 音節.聲母.replace('ʰʲ', 'ʲʰ');
音節.介音 = 音節.介音.replace('ʲ', '');
}
if (is音值 && 音節.聲母.includes('ɰ')) {
音節.聲母 = 音節.聲母.replace('ɰʲ', ''); // 韻圖四等由細音韻母指示
if (音節.介音 === 'ɥ' || !音節.介音 && 音節.韻核 === 'y') 音節.聲母 = 音節.聲母.replace('ɰ', 'w');
if (音節.介音 === 'w' || !音節.介音 && 音節.韻核 === 'u') 音節.聲母 = 音節.聲母.replace('ɰ', '');
}
if (選項.次濁上省略喉化) 音節.聲母 = 音節.聲母.replace('ˀ', '');
if (選項.全濁平省略送氣 && is`全濁`) 音節.聲母 = 音節.聲母.replace('ʰ', '');
if (is`入聲`) {
let 入聲尾 = 選項.入聲尾;
const 韻尾to = 入聲尾.trim().split(' ');
const 韻尾from = 韻尾to.length === 3 ? [...'βɾɣ'] : ['ɾ', 'β', is`曾梗攝` && 'ɣ', /.?ɣ/];
韻尾from.forEach((e, i) => { 音節.韻尾 = 音節.韻尾.replace(e, 韻尾to[i]); });
let 韻尾from = ['p', 't', 'k', 'wk'];
let 韻尾to = 選項.入聲尾.trim().split(' ');
if (韻尾to.length === 4) [韻尾to[1], 韻尾to[0]] = [韻尾to[0], 韻尾to[1]]; // 選項中前兩個對應 t、p
else 韻尾to = 韻尾to.concat(['w' + 韻尾to[2]]);
音節.韻尾 = 韻尾to[韻尾from.indexOf(音節.韻尾)];
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ assert_equal(panwuyun(音韻地位), "ɕiᴇu˧˥");
assert_equal(unt(音韻地位), "ɕéw");
assert_equal(msoeg_v8(音韻地位), "çiɛuˀ");
assert_equal(mid_tang(音韻地位), "ɕiɛw˦˥");
assert_equal(chiangxhua(音韻地位), "ʃiɛ́w");
assert_equal(chiangxhua(音韻地位), "ɕjɛ́w");
assert_equal(mongol(音韻地位), "ꡮꡠꡓ");
assert_equal(zhongyuan(音韻地位), "ʂjɛw³");
assert_equal(fanwan(音韻地位), "shiu2");
Expand Down
15 changes: 8 additions & 7 deletions zhongyuan.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ if (!音韻地位) return [
['包含部分例外音變', true],
['異讀分隔符(留空則爲換行)', ''],
['高元音開口呼', 選項.顯示?.includes('unt') ?? true ? [1, 'ɨ', 'ə'] : null],
['皆來韻梗二見入', 選項.顯示?.includes('unt') ?? true ? [2, 'aj', '(j)aj', 'jaj'] : null],
['齊微韻洪音韻尾', 選項.顯示?.includes('音值(unt') ?? true ? [1, 'j', 'i'] : null],
['皆來韻梗二開見入', 選項.顯示?.includes('unt') ?? true ? [2, 'aj', '(j)aj', 'jaj'] : null],
];

const 例外 = 選項.包含部分例外音變;
Expand Down Expand Up @@ -78,10 +79,9 @@ function get聲母() {
['常母 平聲 (支韻 合口 或 魚尤宵韻)', 'tʂʰ'], // 垂蜍讎韶
['常母 深攝 平聲', 'ʂ'], // 忱煁
['船母 平聲 合口', 'tʂʰ'], // 船唇
[層次 === 1 && '船母 曾攝 舒聲', 'tʂʰ'], // 乗\繩
[層次 === 1 && '船母 曾攝 平聲', 'tʂʰ'], // 乗\繩

[層次 === 1 && '匣母 寒韻 合口 平聲', ''], // 丸\桓
['匣母 肴韻 平聲', 'x'], // 爻。《中州樂府音韻類編》與哮小韻陰陽配對,《中州音韻》與遙小韻合併
['以母 蟹攝 合口', 'ɻ'], // 鋭
[層次 === 0 && '脂韻 以母 合口 平聲', 'ʋ'], // 惟\遺
['疑母', [
Expand All @@ -91,6 +91,7 @@ function get聲母() {
[層次 === 1 && '梗攝 二等 入聲', 'ŋ'], // 額
['效攝 一等 仄聲', 'ŋ'], // 傲奡鏊
]], // 俺《廣韻》未收,不考慮
// x 爻。《中州樂府音韻類編》與哮小韻陰陽配對,《中州音韻》與遙小韻合併
]],

['東鍾微虞廢文元歌陽尤凡韻 三等 非 重紐A類', [ // “非 重紐A類”用於過濾𩦠小韻,“歌韻”用於包含縛小韻
Expand Down Expand Up @@ -303,20 +304,20 @@ function get音節() {
['β', ''],
['ʌw', 'waw', is脣音, 'aw'],
['ɨ', 選項.高元音開口呼],
['jaj', 選項.皆來韻梗二見入, 聲調.includes('ʼ')],
['jaj', 選項.皆來韻梗二開見入, 聲調.includes('ʼ')],
],
'音值(unt, 2021)': [
['β', ''],
['jw', 'ɥ'], ['ɨj', 'ɨi'],
['', 'i'], ['ii', 'i'],
['', 'i'], ['ij', 'i'],
['jw', 'ɥ'], ['ɨj', 'ɨ' + 選項.齊微韻洪音韻尾],
['wɨ', 'u', !韻母.includes('ŋ')],
['ɥɨ', 'y', !韻母.includes('ŋ'), 'ɥi'],
['ʌw', 'waw', is脣音, 'aw'],
['wʌ', 'ɔ', is脣音 || is銳音 && 韻母 === 'wʌ', 'wɔ'],
['ɥʌ', 'jɔ'],
['ɨ', 選項.高元音開口呼],
['ə', 'ɹ̩', 韻母 === 'ə'], ['ɹ̩', 'ɻ̍', !聲母.includes('s')],
['jaj', 選項.皆來韻梗二見入, 聲調.includes('ʼ')],
['jaj', 選項.皆來韻梗二開見入, 聲調.includes('ʼ')],
],
'音位(薛鳳生, 1990)': [
['ʰ', 'h'], ['ʋ', 'v'], ['ʂ', 'sr'], ['ɻ', 'r'],
Expand Down

0 comments on commit 14ce9b4

Please sign in to comment.