One of my esteemed professors from Santa Monica College, Dr. Driscoll asked for an opinion on how one can use a sheet of music and reshuffle some measures to generate a unique exercise for each student. This turned out more fun than anticipated and here's a solution I came up with using the free notation software MuseScore and a Node.js script. I hope it can be useful to someone else in the future for music education or why not for generative music too.
Driscoll博士是我来自圣塔莫尼卡学院( Santa Monica College)的一位尊敬的教授,他要求人们就如何使用乐谱和改组某些措施为每个学生进行独特的锻炼提出意见。 事实证明,这比预期的要有趣,这是我使用免费的注释软件MuseScore和Node.js脚本提出的解决方案。 我希望它对将来的其他人在音乐教育或为什么不在生成音乐中有用。
For the inpatient, here's the code.
对于住院病人,这里是代码。
3步程序 (3-step process)
- Create a MuseScore file to be used as a "template"创建一个MuseScore文件用作“模板”
- Reshuffle the measures by manipulating XML in a Node.js script and spit out an N number of different MuseScore files 通过在Node.js脚本中处理XML来重新整理措施,并吐出N个不同的MuseScore文件
Use a batch-convert plugin in MuseScore to convert the new files to PDF, MP3, MIDI or any other desired output format
使用MuseScore中的批处理转换插件将新文件转换为PDF,MP3,MIDI或任何其他所需的输出格式
模板(The template)
For a template you can create a new file in MuseScore or import some other file into MuseScore for final touches. In my case, the prof gave me a MusicXML file exported from Sibelius (a clunkier commercial alternative to MuseScore).
对于模板,您可以在MuseScore中创建一个新文件,或将其他文件导入MuseScore中以进行最终修饰。 就我而言,教授给了我一个从Sibelius导出的MusicXML文件(MuseScore的笨拙商业替代品)。
Once the music sheet is to your liking, export it as uncompressed XML, native to MuseScore (*.mscx).
一旦您喜欢了音乐表,就可以将其导出为MuseScore(* .mscx)固有的未压缩XML。
Turns out MuseScore's native files are compressed xml (mscz) or its uncompressed brethren (mscx). I used the uncompressed version so I can look around into the XML and also don't have to deal with compression in my Node script.
事实证明,MuseScore的本机文件是压缩的xml(mscz)或未压缩的兄弟文件(mscx)。 我使用了未压缩的版本,因此我可以浏览XML,也不必在Node脚本中处理压缩。
Why MuseScore's XML and not MusicXML? I don't have a good answer other than convenience and habit and reducing one more variable.
为什么使用MuseScore的XML而不是MusicXML? 除了便利和习惯,减少一个变量之外,我没有一个好的答案。
In the template you pick certain measures be reused and reshuffled, for example motive A consist of measures 2 and 3, motive C is just measure 8 and so on. These motives will be defined in the Node script.
在模板中,您选择要重用和重新安排的某些度量,例如动机A由度量2和3组成,动机C仅由度量8组成,依此类推。 这些动机将在Node脚本中定义。
剧本 (The script)
The script does this:
该脚本执行此操作:
Read the XML template using xml-js into a JavaScript object for manipulation
使用xml-js将XML模板读入JavaScript对象以进行操作
- Extract the motive measures from the XML从XML中提取动机措施
- Generate 100 random permutations of the desired motives and their quantity生成所需动机及其数量的100个随机排列
- Write 100 new XML files with the recombined measures用重新组合的方法编写100个新的XML文件
But first...
但首先...
组态 (Configuration)
const MAX = 100; // how many combinations to generate
const ADJOK = false; // is it ok to have adjacent repeated motives
const motives = {
A: [2, 3], // Motive A is measures 2 and 3
B: [4, 5],
C: [8],
D: [10, 11],
E: [16],
F: [17],
G: [19],
H: [22],
I: [23],
};
// we want motive A to happen twice in the new score,
// motive C to happen 4 times and so on
const distribution = 'AADDFFEEEBGHICCCC';
const OUT = 'out/';
The funny-looking AADDFFEEEBGHICCCC is a definition of how many times you want each motive to repeat. This is what's going to be reshuffled to create the new combinations.
看起来很有趣的AADDFFEEEBGHICCCC定义了您希望每个动机重复多少次。 这就是将要改组以创建新组合的内容。
阅读XML (Read the XML)
// imports
const convert = require('xml-js');
const fs = require('fs');
const xml = fs.readFileSync('Template.mscx', 'utf8');
const options = {compact: true, ignoreComment: true, spaces: 4};
const source = convert.xml2js(xml, options);
convert
is the XML-JS library that lets you convert to/from XML, JSON and JavaScript objects. Here we convert the XML to a JavaScript object for easy manipulation.
convert
是XML-JS库,可用于与XML,JSON和JavaScript对象进行相互转换。 在这里,我们将XML转换为JavaScript对象以便于操作。
Next, remembering the location of the measures (a Measure
array in the resulting object) for less typing:
接下来,记住度量的位置(结果对象中的Measure
数组),以减少键入次数:
// an array of all measures
const origMeasures = source.museScore.Score.Staff.Measure;
Then, going through the motives configuration and reading them from the template score:
然后,通过动机配置并从模板分数中读取它们:
// extract the patterns from the template
const patterns = {};
Object.keys(motives).forEach((letter) => {
patterns[letter] = [];
motives[letter].forEach((m) => {
// measures start from 1, arrays from 0
patterns[letter].push(origMeasures[m - 1]);
});
});
产生100个随机排列(Generate 100 random permutations)
The variable combinations
will contain the new reshuffled strings (e.g. ACGFCDCEFIHEDEBCA
, GIECBFCADCHAEFCED
and so on).
变量combinations
将包含新的改组字符串(例如ACGFCDCEFIHEDEBCA
, GIECBFCADCHAEFCED
等)。
Using a Set
prevents duplicates.
使用Set
可以防止重复。
// generate MAX random combinations
const combinations = new Set();
let these = distribution.split('');
while (combinations.size < MAX) {
these.sort(() => 0.5 - Math.random());
if (checkAdjecents(these)) {
combinations.add(these.join(''));
}
}
A helper function to disallow adjacent motives, if desired:
如果需要,可以使用助手功能来禁止相邻的动机:
function checkAdjecents(combo) {
if (ADJOK) {
return true;
}
for (let i = 1; i < combo.length; i++) {
if (combo[i] === combo[i - 1]) {
return false;
}
}
return true;
}
写入100个新的XML文件(Write 100 new XML files)
Last step - going through each new combination and creating a new array of measures. Here the first and last measure are always the same as this was a requirement, but you don't have to do this.
最后一步-经历每种新组合并创建一系列新的衡量指标。 这里的第一个和最后一个度量始终与此要求相同,但是您不必这样做。
Writing the new XML is accomplished by reconverting the modified JS object back to XML.
编写新的XML是通过将修改后的JS对象重新转换为XML来完成的。
combinations.forEach((combo) => {
// first and last measures are always the same
const last = origMeasures[origMeasures.length - 1];
const first = origMeasures[0];
const newMeasures = [first];
combo.split('').forEach((letter) => {
patterns[letter].forEach((_, idx) => {
newMeasures.push(patterns[letter][idx]);
});
});
newMeasures.push(last);
source.museScore.Score.Staff.Measure = newMeasures;
source.museScore.Score.Staff.VBox.Text[0].text._text = combo;
fs.writeFileSync(OUT + combo + '.mscx', convert.js2xml(source, options));
});
The VBox.Text[0].text._text = combo;
is optional, it writes the combination as title of the score.
VBox.Text[0].text._text = combo;
是可选的,它将组合写为乐谱的标题。
Example result open in MuseScore:
在MuseScore中打开示例结果:
Full code listing is on GitHub.
完整的代码清单在GitHub上。
批量转换 (Batch conversion)
At this point it's all done. But we can do one better and generate PDFs to distribute to musicians/students who do not use MuseScore. Thanks to the batch-convert plugin, this is quick and painful.
至此,一切都完成了。 但是我们可以做得更好,并生成PDF,以分发给不使用MuseScore的音乐家/学生。 多亏了batch-convert插件,这既快速又痛苦。
Lots of formats to chose from! You click OK and point to the out
directory where the script wrote all MuseScore XMLs.
有多种格式可供选择! 您单击确定,并指向脚本编写所有MuseScore XML的out
目录。
And this is it. Now the out/
directory contains 100 MuseScore files and 100 PDFs all named after the random combination of letter motives.
就是这样。 现在, out/
目录包含100个MuseScore文件和100个PDF,所有这些文件都是根据字母动机的随机组合命名的。
重用脚本 (Reusing the script)
What if you want to reuse the script for your own purposes, exercises and genarative music? Why, it would give me the most pleasure!
如果您想出于自己的目的,练习和生成音乐重用脚本,该怎么办? 为什么,它将给我带来最大的快乐!
Just clone the github repo, change the Template.mscx
and edit the configuration. Then run...
只需克隆github存储库,更改Template.mscx
并编辑配置。 然后跑...
$ node msms.js
... and find a bunch of files in your out/
directory. Then, if required, do the batch conversion to PDF as described above.
...并在out/
目录中找到一堆文件。 然后,如果需要,如上所述,将其批量转换为PDF。
是Node的新手吗? (New to Node?)
A side note for people who think the section above was mostly gibberish. If you're new to Node.js, here are a few more pointers.
对于那些认为上面的部分主要是乱七八糟的人的补充说明。 如果您不熟悉Node.js,这里还有一些指针。
Download and install Node from here
从这里下载并安装Node
Get a copy of the code: go to https://github.com/stoyan/msms and "Download ZIP".
获取代码副本:转到https://github.com/stoyan/msms ,然后单击“下载ZIP”。
Unzip where you want. Navigate to that directory.
解压缩到所需位置。 导航到该目录。
Install dependencies by running
通过运行安装依赖项
$ npm i
Now edit the configuration in
msms.js
and change the templateTemplate.mscx
, then run现在在
msms.js
编辑配置,并更改模板Template.mscx
,然后运行$ node msms.js
Tell your friends about this post on Facebook and Twitter
在Facebook和Twitter上告诉您的朋友有关此帖子的信息
翻译自: https://www.phpied.com/randomizing-music-musescore-nodejs/