<commit_before>#!/usr/bin/env python

from cStringIO import StringIO

from core import Sequence, Point, OFFSET_64, MIDI_PITCH, DURATION_64


def write_chars(out, chars):
    out.write(chars)


def write_byte(out, b):
    out.write(chr(b))


def write_ushort(out, s):
    write_byte(out, (s >> 8) % 256)
    write_byte(out, (s >> 0) % 256)


def write_ulong(out, l):
    write_byte(out, (l >> 24) % 256)
    write_byte(out, (l >> 16) % 256)
    write_byte(out, (l >> 8) % 256)
    write_byte(out, (l >> 0) % 256)


def write_varlen(out, n):
    data = chr(n & 0x7F)
    while True:
        n = n >> 7
        if n:
            data = chr((n & 0x7F) | 0x80) + data
        else:
            break
    out.write(data)


class SMF:
    
    def __init__(self, sequence):
        self.sequence = sequence
        
    def write(self, out):
        
        Thd(format=1, num_tracks=2, division=16).write(out)
        T = 1 # how to translate events times into time_delta using the division above
        
        # first track will just contain time/key/tempo info
        t = Trk()
        
        t.sequence_track_name("untitled")
        t.time_signature(4, 2, 24, 8) # 4 4 (2nd arg is power of 2)
        t.key_signature(0, 0) # C
        t.tempo(500000) # in microseconds per quarter note
        t.track_end()
        t.write(out)
        
        # second track will contain actual notes
        t = Trk()
        
        # we make a list of events including note off events so we can sort by
        # offset including them (to avoid negative time deltas)
        # @@@ this may eventually be a feature of sequences rather than this
        # MIDI library
        
        events_with_noteoff = []
        for point in self.sequence:
            offset, note_value, duration = point.tuple(OFFSET_64, MIDI_PITCH, DURATION_64)
            events_with_noteoff.append((True, offset, note_value))
            events_with_noteoff.append((False, offset + duration, note_value))
        
        prev_offset = None
        for on, offset, note_value in sorted(events_with_noteoff, key=lambda x: x[1]):
            if prev_offset is None:
                time_delta = 0
            else:
                time_delta = (offset - prev_offset) * T
            if on:
                t.start_note(time_delta, note_value)
            else:
                t.end_note(time_delta, note_value)
            prev_offset = offset
            
        t.track_end()
        t.write(out)


class Thd:
    
    def __init__(self, format, num_tracks, division):
        self.format = format
        self.num_tracks = num_tracks
        self.division = division<commit_msg>don't create a midi event for points that aren't notes<commit_after>#!/usr/bin/env python

from cStringIO import StringIO

from core import Sequence, Point, OFFSET_64, MIDI_PITCH, DURATION_64


def write_chars(out, chars):
    out.write(chars)


def write_byte(out, b):
    out.write(chr(b))


def write_ushort(out, s):
    write_byte(out, (s >> 8) % 256)
    write_byte(out, (s >> 0) % 256)


def write_ulong(out, l):
    write_byte(out, (l >> 24) % 256)
    write_byte(out, (l >> 16) % 256)
    write_byte(out, (l >> 8) % 256)
    write_byte(out, (l >> 0) % 256)


def write_varlen(out, n):
    data = chr(n & 0x7F)
    while True:
        n = n >> 7
        if n:
            data = chr((n & 0x7F) | 0x80) + data
        else:
            break
    out.write(data)


class SMF:
    
    def __init__(self, sequence):
        self.sequence = sequence
        
    def write(self, out):
        
        Thd(format=1, num_tracks=2, division=16).write(out)
        T = 1 # how to translate events times into time_delta using the division above
        
        # first track will just contain time/key/tempo info
        t = Trk()
        
        t.sequence_track_name("untitled")
        t.time_signature(4, 2, 24, 8) # 4 4 (2nd arg is power of 2)
        t.key_signature(0, 0) # C
        t.tempo(500000) # in microseconds per quarter note
        t.track_end()
        t.write(out)
        
        # second track will contain actual notes
        t = Trk()
        
        # we make a list of events including note off events so we can sort by
        # offset including them (to avoid negative time deltas)
        # @@@ this may eventually be a feature of sequences rather than this
        # MIDI library
        
        events_with_noteoff = []
        for point in self.sequence:
            offset, note_value, duration = point.tuple(OFFSET_64, MIDI_PITCH, DURATION_64)
            if note_value is not None:
                events_with_noteoff.append((True, offset, note_value))
                events_with_noteoff.append((False, offset + duration, note_value))
        
        prev_offset = None
        for on, offset, note_value in sorted(events_with_noteoff, key=lambda x: x[1]):
            if prev_offset is None:
                time_delta = 0
            else:
                time_delta = (offset - prev_offset) * T
            if on:
                t.start_note(time_delta, note_value)
            else:
                t.end_note(time_delta, note_value)
            prev_offset = offset
            
        t.track_end()
        t.write(out)


class Thd:
    
    def __init__(self, format, num_tracks, division):
        self.format = format
        self.num_tracks = num_tracks
        self.division = division
{'fraction_non_alphanumeric': 0.09588278931750742, 'fraction_numerical': 0.024480712166172106, 'mean_word_length': 1.9453850354997269, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3348536', 'n_tokens_mistral': 1847, 'n_tokens_neox': 1692, 'n_words': 493}