Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sampler optimizations and more #148

Merged
merged 19 commits into from Jun 28, 2022
Merged

Sampler optimizations and more #148

merged 19 commits into from Jun 28, 2022

Conversation

felixroos
Copy link
Collaborator

@felixroos felixroos commented Jun 27, 2022

This PR includes a multitude of fixes and features. The main ones are

Webaudio sampler

add note to repitch samples + choke to cut samples to hap duration:

samples({ 
  flbass: '00_c2_finger_long_neck.wav' 
}, 'github:cleary/samples-flbass/main/')

note("<8(3,8) <7 7*2> [4 5@3] 8>".sub(1).scale('A1 minor'))
.s("flbass").choke(1)
.out()
  • .out will repitch the sample relative to c3.
  • choke makes sure the samples won't overlap. this is different from cut, as it will also respect rests

samples now also supports object format for pitch declaration

samples({ 
  piano: {
    A3: 'A3v8.mp3',
    C4: 'C4v8.mp3',
    A4: 'A4v8.mp3',
    C5: 'C5v8.mp3',
  }
}, './piano/')

note("<8(3,8) <7 7*2> [4 5@3] 8>".sub(1).scale('A3 minor'))
.s("piano").choke(1)
.out()
  • .out will now find the nearest sample for the given pitch and repitch relative to that pitch
  • to simplify note declaration, now added support to notate sharps with "s" as an alternative to "#"

Prebake Script with Piano

  • added piano samples to replace tone piano, using same samples (Creative Commons, see https://archive.org/details/SalamanderGrandPianoV3)
  • added prebake script to REPL, to load default sounds, where there is now .piano to load the piano samples with choke and stereo effect, as an alternative to tonejs piano
  • refactored tunes to always use the new .piano instead of tonejs piano

Version Safety

After having problems with version collisions:

  • log that @strudel.cycles/core is loaded, warn if it's loaded multiple times
  • warn when a Pattern fails instanceof check

Other

  • can now use ":" in mini notation to set "n" for "s" or "note"

Migrating away from Tone.js

With the above features, many more tunes can now be rewritten without Tone.js, which I will do in the future.
When all are refactored, we could think about changing what happens when no output is chosen.
Currently, the default behavior is playing the pattern with the default synth, supporting only primitive hap values.
It might make more sense to use .out by default in the future, or just log the events to the console, like tidal.

@yaxu
Copy link
Member

yaxu commented Jun 27, 2022

Ace!! How about using legato instead of choke?

@felixroos
Copy link
Collaborator Author

legato has no effect on samples, as samples will always play until the sound buffer ends, which can exceed the hap.duration, creating overlaps. legato will only modify the hap.duration, relative to itself, so legato(2) will multiply the duration by 2, but the sample still won't care about that. Setting choke(1) (1 === true) will tell the sampler: please care about the hap.duration and ignore the buffer duration. Having samples always play till the end can still be useful because overlaps might be wanted in the case of drums.

@yaxu
Copy link
Member

yaxu commented Jun 28, 2022

I think legato should 'just' be another parameter in the value object rather than metadata, then the synthesiser can decide how best to interpret it. Then it can work the same way for samples and synths, and solve #111. This approach works well with tidal/superdirt.
Btw superdirt applies legato slightly differently for samples and synths - for samples legato is default 'off' (i.e. the full sample plays), and for synths it's default 1.

@yaxu
Copy link
Member

yaxu commented Jun 28, 2022

Re-reading your comment, my proposal is that as with superdirt, the default for samples should be as you describe - play the whole sample. When legato is set, it can 'choke' the sample relative to hap duration. But the hap duration shouldn't be changed until it is triggered. That is, legato doesn't change the duration of the hap, but the way it is 'played'.
Whether legato is represented in a visualisation (e.g. pianoroll) depends on whether you want to visualise the underlying pattern structure or the resulting sounds. I guess that should be a pianoroll option.

@felixroos
Copy link
Collaborator Author

Btw superdirt applies legato slightly differently for samples and synths - for samples legato is default 'off' (i.e. the full sample plays), and for synths it's default 1.

I did not know that, that would be a useful behaviour, so legato can do the job of choke..

That is, legato doesn't change the duration of the hap, but the way it is 'played'

Before that can be implemented, all the current usages of legato in the example tunes need to be refactored, which also require the tone.js output to understand object values (because legato expects an object value). Because of that, I did not yet implement it that way.

I'd propose:

  1. keep choke for now, as a workaround
  2. merge this PR (would be nice to have melodic samples sooner than later)
  3. get rid of Tone.js + refactor all other outputs that do not understand object values
  4. refactor tunes
  5. implement legato Fix legato and duration #111
  6. refactor choke to legato, remove choke

When the above is done, all other pattern functions can be paramified as well (see #60 -> 4.)

Okay?

@yaxu
Copy link
Member

yaxu commented Jun 28, 2022

Yes that sounds like a good path to me.

I realise it's a term from percussion but I'm not super keen on the word choke though, and as a concept cymbal choking is closer to how cut works. How about clip?

@felixroos
Copy link
Collaborator Author

I chose choke because that's how it was called on my good old MPC (there were choke groups, similar to cut groups in superdirt). But no strong feelings here, I am also fine with clip. Then I'll rename it

@yaxu
Copy link
Member

yaxu commented Jun 28, 2022

Thanks. I do find it a bit funny how many different functions we have in tidal/strudel with names that mean 'cut things into pieces', good to add another one ;)

@felixroos
Copy link
Collaborator Author

Let's keep this one secret until it's away again :)

@felixroos felixroos merged commit 8a1cd32 into main Jun 28, 2022
@felixroos felixroos deleted the webaudio-optimizations branch June 28, 2022 19:54
@felixroos
Copy link
Collaborator Author

out now! demo: https://strudel.tidalcycles.org?8sxdCCcYKcvp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants