Web Audio API MediaElementSource node and SoundCloud not working with effects? - javascript

I am using a SoundCloud URL as audio.src . It is only playing the unprocessed version when i run it through the delay chain i have.
Here is the fiddle:
http://jsfiddle.net/ehsanziya/nwaH3/
var context = new webkitAudioContext();
var audio = new Audio(); //creates a HTML5 Audio Element
url = 'http://api.soundcloud.com/tracks/33925813/stream' + '?client_id=c625af85886c1a833e8fe3d740af753c';
//wraps the soundcloud stream to an audio element.
audio.src = url;
var source = context.createMediaElementSource(audio);
var input = context.createGainNode();
var output = context.createGainNode();
var fb = context.createGainNode();
fb.gain.value = 0.4;
var delay = context.createDelayNode();
delay.delayTime.value = 0.5;
//dry
source.connect(input);
input.connect(output);
//wet
input.connect(delay);
delay.connect(fb);
fb.connect(delay);
delay.connect(output);
source.mediaElement.play();
The chain works with Oscillator node.
What is the reason for it?
And is there any other way of processing a streaming sound from SoundCloud with Web Audio API?

You need to wait for the canplaythrough event on your audio element to fire before you can use it with createMediaElementSource.
So just add the event listener, and wait until the callback fires before you assign source = context.createMediaElementSource(audio); and make all of your connections.
Here's an updated jsFiddle that'll do what you want: http://jsfiddle.net/nwaH3/3/

Related

Better timing for audio file

So I created the audio:
const jumpy = new Audio();
jumpy.src = "./audio/jump2.wav";
and generated an event listener that triggers the audio:
const cvs = document.getElementById("ghost");
cvs.addEventListener("click", function(evt){
jumpy2.play()
});
the problem is the browser first waits for the audio to play in full (about 1000 ms) before it will play it again but I want the audio to reset every time I click.
How can I go for that?
const jumpy = new Audio();
jumpy.src = "./audio/jump2.wav";
const cvs = document.getElementById("ghost");
cvs.addEventListener("click", function(evt){
jumpy2.play()
});
For short sounds that you want to use multiple times like this, it is better to use the AudioBufferSourceNode in the Web Audio API.
For example:
const buffer = await audioContext.decodeAudioData(/* audio data */);
const bufferSourceNode = audioContext.createBufferSource();
bufferSourceNode.buffer = buffer;
bufferSourceNode.connect(audioContext.destination);
bufferSourceNode.start();
The buffer will be kept in memory, already decoded to PCM and ready to play. Then when you call .start(), it will play right away.
See also: https://stackoverflow.com/a/62355960/362536

load a music file into an audio buffer to use with offlinecontext (web audio api)

I want to use the web audio OfflineAudioContext to save some short sound files into a new longer sound file. It seems that the OfflineAudioContext uses an audiobuffer to save the audio. I'm using the audio tag to load my sound files. How can I convert the sound files into an audio buffer that I can pass to the OfflineAudioContext buffer. I don't want to have to use the XMLHttpRequest to create the audio buffer. I wanted to be able to load each sound file then add it to a buffer, and then pass it to the offline context. I've tried several different ways, but the most I've got done is to pass an empty audio buffer to the context which just gives me a file with no sound.
I've tried several features of the web audio context to create a new buffer, but I either get errors, or no sound
<html>
<body>
<audio controls controlsList = "nodownload" id="audio"><source id="audioSource" src="" />
Your browser does not support the audio format.</audio>
<script>
// define online and offline audio context
var audioCtx1 = new AudioContext();
var offlineCtx = new OfflineAudioContext(2,44100*40,44100);
var channels = 2;
// Create an empty two second stereo buffer at the
// sample rate of the AudioContext
var frameCount = audioCtx1.sampleRate * 2.0;
var myArrayBuffer = audioCtx1.createBuffer(2, frameCount, audioCtx1.sampleRate);
source = offlineCtx.createBufferSource();
var array = ['sound1.mp3','sound2.mp3','sound3.mp3']
var audio = document.querySelector('audio');
audio.src = array[0];
source.buffer = myArrayBuffer;
source.connect(offlineCtx.destination);
source.start();
//source.loop = true;
offlineCtx.startRendering();
offlineCtx.oncomplete = function(e) {
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var song = audioCtx.createBufferSource();
song.buffer = e.renderedBuffer;
song.connect(audioCtx.destination);
song.start();
console.log("completed!");
}
</script>
</body>
</html>
I've changed the code several times during testing, I think with this code I posted I just get no sound playing.

Play recorded audio chunks as you receive them with Web Audio API

Is there a way to play the audio I am recording while I'm still recording it?
This is my code. I'm recording the audio and everytime an audio chunk is ready a call to onaudioprocess is made. It receives an instance of AudioProcessingEvent. I'm not familiar with the Web Audio API, so I'm not sure what to do to listen to it. I want my speakers to output the sound.
function startRecording(stream){
var context = new AudioContext();
var audio_input = context.createMediaStreamSource(stream);
var buffer_size = 2048;
var recorder = context.createScriptProcessor(buffer_size, 1, 1);
recorder.onaudioprocess = function(e){
// var data = e.inputBuffer.getChannelData(0);
// AudioStream.write(data);
var source = context.createBufferSource();
source.buffer = e.inputBuffer;
source.connect(context.destination);
source.start(0);
console.log(e.inputBuffer)
};
audio_input.connect(recorder);
recorder.connect(context.destination);
}
The code inside onaudioprocess does not work. There is no error in the console, but nothing happens.
The output of e.inputBuffer looks fine:
AudioBuffer {length: 4096, duration: 0.09287981859410431, sampleRate: 44100, numberOfChannels: 1}
Read up on the audio processing event at
https://webaudio.github.io/web-audio-api/#dom-audioprocessingevent to
see what the onprocess event does. You basically need to copy the
events inputBuffer to the outputBuffer and you'll be able to hear the
audio.

Creating MediaStream from canvas and video element

I am creating a MediaStream object and adding a video track to it from a canvas using the captureStream() function. This works fine.
However I am trying to add audio as a separate track from a video element. I cant seem to find a way to get an AudioTrack object from a html video element.
Currently HTMLMediaElement.audioTracks is not supported in Chrome. According to the mozilla developer site I should be able to use HTMLMediaElement.captureStream() to return a MediaStream object from which I should be able to retrieve the separate tracks but I just get 'captureStream is not a function' error.
Perhaps i'm missing something very obvious but I would greatly appreciate any help on this.
Below is my current code:
var stream = new MediaStream();
//Works fine for adding video source
var videotracks = myCanvas.captureStream().getTracks();
var videostream = videotracks[0];
stream.addTrack(videostream);
//Currently not supported in Chrome
var audiotracks = myVid.audioTracks;
var audiostream = audiotracks[0];
stream.addTrack(audiostream);
To get an audio stream from a video element in a cross-browser way :
AudioContext API createMediaStreamDestination + createMediaElementSource.
// if all you need is the audio, then you should even probably load your video in an Audio element
var vid = document.createElement('video');
vid.onloadedmetadata = generateAudioStream;
vid.crossOrigin = 'anonymous';
vid.src = 'https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4';
function generateAudioStream() {
var audioCtx = new AudioContext();
// create a stream from our AudioContext
var dest = audioCtx.createMediaStreamDestination();
// connect our video element's output to the stream
var sourceNode = audioCtx.createMediaElementSource(this);
sourceNode.connect(dest)
// start the video
this.play();
// your audio stream
doSomethingWith(dest.stream)
}
function doSomethingWith(audioStream) {
// the audio element that will be shown in the doc
var output = new Audio();
output.srcObject = audioStream;
output.controls = true;
output.play();
document.body.appendChild(output);
}
To add audio to a canvas stream :
MediaStream Capture Canvas and Audio Simultaneously

Will calling audio.play() pre-cache an HTML5 audio in the browser?

I have a bunch of audio clips that I need to repeatedly play in the browser.
As far as I understand doing audio = new Audio(src) does not do any IO on the actual source file until audio.play() is called.
Is there any guarantee that the code below would cache the audio in the browser and minimize latency?
audio = new Audio(src);
audio.volume = 0;
audio.play();
Is there any downside to this approach apart from the fact that volume=0 does not work in some Safari-based browsers, like the ones on IOS?
Is there a better approach for caching short audio clips?
you can try setting the preload attribute of the audio element as auto :
audio = new Audio(src);
audio.preload = 'auto';
Demo:
var aud = new Audio('http://upload.wikimedia.org/wikipedia/commons/5/5b/Ludwig_van_Beethoven_-_Symphonie_5_c-moll_-_1._Allegro_con_brio.ogg')
aud.preload = 'auto'
var bData = document.createElement('span')
document.body.appendChild(bData)
setInterval(() => bData.innerText = 'Buffered Time(in seconds): ' + (aud.buffered.length && aud.buffered.end(0)), 300)

Categories