在人机交互的设计中,声音往往被视觉所掩盖,但它却是不可或缺的一部分。声音波是一种机械波,其物理特性为提供了丰富的应用可能性。
软件工程师用0和1构建他们的乌托邦,而音乐家用音符构建他们的伊甸园。当编码与音乐相遇时,会产生奇妙的化学反应。音乐可以丰富软件的用户体验,而编码则让人们更深入地了解音乐的结构。
旋律由各种音符组成,而音符的时间值和音高是最重要的属性。下面将介绍如何使用JavaScript创建一个音乐音符。
人们能够识别不同音高的音符,因为每个音符都有其特定的频率。根据Web Audio API,可以创建一个振荡器节点,该节点可以生成具有特定频率的声波。可以尝试以下代码:
var context = new webkitAudioContext(),
osc = context.createOscillator();
osc.frequency.value = 440;
osc.connect(context.destination);
osc.start(0);
上述代码创建了一个频率为440赫兹的振荡器。根据十二平均律,440赫兹是'LA'音符的频率。在十二平均律中,将八度音分为12个相等的部分,半音的宽度,即两个相邻音符之间的频率比,是2的12次方根。因此可以计算出其他音符的频率。
var MusicalAlphabet = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'],
freqChat = {},
freqRange = 3,
i, j, base;
for (i = 1; i < freqRange; i++) {
freqChat[i] = {};
base = (i - 1) * 12;
for (j = 0; j < 12; j++) {
freqChat[i][MusicalAlphabet[j]] = 440 * Math.pow(2, (base + j - 9) / 12);
}
}
建议在脚本开始时计算所有音符的频率。现在,可以获取每个音符的音高。下一步是处理时间值。最简单的方法是使用振荡器节点的'stop'和'start'函数。
var context = new webkitAudioContext();
var osc = context.createOscillator();
osc.frequency.value = 440;
osc.connect(context.destination);
var _c = context.currentTime;
osc.start(_c + 1);
osc.stop(_c + 2);
可能已经注意到变量_c。在Web音频的上下文中,它有自己的时间线。上下文的'currentTime'属性是访问这个时间线的唯一方式。所有上下文的节点都按照这个时间线播放。'start'函数需要一个参数来定义振荡器节点的开始时间。如果这个参数小于context.currentTime,'start'函数将立即执行。
不幸的是,每个实例的'start'函数只能调用一次。这意味着一旦调用了'stop'函数,将不得不创建一个新的实例来播放相同的音符。因此,推荐另一种解决方案。关键是增益节点。通过增益节点,可以控制振荡器节点的信号强度。如果曾经玩过吉他放大器,可能会更好地理解这个节点。
var context = new webkitAudioContext(),
gain = context.createGain(),
osc = context.createOscillator(),
_c = context.currentTime;
osc.frequency.value = 440;
gain.gain.value = 0;
osc.connect(gain);
gain.connect(context.destination);
osc.start(_c);
gain.gain.setValueAtTime(1, _c + 1);
gain.gain.setValueAtTime(0, _c + 2);
上面的代码可以在1秒到2秒之间播放'La'(C大调)音符。可以将gain.gain.value的值从0设置为1。当这个值设置为0时,它就像调用了'stop'函数一样。下面的图片显示了信号的变化。
除了'setValueAtTime'函数外,增益节点还有一些其他方法可以改变其值。可以在Web音频API中找到它们。
到目前为止,应该能够通过JavaScript在一段时间内播放一个音乐音符。但是要实现一个音乐作品,还有很多事情要做。在本文的下一部分,将教如何使用名为'Jsonic'的JavaScript框架创建一个音乐作品。
Jsonic是一个小巧且功能丰富的JavaScript库。通过Jsonic,可以创作音乐,通过超声波传输数据,使声波可视化,进行语音识别等。可以从jsonic.net或github获取Jsonic。
上面的图片显示了Jsonic旋律模块的结构。需要创建一个Track或TrackGain的实例来播放音乐作品。音乐作品由许多音符组成。让继续看详细的代码。
var note = new Jsonic.Melody.Note(1, 1/4, 0, false);
根据上面的代码,可以创建一个音乐音符。在Jsonic中,每个Jsonic.Melody.Note的实例都指的是一个音乐音符。Note的构造函数可以接受4个参数。第一个是角色名,第三个参数定义了这个音符所在的八度。Jsonic.Melody.Note使用角色名(0,1,2,3,4,5,6,7)来创建实例,这样就可以在MusicScore中轻松地改变音调。如果想得到中央C,第三个参数应该是0。第二个参数定义了音符的时间值(1,1/2,1/4,1/8,1/16)。MusicScore的速度是另一个影响音符实际时间值的元素。第四个参数定义了这个音符是否有点。
var musicScore = new Jsonic.Melody.MusicScore('C', 'major', '4/4');
当创建一个MusicScore的实例时,可以定义它的音调和节拍。上面的代码创建了一个4/4的C大调音乐作品。这里应该使用音乐字母表。
创建音乐作品后,可以按照以下代码将音符添加到音乐作品中:
musicScore.w(new Jsonic.Melody.Note(3), new Jsonic.Melody.Note(4));
函数'w'会将其所有参数追加到音乐作品的末尾。下一步是创建一个Track或TrackGain的实例来播放音乐作品。但应该先调用'compile'函数。
musicScore.compile();
正如在本文开头提到的,有两种方式来控制音符的时间值。Track和TrackGain分别对应这两种方式。
var track = new Jsonic.Melody.Track();
track.play(musicScore, 90);
上面的代码创建了一个轨道并播放了一个速度为90的音乐作品。速度的值指的是节拍器中的数据。