Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions js/blocks/PitchBlocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -1810,27 +1810,25 @@ function setupPitchBlocks(activity) {

class StepPitchBlock extends FlowBlock {
constructor() {
//.TRANS: step some number of notes in current musical scale
super("steppitch", _("scalar step") + " (+/–)");
super("steppitch", _("scalar step") + " (+/-)");
this.setPalette("pitch", activity);
this.piemenuValuesC1 = [-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7];
this.beginnerBlock(true);
this.setHelpString([
_("The Scalar Step block (in combination with a Number block) will play the next pitch in a scale,") +
" " +
_("The Scalar Step block (in combination with a Number block) will play the next pitch in a scale.") + " " +
_("eg if the last note played was sol, Scalar Step 1 will play la."),
"documentation",
""
]);
this.formBlock({
args: 1,
defaults: [1],
default: [1],
argTypes: ["anyin"]
});
}

flow(args, logo, turtle, blk) {
return Singer.PitchActions.stepPitch(args[0], turtle, blk);
return Singer.PitchActions.stepPitchTemperamentAware(args[0], turtle, blk);
}
}

Expand Down
105 changes: 105 additions & 0 deletions js/turtleactions/PitchActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,111 @@ function setupPitchActions(activity) {
return;
}

/**
* Gets the current temperament for the turtle.
*
* @param {Object} turtle - Turtle object
* @returns {String} temperament name (e.g. "eqaul", "just", "pythagorean", "meantone")
*/
static getTemperament(turtle) {
return turtle.singer.temperament || "equal";
}

/**
* Gets the current the key signature for the turtle.
*
* @param {Object} turtle - Turtle object
* @returns {String} key signature (e.g. "C Major")
*/
static getKeySignature(turtle) {
return turtle.singer.keySignature || "C Major";
}

/**
* Gets the last played pitch for the turtle.
*
* @param {Object} turtle - Turtle object
* @returns {Array} [note, octave]
*/
static getCurrentPitch(turtle) {
return turtle.singer.lastNotePlayed || ["C", 4];
}

/**
* Sets the last played pitch for the turtle.
*
* @param {String} note - Note name (e.g. "C", "G", "A")
* @param {Number} octave - Octave number
* @param {Object} turtle - Turtle object
*/
static setCurrentPitch(note, octave, turtle) {
turtle.singer.lastNotePlayed = [note, octave];
}

/**
* Calculates the frequency for a note using temperament-specific logic.
*
* @param {String} note - Note name
* @param {Number} octave - Octave number
* @param {String} temperament - Temperament name
* @param {String} keySignature - key signature
* @returns {Array} [note, octave, frequency]
*/
static calculateTemperamentFrequency(note, octave, temperament, keySignature, step) {
let frequency = 0;
if(temperament === "equal") {
frequency = pitchToFrequency(note, octave, keySignature, "equal");
} else if(temperament == "just") {
frequency = pitchToFrequency(note, octave, keySignature, "just");
} else if(temperament === "pythagorean") {
frequency = pitchToFrequency(note, octave, keySignature, "pythagorean");
} else if(temperament === "meantone") {
frequency = pitchToFrequency(note, octave, keySignature, "meantone");
} else {
frequency = pitchToFrequency(note, octave, keySignature, "equal");
}
return [note, octave, frequency];
}

/**
* Steps by Scalar degree using temperament-aware logic.
*
* @param {Number} step - number of scale degrees to step
* @param {Number} turtle - Turtle index in turtles.turtleList
* @param {Number|String} blk - corresponding Block object index in block.blockList or custom blockName
* @returns {*} result of playPitch
*/
static stepPitchTemperamentAware(step, turtle, blk) {
const temperament = this.getTemperament(activity.turtles.ithTurtle(turtle));
const keySignature = this.getKeySignature(activity.turtles.ithTurtle(turtle));
const [currentNote, currentOctave] = this.getCurrentPitch(activity.turtles.ithTurtle(turtle));

const scale = buildScale(keySignature)[0];
let idx = scale.indexOf(currentNote);
if (idx === -1) idx = 0;

let newIdx = idx + step;
let octaveShift = 0;
while(newIdx < 0) {
newIdx += scale.length;
octaveShift -= 1;
}
while(newIdx >= scale.length) {
newIdx -= scale.length;
octaveShift += 1;
}
const newNote = scale[newIdx];
const newOctave = currentOctave + octaveShift;

const [note, octave, frequency] = this.calculateTemperamentFrequency(
newNote, newOctave, temperament, keySignature, step
);

this.setCurrentPitch(note, octave, activity.turtles.ithTurtle(turtle));

return this.playPitch(note, octave, 0, turtle, blk);
}

/**
* Plays a nth modal pitch block.
*
Expand Down
Binary file added venv/Scripts/python.exe
Binary file not shown.
Binary file added venv/Scripts/pythonw.exe
Binary file not shown.
3 changes: 3 additions & 0 deletions venv/pyvenv.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
home = C:\Users\Kusum Lata\AppData\Local\Programs\Python\Python38
include-system-site-packages = false
version = 3.8.0
Loading