Skip to content

Instantly share code, notes, and snippets.

@daurnimator
Last active November 7, 2023 07:10
Show Gist options
  • Save daurnimator/7407782 to your computer and use it in GitHub Desktop.
Save daurnimator/7407782 to your computer and use it in GitHub Desktop.
Playing with WebAudio and WebRTC
// Browser compat
window.AudioContext = window.AudioContext || window.webkitAudioContext;
window.RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
var key = window.location.hash.substring(1);
var audio_context = new AudioContext();
var local_output = audio_context.createMediaStreamDestination();
function gen_sinusoid(freq) {
var samples = 1024; // TODO: Pick a number so theres no discontinuity on loop
var buffer = audio_context.createBuffer(1, samples, audio_context.sampleRate);
var data = buffer.getChannelData(0);
for (var i=0; i<data.length; ++i) {
data[i] = Math.sin(i*2*Math.PI*freq/audio_context.sampleRate);
}
return buffer;
}
var tone = null;
function play_tone() {
var n = audio_context.createBufferSource();
n.buffer = tone;
n.connect(local_output);
n.loop = true;
n.start(0);
n.stop(2);
}
function use_mic() {
// Request local microphone access
navigator.getUserMedia({
audio:true
}, function(stream) {
var devices = stream.getAudioTracks();
console.log("Opened audio sources: " + devices.map(function(v){return v.label;}).join());
audio_context.createMediaStreamSource(stream).connect(local_output);
}, function(err) {
console.error(err);
});
}
// Create peer object
var rtc_config = null;
var pc = new RTCPeerConnection(rtc_config);
var ice_list = [];
pc.onsignalingstatechange = function(event) {
console.log("onsignalingstatechange", event);
};
// onicecandidate is called once for each element in list of ice candidates; followed by null
pc.onicecandidate = function(event) {
if (event.candidate !== null) {
ice_list.push(event.candidate);
} else {
// console.log("ICE:"+JSON.stringify(ice_list));
localStorage[key] = JSON.stringify({
type: "ice",
data: ice_list
});
localStorage.removeItem(key);
ice_list = [];
}
};
pc.ondatachannel = function(event) {
console.log("ondatachannel", event);
event.channel.onmessage = function(event) {
console.log("DATA", event);
};
};
//pc.createDataChannel("mydata", {});
pc.onaddstream = function(event) {
console.log("onaddstream", event);
// Connect remote source to local speakers
/* Chrome doesn't support remote audio streams in audio contexts....
var remote_source = audio_context.createMediaStreamSource(event.stream);
remote_source.connect(audio_context.destination);
// Use an audio element instead
*/
var audio_elem = document.createElement("audio");
// var audio_elem = document.getElementById("audio");
audio_elem.src = URL.createObjectURL(event.stream);
audio_elem.play();
};
pc.onremovestream = function(event) {
console.log("onremovestream", event);
};
var on_description = function(desc) {
console.log("on_description", desc);
pc.setLocalDescription(desc);
localStorage[key] = JSON.stringify({
type: desc.type,
data: desc
});
localStorage.removeItem(key);
};
pc.onnegotiationneeded = function(event) {
console.log("onnegotiationneeded", event);
pc.createOffer(on_description);
};
var initiate_call = function() {
pc.createOffer(on_description);
};
var on_incoming_sdp_offer = function(desc) {
pc.setRemoteDescription(new RTCSessionDescription(desc), function() {
pc.createAnswer(on_description);
});
};
var on_incoming_sdp_answer = function(desc) {
pc.setRemoteDescription(new RTCSessionDescription(desc));
};
var on_incoming_ice = function(candidate_list) {
for (var i in candidate_list) {
var candidate = candidate_list[i];
pc.addIceCandidate(new RTCIceCandidate(candidate));
}
console.log("Added ICE Candidates",candidate_list);
};
// Use localStorage to communicate between tabs
function listen_to(who) {
window.addEventListener("storage", function(e){
if (e.newValue === null) return;
if (e.key !== who) return;
var val = JSON.parse(e.newValue);
switch (val.type) {
case "offer":
on_incoming_sdp_offer(val.data);
break;
case "answer":
on_incoming_sdp_answer(val.data);
break;
case "ice":
on_incoming_ice(val.data);
break;
}
}, false);
}
if (key == "local") {
local_output.connect(audio_context.destination);
} else if (key == "asd") {
listen_to("qwe");
initiate_call();
tone = gen_sinusoid(300);
play_tone()
pc.addStream(local_output.stream);
} else if (key == "qwe") {
listen_to("asd");
tone = gen_sinusoid(600);
play_tone()
// pc.addStream(local_output.stream);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment