I’m banging my head up against this issue for hours missing something simple. I’m trying to implement a checkbox in my html page to toggle pitchshifting my microphone input for privacy and am working on combining Twilio.js with Pitchshifter located here:
Original Twilio-voice: [https://github.com/twilio/twilio-voice.js/releases](Twilio JS DIST github) (located in dist folder)
twilio-voice.js-2.12.1 located in the dist folder
Pitchshifter: [https://github.com/urtzurd/html-audio/blob/gh-pages/static/js/pitch-shifter.js](Pitchshifter on Github)
Upon answering a call, I see the console.log(s) being triggered, but no change in voice adjustment like the Pitchshift demo. I believe it has something to do with the way I am connecting the audio processor but after multi multi attempts the voice passing through is still unmodified.
I’ll worrie about adding the checkbox later to enable and disable the pitchshift once I get this part figured out.
Any pointers would be much appreciated as to why.
I attempted the modified code above and expected to hear my voice being modified and unrecognizable. I am doubtful but ultimately unsure if there is some post event that is overwriting the processor from taking effect.
var pitchShifterProcessor;
var initProcessor = function (audioContext) {
var validGranSizes = [256, 512, 1024, 2048, 4096, 8192];
var grainSize = validGranSizes[1];
var pitchRatio = 2.0;
var overlapRatio = 0.50;
console.log("1");
var hannWindow = function (length) {
var window = new Float32Array(length);
for (var i = 0; i < length; i++) {
window[i] = 0.5 * (1 - Math.cos(2 * Math.PI * i / (length - 1)));
}
return window;
};
console.log("2");
var linearInterpolation = function (a, b, t) {
return a + (b - a) * t;
};
console.log("3");
if (pitchShifterProcessor) {
pitchShifterProcessor.disconnect();
}
console.log("4");
if (audioContext.createScriptProcessor) {
pitchShifterProcessor = audioContext.createScriptProcessor(grainSize, 1, 1);
console.log("audioContext.createScriptProcessor");
} else if (audioContext.createJavaScriptNode) {
pitchShifterProcessor = audioContext.createJavaScriptNode(grainSize, 1, 1);
console.log("audioContext.createJavaScriptNode");
}
console.log("5");
pitchShifterProcessor.buffer = new Float32Array(grainSize * 2);
pitchShifterProcessor.grainWindow = hannWindow(grainSize);
console.log("6");
pitchShifterProcessor.onaudioprocess = function (event) {
var inputData = event.inputBuffer.getChannelData(0);
var outputData = event.outputBuffer.getChannelData(0);
for (i = 0; i < inputData.length; i++) {
// Apply the window to the input buffer
inputData[i] *= this.grainWindow[i];
// Shift half of the buffer
this.buffer[i] = this.buffer[i + grainSize];
// Empty the buffer tail
this.buffer[i + grainSize] = 0.0;
}
// Calculate the pitch shifted grain re-sampling and looping the input
var grainData = new Float32Array(grainSize * 2);
for (var i = 0, j = 0.0; i < grainSize; i++, j += pitchRatio) {
var index = Math.floor(j) % grainSize;
var a = inputData[index];
var b = inputData[(index + 1) % grainSize];
grainData[i] += linearInterpolation(a, b, j % 1.0) * this.grainWindow[i];
}
// Copy the grain multiple times overlapping it
for (i = 0; i < grainSize; i += Math.round(grainSize * (1 - overlapRatio))) {
for (j = 0; j <= grainSize; j++) {
this.buffer[i + j] += grainData[j];
}
}
// Output the first half of the buffer
for (i = 0; i < grainSize; i++) {
outputData[i] = this.buffer[i];
}
};
console.log("pitchShifterProcessor.connect()");
return pitchShifterProcessor;
};
/**
* Update the stream source with the new input audio stream.
* @param {MediaStream} stream
* @private
*/
PeerConnection.prototype._updateInputStreamSource = function (stream) {
if (this._inputStreamSource) {
this._inputStreamSource.disconnect();
}
try {
this._inputStreamSource = this._audioContext.createMediaStreamSource(stream);
this._inputStreamSource.connect(this._inputAnalyser);
this._inputStreamSource.connect(this._inputAnalyser2);
console.log("initprocessor");
// Initialize pitch shifting processor
var pitchShifterNode = initProcessor(this._audioContext);
// Connect the pitch shifter to the input stream
this._inputStreamSource.connect(pitchShifterProcessor);
pitchShifterNode.connect(this._audioContext.destination);
console.log("this._inputStreamSource.connect(pitchShifterProcessor);");
}
catch (ex) {
console.log(ex);
this._log.warn('Unable to update input MediaStreamSource', ex);
this._inputStreamSource = null;
}
};