WebAudio / web-audio-api

The Web Audio API v1.0, developed by the W3C Audio WG
https://webaudio.github.io/web-audio-api/
Other
1.06k stars 168 forks source link

Loop event #267

Closed DougGore closed 10 years ago

DougGore commented 11 years ago

I have a suggestion regarding the AudioBufferSourceNode. At present there is only a single event to inform you when the buffer has finished playback which is useful in some scenarios. When in loop mode however there is no event to do the equivalent for generating an event once the loop point has been reached.

The ability to know when the loop point has been reached would be useful for use in logic that limits the number of playback loops to predefined value. There may be other use cases such as a visual indication that the loop has been triggered.

It may be possible to use polling to do an equivalent task but if the loop is quite short in duration and the polling function is delayed due to an activity like garbage collection occurring it could lead to opportunity to disable the loop at the correct point being missed.

ghost commented 11 years ago

Douglas Gore writes:

The ability to know when the loop point has been reached would be useful for use in logic that limits the number of playback loops to predefined value.

Would the |duration| parameter to start() and/or the |when| parameter to stop be useful here, or is the number of loops determined after start is called()?

There may be other use cases such as a visual indication that the loop has been triggered.

It may be possible to use polling to do an equivalent task but if the loop is quite short in duration and the polling function is delayed due to an activity like garbage collection occurring it could lead to opportunity to disable the loop at the correct point being missed.

A loop event could also be delayed.

Another option, though awkward and inefficient, is to connect a ScriptProcessorNode to the output of the AudioBufferSourceNode, to get regular events. The period of notifications is limited to a predefined set, but something could be made to work.

Karl.

cwilso commented 11 years ago

More to the point - loop events would be delayed.

events are only delivered when the main thread is free to do so; loop points could happen VERY quickly (e.g. you could be looping a very small buffer, e.g. a single cycle).

DougGore commented 11 years ago

For the defined number of loops use case Karl suggests using start() with a when offset is a feasible solution. However if I wanted to specify 100 loops up front, I assume I have to create 100 nodes. Would that carry much overhead?

The correct solution of course would probably be to create n loops ahead using the onended event as a check point for creating more.

Chris you make a very valid point that the loop could be extremely short and therefore a loop event could generate an overwhelming amount of activity. This would probably bring a browser / tab to its knees.

I'm not sure what the impact is of creating new buffer nodes is vs being able to loop a single buffer node for as long as needed.

Another possible solution would be if the optional duration parameter of start() accepted a value greater than the length of the buffer when loop is enabled allowing you to loop for as long as necessary. E.g. I could specifiy buffer.duration * 3 to get 3 loops or even 3.25 to get 3 and quarter loops. If the loopStart and loopEnd properties are set then this can be accommodated in the calculation.

ghost commented 11 years ago

Douglas Gore writes:

Another possible solution would be if the optional duration parameter of start() accepted a value greater than the length of the buffer when loop is enabled allowing you to loop for as long as necessary. E.g. I could specifiy buffer.duration * 3 to get 3 loops or even 3.25 to get 3 and quarter loops. If the loopStart and loopEnd properties are set then this can be accommodated in the calculation.

That was what I meant, but I missed that that is not the currently spec'd behaviour.

It sounds a good use case for that behavior.

See https://github.com/WebAudio/web-audio-api/issues/71

Karl.

DougGore commented 11 years ago

I agree as a technique for finite loops it would be great. The most obvious use case is a music sequencing application made out of looping audio segment. They often loop multiple times and to be able to do without having to create a new node for each loop instance would be quite efficient. This change would move to looping logic into native code where it can be most efficiently handled.

ghost commented 11 years ago

On Thu, Oct 24, 2013 at 1:17 PM, Douglas Gore notifications@github.comwrote:

For the defined number of loops use case Karl suggests using start() with a when offset is a feasible solution. However if I wanted to specify 100 loops up front, I assume I have to create 100 nodes. Would that carry much overhead?

Can't you do what you want using something like

source.loop = true; source.start(start_time); source.stop(start_time + 100*buffer_length);

(I didn't actually try this.)

Ray

The correct solution of course would probably be to create n loops ahead using the onended event as a check point for creating more.

Chris you make a very valid point that the loop could be extremely short and therefore a loop event could generate an overwhelming amount of activity. This would probably bring a browser / tab to its knees.

I'm not sure what the impact is of creating new buffer nodes is vs being able to loop a single buffer node for as long as needed.

Another possible solution would be if the optional duration parameter of start() accepted a value greater than the length of the buffer when loop is enabled allowing you to loop for as long as necessary. E.g. I could specifiy buffer.duration * 3 to get 3 loops or even 3.25 to get 3 and quarter loops. If the loopStart and loopEnd properties are set then this can be accommodated in the calculation.

— Reply to this email directly or view it on GitHubhttps://github.com/WebAudio/web-audio-api/issues/267#issuecomment-27026097 .

DougGore commented 11 years ago

On 25 October 2013 00:48, W3C Audio Working Group Notifications < notifications@github.com> wrote:

On Thu, Oct 24, 2013 at 1:17 PM, Douglas Gore notifications@github.comwrote:

Can't you do what you want using something like

source.loop = true; source.start(start_time); source.stop(start_time + 100*buffer_length);

(I didn't actually try this.)

Did a quick test and this is a valid solution. You can do whole and partial loops without issue so that would appear to meet the use case where you want to have a predefined number of loops.

If the final number of loops required isn't known in advance I assume it would be down to the user to track the start time of playback to use to determine the stop time later.

Doug

Ray

The correct solution of course would probably be to create n loops ahead using the onended event as a check point for creating more.

Chris you make a very valid point that the loop could be extremely short and therefore a loop event could generate an overwhelming amount of activity. This would probably bring a browser / tab to its knees.

I'm not sure what the impact is of creating new buffer nodes is vs being able to loop a single buffer node for as long as needed.

Another possible solution would be if the optional duration parameter of start() accepted a value greater than the length of the buffer when loop is enabled allowing you to loop for as long as necessary. E.g. I could specifiy buffer.duration * 3 to get 3 loops or even 3.25 to get 3 and quarter loops. If the loopStart and loopEnd properties are set then this can be accommodated in the calculation.

— Reply to this email directly or view it on GitHub< https://github.com/WebAudio/web-audio-api/issues/267#issuecomment-27026097>

.

— Reply to this email directly or view it on GitHubhttps://github.com/WebAudio/web-audio-api/issues/267#issuecomment-27044054 .

olivierthereaux commented 10 years ago

Discussed by the WG at 20140605 teleconference (http://www.w3.org/2014/06/05-audio-irc#T16-34-13). The group decided to close this as WONTFIX but will look at mapping of dom time and audiocontext time which will help the use case.