IndexError: list out of range?

Hello SCAMPsters!

Short time user, even shorter-time reader.

I’ve been getting this annoying error when trying to reproduce some of Marc’s video material in my own way. I ran the Cooking with Scamp code locally, so I don’t think that it’s an issue with Python and so assume it’s my code. :smiley:

Trying to auto-insert some barlines but keep getting IndexError: list out of range.

The full error is:

Traceback (most recent call last):
File “/Users/vin/Dropbox/Composition/2022/SCAMP/WB7/brains.py”, line 133, in
s.stop_transcribing().to_score(bar_line_locations=bar_lines, simplicity_preference=1.0, max_divisor=14).show()
File “/Users/vin/Library/Python/3.7/lib/python/site-packages/scamp/performance.py”, line 1097, in to_score
simplicity_preference=simplicity_preference, title=title, composer=composer
File “/Users/vin/Library/Python/3.7/lib/python/site-packages/scamp/score.py”, line 924, in from_performance
max_divisor_indigestibility=max_divisor_indigestibility, simplicity_preference=simplicity_preference
File “/Users/vin/Library/Python/3.7/lib/python/site-packages/scamp/quantization.py”, line 557, in from_attributes
simplicity_preference=simplicity_preference, loop=loop)
File “/Users/vin/Library/Python/3.7/lib/python/site-packages/scamp/quantization.py”, line 606, in from_time_signature_list
simplicity_preference=simplicity_preference)
File “/Users/vin/Library/Python/3.7/lib/python/site-packages/scamp/quantization.py”, line 398, in from_time_signature
return cls(beat_schemes, time_signature)
File “/Users/vin/Library/Python/3.7/lib/python/site-packages/scamp/quantization.py”, line 345, in init
self.beat_groupings = self._generate_default_beat_groupings()
File “/Users/vin/Library/Python/3.7/lib/python/site-packages/scamp/quantization.py”, line 402, in _generate_default_beat_groupings
last_beat_length = self.beat_schemes[0].length
IndexError: list index out of range

%Run ScampCooking.py

from scamp import *
import random
s = Session(tempo=130)
oboe = s.new_part("oboe")


bar_lines = []
duration_list = []
pitch_list = []
pitch_base_list = [60, 59, 60, 59, 55, 54, 69, 59]
interval_list = [0, 2, 3, 5, 7, 8, 9, 10]
interval_mult = [1, 2, 3, -2]
def round_multiple(number, multiple):
    return multiple * round(number / multiple)

def construct_parent_list(tuplet_size, output_size, duration_size):
    for i in range(output_size):
        rhythm_sub_list = []
        pitch_sub_list = []
        sub_tuplet = round(random.random() * tuplet_size)
        for i in range(sub_tuplet):
            sub_duration_size = round_multiple(random.random() * duration_size, 0.25)
            sub_pitch = random.choice(pitch_base_list) + random.choice(interval_list) * random.choice(interval_mult)
            rhythm_sub_list.append(sub_duration_size)
            pitch_sub_list.append(sub_pitch)
        duration_list.append(rhythm_sub_list)
        pitch_list.append(pitch_sub_list)
    for f in duration_list:
        if f == []:
            f = None   

def oboe_voice():
    for z in pitch_base_list:
        random_index = round(random.random() * len(duration_list)-1)
        rhythm_pattern = duration_list[random_index]
        pitch_pattern = pitch_list[random_index]
        print(rhythm_pattern)
        bar_lines.append(s.time()) # Trying to do THIS part.
        for x, y in zip(rhythm_pattern, pitch_pattern):
            test_num = random.random()
            if test_num < 0.5:
                if x != 0.0:
                    oboe.play_note(y, random.uniform(0.5, 1.0), x)
                else:
                    s.wait(random.choice(rhythm_pattern))
            elif test_num < 0.8:
                if x != 0.0:
                    oboe.play_note([y, y+random.choice(interval_list) * random.choice(interval_mult)], random.uniform(0.5, 1.0), x)
                else:
                    s.wait(random.choice(rhythm_pattern))
            else:
                if x != 0.0:
                    oboe.play_note(y, random.uniform(0.5, 1.0), x, "staccato")
                    s.wait(random.choice(rhythm_pattern))
                else:
                    s.wait(random.choice(rhythm_pattern))

construct_parent_list(7, 10, 1.3)
s.start_transcribing()
while s.time() <= 4:
    oboe_voice()

s.stop_transcribing().to_score(bar_line_locations=bar_lines, simplicity_preference=1.0, max_divisor=14).show()

Ack, fixed it. Moved the append barline to after the function call in the main transcription script. Dingus error!

Although now it keeps throwing either:

MemoryError

or

ValueError: TimeSignature denominator must be a power of two.

I’m very clearly doing something wrong.

I think the only reasonable approach to this issue is to just re-write all the code from scratch and see if I can refine it with understanding that is further along.

Sorry for the monologue, everybody!

Sounds like you’re figuring it out gradually!

If you get stuck, it would be helpful to see a print out of the bar line locations. I think the issue you’re running into is that some lengths of measure aren’t possible in traditional notation. For example, 0! Or something like 3.2, which would have to be notated as a “4/5” time signature. (Admittedly, some composers do use these time signatures, calling them “irrational time signatures”, but they don’t work nicely with musicxml.)

Anyway, welcome!

Hey Marc,
Thanks for the response! I modified the order of execution to stop it adding a s.time() at 0ms, and that fixed part of the problem. It would still occasionally spit out some weirdness, but I couldn’t be bothered figuring it out.
The irrational time signatures thing is cool, it’d be great to get that integrated at some stage, but it’d make more sense to focus on tuplet nesting first, right? Because how do you determine whether to use an irrational time signature or a normal one with nested tuplets? Obviously there are semantically different use-cases, but from an interpretation/generative perspective? That’s programmatically tough! Even nested tuplets would be tough without using something like rhythm trees syntax, right?

Yeah, nested tuplets would probably be a first goal. To be honest, when I was first developing SCAMP, I think I had an ideological aversion to nested tuplets, since you can always express any nested tuplet as a flat tuplet of the least common denominator. But since then I’ve realized it’s way better to read a nested tuplet in many cases.

I’ve seen a paper by Paul Nauert, I think, about quantizing with rhythm trees, so I’d probably use something like that when I finally feel like dealing with the complexity of nested tuplets!

But irrational time signatures… even more niche, I think. You could just simulate it with a precise tempo change, anyway, and then change the notation by hand after the fact.

1 Like