Exemplo n.º 1
0
    def build_from_intervals(self,
                             root,
                             octave,
                             intervals,
                             scale_name="major"):
        """Given chord specs return a MidiChord object of said chord.

        usage:
            chord = ChordBuilder().build_from_intervals('c', 6, ["1", "3", "5", "b7", "#9"])

        :param root: string of the note.
        :param octave: an integer between 0 and 8 (or 9 or something)
        :param intervals: a list of note intervals relative to the root. Use 'b' for flat and '#' for sharp.
        :param scale_name: the scale from which to select notes

        :return: a Chord object
        """
        named_scale = scale.NAMED_SCALES[scale_name]
        my_scale = Scale(Note((root.upper(), octave)), named_scale)
        num_notes_in_scale = len(my_scale)
        # TODO: is this the correct way to calculate the scale_start_num?
        scale_start_num = octave * num_notes_in_scale
        intervals = [
            self._deal_with_pitch_accidentals(interval)
            for interval in intervals
        ]
        notes = [
            my_scale.get(scale_start_num + interval[0] - 1).transpose(
                interval[1]) for interval in intervals
        ]
        chord = MidiChord([note.note + str(note.octave) for note in notes])
        chord.build_chord()
        return chord
Exemplo n.º 2
0
    def build_randomly_from_scale(root,
                                  octave,
                                  scale_name="major",
                                  num_note_choices=None):
        """Create a MidiChord object based on a given scale.

        :param root: the root note of the scale
        :param octave: the octave to be used when creating the chord
        :param scale_name: the scale name to be used
        :param num_note_choices: a list of how integers representing the number of notes allowed to be chosen at random
            when constructing the chord randomly. None will default to [3, 4, 5].

        :return: a MidiChord
        """
        if num_note_choices is None:
            num_note_choices = [3, 4, 5]
        named_scale = scale.NAMED_SCALES[scale_name]
        my_scale = Scale(Note((root.upper(), octave)), named_scale)
        num_notes_in_scale = len(my_scale)
        scale_start_num = octave * num_notes_in_scale
        num_notes_in_chord = np.random.choice(num_note_choices)
        possible_notes = [
            my_scale.get(temp_note)
            for temp_note in range(scale_start_num, scale_start_num +
                                   num_notes_in_scale * 2)
        ]
        notes = np.random.choice(possible_notes,
                                 size=num_notes_in_chord,
                                 replace=False)
        chord = MidiChord([note.note + str(note.octave) for note in notes])
        chord.build_chord()
        return chord
Exemplo n.º 3
0
class Melody:
    def __init__(self,
                 root_note=None,
                 octave=None,
                 scale_name=None,
                 melody_len=None,
                 quantization=None,
                 note_density=None,
                 note_len_choices=None):
        self.root_note = root_note
        self.octave = octave
        self.scale_name = scale_name
        self.melody_len = melody_len
        self.quantization = quantization  # this maybe should be at note level only
        self.note_density = note_density  # proportion of available ticks (determined by quantization) occupied by notes
        self.note_len_choices = note_len_choices

        self.root = Note((self.root_note, self.octave))
        self.named_scale = scale.NAMED_SCALES[self.scale_name]
        self.scale = Scale(self.root, self.named_scale)

        self.available_notes = [self.scale.get(x) for x in range(21, 30)]
        self.number_of_notes = self._compute_num_notes()
        self.start_ticks = self._get_start_ticks()

    def _compute_num_notes(self):
        return int(self.melody_len * self.note_density /
                   float(self.quantization))

    def _get_start_ticks(self):
        return np.unique(
            sorted([
                Rhythm().find_nearest_note(random.randint(0, self.melody_len),
                                           self.quantization)
                for _ in range(self.number_of_notes)
            ]))

    def _create_melody_note_tuple(self, start_tick):
        velocity = random.randint(50, 90)
        cur_note = random.choice(self.available_notes)
        cur_note = Note.index_from_string(cur_note.note + str(cur_note.octave))
        note_length = random.choice(self.note_len_choices)
        # ["event_type_fun", "tick", "duration", "pitch", "velocity"]
        return [
            MidiEventStager(midi.NoteOnEvent, start_tick, note_length,
                            cur_note, velocity),
            MidiEventStager(midi.NoteOffEvent, start_tick + note_length,
                            note_length, cur_note, 0)
        ]

    def create_melody(self):
        melody_notes = []
        for tick in self.start_ticks:
            melody_tuples = self._create_melody_note_tuple(tick)
            melody_notes.extend(melody_tuples)
        return melody_notes
Exemplo n.º 4
0
# Define key and scale
key = Note('E3')
scale = Scale(key, 'harmonic minor')

time = 0.0  # Keep track of currect note placement time in seconds

timeline = Timeline()

note = key

# Semi-randomly queue notes from the scale
for i in range(64):
    if note.index > 50 or note.index < 24:
        # If note goes out of comfort zone, randomly place back at base octave
        note = scale.get(random.randrange(4) * 2)
        note = note.at_octave(key.octave)
    else:
        # Transpose the note by some small random interval
        note = scale.transpose(note, random.choice((-2, -1, 1, 2)))
    length = random.choice((0.125, 0.125, 0.25))
    timeline.add(time, Hit(note, length + 0.125))
    time += length

# Resolve
note = scale.transpose(key, random.choice((-1, 1, 4)))
timeline.add(time, Hit(note, 0.75))  # Tension
timeline.add(time + 0.5, Hit(key, 4.0))  # Resolution

print("Rendering audio...")
# Define key and scale
key = Note('E3')
scale = Scale(key, 'major')

time = 0.0 # Keep track of currect note placement time in seconds

timeline = Timeline()

note = key

# Semi-randomly queue notes from the scale
for i in xrange(64):
  if note.index > 50 or note.index < 24:
    # If note goes out of comfort zone, randomly place back at base octave
    note = scale.get(random.randrange(4) * 2)
    note = note.at_octave(key.octave)
  else:
    # Transpose the note by some small random interval
    note = scale.transpose(note, random.choice((-2, -1, 1, 2)))
  length = random.choice((0.125, 0.125, 0.25))
  timeline.add(time, Hit(note, length + 0.125))
  time += length

# Resolve
note = scale.transpose(key, random.choice((-1, 1, 4)))
timeline.add(time, Hit(note, 0.75))     # Tension
timeline.add(time + 0.5, Hit(key, 4.0)) # Resolution

print "Rendering audio..."