I am trying to build a loop sequencer that utilises the web audio API and many different musical loops of different lengths. The general idea is that the loops are chosen at random (to a degree), then played back in in a specific order for a beginning, middle and end section. There are four channels - bass, drums, lead, and FX. Just before the end of the last section a new set of samples are chosen and played back using the same formula.
I then intend to add a visualiser and maybe some automation - i.e maybe reverb for the final few bars.
I have to tried to follow the 'Tale of Two Clocks' method but as I am relatively new to programming - and to javascript - I am having a hard time implementing it. I think it might make things more complicated than necessary to complete this.
My initial idea was to create a for loop with the play method inside that specified the amount of times I want a loop to play, but I have found that the samples will instead all play at once. As per the 'Tale of Two Clocks', I am avoiding using setTimeout() and setInterval() as much as possible as it will only lead to lag.
My second idea was to call all the play methods at once, except each is cued at a certain point in the 'song', for example
START SECTION
playlead(time, buffer);
playdrums(time + length*2, buffer);
MIDDLE SECTION
playlead(time + length*10, buffer);
playdrums(time + length*10, buffer);
playlead2(time + length*10, buffer);
playbass(time + length*10, buffer);
and so on. This has caused its own set of problems however and seems like a fairly inefficient way to go about it.
It feels like a may be missing an obvious solution but after quite a bit of research, I have still not been able to solve it. It seems like the easiest thing to do would be to make the playSound function in my for loop wait for the sample to finish before iterating again but this is a lot harder to do than it seems. Please if anyone could offer up any advice I would be very grateful as I am at wits end with this. Thank you in advance!
//Just to add, the issue I am having in my second method is that in order to play even just the start section realistically the code will have to look something like this to play for around 30 seconds:
///START SECTION ( for 30 seconds or so)
playlead(time, buffer);
playlead(time + length, buffer);
playlead(time + length*2, buffer);
playlead(time, + length*3, buffer);
playbass(time, buffer);
playbass(time + length, buffer);
playbass(time + length*2, buffer);
playbass(time, + length*3, buffer);
playlead1(time, buffer);
playlead1(time + length, buffer);
playlead1(time + length*2, buffer);
playlead1(time, + length*3, buffer);
playdrums(time, buffer);
playdrums(time + length, buffer);
playdrums(time + length*2, buffer);
playdrums(time, + length*3, buffer);
this is 16 calls to the play() method at once. For the full song to play there will more than likely be 4 sections before being rebuffered and asked to play again. That is at least 16*4 (64) calls at the same time straight after loading. I am guessing that with a spectograph, automated audioParam's and volume/effects sliders included this might cause some issues?Thanks.
//// Here is an example of the code which most of my problems are stemming from:
function LeadStartSection
(buffer, time, gainNode, bufferList)
{
console.log("playing lead Start section");
var timer = setTimeout(function() { //checks when audiobuffer has finished
console.log('sample times out at' + timer);
}, buffer.duration * 1000);
var Length = buffer.duration;
console.log(Length);
var n = 1;
////Example of second method/////
playLead(buffer, time, gainNode,n, bufferList);
playLead(buffer, time + Length, gainNode, Length,n, bufferList);
playLead(buffer, time + Length*2, gainNode, Length,n, bufferList);
playLead(buffer, time + Length*3, gainNode, Length, n+2, bufferList);
}
///example of what I would like to do///
for (i=o; i<leadPlayCount; i++)
{
PlayLead(buffer, gainNode, Length, bufferList);
}
*in first example n is passed to the function because the middle section will be cued once n = n+2.
*in the second example I am having trouble calling playLead so that each loop starts just after the one before it ends. Instead, the method is called 4 times at once. it does not sound too good!I was thinking that maybe there was a way that the for loop would not continue until it recieved a return for the playLead method but it seems i am wrong.
I hope this might give you a bit more of an understanding of where I am at. Please ask if there is anything else you would like me to include. thanks a million for any help!