Ejemplo n.º 1
0
def sounds_to_key_and_stream(sounds):
    key = set()
    stream = Stream()
    for sound in sounds:
        stream.add_sound(sound)

        key.add(
            KeySound(
                frequency=sound.frequency,
                duration=sound.duration,
                volume=sound.volume,
            )
        )
    return frozenset(key), stream
Ejemplo n.º 2
0

twinkle_twinkle_little_star = Stream()
current_time = 0
for phrase in twinkle_twinkle_little_star_notes:
    for note, timing in zip(
        phrase.split(" "), tinkle_twinkle_little_star_timings
    ):
        duration = note_length * timing
        twinkle_twinkle_little_star.add_sound(
            Tone(
                start=current_time,
                duration=duration,
                frequency=scientific_note_frequency(note),
                overtones=[],
                volume=0.4,
                attack_seconds=0.1,
                decay_seconds=0.1,
                sustain_level=0.75,
                release_seconds=0.2,
            )
        )
        current_time += duration


def fuzzy_start(sounds):
    for sound in sounds:
        yield sound.delayed(
            random.uniform(-note_length / 32.0, note_length / 32.0)
        )
Ejemplo n.º 3
0
def build_stream_from_midi(filename):
    mid = mido.MidiFile(filename)
    merged_tracks = mido.merge_tracks(mid.tracks)

    bpm = None
    current_time = 0

    active_notes = {
        channel: defaultdict(list)
        for channel in set(
            msg.channel for msg in merged_tracks if "channel" in msg.dict())
    }

    stream = Stream()

    for msg in merged_tracks:
        if msg.type == "note_on" and msg.velocity == 0:
            # turn a zero velocity note on into an equivalent note off
            data = msg.dict()
            data["type"] = "note_off"
            msg = msg.from_dict(data)

        if bpm is not None:
            current_time += msg.time / mid.ticks_per_beat / bpm * 60

        if msg.type == "set_tempo":
            bpm = mido.tempo2bpm(msg.tempo)

        elif msg.type == "note_on":
            if bpm is None:
                raise Exception(f"no tempo found before the first note")

            active_notes[msg.channel][msg.note].append(
                (current_time, msg.velocity))

        elif msg.type == "note_off":
            if not active_notes[msg.channel][msg.note]:
                raise Exception(
                    f"notes: {active_notes}, disabling note: {msg}")

            if current_time is None:
                raise Exception(f"no tempo found before the first note")

            if msg.velocity != 0:
                raise Exception(
                    f"do not konw how to work with non-zero note_off velocity: {msg}"
                )

            started, initial_velocity = active_notes[msg.channel][
                msg.note].pop()

            if msg.channel == 2:
                continue

            duration = current_time - started
            if duration > 5:
                raise Exception(f"would have created a very long note: {msg}")
            stream.add_sound(
                Tone(
                    start=started,
                    duration=duration,
                    frequency=midi_note_frequency(msg.note),
                    overtones=[
                        Overtone(2, 0.5 * pi, 0.5),
                        Overtone(3, 0, 0.3),
                        Overtone(4, 0.25 * pi, 0.2),
                        Overtone(5, 0, 0.2),
                    ],
                    volume=0.4 * initial_velocity / 127,
                    attack_seconds=0.1,
                    decay_seconds=0.1,
                    sustain_level=0.75,
                    release_seconds=0.1,
                ))

        elif msg.type in (
                "time_signature",
                "key_signature",
                "program_change",
                "control_change",
                "track_name",
                "smpte_offset",
                "midi_port",
                "end_of_track",
        ):
            continue

        else:
            raise Exception(f"unkown message: {msg}")

    return stream