Live_Loop thread death with samples from directory


#1

Hi Everyone,

I running v 3.1.0 on a Windows 8.1 machine (64 bit) and I’m new to Sonic Pi - still working through the tutorial, but trying to take what I’ve learned and apply it to ideas I’ve had for performances, recordings, etc.

One such idea involves randomly looping a number of samples in a directory filled with .wav files. I’ve had a lot of success with both loops and live_loops, but now that I am working with a large number of samples of my own creation (all recorded with a H4n mic), I keep running into errors I can’t explain.

Here is the code I am working with:

load_samples "D:/Path/to/files/"

live_loop :attempt do
  rec_idx = rrand_i(0, 37)
  puts rec_idx
  if rec_idx < 11
    sample "D:/Path/to/files/", rec_idx, start: rrand(0, 0.8), sustain: 2, amp: 2
    sleep 2
  else
    sample "D:/Path/to/files/", rec_idx, start: rrand(0, 0.8), sustain: 2, amp: 0.2
    sleep 2
  end
end

If I try to run this as a regular loop, it does what I expect it to do. But once I switch to the above code, I run into a thread death error, which I’ve pasted below. Any clue why this might happen? What’s particularly curious is that, once I receive this error, all live_loops fail for me, even live_loops as simple as “play 60, sleep 1.” To make that simple code work again, I have to clear the buffer, restart the program, and then re-enter the code.

Any idea what might cause this?

As a side note, I first ran into this problem working with a definition that set the duration of the sleep command to equal the value of the sustain opt (it also randomized things in one line, instead multiple lines). Once I started getting the error, I assumed I couldn’t use a definition with a live_loop and substituted a direct call to the path where my samples exist (this explains my use of the rec_idx definition hopefully). Only the error persists. Can anyone confirm for me whether or not I can execute definitions inside live_loops?

Many thanks for any help you can offer!

Runtime Error: [workspace_one] - TypeError

Thread death +--&gt; :live_loop_attempt

class or module required

C:/Program Files (x86)/Sonic Pi/app/server/ruby/lib/sonicpi/runtime.rb:1300:in `is_a?'

C:/Program Files (x86)/Sonic Pi/app/server/ruby/lib/sonicpi/runtime.rb:1300:in `block in initialize'

C:/Program Files (x86)/Sonic Pi/app/server/ruby/lib/sonicpi/lang/core.rb:4079:in `__live_loop_cue'

C:/Program Files (x86)/Sonic Pi/app/server/ruby/lib/sonicpi/lang/core.rb:2134:in `block (2 levels) in live_loop'

C:/Program Files (x86)/Sonic Pi/app/server/ruby/lib/sonicpi/lang/core.rb:2055:in `block (2 levels) in loop'

C:/Program Files (x86)/Sonic Pi/app/server/ruby/lib/sonicpi/lang/core.rb:2276:in `block_duration'

C:/Program Files (x86)/Sonic Pi/app/server/ruby/lib/sonicpi/lang/core.rb:2313:in `block_slept?'

C:/Program Files (x86)/Sonic Pi/app/server/ruby/lib/sonicpi/lang/core.rb:2054:in `block in loop'

C:/Program Files (x86)/Sonic Pi/app/server/ruby/lib/sonicpi/lang/core.rb:2052:in `loop'

C:/Program Files (x86)/Sonic Pi/app/server/ruby/lib/sonicpi/lang/core.rb:2052:in `loop'

C:/Program Files (x86)/Sonic Pi/app/server/ruby/lib/sonicpi/lang/core.rb:2133:in `block in live_loop'

C:/Program Files (x86)/Sonic Pi/app/server/ruby/lib/sonicpi/runtime.rb:1043:in `block (2 levels) in __in_thread'

#2

Hi there,

this is incredibly strange indeed!

The error doesn’t appear to be anything to do with live loops or the code within, rather it appears to be an issue with cue messages. (It just so happens that live loops automatically call cue every time they spin round).

Looking at my branch of the v3.1.0 code, the line that’s causing the error seems to be:

address, sym = *address if address.is_a?(Array)

Specifically the issue appears to be the if part of this:

address.is_a?(Array)

Looking on Google, the error you get can happen if the thing you’re checking against (Array) in this case isn’t a valid Ruby type. However, as far as I’m aware, Array is very much a built-in valid type and always has been. This makes things really rather curious indeed - especially as I’m not aware of this happening on anybody else’s installation of Sonic Pi regardless of OS.

Would it be possible to restart Sonic Pi and type the following into an empty buffer:

puts [].is_a?(Array)

and see if that causes an error? If not, could you try the following:

cue :foo

Does this cause an error?


#3

Hi Sam,

Thanks so much for replying. It’s interesting that you caught that reference to “Array” as that is a leftover from the first error I encountered with live_loops.

Initially, I had this variable set at the very top of my composition (and I still did in my first buffer, when I posted initially):

Array = "D:/Path/to/Files/" #sample source

It was just a handy shortcut to my “array” of samples. I then used that to create a fairly simple definition that would help me set the sleep value to the same value as the sustain opt:

define :AllVar do |location, duration|
  sample Array, location, sustain: duration, start: rrand(0, 0.75)
  sleep duration
end

That way I could call AllVar, give it two parameters, and loop without any of the samples crossing over one another. It plays a randomly generated integer, sets a random amount of time for the sustain, and sleeps for that same duration:

AllVar rrand_i(0, 37), rrand(1, 4)

But when I started getting the error, I figured it was a problem with using a definition like that inside a live_loop, so I went back to the drawing board and came up with my rec_idx solution, which gives me a little more control over the amp opt, but makes it hard to set sleep and sustain to the same value (still working that bit out).

Anyway, your post gave me an idea and I went back and removed all instances of “Array” from my buffers. Doing so (and restarting the program) seemed to do the trick. Now that live_loop code I posted works. Not sure why, but there it is.

Maybe of interest: both the “puts []” code you suggested and the “cue :foo” code work, even if that “Array” variable is present in one of the other buffers. The first one returns “True” and the second simply shows me a call to “/cue/foo” in the Cues viewer (all I get in the Log is that the run started, completed, and that all runs are complete).

Have I made a mistake and used a variable (“Array”) that I shouldn’t use? Is there a conflict happening in the background somewhere?

Thanks again for looking at this!!


#4

Hi @laughtercs,

Indeed, by convention in Ruby (which Sonic Pi’s language is built on) Array and many other capitalised names are in fact names of built in classes. So Ruby thought that you were trying to redefine the Array class into something completely different. In this case, the ideal solution is to prefer using lowercase names for variables so that this potential clash can’t occur.


#5

Wow, what an unlucky gaffe on my part. But glad to learn something new about Ruby and Sonic Pi. Thank you for looking into this. It means I get to move foreword with my project. Much appreciated!