Client-side sonification for datacubes#3843
Conversation
|
Hi @james-trayford, I could not find a potential memory leak in your code. What could happen though, is when running the cell with UI again, the old widget is kept around. This is inherent to the ipywidget system and in this case is keeping a reference to hundreds of MBs of wav data in front and back end. Could this be the cause? A potential solution to one of the open questions:
I think the native browser API supports everything you use, so Tone.js might not be needed. See:
I also think we could send only the audio data that is used for the target pixel when |
|
I was wondering how Tone.js did the scheduling you mentioned and found out they use requestAnimationFrame (see https://github.com/Tonejs/Tone.js/blob/feffad41cdcd8ec644d8b3e00e5ce7bebaefc0f6/Tone/core/util/Draw.ts#L108). This runs at the refresh rate of the monitor, which is 60 Hz for a typical monitor. That gives a granularity of 16.7 ms for the scheduling. They also use a 0.008 s margin in which they call the scheduled task early (see https://github.com/Tonejs/Tone.js/blob/feffad41cdcd8ec644d8b3e00e5ce7bebaefc0f6/Tone/core/util/Draw.ts#L42-L47) Maybe this had an impact on the issues you had with the 30ms crossfade time I saw in the comments. I think it could be better for this use case to just use Tone.Draw.schedule(() => this.handleFadeComplete(newVal), Tone.now() + fadeTime);could be replaced with setTimeout(() => this.handleFadeComplete(newVal), fadeTime * 1000); |
…ented in an older branch between commits ec7b7a9 and 3502fbd (see PR javerbukh#33) to avoid hairy rebase
…sets, and crucial fix for sonified cube indexing to make consistent with old mode
…tion sound plays on render
c00e020 to
a87ad32
Compare
Codecov Report❌ Patch coverage is
❌ Your patch check has failed because the patch coverage (32.67%) is below the target coverage (90.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #3843 +/- ##
==========================================
- Coverage 88.28% 88.06% -0.23%
==========================================
Files 198 198
Lines 27241 27366 +125
==========================================
+ Hits 24049 24099 +50
- Misses 3192 3267 +75 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Just to summarise some outstanding aspects: There's a difficulty in terms of data volume for an arbitrary number of layers (representing a cube of any size can be >~ 10s-100s Mb per layer to transmit, so multiple layers will stack up fast) - also these need to be transmitted to the user before mixing to efficiently control things like relative volume. The layer implementation is great of course and will allow us to mix / match / export layers efficiently and allows us to follow the same data handling as other layer types. However, the use-case for playing multiple audio layers at once isn't really there yet as we explore the fundamental approach. What I thought would be best would be to start with an 'active layer' implementation with just the one layer at once loaded into the JS player. This simpler implementation will be feasible to operate on platforms sooner I think - and for our project we'd be really keen to prioritise that feature to be so we can broaden our testers for the approach (open a web url and listen to the data) This 'single active layer' approach is basically how it's working at the moment, and is something we discussed as having precedent in the code already. If that sounds good, I would appreciate pointers to places in the code where a similar approach so I can make sure I'm conforming. I'm keen to continue working on multiple layers at the same time as we develop the approach. A couple of other things I'm thinking about:
appreciate any thoughts on this! |
I think the way to get here and still keep the door open for the flexibility down the road would be to just enforce one "visible" audio layer per-viewer (when one gets turned on, all others get turned off). Is that something you want to add here or would you rather we add it to main and you pull it in? |
|
@kecnry this sounds great - I think the '1 visible (audible?) layer' paradigm sounds like a good solution. I'd be happy to add it here if that's cleaner - I think it's closely tied to this functionality - but no very strong feelings either way. For me to implement this, I'd appreciate an example of this being done for visual layers in the existing code if that was available |
|
Ok, works for me! We don't have an example of anything terribly similar, but I suspect it would best belong in the data-menu |
Description
CC @javerbukh @mariobuikhuizen @kecnry
Reimplementation of javerbukh#33 to avoid complex rebase, see original description below:
Initial implementation with playback handling fully in JS so we can but audio rendering client side.
With the JS-heavy implementation, some diagnostic logging has been added so turn on the JS console in the browser to see this.
Basic summary of behaviour: This creates the sonified cube as before, but flattens the array into a single 1D audio buffer of audio clips stacked end-to-end, representing the entire cube. Each (x,y) pixel then represents an exact audio sample range in the audio clip. To handle chnges between these we operate two audio players where:
For this to work we need to hold two copies of the audio in memory at once. the size of the audio clip depends on the number of pixels. We can catch big cubes. Need to work out tolerable limits for transmitting audio data and whether to load staggered. would also need to generallise player A and B to list of players to handle simultaneously playing audio layers (rather than just most recent)
Outstanding issues / Questions:
Tone.js- an external library. Currently it pulls it when sonify plugin is opened, but could we package with install for offline mode?jdaviz/configs/imviz/plugins/coords_infoandjdaviz/configs/default/plugins/markersfor inspirationSome additional issues noticed since:
mainproblem or specific to the new features yetstraussrequirement: currentlystraussisn't required by default so will say sonification unavailable until it is installed manually - is there a reason not to add?This pull request is to solve client-side sonification, making sonification via platforms viable
Fixes #
Change log entry
CHANGES.rst? If you want to avoid merge conflicts,list the proposed change log here for review and add to
CHANGES.rstbefore merge. If no, maintainershould add a
no-changelog-entry-neededlabel.Checklist for package maintainer(s)
This checklist is meant to remind the package maintainer(s) who will review this pull request of some common things to look for. This list is not exhaustive.
triviallabel.cache-download.ymlworkflow?