mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-24 23:12:24 -05:00
Add support for scratch 1.x MIDI drum blocks
This commit is contained in:
parent
e0550db404
commit
f617723348
1 changed files with 116 additions and 7 deletions
|
@ -611,6 +611,64 @@ class Scratch3MusicBlocks {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array that is a mapping from MIDI drum numbers in range (35..81) to Scratch drum numbers.
|
||||||
|
* It's in the format [drumNum, pitch, decay].
|
||||||
|
* The pitch and decay properties are not currently being used.
|
||||||
|
* @type {Array[]}
|
||||||
|
*/
|
||||||
|
get MIDI_DRUMS () {
|
||||||
|
return [
|
||||||
|
[1, -4], // "BassDrum" in 2.0, "Bass Drum" in 3.0 (which was "Tom" in 2.0)
|
||||||
|
[1, 0], // Same as just above
|
||||||
|
[2, 0],
|
||||||
|
[0, 0],
|
||||||
|
[7, 0],
|
||||||
|
[0, 2],
|
||||||
|
[1, -6, 4],
|
||||||
|
[5, 0],
|
||||||
|
[1, -3, 3.2],
|
||||||
|
[5, 0], // "HiHatPedal" in 2.0, "Closed Hi-Hat" in 3.0
|
||||||
|
[1, 0, 3],
|
||||||
|
[4, -8],
|
||||||
|
[1, 4, 3],
|
||||||
|
[1, 7, 2.7],
|
||||||
|
[3, -8],
|
||||||
|
[1, 10, 2.7],
|
||||||
|
[4, -2],
|
||||||
|
[3, -11],
|
||||||
|
[4, 2],
|
||||||
|
[6, 0],
|
||||||
|
[3, 0, 3.5],
|
||||||
|
[10, 0],
|
||||||
|
[3, -8, 3.5],
|
||||||
|
[16, -6],
|
||||||
|
[4, 2],
|
||||||
|
[12, 2],
|
||||||
|
[12, 0],
|
||||||
|
[13, 0, 0.2],
|
||||||
|
[13, 0, 2],
|
||||||
|
[13, -5, 2],
|
||||||
|
[12, 12],
|
||||||
|
[12, 5],
|
||||||
|
[10, 19],
|
||||||
|
[10, 12],
|
||||||
|
[14, 0],
|
||||||
|
[14, 0], // "Maracas" in 2.0, "Cabasa" in 3.0 (TODO: pitch up?)
|
||||||
|
[17, 12],
|
||||||
|
[17, 5],
|
||||||
|
[15, 0], // "GuiroShort" in 2.0, "Guiro" in 3.0 (which was "GuiroLong" in 2.0) (TODO: decay?)
|
||||||
|
[15, 0],
|
||||||
|
[8, 0],
|
||||||
|
[9, 0],
|
||||||
|
[9, -4],
|
||||||
|
[17, -5],
|
||||||
|
[17, 0],
|
||||||
|
[11, -6, 1],
|
||||||
|
[11, -6, 3]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The key to load & store a target's music-related state.
|
* The key to load & store a target's music-related state.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -725,6 +783,27 @@ class Scratch3MusicBlocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
opcode: 'midiPlayDrumForBeats',
|
||||||
|
blockType: BlockType.COMMAND,
|
||||||
|
text: formatMessage({
|
||||||
|
id: 'music.midiPlayDrumForBeats',
|
||||||
|
default: 'play drum [DRUM] for [BEATS] beats',
|
||||||
|
description: 'play drum sample for a number of beats according to a mapping of MIDI codes'
|
||||||
|
}),
|
||||||
|
arguments: {
|
||||||
|
DRUM: {
|
||||||
|
type: ArgumentType.NUMBER,
|
||||||
|
menu: 'DRUM',
|
||||||
|
defaultValue: 1
|
||||||
|
},
|
||||||
|
BEATS: {
|
||||||
|
type: ArgumentType.NUMBER,
|
||||||
|
defaultValue: 0.25
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideFromPalette: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
opcode: 'restForBeats',
|
opcode: 'restForBeats',
|
||||||
blockType: BlockType.COMMAND,
|
blockType: BlockType.COMMAND,
|
||||||
|
@ -846,14 +925,44 @@ class Scratch3MusicBlocks {
|
||||||
* @property {number} BEATS - the duration in beats of the drum sound.
|
* @property {number} BEATS - the duration in beats of the drum sound.
|
||||||
*/
|
*/
|
||||||
playDrumForBeats (args, util) {
|
playDrumForBeats (args, util) {
|
||||||
|
this._playDrumForBeats(args.DRUM, args.BEATS, util);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Play a drum sound for some number of beats according to the range of "MIDI" drum codes supported.
|
||||||
|
* This block is implemented for compatibility with old Scratch projects that use the
|
||||||
|
* 'drum:duration:elapsed:from:' block.
|
||||||
|
* @param {object} args - the block arguments.
|
||||||
|
* @param {object} util - utility object provided by the runtime.
|
||||||
|
*/
|
||||||
|
midiPlayDrumForBeats (args, util) {
|
||||||
|
let drumNum = Cast.toNumber(args.DRUM);
|
||||||
|
drumNum = Math.round(drumNum);
|
||||||
|
const midiDescription = this.MIDI_DRUMS[drumNum - 35];
|
||||||
|
if (midiDescription) {
|
||||||
|
drumNum = midiDescription[0];
|
||||||
|
} else {
|
||||||
|
drumNum = 2; // Default instrument used in Scratch 2.0
|
||||||
|
}
|
||||||
|
drumNum += 1; // drumNum input to _playDrumForBeats is one-indexed
|
||||||
|
this._playDrumForBeats(drumNum, args.BEATS, util);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal code to play a drum sound for some number of beats.
|
||||||
|
* @param {number} drumNum - the drum number.
|
||||||
|
* @param {beats} beats - the duration in beats to pause after playing the sound.
|
||||||
|
* @param {object} util - utility object provided by the runtime.
|
||||||
|
*/
|
||||||
|
_playDrumForBeats (drumNum, beats, util) {
|
||||||
if (this._stackTimerNeedsInit(util)) {
|
if (this._stackTimerNeedsInit(util)) {
|
||||||
let drum = Cast.toNumber(args.DRUM);
|
drumNum = Cast.toNumber(drumNum);
|
||||||
drum = Math.round(drum);
|
drumNum = Math.round(drumNum);
|
||||||
drum -= 1; // drums are one-indexed
|
drumNum -= 1; // drums are one-indexed
|
||||||
drum = MathUtil.wrapClamp(drum, 0, this.DRUM_INFO.length - 1);
|
drumNum = MathUtil.wrapClamp(drumNum, 0, this.DRUM_INFO.length - 1);
|
||||||
let beats = Cast.toNumber(args.BEATS);
|
beats = Cast.toNumber(beats);
|
||||||
beats = this._clampBeats(beats);
|
beats = this._clampBeats(beats);
|
||||||
this._playDrumNum(util, drum);
|
this._playDrumNum(util, drumNum);
|
||||||
this._startStackTimer(util, this._beatsToSec(beats));
|
this._startStackTimer(util, this._beatsToSec(beats));
|
||||||
} else {
|
} else {
|
||||||
this._checkStackTimer(util);
|
this._checkStackTimer(util);
|
||||||
|
|
Loading…
Reference in a new issue