musikinformatik / SuperDirt

Tidal Audio Engine
GNU General Public License v2.0
520 stars 74 forks source link

long, 1-hour samples sound bad #196

Closed kindohm closed 4 years ago

kindohm commented 4 years ago

When using very, very long samples, SuperDirt seems to degrade the quality of the sample, as if the sample rate is downscaled. I haven't found the time cutoff point, but this effect can be produced with a 60-minute sample:

d1 $ s "extremelylongsample" # legato 1

The audible difference is very obvious and unpleasant.

telephon commented 4 years ago

Yes, SuperDirt is not really made for playing long samples, the precision limit is rather around 3 minutes, I think (32-addresses for phase of a BufRd). But it may be possible to solve this with a PlayBuf, but you'd lose the nice cubic interpolation and there are a few calculations you'd have to do. We could automatically switch if the playback rate is >= 1.

The synth is this this, maybe you find a solution with PlayBuf?

(
var numChannels = ~dirt.numChannels;

    // write variants for different sample buffer sizes
    (1..SuperDirt.maxSampleNumChannels).do { |sampleNumChannels|

        var name = format("dirt_sample_%_%", sampleNumChannels, numChannels);

        SynthDef(name, { |out, bufnum, sustain = 1, begin = 0, end = 1, speed = 1, endSpeed = 1, freq = 440, pan = 0|

            var sound, rate, phase, sawrate, numFrames;

            // playback speed
            rate = Line.kr(speed, endSpeed, sustain) * (freq / 60.midicps);

            // sample phase
            // BufSampleRate adjusts the rate if the sound file doesn't have the same rate as the soundcard
            //phase =  Sweep.ar(1, rate * BufSampleRate.ir(bufnum)) + (BufFrames.ir(bufnum) * begin);

            numFrames = BufFrames.ir(bufnum);
            sawrate = rate * BufSampleRate.ir(bufnum) / (absdif(begin, end) * numFrames);
            phase = (speed.sign * LFSaw.ar(sawrate, 1)).range(begin,end) * numFrames;

            sound = BufRd.ar(
                numChannels: sampleNumChannels,
                bufnum: bufnum,
                phase: phase,
                loop: 0,
                interpolation: 4 // cubic interpolation
            );

            sound = DirtPan.ar(sound, numChannels, pan);

            Out.ar(out, sound)
        }, [\ir, \ir, \ir, \ir, \ir, \ir, \ir, \ir]).add;
    };
)
telephon commented 4 years ago

@kindohm here is a branch that implements support for long soundfiles. Do you want to test? Perhaps you have an example that could be used to test it?

https://github.com/musikinformatik/SuperDirt/tree/long-soundfile-support

kindohm commented 4 years ago

@telephon thank you, I will test it today when I get a chance. I can create a very long .wav file to test with.

kindohm commented 4 years ago

@telephon I tested this with a 70-minute sample and it sounded really good. Thank you for working on this!

telephon commented 4 years ago

Great! btw. how do you work with these long soundfiles? How do you make sure they don't hang? Do you always use a cutgroup?

I find that in very long soundfiles, using begin and end is tedious because they are in the range 0...1.

kindohm commented 4 years ago

I usually favor legato, because cut will not stop the sound from playing if it is never triggered again. legato will ensure that the sound stops after the specified unit of time.

With hour-long samples, I'm not really interested in finding a specific point in the file with begin. I will use arbitrary begin points typed by hand, or generated with rand.

One fun thing to do is "scan" through the sample with begin, going forwards or backwards:

d1 $ s "longsample*4" # legato 1 # begin (rev $ range 0.5 0.6 $ slow 200 saw)
telephon commented 4 years ago

ah yes, that makes sense. Sustain works that way too. I am surprised that legato has been working for samples, I recently fixed it only recently …

yaxu commented 4 years ago

I've been using legato for samples for ages, it's been working well, afaik!

telephon commented 4 years ago

interesting. I hope it still works :)

I've just pushed support for long soundfiles.