Adding crossfade to mincer

Hi everyone,

My project is getting very close to what I’ve been envisioning. There’s one final piece that I’m wrestling with. At its heart, my project loops wav files with mincer which allows me to adjust speed and pitch independently as well select which range of samples within the files to loop. I’d like to add crossfading in the transition between loops like in flooper2.

Here’s what I was thinking of doing.

  1. Add an amplitude envelope that kicks in every time the loop is reset to the beginning.
  2. Define a UDO that kicks in at the end of the loop which plays an extend section of the file with mincer starting from where the loop ended and applies an amplitude envelope.

Before I embark on coding this up, does that sound like a reasonable approach? Or is there a different approach that’s simpler?

As always, thanks for your guidance! I’ll share this project with everyone when it’s ready.

Jason

Okay, here’s an initial attempt at this, and it ain’t pretty. Right now I’m just trying to play an extended part of the sample after it has looped. I haven’t even incorporated the amplitude envelope at the start of the loop. Here’s the code.

while (kndx < ksmps) do  ;  ksmps loop which constructs the phasor
		aphs[kndx] = kphs/sr  ; constructs the main phasor of the loop
		kphs = kphs + ktimescale 

		aphs_crossfade[kndx] = kcrossfade_phase/sr  ; constructs the crossfade phasor
		kcrossfade_phase = kcrossfade_phase + ktimescale
		if kcrossfade_phase > kend_point + kcrossfade_duration then  ; if crossfade duration is reached, turn off crossfade
			kcrossfade_status = 0
		endif

		if (ktimescale > 0 && kphs > kloop_end) then  ; when you reach end of loop
			kend_point = kphs  ; store the position of the end of the loop
			kcrossfade_phase = kphs
			kcrossfade_status = 1  ; trigger the crossfade
			kphs = kloop_start  ; reset the main loop to the beginning
			kreset_count += 1
		endif

		kndx += 1
od
	
asigl mincer aphs, kamp, kpitch, kfunction, ilock, 2048, 10 ; play the main loop

if kcrossfade == 1 then  ; if crossfade is on
	kcrossfade_env oscili 1, sr/kcrossfade_duration, 100, 1  ; read amplitude envelope from table
	asigl_crossfade mincer aphs_crossfade, kamp*kcrossfade_env, kpitch, kfunction, ilock, 2048, 10  ; play the tail end of the loop
	asigl = asigl + asigl_crossfade  ; add the crossfade to the main loop (crude implementation)
endif

asigr = asigl
outs asigr, asigl

This kind of works. You can test it out here. I suggest setting the track to “my_girl_2.wav”, making the sample window small, and moving the Crossfade Duration slider around. It sounds noisy. The amplitude oscillates. I’m sure what I’ve done is very crude and messy in terms of sound design and not sample-accurate.

Can you give me any tips? This is my first foray into sample-level instrument design, so I’m having a hard time wrapping my head around everything. I want this to be precise and know it’s possible, but my skills aren’t there yet. Growing pains…

Thanks,
Jason

Whenever I apply a crossfade, I start my new segment a few moments before the other one ends. Note this means the overall ‘loop’ times will be shortened. In terms of implementation I would typically involve the use of two instances, both with a short fade in and fade out. When the first instance enters its release phase I start a new instance. When that hits its release phase I start a new instance instance, and so one.

I guess you could get away with doing all this in one instrument with mincer because you can control the playback pointer. But for me it would be cleaner to use two instances.

p.s. the instrument works very well. I had a lot of fun playing with it!

Thank you, Rory! I took your suggestion to play the crossfade segment in a separate instrument instance. Everything runs smoother now. I just need to iron out the amplitude envelope because I’m hearing a bit of hiccup when the crossfade kicks in. But it sounds 90% of the way there. I’ve updated the instrument on my site in case you want to hear the new and improved version.

I’m glad you enjoyed playing with it. The whole inspiration was Carl Stone’s piece “Shing Kee”. Now YOU TOO can play “Shing Kee” if you use “akiko1.wav”, set Time Lock to 5, set Reset Shift to 0 5, and toss in some Crossfade.

Thanks! I appreciate all your help.
Jason

Neat project! One thing I thought might be useful is that for pitch controls you might expose semitones rather than the 0.5 to 2.0 range. Could use -12,12 range with semitone() opcode.

Thanks for checking it out and for the suggestion, Steven. It’s good to know about the semitone() opcode. I’ve sort of exposed the possibility of pitch shifting by semitones by adding a keyboard to the right, but it only does the 0-13 range. My thinking was that the Ptc slider would be used for fine-grained pitch adjustments of the fundamental, and then the keyboard plays the semitones based on that pitch.

This instrument is still in its early stages, lots more functionality to add and user experience to improve, so I’ll keep your suggestion in mind! I might go that route at some point.

Jason

Makes sense for the design. I think having a logarithmic input as you would with semitone() helps for this kind of thing. Could also use cents() for more fine-grained options. Either way, looking forward to seeing this develop! :slight_smile:

Ah, now I get what you mean about using semitone. At first I was thinking semitone would have to be a stepped input (i.e. 0, 1, 2, 3, etc), but I see that it can be continuous. So it’s definitely a better choice because it’s a more balanced input than 0.5 to 2. I’ve incorporated it into my design. Thanks for the suggestion!

1 Like