Skip to content
Closed
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
84 changes: 84 additions & 0 deletions examples/check-piano-usage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Utility to check if piano_multi is actually being used
// Copy and paste this into your browser console while in Music Blocks

(function() {
console.log("%c🔍 CHECKING PIANO USAGE IN MUSIC BLOCKS 🔍", "background: #2196F3; color: white; font-size: 16px; padding: 5px;");

// Check if instrumentsSource is available in global scope
if (typeof instrumentsSource !== 'undefined') {

Check warning on line 8 in examples/check-piano-usage.js

View workflow job for this annotation

GitHub Actions / Lint updated JavaScript files with ESLint

Strings must use doublequote
console.log("Found instrumentsSource object:");
console.log(instrumentsSource);

// Check if piano_multi is being used
const pianoMultiUsed = Object.values(instrumentsSource).some(source => source[1] === "piano_multi");

if (pianoMultiUsed) {
console.log("%c✅ piano_multi is being used in your project!", "background: #4CAF50; color: white; font-size: 14px; padding: 3px;");

// Find which instrument is using piano_multi
const instrumentsUsingPianoMulti = Object.entries(instrumentsSource)
.filter(([_, source]) => source[1] === "piano_multi")
.map(([name, _]) => name);

console.log("Instruments using piano_multi:", instrumentsUsingPianoMulti);
} else {
console.log("%c❌ piano_multi is NOT being used in your project!", "background: #F44336; color: white; font-size: 14px; padding: 3px;");
console.log("You might be using the regular piano sample instead.");

// Check if regular piano is being used
const regularPianoUsed = Object.values(instrumentsSource).some(source => source[1] === "piano");
if (regularPianoUsed) {
console.log("%c⚠️ Regular piano sample is being used instead of piano_multi", "background: #FF9800; color: white; font-size: 14px; padding: 3px;");

const instrumentsUsingPiano = Object.entries(instrumentsSource)
.filter(([_, source]) => source[1] === "piano")
.map(([name, _]) => name);

console.log("Instruments using regular piano:", instrumentsUsingPiano);
}
}
} else {
console.error("instrumentsSource not found. Are you running this in Music Blocks?");
}

// Check if we can access the synth objects
if (typeof instruments !== 'undefined') {

Check warning on line 45 in examples/check-piano-usage.js

View workflow job for this annotation

GitHub Actions / Lint updated JavaScript files with ESLint

Strings must use doublequote
console.log("Found instruments object:");

// Count how many instruments are available
let instrumentCount = 0;
let samplerCount = 0;

for (const turtleId in instruments) {
for (const instrumentName in instruments[turtleId]) {
instrumentCount++;
const synth = instruments[turtleId][instrumentName];
if (synth && synth.name === "Sampler") {
samplerCount++;
console.log(`Found Sampler: ${instrumentName} for turtle ${turtleId}`);

// Check if this sampler has multiple buffers (indicating multi-sample)
if (synth._buffers) {
const bufferKeys = Array.from(synth._buffers.keys());
console.log(`Sampler buffers: ${bufferKeys.join(", ")}`);

if (bufferKeys.includes("C2") && bufferKeys.includes("C4") && bufferKeys.includes("C6")) {
console.log("%c✅ This sampler has C2, C4, and C6 buffers - it's using multi-samples!",

Check warning on line 66 in examples/check-piano-usage.js

View workflow job for this annotation

GitHub Actions / Lint updated JavaScript files with ESLint

Trailing spaces not allowed
"background: #4CAF50; color: white; font-size: 14px; padding: 3px;");
} else if (bufferKeys.length === 1 && bufferKeys[0] === "C4") {
console.log("%c❌ This sampler only has a C4 buffer - it's using a single sample",

Check warning on line 69 in examples/check-piano-usage.js

View workflow job for this annotation

GitHub Actions / Lint updated JavaScript files with ESLint

Trailing spaces not allowed
"background: #F44336; color: white; font-size: 14px; padding: 3px;");
}
}
}
}
}

console.log(`Total instruments: ${instrumentCount}, Samplers: ${samplerCount}`);
} else {
console.error("instruments object not found. Are you running this in Music Blocks?");
}

console.log("%c💡 SOLUTION: If piano_multi is not being used, try selecting 'piano multi' in the Set Timbre block",

Check warning on line 82 in examples/check-piano-usage.js

View workflow job for this annotation

GitHub Actions / Lint updated JavaScript files with ESLint

Trailing spaces not allowed
"background: #673AB7; color: white; font-size: 14px; padding: 3px;");
})();
151 changes: 151 additions & 0 deletions examples/piano-multi-debug.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Piano Multi-Sample Debug</title>
<script src="../lib/tone.min.js"></script>
<script src="../sounds/samples/piano_multi.js"></script>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
button {
margin: 5px;
padding: 10px;
font-size: 16px;
}
.note-group {
margin-bottom: 20px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
.log {
margin-top: 20px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
height: 200px;
overflow-y: auto;
background-color: #f9f9f9;
}
</style>
</head>
<body>
<h1>Piano Multi-Sample Debug Test</h1>
<p>This page tests whether the multi-sample piano is correctly using different samples for different note ranges.</p>

<div class="note-group">
<h2>Low Register (should use C2 sample)</h2>
<button id="playC2">Play C2</button>
<button id="playF2">Play F2</button>
<button id="playA2">Play A2</button>
<button id="playC3">Play C3</button>
</div>

<div class="note-group">
<h2>Middle Register (should use C4 sample)</h2>
<button id="playC4">Play C4</button>
<button id="playF4">Play F4</button>
<button id="playA4">Play A4</button>
<button id="playC5">Play C5</button>
</div>

<div class="note-group">
<h2>High Register (should use C6 sample)</h2>
<button id="playC6">Play C6</button>
<button id="playF6">Play F6</button>
<button id="playA6">Play A6</button>
<button id="playC7">Play C7</button>
</div>

<div class="log" id="log">
<h3>Debug Log:</h3>
</div>

<script>
// Function to log messages
function logMessage(message) {
const logElement = document.getElementById('log');
const logEntry = document.createElement('div');
logEntry.textContent = message;
logElement.appendChild(logEntry);
logElement.scrollTop = logElement.scrollHeight;
}

// Create a dictionary of samples for different registers
window.onload = function() {
// Extract sample identifiers to verify which sample is being used
const c2Sample = PIANO_C2_SAMPLE();
const c4Sample = PIANO_C4_SAMPLE();
const c6Sample = PIANO_C6_SAMPLE();

// Log the sample sources to verify they're different
logMessage("C2 Sample length: " + c2Sample.length);
logMessage("C4 Sample length: " + c4Sample.length);
logMessage("C6 Sample length: " + c6Sample.length);

// Create a modified version of each sample with an identifier
const c2SampleWithId = c2Sample;
const c4SampleWithId = c4Sample;
const c6SampleWithId = c6Sample;

// Create a dictionary for Tone.Sampler
const noteDict = {
"C2": c2SampleWithId,
"C4": c4SampleWithId,
"C6": c6SampleWithId
};

// Create a sampler with our samples
const sampler = new Tone.Sampler(noteDict).toDestination();

// Function to play a note and log which sample is being used
function playNote(note) {
// Start audio context if needed
if (Tone.context.state !== 'running') {
Tone.start();
}

// Determine which sample will be used based on the note
let sampleUsed;
const noteNum = Tone.Frequency(note).toMidi();

if (noteNum < 48) { // Notes below C3
sampleUsed = "C2";
} else if (noteNum < 72) { // Notes below C5
sampleUsed = "C4";
} else { // Notes C5 and above
sampleUsed = "C6";
}

logMessage(`Playing ${note} (MIDI: ${noteNum}) using ${sampleUsed} sample`);

// Play the note
sampler.triggerAttackRelease(note, "2n");
}

// Add event listeners to buttons
document.getElementById('playC2').addEventListener('click', () => playNote('C2'));
document.getElementById('playF2').addEventListener('click', () => playNote('F2'));
document.getElementById('playA2').addEventListener('click', () => playNote('A2'));
document.getElementById('playC3').addEventListener('click', () => playNote('C3'));

document.getElementById('playC4').addEventListener('click', () => playNote('C4'));
document.getElementById('playF4').addEventListener('click', () => playNote('F4'));
document.getElementById('playA4').addEventListener('click', () => playNote('A4'));
document.getElementById('playC5').addEventListener('click', () => playNote('C5'));

document.getElementById('playC6').addEventListener('click', () => playNote('C6'));
document.getElementById('playF6').addEventListener('click', () => playNote('F6'));
document.getElementById('playA6').addEventListener('click', () => playNote('A6'));
document.getElementById('playC7').addEventListener('click', () => playNote('C7'));

// Log that everything is ready
logMessage("Multi-sample piano test initialized. Click buttons to test different notes.");
logMessage("Tone.js will automatically select the appropriate sample based on the note's pitch.");
};
</script>
</body>
</html>
133 changes: 133 additions & 0 deletions examples/piano-multi-direct-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Direct test script for piano multi-samples
// Copy and paste this entire script into your browser console while in Music Blocks

(function() {
console.log("%c🎹 PIANO MULTI-SAMPLE DIRECT TEST 🎹", "background: #FF5722; color: white; font-size: 16px; padding: 5px;");

// First, verify that the samples are different
if (typeof verifyPianoMultiSamples === 'function') {

Check warning on line 8 in examples/piano-multi-direct-test.js

View workflow job for this annotation

GitHub Actions / Lint updated JavaScript files with ESLint

Strings must use doublequote
console.log("Running sample verification...");
const result = verifyPianoMultiSamples();
console.log("Verification result:", result);
} else {
console.warn("verifyPianoMultiSamples function not found. Make sure piano_multi.js is loaded.");
}

// Check if we're in Music Blocks with access to Tone.js
if (typeof Tone === 'undefined') {

Check warning on line 17 in examples/piano-multi-direct-test.js

View workflow job for this annotation

GitHub Actions / Lint updated JavaScript files with ESLint

Strings must use doublequote
console.error("Tone.js not found. This test must be run within Music Blocks.");
return;
}

// Make sure Tone.js is started
Tone.start().then(() => {
console.log("%c✅ Tone.js audio context started", "color: green; font-weight: bold;");
runTest();
}).catch(err => {
console.error("Failed to start Tone.js:", err);
});

function runTest() {
// Find the instrument name that's using piano_multi
let isPianoMultiRegistered = false;
let instrumentName = "";

if (typeof instrumentsSource !== 'undefined') {

Check warning on line 35 in examples/piano-multi-direct-test.js

View workflow job for this annotation

GitHub Actions / Lint updated JavaScript files with ESLint

Strings must use doublequote
for (const key in instrumentsSource) {
if (instrumentsSource[key][1] === "piano_multi") {
isPianoMultiRegistered = true;
instrumentName = key;
break;
}
}

console.log("%c🔍 Checking if piano_multi is registered:", "font-weight: bold;");
console.log(isPianoMultiRegistered ?

Check warning on line 45 in examples/piano-multi-direct-test.js

View workflow job for this annotation

GitHub Actions / Lint updated JavaScript files with ESLint

Trailing spaces not allowed
`✅ piano_multi is registered as "${instrumentName}"` :

Check warning on line 46 in examples/piano-multi-direct-test.js

View workflow job for this annotation

GitHub Actions / Lint updated JavaScript files with ESLint

Trailing spaces not allowed
"❌ piano_multi is NOT registered in instrumentsSource");
} else {
console.warn("instrumentsSource not found. Can't check if piano_multi is registered.");
}

// Test playing notes in different registers to verify sample selection
console.log("%c🎵 Testing piano multi-sample note selection:", "font-weight: bold;");

// Create a test synth with our samples
const testSynth = new Tone.Sampler({
"C2": PIANO_C2_SAMPLE(),
"C4": PIANO_C4_SAMPLE(),
"C6": PIANO_C6_SAMPLE()
}).toDestination();

// Define test notes in different registers - updated to match the corrected boundaries
const testNotes = [
{ note: "C2", register: "low", expectedSample: "C2" },
{ note: "G2", register: "low", expectedSample: "C2" },
{ note: "B2", register: "low", expectedSample: "C2" }, // B2 is MIDI 47, last note using C2 sample
{ note: "C3", register: "middle", expectedSample: "C4" }, // C3 is MIDI 48, first note using C4 sample
{ note: "G4", register: "middle", expectedSample: "C4" },
{ note: "B4", register: "middle", expectedSample: "C4" }, // B4 is MIDI 71, last note using C4 sample
{ note: "C5", register: "high", expectedSample: "C6" }, // C5 is MIDI 72, first note using C6 sample
{ note: "G6", register: "high", expectedSample: "C6" },
{ note: "C7", register: "high", expectedSample: "C6" }
];

// Create a table to track results
const results = [];

// Play each note with a delay
testNotes.forEach((test, index) => {
setTimeout(() => {
const noteNum = Tone.Frequency(test.note).toMidi();
console.log(`%cPlaying ${test.note} (MIDI: ${noteNum}) in ${test.register} register...`, "color: blue;");

// Play the note
testSynth.triggerAttackRelease(test.note, 0.5);

// Record which sample was used
let actualSample;
// Use the same boundaries as in synthutils.js
if (noteNum <= 47) { // Notes up to B2
actualSample = "C2";
} else if (noteNum <= 71) { // Notes from C3 to B4
actualSample = "C4";
} else { // Notes C5 and above
actualSample = "C6";
}

const result = {
note: test.note,
midi: noteNum,
register: test.register,
expectedSample: test.expectedSample,
actualSample: actualSample,
correct: actualSample === test.expectedSample
};

results.push(result);
console.log(`%c${result.correct ? '✅' : '❌'} Used ${actualSample} sample (${result.correct ? 'correct' : 'incorrect'})`,
result.correct ? "color: green;" : "color: red; font-weight: bold;");

// Show final results table after all notes have played
if (index === testNotes.length - 1) {
setTimeout(() => {
console.log("%c📊 FINAL TEST RESULTS:", "background: #2196F3; color: white; font-size: 14px; padding: 3px;");
console.table(results);

const allCorrect = results.every(r => r.correct);
console.log(`%c${allCorrect ? '✅ ALL TESTS PASSED!' : '❌ SOME TESTS FAILED!'}`,
`background: ${allCorrect ? '#4CAF50' : '#F44336'}; color: white; font-size: 14px; padding: 3px;`);

if (allCorrect) {
console.log("%c🎉 The piano multi-sample implementation is working correctly! The system is using the appropriate sample for each note range and not just transposing a single sample.",
"color: green; font-weight: bold;");
} else {
console.log("%c⚠️ There may be an issue with the piano multi-sample implementation. Some notes are not using the expected sample.",
"color: red; font-weight: bold;");
}
}, 500);
}
}, index * 700); // 700ms between notes
});
}
})();
Loading