首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用JavaScript转换音乐和弦?

如何使用JavaScript转换音乐和弦?
EN

Stack Overflow用户
提问于 2011-10-29 03:31:52
回答 8查看 7K关注 0票数 12

我想知道如何创建一个javascript函数来转换音乐和弦。

因为我并不指望这里的每个人都能成为音乐家,所以我将尝试解释音乐理论中它是如何工作的。希望我别忘了什么。如果是,音乐家们,请纠正我。

1)简单和弦

简单的和弦几乎和字母表一样简单,它是这样的:

C,C#,D,D#,E,F,F#,G,G#,A,A# B

因此,如果最初的chord是E,并且我们想要转置+1,则得到的和弦是F。如果我们转置+4,得到的和弦是G#

2)扩展和弦

它们的工作方式几乎像简单的和弦,但包含更多的字符,这些字符在转换时可以安全地忽略。例如:

C#7,Dsus7,Emi,Fsus4,F#mi,G.

同样,和简单的和弦一样,如果我们转换Dsus7 +3= Fsus7

3)非根部低音

当低音演奏的音调与和弦的根音不同时,就会出现问题。这是由一个斜杠后的和弦,也需要转置。示例:

C/G、Dmi/A、F#sus7 7/A#

与示例1和例2一样,所有内容都是相同的,但斜杠后面的部分也需要转换,因此:

C/G +5= F/C

F#sus7/A# +1= Gsus7/B

我认为这应该是全部,除非我忘了什么。

因此,基本上,假设您有一个名为chord的javascript变量和transpose值transpose。什么代码会把和弦转过来?

示例:

代码语言:javascript
复制
var chord = 'F#sus7/C#';
var transpose = 3; // remember this value also may be negative, like "-4"
... code here ...
var result; // expected result = 'Asus7/E';
EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2011-10-29 04:22:41

像这样的事怎么样:

代码语言:javascript
复制
function transposeChord(chord, amount) {
  var scale = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
  return chord.replace(/[CDEFGAB]#?/g,
                       function(match) {
                         var i = (scale.indexOf(match) + amount) % scale.length;
                         return scale[ i < 0 ? i + scale.length : i ];
                       });
}

alert(transposeChord("Dm7/G", 2)); // gives "Em7/A"
alert(transposeChord("Fmaj9#11", -23)); // gives "F#maj9#11"

请注意,我加入了"F#maj9#11“示例,只是为了让您更多地思考如何构成有效的和弦名称:您可能会找到一个"#”尖锐符号,它不跟在字母后面(在本例中,它属于"11")。

而且,很明显,我的函数只理解锐利,不懂平面语,不懂键,因此,当它真正应该是"C#/E#“时,transposeChord("C/E", 1)会给出"C#/F”。

票数 13
EN

Stack Overflow用户

发布于 2017-08-31 11:01:25

只是为了进一步了解nnnnnn的答案。我们可以使用他的代码,并添加更多的代码,以使它实际上工作的单位。

代码语言:javascript
复制
transposeChord("F#sus7/A#", 1)
> "Gsus7/B"

transposeChord("Bb", 1)
> "B"

... works like a charm

代码语言:javascript
复制
function transposeChord(chord, amount) {
    var scale = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
    var normalizeMap = {"Cb":"B", "Db":"C#", "Eb":"D#", "Fb":"E", "Gb":"F#", "Ab":"G#", "Bb":"A#",  "E#":"F", "B#":"C"}
    return chord.replace(/[CDEFGAB](b|#)?/g, function(match) {
        var i = (scale.indexOf((normalizeMap[match] ? normalizeMap[match] : match)) + amount) % scale.length;
        return scale[ i < 0 ? i + scale.length : i ];
    })
}
代码语言:javascript
复制
<!-- Example Page -->
Chord:        <input id="chord" type="text" value="C#" style="width:70px"> 
transposed by <input id="amount" type="number" value="0" style="width:30px"> 
=             <input id="new-chord" type="text" style="width:70px">
              <button onclick="document.getElementById('new-chord').value = transposeChord(document.getElementById('chord').value,parseInt(document.getElementById('amount').value))">Calculate</button>

票数 4
EN

Stack Overflow用户

发布于 2011-10-29 03:40:17

代码语言:javascript
复制
function transpose(chord, increment)
{
    var cycle = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
    var el = chord.charAt(0);
    if(chord.length > 1 && chord.charAt(1) == '#')
    {
        el += "#";   
    }
    var ind = cycle.indexOf(el);
    var newInd = (ind + increment + cycle.length) % cycle.length;
    var newChord = cycle[newInd];
    return newChord + chord.substring(el.length);
}

我会让你找出低音部分,因为它实际上只是调用功能两次。

此外,对于不支持这里的旧浏览器,可以在函数之前添加代码indexOf

我在演示上放了一个jsFiddle。

编辑:问题是负模数。只要负数不超过长度(例如,你不能向下转100步),上面的内容就会起作用。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7936843

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档