クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【Tone.js】Tone.Part()でいろいろなリズムを鳴らす ※1〜8拍子編

Tone.jsの続きです。前回Tone.Part()で細かいタイミングのエイトビートを鳴らしました。今回はエイトビート以外のリズムも鳴らしてみたく思います。今回は1〜8拍子編です。奇数拍子や変拍子も作ってみました。それではいきましょう!

【目次】

※参考:前回記事
【Tone.js】Tone.Part()で細かいタイミングのエイトビートを鳴らす - クモのようにコツコツと

※参考:Tone.jsを習得するためにやった事まとめ
qiita.com

前回のおさらい

See the Pen tone.js-DrumBeat_7 by イイダリョウ (@i_ryo) on CodePen.

※音が鳴らない場合:https://codepen.io/i_ryo/full/jObJpeg/

Tone.Part()を使ってキック、スネア、ハイハットそれぞれを細かいタイミングで鳴らすことができた!

JSコード

// DOM
const beat = document.querySelector('#beat');

// エンベロープ(キック)
let optsMembrane = {
  pitchDecay: 0.001,
  envelope: {
    attack: 0.001 ,
    decay: 0.75 ,
    sustain: 0.01 ,
    release: 0.01 
  },
  volume: 25
}

// エンベロープ(スネア)
let optsNoiseSnare = {
  envelope: {
    attack: 0.001 ,
    decay: 0.5 ,
    sustain: 0
  }
}

// エンベロープ(ハイハット)
let optsNoiseHihat = {
  type: "brown",
  envelope: {
    attack: 0.001 ,
    decay: 0.03 ,
    sustain: 0
  }
}

// シンセ生成
const membrane = new Tone.MembraneSynth(optsMembrane).toMaster();
const noise1 = new Tone.NoiseSynth(optsNoiseSnare).toMaster();
const noise2 = new Tone.NoiseSynth(optsNoiseHihat).toMaster();

// シンセ実行
const kick = () => {
  membrane.triggerAttackRelease('C0','2n'); 
};

const snare = () => {
  noise1.triggerAttackRelease('8n');
};

const hihat = () => {
  noise2.triggerAttackRelease('32n');
};

//リズム設定
let kickRhythm = [
  ['0:0:0'],
  ['0:0.75:0'],
  ['0:2.5:0'],
  ['0:3.25:0'],
];

let snareRhythm = [
  ['0:1:0'],
  ['0:1.75:0'],
  ['0:3:0'],
];

let hihatRhythm = [
  ['0:0:0'],
  ['0:0.5:0'],
  ['0:1:0'],
  ['0:1.5:0'],
  ['0:2:0'],
  ['0:2.5:0'],
  ['0:3:0'],
  ['0:3.5:0'],
];

// シンセにリズムを設定
let kickPart = new Tone.Part(kick, kickRhythm).start();
let snarePart = new Tone.Part(snare, snareRhythm).start()
let hihatPart = new Tone.Part(hihat, hihatRhythm).start();

// ループ設定
kickPart.loop = true;
snarePart.loop = true;
hihatPart.loop = true;

// BPM設定
Tone.Transport.bpm.value = 90;

// クリックイベント
beat.addEventListener('click', () => {
  Tone.Transport.toggle();
}, false);

※参考:前回記事
【Tone.js】Tone.Part()で細かいタイミングのエイトビートを鳴らす - クモのようにコツコツと

1拍子(全音符)

今回は引き続きTone.Part()を使ってエイトビート以外のリズムも鳴らしてみる。

まずは1拍子から。このようなリズム。 f:id:idr_zz:20200523201649j:plain
1小節に全音符が一つだけ入る。強拍、弱拍のアクセントもない。一番シンプルなリズム。

「ドン…|……」という音が鳴る。

See the Pen tone.js-DrumBeat_1beat by イイダリョウ (@i_ryo) on CodePen.

※音が鳴らない場合:https://codepen.io/i_ryo/full/pojMxxE/

実に静かなリズムですなw

//リズム設定
let kickRhythm = [
  ['0:0:0'],
];

let snareRhythm = [
];

let hihatRhythm = [
  ['0:0:0'],
];

小説の頭にキックとハイハットを鳴らす。弱拍がないのでスネアは無し。

1拍子だと間がもたないのでBPMを90→100にしてみたw

// BPM設定
Tone.Transport.bpm.value = 100;

2拍子(二分音符)

2拍子はこのようなリズム f:id:idr_zz:20200523201653j:plain
二分音符のリズムで、1拍子目が強拍、2拍子目が弱拍になる。

「ドン…|タン…」という音が鳴る。

See the Pen tone.js-DrumBeat_2beat by イイダリョウ (@i_ryo) on CodePen.

※音が鳴らない場合:https://codepen.io/i_ryo/full/abveRrG/

キック=強拍、スネア=弱拍にした。

JSコード

//リズム設定
let kickRhythm = [
  ['0:0:0'],
];

let snareRhythm = [
  ['0:2:0'],
];

let hihatRhythm = [
  ['0:0:0'],
  ['0:2:0'],
];

キックは1拍子目、スネアは2拍子目、ハイハットは両方に入っている。

3拍子(ワルツ)

3拍子はこんなリズム f:id:idr_zz:20200523201658j:plain

「ドン|タン|タン」という音が鳴る。

See the Pen tone.js-DrumBeat_3beat by イイダリョウ (@i_ryo) on CodePen.

※音が鳴らない場合:https://codepen.io/i_ryo/full/oNjKQXm/

1拍目のキック(強拍)、2・3拍目のスネア(弱拍)になる。いわゆる「ワルツ」のビート。

音符的には四分音符ベースが3つで1小節のため「3/4拍子」になる。

JSコード

let beatNumber = 3;
let beatLength = 4 / beatNumber;

//リズム設定
let kickRhythm = [
  ['0:' + beatLength * 0 + ':0'],
];

let snareRhythm = [
  ['0:' + beatLength * 1 + ':0'],
  ['0:' + beatLength * 2 + ':0'],
];

let hihatRhythm = [];
for(i = 0; i < beatNumber ; i++) {
  hihatRhythm.push('0:' + beatLength * i + ':0');
}

ここからビートがだんだん複雑になってくるので書き方を変えてみた。

まず拍数は4拍子ベースだったので3拍子の長さは4割る3。計算は苦手なのでここからはプログラムにやってもらおうw

let beatNumber = 3;
let beatLength = 4 / beatNumber;
  • 変数beatNumberに3拍子の3を入れる
  • 変数beatLength4beatNumberを割ると音の長さが出る。1.33333…かな。

beatLengthをリズムの配列に入れる。まずはキック。

let kickRhythm = [
  ['0:' + beatLength * 0 + ':0'],
];

キック1拍目はの数値0なのでbeatLength掛ける0になる。

次はスネア

let snareRhythm = [
  ['0:' + beatLength * 1 + ':0'],
  ['0:' + beatLength * 2 + ':0'],
];

スネアは2、3拍目だが、数値的には1つずつ前にズレて掛ける1、掛ける2になる。

ハイハット。こちらは全ての拍に機械的に入れる。

let hihatRhythm = [];
for(i = 0; i < beatNumber ; i++) {
  hihatRhythm.push('0:' + beatLength * i + ':0');
}
  • 変数hihatRhythmに空の配列を設定
  • for文でbeatNumberの数量分ループ
  • 配列hihatRhythmpush()メソッドで値を追加(beatLengthiを掛ける)

push()はJSの組み込みメソッドで配列に値を追加する。

※参考:Array.prototype.push() - JavaScript | MDN

ハイハットはこれが完成系。以降も変更無しでOK。

4拍子(マーチ)

4拍子はこんなリズム f:id:idr_zz:20200523201702j:plain

「ドン|タン|ドン|タン」という音が鳴る。

See the Pen tone.js-DrumBeat_4beat by イイダリョウ (@i_ryo) on CodePen.

※音が鳴らない場合:https://codepen.io/i_ryo/full/PoPMxQz/

4分音符が4つで1小節。1、3拍目がキック(強拍)、2、4拍目がスネア(弱拍)。先程の2拍子のアクセントが倍になった感じ。

マーチなどの行進曲みたいなビート(BPMが遅いけどねw)*1

JSコード

let beatNumber = 4;
let beatLength = 4 / beatNumber;

//リズム設定
let kickRhythm = [
  ['0:' + beatLength * 0 + ':0'],
  ['0:' + beatLength * 2 + ':0'],
];

let snareRhythm = [
  ['0:' + beatLength * 1 + ':0'],
  ['0:' + beatLength * 3 + ':0'],
];

let hihatRhythm = [];
for(i = 0; i < beatNumber ; i++) {
  hihatRhythm.push('0:' + beatLength * i + ':0');
}

4拍子なのでbeatNumberを4にする。数値的には4割る4で「1」になる。

let beatNumber = 4;
let beatLength = 4 / beatNumber;

キックは1拍目、3拍目なので02

let kickRhythm = [
  ['0:' + beatLength * 0 + ':0'],
  ['0:' + beatLength * 2 + ':0'],
];

スネアは2拍目、4拍目なので13

let snareRhythm = [
  ['0:' + beatLength * 1 + ':0'],
  ['0:' + beatLength * 3 + ':0'],
];

5拍子(ハチロク-1)

5拍子はこんなリズム。いわゆる「変拍子」 f:id:idr_zz:20200523201706j:plain

「ド|ツ|ツ|タ|ツ」という音が鳴る。

See the Pen tone.js-DrumBeat_5beat by イイダリョウ (@i_ryo) on CodePen.

※音が鳴らない場合:https://codepen.io/i_ryo/full/qBOeQoG/

変拍子といっても3拍子と2拍子の組み合わせが基本になる。今回は「3+2」という順番だが「2+3」というパターンもある。

拍子的にはここからは8拍子ベース。8拍子が5つで1小節のため「5/8拍子」になる。後述の「6拍子(ハチロク)」から最後の1拍を抜いたリズムと考えるとわかりやすい。

JSコード

let beatNumber = 5;
let beatLength = 4 / beatNumber;

//リズム設定
let kickRhythm = [
  ['0:' + beatLength * 0 + ':0'],
];

let snareRhythm = [
  ['0:' + beatLength * 3 + ':0'],
];

let hihatRhythm = [];
for(i = 0; i < beatNumber ; i++) {
  hihatRhythm.push('0:' + beatLength * i + ':0');
}

5拍子なのでbeatNumber5に。数値的には4割る5で「0.8」になる。

let beatNumber = 5;
let beatLength = 4 / beatNumber;

キックは1拍目なので0

let kickRhythm = [
  ['0:' + beatLength * 0 + ':0'],
];

スネアは4拍目なので3

let snareRhythm = [
  ['0:' + beatLength * 3 + ':0'],
];

ちなみに5拍子(変拍子)がどんな音楽かはこちらで紹介されている曲を聞くとイメージしやすい。

※参考:「人類には早すぎる音楽」有名な変拍子曲をいくつか紹介します。 - CAMPFIRE (キャンプファイヤー)

6拍子(ハチロク)

6拍子はこんなリズム。いわゆる「ハチロク」 f:id:idr_zz:20200523201709j:plain

「ド|ツ|ツ|タ|ツ|ツ」という音が鳴る。

See the Pen tone.js-DrumBeat_6beat by イイダリョウ (@i_ryo) on CodePen.

※音が鳴らない場合:https://codepen.io/i_ryo/full/NWGQEMg/

「ハチロク」とは8分音符が6つで1小節、という意味で「6/8拍子」になる。

1拍目がキック(強拍)、4拍目がスネア(弱拍)でブルースやバラードなどで使われるリズム。

JSビート

let beatNumber = 6;
let beatLength = 4 / beatNumber;

//リズム設定
let kickRhythm = [
  ['0:' + beatLength * 0 + ':0'],
];

let snareRhythm = [
  ['0:' + beatLength * 3 + ':0'],
];

let hihatRhythm = [];
for(i = 0; i < beatNumber ; i++) {
  hihatRhythm.push('0:' + beatLength * i + ':0');
}

6拍子なのでbeatNumber6に。数値的には4割る6で「0.666…」になる。

let beatNumber = 6;
let beatLength = 4 / beatNumber;

キックとスネアは先程の5拍子から変更無しでOK!

let kickRhythm = [
  ['0:' + beatLength * 0 + ':0'],
];

let snareRhythm = [
  ['0:' + beatLength * 3 + ':0'],
];

7拍子(エイトビート-1)

7拍子はこんなリズム。これも変拍子 f:id:idr_zz:20200523201712j:plain

「ド|ツ|タ|ツ|ド|ツ|タ」という音が鳴る。

See the Pen tone.js-DrumBeat_7beat by イイダリョウ (@i_ryo) on CodePen.

※音が鳴らない場合:https://codepen.io/i_ryo/full/jObgQKa/

8拍子が7つで1小節なので「7/8拍子」になる。鳴らしてみるとわかるが後述するエイトビートから最後の1拍を抜いたリズム、と考えるとわかりやすい。

JSコード

let beatNumber = 7;
let beatLength = 4 / beatNumber;

//リズム設定
let kickRhythm = [
  ['0:' + beatLength * 0 + ':0'],
  ['0:' + beatLength * 4 + ':0'],
];

let snareRhythm = [
  ['0:' + beatLength * 2 + ':0'],
  ['0:' + beatLength * 6 + ':0'],
];

let hihatRhythm = [];
for(i = 0; i < beatNumber ; i++) {
  hihatRhythm.push('0:' + beatLength * i + ':0');
}

7拍子なのでbeatNumber7に。数値的には4割る7で「0.571…」になる。

let beatNumber = 7;
let beatLength = 4 / beatNumber;

キックは1拍目と5拍目なので04

let kickRhythm = [
  ['0:' + beatLength * 0 + ':0'],
  ['0:' + beatLength * 4 + ':0'],
];

スネアは3拍目と7拍目なので26

let snareRhythm = [
  ['0:' + beatLength * 2 + ':0'],
  ['0:' + beatLength * 6 + ':0'],
];

7拍子(変拍子)の音楽も先程の記事で紹介されている。

※参考:「人類には早すぎる音楽」有名な変拍子曲をいくつか紹介します。 - CAMPFIRE (キャンプファイヤー)

8拍子(エイトビート)

最後、帰ってきたエイトビート!ただいま! f:id:idr_zz:20200523201715j:plain

「ド|ツ|タ|ツ|ド|ツ|タ|ツ」という音が鳴る。

See the Pen tone.js-DrumBeat_8beat by イイダリョウ (@i_ryo) on CodePen.

※音が鳴らない場合:https://codepen.io/i_ryo/full/NWGQEBv/

8分音符が8つで1小節なので8/8拍子。アクセント的には先程の4拍子と同じだがハイハットの刻みが倍の8つになっている。

JSコード

let beatNumber = 8;
let beatLength = 4 / beatNumber;

//リズム設定
let kickRhythm = [
  ['0:' + beatLength * 0 + ':0'],
  ['0:' + beatLength * 4 + ':0'],
];

let snareRhythm = [
  ['0:' + beatLength * 2 + ':0'],
  ['0:' + beatLength * 6 + ':0'],
];

let hihatRhythm = [];
for(i = 0; i < beatNumber ; i++) {
  hihatRhythm.push('0:' + beatLength * i + ':0');
}

エイトビートも新バージョンに書き直した。

8拍子なのでbeatNumber8に。数値的には4割る8で「0.5」になる。

let beatNumber = 8;
let beatLength = 4 / beatNumber;

キックとスネアの位置は先程の7拍子から変更なしでOK!

let kickRhythm = [
  ['0:' + beatLength * 0 + ':0'],
  ['0:' + beatLength * 4 + ':0'],
];

let snareRhythm = [
  ['0:' + beatLength * 2 + ':0'],
  ['0:' + beatLength * 6 + ':0'],
];

最後に

ということでTone.Part()で1〜8拍子のリズムを作ってみました。電子音楽って偶数リズムの曲が多いので3拍子や変拍子を打ち込むのって結構難しいんじゃないかな、とイメージしてました。

やってみると意外と簡単にできました!Tone.Part()は4拍子ベースですが割り算とループを使えば割り切れない数値でも問題なかったです♪

次回はシャッフルリズムとか16ビートとかもっと細かいビートも作ってみたく。引き続きTone.Part()でいろいろなリズムを鳴らしてみます。それではまた!


※参考:Tone.jsを習得するためにやった事まとめ
qiita.com

*1:ジャズのハイハットのアクセントも「フォービート」