How to resample a list quickly?

(This is my first post to this forum!)

I would like to resample a list, e.g., take every other element of the list in making a new list, or taking every third element. My purpose is to shift the frequency of a recorded sound.

My first attempt was recursive. It worked, but was too slow for even a second of sound at 22Khz.

My next attempt was iterative. Maybe that would be faster? Turns out to be even slower.

untitled script pic (1)

I've tried to figure out a way to use the array processing blocks in Snap, but I don't think in APL yet to figure it out.

So, let me ask this question at a higher level: What makes list processing fast (or in my case, slow) in Snap? What are the best techniques for speeding up list processing?

Thanks!

Hey, Mark! Welcome to the forum.

The canonical way to do this is


where SKIP FACTOR is the 2 or 3 or whatever.

You get the lightning bolt in the KEEP block by using an ordinary KEEP block and choosing "compile" from its context menu (right-click). You get the INPUT NAMES in the ring by clicking the right arrowhead.

The hyperblock primitives are sort of equivalent to MAP, but not to KEEP. There are APL blocks in the APL library that do selection (SELECT ROWS and SELECT COLUMNS), but they are implemented using KEEP as above.

Just need to try and see what gives you acceptable speed
The simplest native way that comes to mind is
image

or maybe

image

Typed at same time as Brian :slight_smile:

Thank you both! I tried the keep block, and it does work much faster. That makes shifting up in frequency much more do-able.

I also just discovered the turbo block! If I wrap my iterative approach in a turbo block, it's less painfully slow AND I can get the ability to do negative increments (-2 goes twice as fast, in reverse) and < 1 increments (0.5 gives me a twice as long and half the frequency sound). The <1 increments are VERY slow, but they work.

I and the students working with me on our new classes are enjoying reading the Snap manual, Brian! We keep texting one another "Did you see this?" and "Quick -- check out Section <blah!>."

Glad to hear it!

For fractional increments 1/N, I guess you need N copies of each sample? Try this:


This works only if each sample is atomic, because FLATTEN flattens all the way down to atoms, rather than flattening one level as I think it should.

I'm not sure how you do factors of M/N where neither is 1. I guess you could drop N-1 out of every N samples, then copy M times?

You guys are overthinking this! Just use Hyperblocks and it'll be so fast you don't even have to think about it:

even more versatile is using multiplication instead of division:

this lets you stretch the list of samples (to get a deeper pitch) using factors greater than 1, and condense it (to get a higher pitch) using fractional factors less than 1.

Oh right! Somehow it never occurs to me to use ITEM with a vector in the first input. My bad!

That is terrific! I've implemented the top one, which works for all values > 0, including values < 1. Hmm, I bet I can use this trick to handle negative skips, too. Very cool -- thanks, Jens!

That only works for mono sounds. You'd have to map that function over stereo sounds to get it to work.

Everyone: Makes long comments with big and hard solutions

Jens: Just use hyper blocks!

ITEM is way more magic than you're thinking.


You can have as many channels as you want. If SAMPLES is a 2D list, then ITEM will take a 2D list in which the first item selects rows and the second item select columns. In this case, the first item of the input to ITEM is an empty list, which means to select all of the items in that dimension. The second item is the computation Jens did.

If you had, say, 5-channel surround sound and you wanted only the two front channels, that'd be

Jens's solution isn't really any shorter or simpler than the KEEP one, just faster.

I just tested it out, and it is faster than map. Only problem is, I have to make sounds with one channel a 2D list. It isn't that hard though.

No, Jens's code is for a plain list of numbers. My code is a little more complicated because you raised the question of stereo sounds, which are already 2D lists.

I fixed the issue with this code

Ah, I didn't understand that you considered this an "issue" needing fixing, i.e., that you wanted one procedure to work for mono and stereo.

Good point about stereo sounds. For the pedagogical reason of introducing "plain", i.e. one-dimensional, lists @jadga and I always use mono sounds first. In fact, for that same pedagogical reason I've made sure that Snap only records sounds in mono, when you record them yourself. When we teach MediaComp, we start with (mono) sounds (one dimension of samples), and introduce tables with pictures (2 dimensions of color samples). Our punch line then is "tables are just lists", so you can use the same strategies that work for sounds on pictures.

In case any of y'all are interested, I now have a Snap project where I've replicated my favorite MediaComp sound demos: Resampling (positive and negative, including non-integer values), one-bit sound, and live sonogram plotting. Snap! Build Your Own Blocks

I learned that plot sound only works in sprites, not in stage scripts. I found (to my delight) that I could drag a sound from the stage onto a sprite, and it copies into the sprite's sounds. I was surprised at the lack of surprises when I made the sonogram view. It just worked!

Beautiful, Mark! I'm soooo excited that you're even exploring the latest uses of the hyper-IF reporter, and I'm stoked that the sonogram plot just works. You know, your SIGCSE keynote - and of course all your GP demos - about this have totally inspired us to all out embrace MediaComp in Snap! To me it's the perfect story about data and digitalization. Also, live plotting sounds has become one of my and @jadga's all-time favorite activities. Check out @jadga's part of her her recent RobOLOT talk in which she combines a sonogram with a concealed picture! (watch it to the end of her talk, it's worth it!): Jornada d'innovació | Robolotcon22 - YouTube

Wait, that's hyperized now? Wow, I can't wait to se how much I can do with it.