Soundmanager2 as a web worker?

Hello. First thanks a lot for this very versatile library.

I am using Soundmanager2 via the Drupal module. I have setup one Drupal content type to generate a playlist for the page player and one content type for photo galleries with 1 background sound displayed as 360UI.The defaults carry me a major part of the way, but now I'm running into performance problems.

I am sure that this is due to several interval based scripts on the same page. In my theme, I have implemented a smoothly fading background slideshow that is based on two layered DIVs which are faded alternatingly every ten seconds using jQuery UI. The transition length is 5 seconds and is very smooth on most devices and browsers. When I now start the page player, the transitions slowly begin to stutter with more and more dropping frame rate. After a while the transitions are lost and images begin to simply flip. When I pause the page player, the transitions immediately run smooth again.

For my slideshow I am using an interval callback (window.setInterval(crossFade(), 10000), that sets the background-image in the invisible layer DIV to the next one on the list and then starts a 5 second jQuery UI fade of both DIVs.

Interesting and dissappointing is, that suddenly my favourite browser Firefox (9, since today) has the most noticable problems with it. In IE9 the effect is not as noticable. Opera 10 performs slow (3-4 fps) but constant, independently of visible, stopped or playing state.

Until yesterday, instead of the setInterval-Solution, I used setTimeout in a loop. I chose to switch to setInterval, because the setTimeout-Loop seemed to stop, after the last "scheduled" transition had finished. Then the music played fine, but the slideshow stood still.

So, I wonder whether there's a way to decouple my slideshow from the player by running the latter in a web worker, or if there is a simpler way to reduce the hunger of the page player.

Any recommendations?

Merry Christmas everyone from the city of Bielefeld in Germany

Henning
1 person has
this problem
+1
Reply
  • Scott (Official Rep) January 02, 2012 17:54
    If you have "several" timers, you may be OK; if they are all running at aggressive rates eg. 100 msec or less and you are doing expensive things within each, then I could see that being a problem.

    Generally-speaking, it's DOM updates that will be slowest in browsers and can lead to performance issues as they will block other scripts from running. Given you're fading images, those are likely to be very expensive. If you can, I would look at using CSS transitions where possible as it should use hardware acceleration and lighten the JS load simultaneously where supported.

    setInterval is also generally preferable to setTimeout in my findings for JS animation, as the former is more "fixed" and you don't need to make recursive calls to keep the animation going.

    If audio playback is stopping, then the browser is saturated to the point where the Flash plugin is lagging, and that is pretty bad. I would look at optimizing your fades/transitions.

    A web worker is not an option as far as I'm aware due to the plugin nature of SM2; web workers are minimal in terms of their API/capabilities as I understand, they're only useful for passing strings and data around - not sound playback, etc.

    [ Pardon late reply, was on vacation. ]
  • (some HTML allowed)
    How does this make you feel?
    Add Image
    I'm

    e.g. indifferent, undecided, unconcerned happy, confident, thankful, excited kidding, amused, unsure, silly sad, anxious, confused, frustrated

  • I’m thankful
    Thanks for your reply.
    You support my conviction of setInterval being the better choice. I just was not sure whether there are any performance inflictions.

    It's a shame for me to confess, but I was not even aware of CSS transitions, yet. I have been using jQuery UI fades so far and I am not sure, how these are implemented. Anyway, I want to give CSS transitions a try, hoping that the browser differences will not complicate my style sheets and code too much.

    As soon as I have results, I am going to post them here.

    Cheers and a happy new year to you.
    Henning
  • (some HTML allowed)
    How does this make you feel?
    Add Image
    I'm

    e.g. indifferent, undecided, unconcerned happy, confident, thankful, excited kidding, amused, unsure, silly sad, anxious, confused, frustrated

  • I’m indifferent
    Ok, so I've changed my implementation, but the performance issue stays.

    I've added the following CSS for both DIVs:

    transition-property: opacity;
    transition-duration: 2000ms;
    transition-timing-function: ease-in-out;
    -moz-transition-property: opacity;
    -moz-transition-duration: 2000ms;
    -moz-transition-timing-function: ease-in-out,
    -webkit-transition-property: opacity;
    -webkit-transition-duration: 2000ms;
    -webkit-transition-timing-function: ease-in-out;


    And now I am switching the images and simply setting the opacities using jQuery css('opacity', targetOpacityValue) instead of fadeTo(). I cannot prove it, but the transitions seem to have become a tiny bit smoother. But this might as well be an effect of the ease-in-out.

    What remains is, that as soon as I click a track and the page player starts, my dual core processor (2 x 2.5GHz, Core2 Duo T9300) jumps from about 6-20% load to a high load on both cores between 60-70% and the transitions become very jumpy again. I do not use any visualization other than timer and progress bar with the page player. I think the page player draws too much performance.

    Most curious is, that the 360ui player with full visualization does not consume half as much core power.
  • (some HTML allowed)
    How does this make you feel?
    Add Image
    I'm

    e.g. indifferent, undecided, unconcerned happy, confident, thankful, excited kidding, amused, unsure, silly sad, anxious, confused, frustrated

  • The problem seems to be, what is done "whileplaying" in page-player.js. The if block beginning in line 440 is allowed to execute about 33 times a second.

    if (d-self.lastWPExec>30) {
    self.updateTime.apply(this);
    if (sm.flashVersion >= 9) {
    if (pl.config.usePeakData && this.instanceOptions.usePeakData) {
    self.updatePeaks.apply(this);
    }
    if (pl.config.useWaveformData && this.instanceOptions.useWaveformData || pl.config.useEQData && this.instanceOptions.useEQData) {
    self.updateGraph.apply(this);
    }
    }
    if (this._data.metadata) {
    this._data.metadata.refreshMetadata(this);
    }
    this._data.oPosition.style.width = (((this.position/self.getDurationEstimate(this))*100)+'%');
    self.lastWPExec = d;
    }


    By changing the first line to

    if (d-self.lastWPExec>500) {

    I achieved a significant improvement. I do not know, why progress update is so expensive, but now that it is peformed at most twice a second, the cpu meter only jumps over the 20% mark while fading images. Another thing: Before that adjustment, pressing page reload in FF while playing took ages to process, while the same action during stopped playback processed immediately. After the adjustment "reload" executes instantaneously as well.

    Debugging the block with Firebug showed that the metadata and flash>=9 blocks were not executed, which is what I configured. So time is lost during "apply" or "width="

    Could it be, that the width adjustment at this point causes a re-pack of the layout containers?

    I'd be glad, if you could once again have a short look into this.
  • (some HTML allowed)
    How does this make you feel?
    Add Image
    I'm

    e.g. indifferent, undecided, unconcerned happy, confident, thankful, excited kidding, amused, unsure, silly sad, anxious, confused, frustrated

  • Scott (Official Rep) January 11, 2012 02:41
    Ah, good eye. I had forgotten about this relatively-expensive call which can fire many times during whileloading() events - and I hadn't had any recent reports about CPU use related to this player.

    It's quite possible that the width change during doWork() is causing a lot of reflow/layout on the player element, and that is unexpectedly expensive.

    I'll bump the rate limiting to 50 (~20 fps) instead of 30, since that seems excessive. Sounds like I may need to review this script, and see exactly what it's calling that may be making things unusually slow.
  • (some HTML allowed)
    How does this make you feel?
    Add Image
    I'm

    e.g. indifferent, undecided, unconcerned happy, confident, thankful, excited kidding, amused, unsure, silly sad, anxious, confused, frustrated

  • Thanks Scott,

    I have checked a period of 50, but unfortunately this is not enough. There is only a small gain compared to 30. And then I checked on the layout and css again, setting 'statusbar' div to a static width, so any reflow should not cascade through the containment hierarchy too far, when the width of the 'position' bar is set to another percentage value in a layout like this:

    <div class="controls">
    <div class="statusbar">
    <div class="loading" style="width: 100%;">
    <div class="position" style="width: 63.6546%;">
    </div>
    </div>


    After this did not improve performance, I used rounding of the width value. This effectively leads to width value changes only every 2 seconds for a 3:20 minute track. The value updates can be seen nicely in FireBug. Writing the same value over and over does not cause a reflow, but well, still no improvement. So the performance loss is not in the reflow.

    The whole block is executed in between 2-3 ms as can be seen by logging "new Date()-d" to the console after the "width=" line. So the cpu capacity must be used up asynchronously on other threads by something the "updateTime.apply(this)" or "getDurationEstimate(this)" cause happening. Both functions are quite simple. I don't know...

    Still the smallest period value that leads to satisfying performance is 300 (~3fps), which is acceptable for a progress bar and the time indicator in my case. But still, there is something in the progress update, that eats up my cpu, that the 360ui and the inline player do not do.
  • (some HTML allowed)
    How does this make you feel?
    Add Image
    I'm

    e.g. indifferent, undecided, unconcerned happy, confident, thankful, excited kidding, amused, unsure, silly sad, anxious, confused, frustrated

  • I’m thankful and happy
    Just wanted to say "thank you", again. We have released the page I have built with SM2 to the public. So, if you like to put an ear on the things people create with your library: http://rohton.de.

    Most textual content is in German, but there's a lot to gaze at and to listen to. Enjoy.
  • (some HTML allowed)
    How does this make you feel?
    Add Image
    I'm

    e.g. indifferent, undecided, unconcerned happy, confident, thankful, excited kidding, amused, unsure, silly sad, anxious, confused, frustrated