-
-
Save aggresss/2d57bf64679e4476820dcf06a8328644 to your computer and use it in GitHub Desktop.
Playing with WebAudio and WebRTC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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