Skip to content

Commit 120fe0c

Browse files
l17813182030v-liukun
andauthored
Handle cases where the word segmentation results are out of order. (#2755)
Co-authored-by: v-liukun <[email protected]>
1 parent 32eb3a2 commit 120fe0c

File tree

1 file changed

+92
-1
lines changed

1 file changed

+92
-1
lines changed

samples/js/node/pronunciationAssessmentContinue.js

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,97 @@ export const main = async (settings) => {
9595
endOffset = nb.Words.slice(-1)[0].Offset + nb.Words.slice(-1)[0].Duration + 100000;
9696
};
9797

98+
function convertReferenceWords(referenceText, referenceWords) {
99+
const dictionary = [...new Set(referenceWords)];
100+
const maxLength = Math.max(...dictionary.map(word => word.length));
101+
102+
// From left to right to do the longest matching to get the word segmentation
103+
function leftToRightSegmentation(text, dictionary) {
104+
var result = [];
105+
while (text.length > 0) {
106+
let subText = "";
107+
// If the length of the text is less than the maxLength, then the subText is the text itself
108+
if (text.length < maxLength) {
109+
subText = text;
110+
} else {
111+
subText = text.substring(0, maxLength);
112+
}
113+
while (subText.length > 0) {
114+
// If the subText is in the dictionary or the length of the subText is 1, then add it to the result
115+
if (dictionary.includes(subText) || subText.length === 1) {
116+
result.push(subText);
117+
// Remove the subText from the text
118+
text = text.slice(subText.length);
119+
break;
120+
} else {
121+
// If the subText is not in the dictionary, then remove the last character of the subText
122+
subText = subText.slice(0, -1);
123+
}
124+
}
125+
}
126+
return result;
127+
}
128+
129+
// From right to left to do the longest matching to get the word segmentation
130+
function rightToLeftSegmentation(text, dictionary) {
131+
var result = [];
132+
while (text.length > 0) {
133+
let subText = "";
134+
// If the length of the text is less than the maxLength, then the subText is the text itself
135+
if (text.length < maxLength) {
136+
subText = text;
137+
} else {
138+
subText = text.slice(-maxLength);
139+
}
140+
while (subText.length > 0) {
141+
// If the subText is in the dictionary or the length of the subText is 1, then add it to the result
142+
if (dictionary.includes(subText) || subText.length === 1) {
143+
result.push(subText);
144+
// Remove the subText from the text
145+
text = text.slice(0, -subText.length);
146+
break
147+
} else {
148+
// If the subText is not in the dictionary, then remove the first character of the subText
149+
subText = subText.slice(1);
150+
}
151+
}
152+
}
153+
// Reverse the result to get the correct order
154+
result = result.reverse();
155+
return result;
156+
}
157+
158+
function segment_word(referenceText, dictionary) {
159+
const leftToRight = leftToRightSegmentation(referenceText, dictionary);
160+
const rightToLeft = rightToLeftSegmentation(referenceText, dictionary);
161+
if (leftToRight.join("") === referenceText) {
162+
return leftToRight;
163+
} else if (rightToLeft.join("") === referenceText) {
164+
return rightToLeft;
165+
} else {
166+
console.log("WW failed to segment the text with the dictionary")
167+
if (leftToRight.length < rightToLeft.length) {
168+
return leftToRight;
169+
} else if (leftToRight.length > rightToLeft.length) {
170+
return rightToLeft;
171+
} else {
172+
// If the word number is the same, then return the one with the smallest single word
173+
const leftToRightSingle = leftToRight.filter(word => word.length === 1).length;
174+
const rightToLeftSingle = rightToLeft.filter(word => word.length === 1).length;
175+
if (leftToRightSingle < rightToLeftSingle) {
176+
return leftToRight;
177+
} else {
178+
return rightToLeft;
179+
}
180+
}
181+
}
182+
}
183+
184+
// Remove punctuation from the reference text
185+
referenceText = referenceText.split("").filter(char => /[\p{L}\p{N}\s]/u.test(char)).join("");
186+
return segment_word(referenceText, dictionary);
187+
}
188+
98189
async function getReferenceWords(waveFilename, referenceText, language) {
99190
const audioConfig = sdk.AudioConfig.fromWavFileInput(fs.readFileSync(waveFilename));
100191
const speechConfig = sdk.SpeechConfig.fromSubscription(settings.subscriptionKey, settings.serviceRegion);
@@ -131,7 +222,7 @@ export const main = async (settings) => {
131222
console.log(`Speech Recognition canceled: ${result.errorDetails}`);
132223
reject([]);
133224
}
134-
resolve(referenceWords);
225+
resolve(convertReferenceWords(referenceText, referenceWords));
135226
speechRecognizer.close();
136227
},
137228
(err) => {

0 commit comments

Comments
 (0)