Reputation: 1
I'm trying to figure out why this simple Web Audio synthesizer code is working in Chromium but not in Firefox. Could be a Firefox bug, or it could be that my code is not standard compliant and Chromium is overly forgiving. This looks like a long example but the first half is just test data. I'm struggling to pinpoint more precisely where the issue is.
<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>test</title><style></style>
</head>
<body>
<button onclick="generateMusic()">test</button>
<script>
const timbres = {
"default": [{g: 0, w: "sine", t: 1, f: 0, v: 0.5, a: 0, h: 0.01, d: 0.01, s: 0, r: 0.05, p: 1, q: 1, k: 0}], "test": [{w: "triangle", v: 0.4, d: 0.7, r: 0.1,},
{w: "triangle", v: 4, t: 3, d: 0.4, s: 0.1, g: 1, k: -1, a: 0.01,}],
};
var testMusic = [ [0, "test", 518.75, 71, 71, 2],
[1, "test", 207.5, 72, 71, 1],
[1, "test", 153.7037037037037, 71, 71, 1],
[1, "test", 103.75, 75, 71, 1],
[2, "test", 518.75, 71, 71, 1],
[2, "test", 415, 71, 71, 1],
[2, "test", 307.4074074074074, 71, 71, 1],
[2, "test", 207.5, 71, 71, 1],
[3, "test", 614.8148148148148, 71, 71, 3],
[4, "test", 194.53125, 71, 71, 1],
[4, "test", 153.7037037037037, 72, 71, 1],
[4, "test", 103.75, 73, 71, 1],
[5, "test", 389.0625, 71, 71, 1],
[5, "test", 307.4074074074074, 70, 71, 1],
[5, "test", 207.5, 71, 71, 1],
[6, "test", 691.6666666666667, 71, 71, 2],
[7, "test", 259.375, 71, 71, 1],
[7, "test", 207.5, 71, 71, 1],
[7, "test", 153.7037037037037, 69, 71, 1],
[7, "test", 103.75, 72, 71, 1],
[8, "test", 518.75, 71, 71, 1],
[8, "test", 415, 71, 71, 1],
[8, "test", 307.4074074074074, 70, 71, 1],
[8, "test", 207.5, 71, 71, 1],
[9, "test", 518.75, 70, 71, 3],
[10, "test", 207.5, 71, 71, 1],
[10, "test", 153.7037037037037, 71, 71, 1],
[10, "test", 129.6875, 71, 71, 1],
[10, "test", 97.265625, 71, 71, 1],
[11, "test", 415, 71, 71, 1],
[11, "test", 307.4074074074074, 71, 71, 1],
[11, "test", 259.375, 71, 71, 1],
[11, "test", 194.53125, 71, 71, 1],
[13, "test", 518.75, 67, 71, 1],
[13, "test", 207.5, 69, 71, 1],
[13, "test", 172.91666666666669, 71, 71, 1],
[13, "test", 129.6875, 74, 71, 1],
[13, "test", 86.45833333333334, 71, 71, 1],
[14, "test", 518.75, 75, 71, 1],
[14, "test", 415, 74, 71, 1],
[14, "test", 345.83333333333337, 71, 71, 1],
[14, "test", 259.375, 70, 71, 1],
[14, "test", 207.5, 71, 71, 1],
[15, "test", 614.8148148148148, 71, 71, 2],
[16, "test", 276.6666666666667, 71, 71, 1],
[16, "test", 230.55555555555557, 71, 71, 1],
[16, "test", 172.91666666666669, 71, 71, 1],
[16, "test", 115.27777777777779, 71, 71, 1],
[17, "test", 461.11111111111114, 71, 71, 1],
[17, "test", 345.83333333333337, 71, 71, 1],
[17, "test", 276.6666666666667, 71, 71, 1],
[17, "test", 230.55555555555557, 71, 71, 1],
[19, "test", 415, 71, 71, 1],
[19, "test", 288.19444444444446, 71, 71, 1],
[19, "test", 207.5, 71, 71, 1],
[19, "test", 172.91666666666669, 71, 71, 1],
[19, "test", 115.27777777777779, 69, 71, 1],
[20, "test", 415, 69, 71, 1],
[20, "test", 345.83333333333337, 71, 71, 1],
[20, "test", 288.19444444444446, 71, 71, 1],
[20, "test", 230.55555555555557, 68, 71, 1],
[21, "test", 518.75, 71, 71, 2],
[22, "test", 194.53125, 71, 71, 1],
[22, "test", 138.33333333333334, 71, 71, 1],
[22, "test", 115.27777777777779, 71, 71, 1],
[22, "test", 76.85185185185185, 71, 71, 1],
[23, "test", 389.0625, 71, 71, 1.25],
[23, "test", 276.6666666666667, 71, 71, 1],
[23, "test", 230.55555555555557, 71, 71, 1],
[23, "test", 153.7037037037037, 71, 71, 1],
[24.25, "test", 368.8888888888889, 71, 71, 0.25],
[24.5, "test", 345.83333333333337, 71, 71, 0.25],
[24.75, "test", 553.3333333333334, 71, 71, 0.25],
[24.75, "test", 324.21875, 71, 71, 0.5],
[25, "test", 461.11111111111114, 71, 71, 0.75],
[25.25, "test", 415, 71, 71, 0.25],
[25.5, "test", 389.0625, 71, 71, 0.75],
[25.75, "test", 648.4375, 71, 71, 0.25],
[26, "test", 553.3333333333334, 71, 71, 0.75],
[26.25, "test", 518.75, 71, 71, 0.25],
[26.5, "test", 461.11111111111114, 71, 71, 0.5],
[26.75, "test", 778.125, 71, 71, 0.25],
[27, "test", 648.4375, 71, 71, 0.25],
[27, "test", 461.11111111111114, 75, 71, 0.25],
[27.25, "test", 922.2222222222223, 71, 71, 0.25],
[27.25, "test", 553.3333333333334, 71, 71, 0.25],
[27.25, "test", 194.53125, 71, 71, 0.25],
[27.25, "test", 162.109375, 71, 71, 0.25],
[27.5, "test", 778.125, 71, 71, 0.25],
[27.5, "test", 461.11111111111114, 71, 71, 0.25],
[27.5, "test", 324.21875, 71, 71, 0.25],
[27.5, "test", 276.6666666666667, 71, 71, 0.25],
[27.75, "test", 1106.6666666666667, 71, 71, 0.25],
[27.75, "test", 648.4375, 71, 71, 0.25],
[27.75, "test", 230.55555555555557, 71, 71, 0.25],
[27.75, "test", 194.53125, 71, 71, 0.25],
[28, "test", 922.2222222222223, 71, 71, 0.25],
[28, "test", 553.3333333333334, 71, 71, 0.25],
[28, "test", 389.0625, 71, 71, 0.25],
[28, "test", 324.21875, 71, 71, 0.25],
[28.25, "test", 1296.875, 71, 71, 0.25],
[28.25, "test", 778.125, 71, 71, 0.25],
[28.25, "test", 276.6666666666667, 71, 71, 0.25],
[28.25, "test", 230.55555555555557, 71, 71, 0.25],
[28.5, "test", 1106.6666666666667, 71, 71, 0.25],
[28.5, "test", 648.4375, 71, 71, 0.25],
[28.5, "test", 461.11111111111114, 71, 71, 0.25],
[28.5, "test", 389.0625, 71, 71, 0.25],
[28.75, "test", 1556.25, 71, 71, 0.25],
[28.75, "test", 922.2222222222223, 71, 71, 0.25],
[28.75, "test", 324.21875, 71, 71, 0.25],
[28.75, "test", 276.6666666666667, 71, 71, 0.25],
[29, "test", 1296.875, 71, 71, 0.25],
[29, "test", 778.125, 71, 71, 0.25],
[29, "test", 553.3333333333334, 71, 71, 0.25],
[29, "test", 461.11111111111114, 71, 71, 0.25],
[29.25, "test", 1844.4444444444446, 71, 71, 0.25],
[29.25, "test", 1106.6666666666667, 71, 71, 0.25],
[29.25, "test", 389.0625, 71, 71, 0.25],
[29.25, "test", 324.21875, 71, 71, 0.25],
[29.5, "test", 1556.25, 71, 71, 0.25],
[29.5, "test", 922.2222222222223, 71, 71, 0.25],
[29.5, "test", 648.4375, 71, 71, 0.25],
[29.5, "test", 553.3333333333334, 71, 71, 0.25],
[29.75, "test", 2593.75, 71, 71, 0.25],
[29.75, "test", 1660, 71, 71, 0.25],
[29.75, "test", 922.2222222222223, 71, 71, 0.25],
[29.75, "test", 461.11111111111114, 71, 71, 0.25],
[30, "test", 2459.259259259259, 71, 71, 1],
[30, "test", 1556.25, 71, 71, 1],
[30, "test", 1106.6666666666667, 71, 71, 1],
[30, "test", 922.2222222222223, 75, 71, 1],
[30, "test", 614.8148148148148, 71, 71, 1],
[36, "test", 518.75, 71, 71, 2],
[37, "test", 207.5, 71, 71, 1],
[37, "test", 153.7037037037037, 71, 71, 1],
[37, "test", 103.75, 71, 71, 1],
[38, "test", 518.75, 73, 71, 1],
[38, "test", 415, 71, 71, 1],
[38, "test", 307.4074074074074, 71, 71, 1],
[38, "test", 207.5, 71, 71, 1],
[39, "test", 614.8148148148148, 71, 71, 3],
[40, "test", 194.53125, 71, 71, 1],
[40, "test", 153.7037037037037, 69, 71, 1],
[40, "test", 103.75, 72, 71, 1],
[41, "test", 389.0625, 71, 71, 1],
[41, "test", 307.4074074074074, 71, 71, 1],
[41, "test", 207.5, 72, 71, 1],
[42, "test", 691.6666666666667, 71, 71, 2],
[43, "test", 259.375, 71, 71, 1],
[43, "test", 207.5, 71, 71, 1],
[43, "test", 153.7037037037037, 68, 71, 1],
[43, "test", 103.75, 72, 71, 1],
[44, "test", 518.75, 71, 71, 1],
[44, "test", 415, 71, 71, 1],
[44, "test", 307.4074074074074, 70, 71, 1],
[44, "test", 207.5, 72, 71, 1],
[45, "test", 518.75, 70, 71, 3],
[46, "test", 207.5, 71, 71, 1],
[46, "test", 153.7037037037037, 71, 71, 1],
[46, "test", 129.6875, 71, 71, 1],
[46, "test", 97.265625, 71, 71, 1],
[47, "test", 415, 69, 71, 1],
[47, "test", 307.4074074074074, 71, 71, 1],
[47, "test", 259.375, 71, 71, 1],
[47, "test", 194.53125, 71, 71, 1],
[49, "test", 830, 71, 71, 1],
[49, "test", 207.5, 67, 71, 1],
[49, "test", 172.91666666666669, 71, 71, 1],
[49, "test", 129.6875, 74, 71, 1],
[49, "test", 86.45833333333334, 71, 71, 1],
[50, "test", 830, 73, 71, 1],
[50, "test", 415, 73, 71, 1],
[50, "test", 345.83333333333337, 71, 71, 1],
[50, "test", 259.375, 71, 71, 1],
[51, "test", 922.2222222222223, 71, 71, 2],
[52, "test", 276.6666666666667, 71, 71, 1],
[52, "test", 230.55555555555557, 71, 71, 1],
[52, "test", 172.91666666666669, 71, 71, 1],
[52, "test", 138.33333333333334, 71, 71, 1],
[52, "test", 115.27777777777779, 71, 71, 1],
[53, "test", 691.6666666666667, 71, 71, 1],
[53, "test", 553.3333333333334, 71, 71, 1],
[53, "test", 461.11111111111114, 71, 71, 1],
[53, "test", 345.83333333333337, 71, 71, 1],
[53, "test", 276.6666666666667, 71, 71, 1],
[53, "test", 230.55555555555557, 71, 71, 1],
[55, "test", 830, 71, 71, 1],
[55, "test", 243.1640625, 71, 71, 1],
[55, "test", 207.5, 71, 71, 1],
[55, "test", 172.91666666666669, 71, 71, 1],
[55, "test", 144.09722222222223, 71, 71, 1],
[56, "test", 778.125, 71, 71, 1],
[56, "test", 486.328125, 71, 71, 1],
[56, "test", 415, 71, 71, 1],
[56, "test", 345.83333333333337, 71, 71, 1],
[56, "test", 288.19444444444446, 71, 71, 1],
[57, "test", 691.6666666666667, 71, 71, 2],
[58, "test", 259.375, 71, 71, 1],
[58, "test", 207.5, 71, 71, 1],
[58, "test", 153.7037037037037, 71, 71, 1],
[59, "test", 518.75, 71, 71, 1],
[59, "test", 415, 71, 71, 1],
[59, "test", 307.4074074074074, 71, 71, 1],
[61, "test", 737.7777777777778, 71, 71, 1],
[61, "test", 216.14583333333334, 71, 71, 1],
[61, "test", 184.44444444444446, 71, 71, 1],
[61, "test", 153.7037037037037, 71, 71, 1],
[61, "test", 108.07291666666667, 71, 71, 1],
[62, "test", 691.6666666666667, 71, 71, 1],
[62, "test", 432.2916666666667, 71, 71, 1],
[62, "test", 368.8888888888889, 71, 71, 1],
[62, "test", 307.4074074074074, 71, 71, 1],
[62, "test", 216.14583333333334, 71, 71, 1],
[63, "test", 614.8148148148148, 71, 71, 2],
[64, "test", 230.55555555555557, 71, 71, 1],
[64, "test", 172.91666666666669, 71, 71, 1],
[64, "test", 138.33333333333334, 71, 71, 1],
[64, "test", 115.27777777777779, 71, 71, 1],
[65, "test", 461.11111111111114, 71, 71, 1],
[65, "test", 345.83333333333337, 71, 71, 1],
[65, "test", 276.6666666666667, 71, 71, 1],
[65, "test", 230.55555555555557, 71, 71, 1],
[66, "test", 138.33333333333334, 73, 71, 2],
[66.5, "test", 345.83333333333337, 71, 71, 0.5],
[67, "test", 345.83333333333337, 73, 71, 0.5],
[67, "test", 230.55555555555557, 71, 71, 1],
[67, "test", 194.53125, 71, 71, 1],
[67, "test", 76.85185185185185, 71, 71, 2],
[67.5, "test", 324.21875, 71, 71, 0.5],
[68, "test", 324.21875, 71, 71, 0.5],
[68, "test", 259.375, 71, 71, 1],
[68, "test", 216.14583333333334, 71, 71, 1],
[68, "test", 184.44444444444446, 71, 71, 1],
[68, "test", 129.6875, 71, 71, 1],
[68.5, "test", 307.4074074074074, 71, 71, 0.5],
[69, "test", 121.58203125, 71, 71, 2],
[69.5, "test", 307.4074074074074, 67, 71, 0.5],
[70, "test", 307.4074074074074, 75, 71, 0.5],
[70, "test", 207.5, 71, 71, 1],
[70, "test", 172.91666666666669, 71, 71, 1],
[70, "test", 76.85185185185185, 71, 71, 2],
[70.5, "test", 288.19444444444446, 71, 71, 0.5],
[71, "test", 288.19444444444446, 71, 71, 0.5],
[71, "test", 194.53125, 71, 71, 1],
[71, "test", 162.109375, 71, 71, 1],
[71, "test", 115.27777777777779, 71, 71, 1],
[71.5, "test", 276.6666666666667, 71, 71, 0.5],
[73, "test", 194.53125, 71, 71, 1],
[73, "test", 162.109375, 71, 71, 1],
[73, "test", 138.33333333333334, 71, 71, 1],
[73, "test", 115.27777777777779, 72, 71, 1],
[73, "test", 76.85185185185185, 68, 71, 1],
[74, "test", 194.53125, 69, 71, 1],
[74, "test", 162.109375, 72, 71, 1],
[74, "test", 138.33333333333334, 74, 71, 1],
[74, "test", 115.27777777777779, 72, 71, 1],
[74, "test", 76.85185185185185, 74, 71, 1],
[75, "test", 194.53125, 70, 71, 2],
[75, "test", 162.109375, 67, 71, 2],
[75, "test", 138.33333333333334, 67, 71, 2],
[75, "test", 115.27777777777779, 67, 71, 2],
[75, "test", 76.85185185185185, 67, 71, 2],
[77, "test", 207.5, 71, 71, 1],
[77, "test", 153.7037037037037, 71, 71, 1],
[77, "test", 129.6875, 71, 71, 1],
[77, "test", 103.75, 71, 71, 1],
[77, "test", 51.875, 71, 71, 1]
]
function generateMusic() {
function impulseResponse(duration, decay, reverse) {
var sampleRate = ctx.sampleRate;
var length = sampleRate * duration;
var impulse = ctx.createBuffer(2, length, sampleRate);
var impulseL = impulse.getChannelData(0);
var impulseR = impulse.getChannelData(1);
if (!decay)
decay = 2.0;
for (let i = 0; i < length; i++) {
var n = reverse ? length - i : i;
impulseL[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);
impulseR[i] = (Math.random() * 2 - 1) * Math.pow(1 - n / length, decay);
}
return impulse;
}
var ctx = new OfflineAudioContext(2, 44100 * (testMusic[testMusic.length - 1][0] + testMusic[testMusic.length - 1][5] + 5), 44100); //needs to become a bit more sophisticated in case the note that starts last in testMusic is not the note that finishes last
var out = ctx.destination;
var lookahead = 50.0; //25.0; //in milliseconds
var scheduleAheadTime = 2; //in seconds
// This is calculated from lookahead, and overlaps
// with next interval (in case the timer is late)
var timerID = 0; //setInterval identifier
var currentNote = 0;
function scheduleNote(i) {
var addToCurrentTime = testMusic[i][0];
var timbre = timbres[testMusic[i][1]];
var frequency = testMusic[i][2];
var dynamicBeginning = testMusic[i][3];
var dynamicEnding = testMusic[i][4];
var length = testMusic[i][5];
const op = [];
const op_gain = [];
for (let j = 0; j < timbre.length; j++) {
op_gain[j] = [];
for (let k = 0; k < Object.entries(timbres["default"][0]).length; k++) { //the following hopeless mess simply fills in the default values into the current timbre's parameters if the timbre does not provide its own parameters
if (typeof timbre[j][Object.keys(timbres["default"][0])[k]] == "undefined") {
timbre[j][Object.keys(timbres["default"][0])[k]] = timbres["default"][0][Object.keys(timbres["default"][0])[k]];
}
}
function frequencyToApproximateMidiNote(frequency) {
return Math.round(12 * Math.log2(frequency / 415) + 69);
}
if (timbre[j]["k"] != 0) {
var keyboardScalingFactor = Math.pow(2, (frequencyToApproximateMidiNote(frequency) - 60) / 12 * timbre[j]["k"]);
} else {
var keyboardScalingFactor = 1;
}
//assume for now that timbre[j]["w"][0] != "n"
op[j] = ctx.createOscillator();
op[j].type = timbre[j]["w"];
op[j].frequency.value = timbre[j]["t"] * frequency + timbre[j]["f"];
op_gain[j] = ctx.createGain();
op_gain[j].gain.cancelScheduledValues(addToCurrentTime);
op_gain[j].gain.setValueAtTime(0.0001, addToCurrentTime);
if (timbre[j]["g"] == 0) {
op_gain[j].gain.exponentialRampToValueAtTime(timbre[j]["v"] * (dynamicBeginning + 1) * (dynamicBeginning + 1) / 128 / 128, addToCurrentTime + timbre[j]["a"]);
op_gain[j].gain.setValueAtTime(timbre[j]["v"] * (dynamicBeginning + 1) * (dynamicBeginning + 1) / 128 / 128, addToCurrentTime + timbre[j]["a"]);
op_gain[j].gain.setValueAtTime(timbre[j]["v"] * (dynamicBeginning + 1) * (dynamicBeginning + 1) / 128 / 128, addToCurrentTime + timbre[j]["a"] + timbre[j]["h"]);
if (timbre[j]["s"] != 0) {
op_gain[j].gain.exponentialRampToValueAtTime(timbre[j]["s"] * (dynamicBeginning + 1) * (dynamicBeginning + 1) / 128 / 128 * timbre[j]["v"], addToCurrentTime + timbre[j]["a"] + timbre[j]["h"] + timbre[j]["d"]);
op_gain[j].gain.setValueAtTime(timbre[j]["s"] * (dynamicBeginning + 1) * (dynamicBeginning + 1) / 128 / 128 * timbre[j]["v"], addToCurrentTime + timbre[j]["a"] + timbre[j]["h"] + timbre[j]["d"]);
op_gain[j].gain.exponentialRampToValueAtTime(timbre[j]["s"] * (dynamicEnding + 1) * (dynamicEnding + 1) / 128 / 128 * timbre[j]["v"], addToCurrentTime + length);
op_gain[j].gain.setValueAtTime(timbre[j]["s"] * (dynamicEnding + 1) * (dynamicEnding + 1) / 128 / 128 * timbre[j]["v"], addToCurrentTime + length);
op_gain[j].gain.exponentialRampToValueAtTime(0.0001, addToCurrentTime + length + timbre[j]["r"]);
op_gain[j].gain.setValueAtTime(0, addToCurrentTime + length + timbre[j]["r"]);
} else {
op_gain[j].gain.exponentialRampToValueAtTime(0.0001, addToCurrentTime + timbre[j]["a"] + timbre[j]["h"] + timbre[j]["d"] + timbre[j]["r"]);
op_gain[j].gain.setValueAtTime(0, addToCurrentTime + timbre[j]["a"] + timbre[j]["h"] + timbre[j]["d"] + timbre[j]["r"]);
}
} else {
var gainFactorFromFrequency = frequency * timbre[timbre[j]["g"] - 1]["t"] + timbre[timbre[j]["g"] - 1]["f"];
if (timbre[j - 1]["w"][0] == "n") {
gainFactorFromFrequency /= 415;
}
op_gain[j].gain.exponentialRampToValueAtTime(timbre[j]["v"] * 100 / 127 * keyboardScalingFactor, addToCurrentTime + timbre[j]["a"]);
op_gain[j].gain.setValueAtTime(timbre[j]["v"] * 100 / 127 * keyboardScalingFactor, addToCurrentTime + timbre[j]["a"]);
op_gain[j].gain.setValueAtTime(timbre[j]["v"] * 100 / 127 * keyboardScalingFactor, addToCurrentTime + timbre[j]["a"] + timbre[j]["h"]);
if (timbre[j]["s"] != 0) {
op_gain[j].gain.exponentialRampToValueAtTime(timbre[j]["s"] * gainFactorFromFrequency * timbre[j]["v"] * 100 / 127 * keyboardScalingFactor, addToCurrentTime + timbre[j]["a"] + timbre[j]["h"] + timbre[j]["d"]);
op_gain[j].gain.setValueAtTime(timbre[j]["s"] * gainFactorFromFrequency * timbre[j]["v"] * 100 / 127 * keyboardScalingFactor, addToCurrentTime + timbre[j]["a"] + timbre[j]["h"] + timbre[j]["d"]);
op_gain[j].gain.exponentialRampToValueAtTime(timbre[j]["s"] * gainFactorFromFrequency * timbre[j]["v"] * 100 / 127 * keyboardScalingFactor, addToCurrentTime + length);
op_gain[j].gain.setValueAtTime(timbre[j]["s"] * gainFactorFromFrequency * timbre[j]["v"] * 100 / 127 * keyboardScalingFactor, addToCurrentTime + length);
}
op_gain[j].gain.exponentialRampToValueAtTime(0.0001, addToCurrentTime + timbre[j]["a"] + timbre[j]["h"] + timbre[j]["d"] + timbre[j]["r"]);
op_gain[j].gain.setValueAtTime(0, addToCurrentTime + timbre[j]["a"] + timbre[j]["h"] + timbre[j]["d"] + timbre[j]["r"]);
}
}
var convolver = ctx.createConvolver();
convolver.buffer = impulseResponse(4, 4, false);
for (let j = 0; j < timbre.length; j++) {
op[j].connect(op_gain[j]);
if (timbre[j]["g"] == 0) {
op_gain[j].connect(convolver);
convolver.connect(out);
op_gain[j].connect(out);
} else {
op_gain[j].connect(op[timbre[j]["g"] - 1].frequency);
}
op[j].start(addToCurrentTime);
op[j].stop(addToCurrentTime + length + timbre[j]["r"]);
op[j].onended = function() {
op[j].disconnect();
op_gain[j].disconnect();
delete op[j];
delete op_gain[j];
}
}
}
var offlineRunning = 0;
function scheduler() {
if (currentNote + 1 == testMusic.length) {
return;
}
scheduleNextBlock();
if (offlineRunning == 0) {
offlineRunning = 1;
ctx.startRendering().then((renderedBuffer) => {
offlineRunning == 0;
const offlineAudioCtx = new AudioContext();
const song = offlineAudioCtx.createBufferSource();
song.buffer = renderedBuffer;
var playbackContext = new AudioContext;
var playSound = playbackContext.createBufferSource();
playSound.buffer = song.buffer;
playSound.connect(playbackContext.destination);
playSound.start(playbackContext.currentTime);
}).catch((err) => {
console.error(`Rendering failed: ${err}`);
console.log(err.lineNumber);
});
}
}
function scheduleNextBlock() {
if (currentNote >= testMusic.length) {
return;
}
while (testMusic[currentNote][0] < ctx.currentTime + scheduleAheadTime && currentNote < testMusic.length) {
console.log(String(Math.floor(currentNote / testMusic.length * 100)) + '%');
scheduleNote(currentNote);
if (currentNote + 1 < testMusic.length) {
currentNote++;
} else {
return;
}
}
window.clearTimeout(timerID);
timerID = window.setTimeout(scheduleNextBlock, lookahead);
}
scheduler();
}
</script>
</body></html>
Expected behavior and behavior in Chromium: on clicking the "test" button, an offline audio context renders synthesized audio, console.log()ing the percentage complete, and immediately afterward audio is played through the speakers (the test data happens to be a minute-long excerpt from Tchaikovsky's sonata in C sharp minor, but the issue applies to anything that I've tested regardless).
Behavior in Firefox: percentages are written to the console, but only the first note plays. The "rendering failed" error is not triggered. In fact, no errors are written to the console at all.
Upvotes: 0
Views: 73
Reputation: 9136
I believe the bug you ran into is already fixed in Firefox but not yet published in the stable release. It was a long standing bug that got finally fixed last month.
When running your code in the current Firefox Developer Edition (v120) it works as expected. Firefox v120 should become the stable version in about two weeks.
Upvotes: 0