danigb / smplr

A web audio sampler instrument
https://danigb.github.io/smplr/
186 stars 19 forks source link

Possible bug? No notes longer than about 3 seconds in duration when using Soundfont #23

Closed drscottlobo closed 1 year ago

drscottlobo commented 1 year ago

Hi @danigb !

OK, I just ran into something strange, I was playing some long tones against a metronome click at 60BPM, currently using any instrument in the soundfonts list that's capable of a long tone, I've tried several, but right now I'm using "drawbar_organ." But for some reason, nothing will last longer than about 3.5 seconds, it cuts off there every time, and with every instrument I load from the default set. I'm not sure why it won't play a note any longer than that? Is that just a limitation of those sample libraries?

Here's a basic mock-up:

const ctx = new AudioContext()
const organ = await new Soundfont(ctx, {instrument: 'drawbar_organ').loaded();

organ.start({note: 'C4', time: 0, duration: 5}) /// always cuts off at around 3.5 seconds

Are you getting the same behavior? Any reason why the sample won't go above that duration?

Thanks for any help!

danigb commented 1 year ago

Hello,

Yes, looping samples are not supported right now. Basically, in order to make a long sound you need:

  1. Play the initial part of the sample
  2. Loop the middle part while the key is pressed (aka: until stop event)
  3. Play the last part of the sample, or something similar, to simulate a longer release

Sampler file formats used include the "loop" timing information for each sample in order to do so, but as far as I know, that information is not in the soundfont.js file (where we get samples from). I could try to implement something that simulates that behaviour, but not sure if will be good enough to use...

drscottlobo commented 1 year ago

Ok. No worries! Thanks!___Scott Wolf, DMAOxnard College - Professor of MusicOn May 26, 2023, at 8:23 AM, danigb @.***> wrote:ο»Ώ Hello, Yes, looping samples are not supported right now. Basically, in order to make a long sound you need:

Play the initial part of the sample Loop the middle part while the key is pressed (aka: until stop event) Play the last part of the sample, or something similar, to simulate a longer release

Sampler file formats used include the "loop" timing information for each sample in order to do so, but as far as I know, that information is not in the soundfont.js file (where we get samples from). I could try to implement something that simulates that behaviour, but not sure if will be good enough to use...

β€”Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you authored the thread.Message ID: @.***>

goldst commented 1 year ago

@drscottlobo thanks for bringing this up, I had exactly the same problem the other day.

@danigb I did some experimentation on this. My fork of Midi.js Soundfonts now contains the missing loop data in separate files as well as instructions and a script to generate the loop data. The data seems to be somewhat incomplete for now, but I was able to confirm that it seems to partially work when smplr is slightly adjusted. I tested it with the Musyng Cello. For my test, I added source.loop = true after this line and sliced the AudioBuffer using a modified version of this code snippet after this line.

Are you interested in implementing a loop feature? If yes, I'm open on putting my fork on github pages so you can fetch the data. Feel free to request changes to the format. Alternatively, because I am converting the sf2 files to sfz for the generation of the loop data, it might make more sense to read the loop information directly from (web)sfz files. What do you think?

danigb commented 1 year ago

Wow, @goldst definitely interested. If you serve the files on github, I'll implement that on this library πŸ‘ Thanks for keeping an eye on this πŸ‘οΈ

goldst commented 1 year ago

Ok, @danigb! Now available at https://goldst.dev/midi-js-soundfonts/${font}/${instrument}-loop.json, for example https://goldst.dev/midi-js-soundfonts/MusyngKite/cello-loop.json. I'm deploying from my feature/loop branch and could PR to your fork if you prefer that. Some instrument names are still wrong right now: for example for the instrument telephone_ring, the file name is telephone-loop.json, without the _ring. I'll try to figure that out, but I will probably have to map the names manually. For now, you can start with the correct names if you want to. The current format is:

{
    keyName: [loopStartOffset, loopEndOffset]
}

Feel free to let me know if there is anything else I can help you with.

drscottlobo commented 1 year ago

Thanks @goldst Excited to try it out!

FredericoGauz commented 1 year ago

Hi all, I was having the same issue and you can imagine how glad I was to find this issue! =)

I would be happy to implement this fix, but since I am new to this kind of sound libraries it would be great to get some pointers.

@goldst would you be able to help me with that?

Thanks in advance!

goldst commented 1 year ago

Great, @FredericoGauz! Probably @danigb can give you better pointers because I don't really have experience with these kinds of sound libraries either. There also was some activity in the repo in June, so maybe you two should ensure that you're not implementing the same thing simultaneously. I would probably try to do the following:

  1. Try to recreate what I did here. I'm afraid I don't have my code for that anymore, unfortunately. You can clone this repo, create a small separate example project and install your cloned version in the example project using npm link. The code snippet that I refer to in my comment takes in ms and if I recall correctly my data is in frames, so you need to change a few lines slightly. Also, there is a callback thing that you can remove, I think. You don't need my URL for this part yet.
  2. See if you can replace the previous URL here with mine. If everything works, it shouldn't change anything.
  3. You could then come up with a similar function to get the JSON files that I added to my version.
  4. The numbers in the JSON files describe the start and end of part 2 from @danigb's list. You should be able to pass them in as parameters to the function from step 1.
  5. This is the part where I am not sure either how to accomplish it: you need to play parts 1 and 3 without looping before/after part 2. Maybe you can find something in the mdn web docs for AudioBuffer or the Web Audio API in general

Just a short note, I didn't really test that the data in my json files is correct. So if it doesn't work, that's not necessarily on your end. Let me know in that case :)

danigb commented 1 year ago

Hi, just a quick note to say that I didn't have time to start the implementation, so very open to PRs πŸ‘

FredericoGauz commented 1 year ago

Hi Leonard and @danigb,

Thanks for the explanations, I managed to link the lib locally a few days ago but got sick this week. I will see if I can work on the loop issue in the next days or weekend.

Thanks for the detailed explanations Leonard, I hope I will manage to add this feature.

I am also keen on exposing some of the web audio api to the user, because I need to have a bit more control on the audio produced. Is that something that you also would be keen danigb?

On Mon, Jul 31, 2023, 12:43 PM danigb @.***> wrote:

Hi, just a quick note to say that I didn't have time to start the implementation, so very open to PRs πŸ‘

β€” Reply to this email directly, view it on GitHub https://github.com/danigb/smplr/issues/23#issuecomment-1658206786, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEL2SSVZ53QOQBRD2RCE4J3XS6K7BANCNFSM6AAAAAAYOASRSQ . You are receiving this because you were mentioned.Message ID: @.***>

FredericoGauz commented 1 year ago

Just a quick update, yesterday I decided not to keep working with this directly with this library but to integrate the soundfont playback in my project.

I want however to enable longer notes and when I figure out how to do it I will update this thread.

Thanks everyone!

FredericoGauz commented 1 year ago

By the way, @goldst , you mentioned that you changed the soundfonts data as well, but I couldn't find them. I tested the intervals with the data I have (on piccolo) but it does not seems to be fitting very well.

danigb commented 1 year ago

Hi all. A first implementation of Soundfont loops is live. Unfortunately it doesn't sound very good. You can try it on the demo or read the docs.

Possible improvements:

Screenshot 2023-09-15 at 17 01 45

goldst commented 1 year ago

@FredericoGauz Sorry for the late reply, I wanted to check that but didn't have the time yet. I'm not 100% sure what you are referring to in regards to changed soundfont data.

@danigb Awesome, thank you! I'll check what causes the problem - if it's my numbers and there is a way to fix it, I'll update them.

henrikvilhelmberglund commented 1 year ago

I'm also interested in looping. I think the loops are defined in the soundfonts, however each sample has its own loop points basically. I checked this in polyphone: image

Anything new on this front? 😊

danigb commented 1 year ago

That should be working: https://github.com/danigb/smplr#soundfont-sustained-notes Give it a try and if you have specific question or suggestion, I'm all ears πŸ‘‚