HISE Logo Forum
    • Categories
    • Register
    • Login

    Sample Import Tutorial - It's Broken!

    Scheduled Pinned Locked Moved General Questions
    13 Posts 5 Posters 500 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • M
      Mighty23 @griffinboy
      last edited by

      @griffinboy said in Sample Import Tutorial - It's Broken!:

      Additionally there is some very odd behaviour when dragging the loop points. Grab one of the loop handles and move it close to the other handle, when you release the handle the loop points will suddenly rearrange themselves.

      @griffinboy
      https://forum.hise.audio/post/85769 Try this

      Free Party, Free Tekno & Free Software too

      1 Reply Last reply Reply Quote 0
      • M
        Mighty23 @griffinboy
        last edited by

        @griffinboy said in Sample Import Tutorial - It's Broken!:

        Additionally there is some very odd behaviour when dragging the loop points. Grab one of the loop handles and move it close to the other handle, when you release the handle the loop points will suddenly rearrange themselves.

        Try replacing LoopPointDagger.js with this new implementation - I think I solved the problem, not sure.

        /** This defines a panel that will mimic the loop dragging facilities from the sampler */
        namespace LoopPointDragger
        {
        	// Create the path for the fade in
        	const var fadePath = Content.createPath();
        	
        	fadePath.startNewSubPath(0.0, 1.0);
        	fadePath.lineTo(1.0, 0.0);
        	fadePath.lineTo(1.0, 1.0);
        	fadePath.closeSubPath();
        	
        	const var fadeOutPath = Content.createPath();
        	fadeOutPath.startNewSubPath(0.0, 1.0);
        	fadeOutPath.lineTo(0.0, 0.0);
        	fadeOutPath.lineTo(1.0, 1.0);
        	fadeOutPath.closeSubPath();
        	
        	/** this will update the internal data for the panel and must be called
        		whenever one of the sample property changes.
        	*/
        	inline function updateLoopPoints()
        	{
        		if(!isDefined(sound))
        		{
        			LoopPanel.data.sx = 0;
        			LoopPanel.data.sw = 0;
        			LoopPanel.data.lx = 0;
        			LoopPanel.data.lw = 0;
        			LoopPanel.data.dx = 0;
        			LoopPanel.data.dw = 0;
        			LoopPanel.data.xfw = 0;
        	
        			LoopPanel.repaint();
        			return;
        		}
        	
        		local w = LoopPanel.getWidth();
        		local ss = sound.get(Sampler.SampleStart) / totalSamples;
        		local se = sound.get(Sampler.SampleEnd) / totalSamples;
        		local ls = sound.get(Sampler.LoopStart) / totalSamples;
        		local le = sound.get(Sampler.LoopEnd) / totalSamples;
        		
        		LoopPanel.data.sx = ss * w;
        		LoopPanel.data.sw = (se - ss) * w;
        		LoopPanel.data.lx = ls * w;
        		LoopPanel.data.lw = (le - ls) * w;
        		LoopPanel.data.dx = LoopPanel.data.lx;
        		LoopPanel.data.dw = LoopPanel.data.lw;
        		LoopPanel.data.xfw = parseInt(sound.get(Sampler.LoopXFade) / totalSamples * w);
        		LoopPanel.repaint();
        	}
        	
        	SampleLoadSave.initAfterSampleLoad();
        	
            const var MINIMUM_LOOP_LENGTH = 5;
        
            LoopPanel.setMouseCallback(function(event)
            {
                this.data.hover = event.hover || event.drag;
                
                var midX = this.data.dx + 0.5 * this.data.dw;
                
                if(!event.drag)
                    this.data.setLeft = event.x < midX;
                
                if(event.drag || event.mouseUp)
                {
                    if(this.data.setLeft)
                    {
                        var right = this.data.dx + this.data.dw;
                        var newLeft = Math.range(event.x, this.data.sx, right - MINIMUM_LOOP_LENGTH);
                        this.data.dx = newLeft;
                        this.data.dw = right - newLeft;
                    }
                    else
                    {
                        var maxRight = this.data.sx + this.data.sw;
                        var newRight = Math.range(event.x, this.data.dx + MINIMUM_LOOP_LENGTH, maxRight);
                        this.data.dw = newRight - this.data.dx;
                    }
                }
                
                if(event.mouseUp)
                {
                    var totalWidth = this.getWidth();
                    var loopStart = Math.round((this.data.dx / totalWidth) * totalSamples);
                    var loopEnd = Math.round(((this.data.dx + this.data.dw) / totalWidth) * totalSamples);
                    
                    SampleLoadSave.setAndStore(Sampler.LoopStart, loopStart);
                    SampleLoadSave.setAndStore(Sampler.LoopEnd, loopEnd);
                    
                    updateLoopPoints();
                }
        
                this.repaint();
            });
        	
        	LoopPanel.setPaintRoutine(function(g)
        	{
        		var alpha = 0.2;
        		
        		var h = this.getHeight();
        		
        		if(this.data.hover)
        			alpha += 0.1;
        		
        		if(this.data.down)
        			alpha += 0.1;
        			
        		var loopColour = Colours.withAlpha(Colours.cornflowerblue, alpha);
        		var sampleColour = Colours.withAlpha(Colours.white, alpha);
        		
        		g.setColour(sampleColour);
        		g.fillRect([this.data.sx, 0, this.data.sw, h]);
        		
        		if(!isDefined(sound))
        			return;
        		
        		if(sound.get(Sampler.LoopEnabled))
        		{
        			g.setColour(loopColour);
        			g.fillRect([this.data.dx, 0, this.data.dw, h]);
        			
        			if(this.data.xfw > 0)
        			{
        				var isReversed = Reverse.getValue();
        	
        				var fadeInRect = [this.data.dx - this.data.xfw, 0, this.data.xfw, h];
        				var fadeOutRect = [this.data.dx - this.data.xfw + this.data.dw, 0, this.data.xfw, h];
        	
        				if(isReversed)
        				{
        					fadeInRect[0] += this.data.dw + this.data.xfw;
        					fadeOutRect[0] -= this.data.dw - this.data.xfw;
        				}
        	
        				g.setColour(0x55447788);
        				g.fillPath(isReversed ? fadeOutPath : fadePath, fadeInRect);
        				
        				g.setColour(0x33447788);
        				g.fillPath(fadePath, fadeOutRect);
        				g.fillPath(fadeOutPath, fadeOutRect);
        			}
        			
        			if(this.data.hover)
        			{
        				g.setColour(Colours.withAlpha(loopColour, 1.0));
        				var handleX = this.data.dx;
        				
        				if(!this.data.setLeft)
        					handleX += this.data.dw - 5;
        				
        				g.fillRect([handleX, 0, 5, h]);
        			}
        		}	
        	});
        }
        

        Free Party, Free Tekno & Free Software too

        griffinboyG 1 Reply Last reply Reply Quote 0
        • griffinboyG
          griffinboy @Mighty23
          last edited by griffinboy

          @Mighty23

          Thanks, that's definitely closer, but the main issue persists.

          af61661d-0010-4da2-a6cd-6976896875f4-image.png

          The interesting thing, is that this situation does not work, playback does not match up with the loop points. But when you hit REVERSE and then REVERSE again to flip it back to normal... Hurrah, suddenly it works perfectly.

          It's very strange. I wonder if I need to raise this as a bug with Hise, because I can't spot what I'm doing wrongly.

          griffinboyG 1 Reply Last reply Reply Quote 0
          • griffinboyG griffinboy marked this topic as a question on
          • griffinboyG
            griffinboy @griffinboy
            last edited by griffinboy

            @griffinboy

            What's really odd is that the functionality for the 'reverse' button aren't visible. I am struggling to find any place where it is actually used to reverse the playback, yet, it mysteriously works.
            Perhaps this topic is too advanced for me! I need to learn more about the inner workings of Hise.

            It would be really nice to get this fixed.
            A lot of my Kontakt products involved doing wacky things with sampling, it would be fantastic to get this stuff working in Hise. It all works apart from the loop stuff. I wonder if something changed in Hise to cause this issue, or if the template always had this problem and it just hadn't been tested robustly.

            Looking at the History, it seems that the Sampler isn't really intended to be used for dynamically controlling for external samples.

            Christoph HartC 1 Reply Last reply Reply Quote 0
            • Christoph HartC
              Christoph Hart @griffinboy
              last edited by

              @griffinboy said in Sample Import Tutorial - It's Broken!:

              Looking at the History, it seems that the Sampler isn't really intended to be used for dynamically controlling for external samples.

              Yes you're right with that assumption. The priority of the sampler module is to allow high performant streaming of large sample sets and while you can bend it a little bit into the direction of a "creative" sampler tool, it will quickly show its limitations in this regard.

              If you really want to go crazy with sample manipulation, I would actually encourage you to dive into the C++ side and create your custom sample playback node (you can get a basic starting point from the file_player and granulator nodes). This might be even a good part 3 of your tutorial series after the filter :)

              Also, this:

              Link Preview Image
              HISE | Docs

              favicon

              (docs.hise.dev)

              griffinboyG 1 Reply Last reply Reply Quote 1
              • griffinboyG
                griffinboy @Christoph Hart
                last edited by

                @Christoph-Hart
                Thanks for the response, I was hoping to tap into the sampler to make use of the disk streaming and other fancy optimisations, but you are right.
                A custom solution will allow for much more direct control over the buffer(s), which will probably be much more beneficial in the long run.

                LindonL 1 Reply Last reply Reply Quote 0
                • LindonL
                  Lindon @griffinboy
                  last edited by

                  @griffinboy said in Sample Import Tutorial - It's Broken!:

                  @Christoph-Hart
                  Thanks for the response, I was hoping to tap into the sampler to make use of the disk streaming and other fancy optimisations, but you are right.
                  A custom solution will allow for much more direct control over the buffer(s), which will probably be much more beneficial in the long run.

                  But actually @Christoph-Hart - getting the loop points to work correctly is something I'm really going to need in an up-coming project so sorting this to be consistent would eb a win for me.

                  HISE Development for hire.
                  www.channelrobot.com

                  P 1 Reply Last reply Reply Quote 0
                  • P
                    paper_lung @Lindon
                    last edited by

                    @Lindon said in Sample Import Tutorial - It's Broken!:

                    @griffinboy said in Sample Import Tutorial - It's Broken!:

                    @Christoph-Hart
                    Thanks for the response, I was hoping to tap into the sampler to make use of the disk streaming and other fancy optimisations, but you are right.
                    A custom solution will allow for much more direct control over the buffer(s), which will probably be much more beneficial in the long run.

                    But actually @Christoph-Hart - getting the loop points to work correctly is something I'm really going to need in an up-coming project so sorting this to be consistent would eb a win for me.

                    +1 - I would love to make use of the tutorial project for this as well. as an alternative, adding a crossfade function to the audio loop player would be a great solution

                    griffinboyG 1 Reply Last reply Reply Quote 1
                    • griffinboyG
                      griffinboy @paper_lung
                      last edited by

                      @paper_lung

                      In case He doesn't fix it, I'm working on a custom solution now.
                      I'll upload it when it's working.

                      griffinboyG 1 Reply Last reply Reply Quote 3
                      • griffinboyG griffinboy marked this topic as a regular topic on
                      • griffinboyG
                        griffinboy @griffinboy
                        last edited by griffinboy

                        @griffinboy

                        Edit, we are halfway there. I've got polyphonic playback with Cubic interpolation.
                        Working on the looping now.

                        https://imgur.com/ArjtDwx

                        @Christoph-Hart By the way, what are you finding works well for antialising the sampler? I've not written one of these before and I'm wondering if you have a particular method.
                        I'm guessing interpolation + oversampling then a filter at nyquist then downsampling? As like the first things that can be done.

                        Christoph HartC 1 Reply Last reply Reply Quote 1
                        • Christoph HartC
                          Christoph Hart @griffinboy
                          last edited by

                          @griffinboy actually I‘m doing linear interpolation with no oversampling on most sample playback algorithms. Yes there is a drastic difference if you look for it with artificial signals and a high repitch ratio but for the usual use case it‘s not worth the performance IMHO.

                          Don‘t bother about oversampling (you can always wrap your node later), but if you‘re using the index classes from SNEX then you can just swap linear and hermite and check the difference between linear and cubic interpolation.

                          griffinboyG 1 Reply Last reply Reply Quote 0
                          • griffinboyG
                            griffinboy @Christoph Hart
                            last edited by griffinboy

                            @Christoph-Hart
                            Uh oh! In that case I must be doing something badly because I'm getting worse aliasing than you, with more advanced interpolation 😂
                            I was getting it so bad I even tried windowed sinc AND oversampling.
                            Back to the drawing board then.

                            Edit: Fixed it, thanks that was helpful to know. I'm getting almost no visible aliasing now. I can probably back off it a bunch. No wonder I couldn't find any articles online about antialiasing samplers. I was surprised if it was such an issue xD

                            1 Reply Last reply Reply Quote 0
                            • First post
                              Last post

                            46

                            Online

                            1.7k

                            Users

                            11.7k

                            Topics

                            101.9k

                            Posts