Exemple #1
0
 def test_sub(self):
     """ Test subtraction """
     f0 = Fraction(5)
     f1 = Fraction(6)
     self.assertEqual(f0 - f1, -1)
     f2 = Fraction(7, 12) - f0
     self.assertEqual(f2, Fraction("-4 5/12"))
     self.assertEqual(f2, Fraction(-53, 12))
Exemple #2
0
 def test_simplify(self):
     """
     Basic test of simplification of fractions.
     
     """
     f0 = Fraction(9, 10)
     f1 = Fraction(18, 20)
     self.assertEqual(f0, f1)
     f2 = Fraction(17, 20)
     self.assertNotEqual(f0, f2)
Exemple #3
0
 def test_add(self):
     """
     Try adding Fractions together.
     
     """
     f0 = Fraction(5)
     f1 = Fraction(6)
     self.assertEqual(f0 + f1, 11)
     f2 = Fraction(7, 12) + f0
     self.assertEqual(f2, Fraction("5 7/12"))
     self.assertEqual(f2, Fraction(67, 12))
Exemple #4
0
 def test_reparse_string(self):
     """
     Create some random fractions, get their string representation and check 
     the this can by used to correctly reinstantiate the fraction.
     
     """
     from random import randint
     for i in range(50):
         # Create a random fraction
         f0 = Fraction(randint(0, 100), randint(1, 100))
         f0_str = str(f0)
         self.assertEqual(f0, Fraction(f0_str))
Exemple #5
0
 def test_mul(self):
     """ Test multiplication """
     f0 = Fraction(1, 2) * Fraction(3)
     self.assertEqual(f0, Fraction(3, 2))
     f1 = Fraction(5, 7) * Fraction(3, 9)
     self.assertEqual(f1, Fraction(15, 63))
     f2 = Fraction(-5, 7) * Fraction(3, -9)
     self.assertEqual(f2, f1)
Exemple #6
0
 def test_int(self):
     """ Conversion to int """
     from random import randint
     for i in range(50):
         n = randint(0, 100)
         d = randint(1, 100)
         self.assertEqual(int(Fraction(n, d)), n / d)
Exemple #7
0
 def test_long(self):
     """ Conversion to long """
     from random import randint
     for i in range(50):
         n = randint(0, 100)
         d = randint(1, 100)
         self.assertEqual(long(Fraction(n, d)), long(n) / long(d))
Exemple #8
0
 def get_signs_for_word(self, index, offset=0):
     if offset > 0:
         return []
     else:
         all_signs = self.tags[index]
         return [(sign, sign.tag, Fraction(1, len(all_signs)))
                 for sign in all_signs]
Exemple #9
0
 def test_float(self):
     """ Conversion to float """
     from random import randint
     for i in range(50):
         n = randint(0, 100)
         d = randint(1, 100)
         self.assertEqual(float(Fraction(n, d)), float(n) / float(d))
Exemple #10
0
 def test_zero_denominator(self):
     """
     Setting a Fraction's denominator to 0 should raise an error.
     
     """
     self.assertRaises(ZeroDivisionError, Fraction, 5, 0)
     f = Fraction(1)
     self.assertRaises(ZeroDivisionError, lambda x: f / x, 0)
Exemple #11
0
def _get_duration(tokens):
    """Get a 'for' duration specification out of a line's tokens.
    Returns duration in quarter notes."""
    duration = 1
    if "for" in tokens:
        forpos = tokens.index("for")
        try:
            duration = float(Fraction(tokens.pop(forpos+1)))
        except:
            raise HarmonicalInputFileReadError, "'for' "\
                "must be followed by an integer number "\
                "of beats."
        tokens.pop(forpos)
    return duration
Exemple #12
0
    def __init__(self,
                 inputs,
                 durations=None,
                 times=None,
                 roman=False,
                 *args,
                 **kwargs):
        super(ChordInput, self).__init__(*args, **kwargs)

        self.inputs = inputs
        self.durations = durations
        self.times = times
        self.roman = roman

        # Compute the durations from times or vice versa
        if durations is None and times is None:
            raise ValueError, "cannot create a ChordInput with neither "\
                "times nor durations given"
        elif times is None:
            self.times = [
                sum(durations[:i], Fraction(0)) for i in range(len(durations))
            ]
        elif durations is None:
            from jazzparser.utils.base import group_pairs
            self.durations = [
                time1 - time0 for (time1, time0) in group_pairs(times)
            ] + [Fraction(1)]

        # Convert all strings to internal chord representation
        # Done now so we check the chords can all be understood before doing
        #  anything else
        self.chords = [
            Chord.from_name(name, roman=roman).to_db_mirror()
            for name in inputs
        ]
        for chord, dur in zip(self.chords, self.durations):
            chord.duration = dur
Exemple #13
0
 def test_create_string(self):
     """
     Test creating a fraction from a string representation.
     
     """
     f0 = Fraction("1 1/4")
     self.assertEqual(f0, Fraction(5, 4))
     f1 = Fraction("5")
     self.assertEqual(f1, Fraction(5))
     f2 = Fraction("5/4")
     self.assertEqual(f2, Fraction(5, 4))
     for invalid in ["", "1.5", "1/1/1", "5 5", "4\\5", "a", "X"]:
         self.assertRaises(Fraction.ValueError, Fraction, invalid)
Exemple #14
0
    def __init__(self, inputs, durations=None, times=None, id=None, \
                    chords=None, sequence=None, *args, **kwargs):
        super(DbInput, self).__init__(*args, **kwargs)

        self.inputs = inputs
        self.durations = durations
        self.times = times
        self.id = id
        self.chords = chords
        self.sequence = sequence

        if durations is None and times is None:
            raise ValueError, "cannot create a DbInput with neither "\
                "times nor durations given"
        elif times is None:
            self.times = [sum(durations[:i]) for i in range(len(durations))]
        elif durations is None:
            from jazzparser.utils.base import group_pairs
            self.durations = [
                time1 - time0 for (time1, time0) in group_pairs(times)
            ] + [Fraction(1)]
Exemple #15
0
def assign_durations(string):
    """
    Computes the durations for each chord token in the string.
    Chords on their own get a duration of 1. Comma-separated sequences
    of chords get a duration of 1, split evenly between the members
    of the sequence.
    
    """
    from jazzparser.data import Fraction
    # Make sure the commas are separate tokens
    string = string.replace(",", " , ")
    string = string.replace(":", " : ")
    string = string.replace("|", "")
    tokens = string.split()
    # Group tokens into comma-separated sequences
    in_sequence = False
    units = []
    for token in tokens:
        if token == "," or token == ":":
            # The next token is in the same sequence as the last
            in_sequence = True
        elif in_sequence:
            # This token should be added to the previous token's sequence
            units[-1].append(token)
            in_sequence = False
        else:
            # Start of a new sequence
            units.append([token])
            
    # Now build the list of durations
    durations = []
    for unit in units:
        # Each sequence has a total length of 4 (assume 4 beats in bar)
        # Split this between its members.
        denominator = len(unit)
        members = [Fraction(4,denominator)] * denominator
        durations.extend(members)
    
    return durations
Exemple #16
0
 def test_div(self):
     """ Test division """
     f0 = Fraction(1, 2) / 3
     self.assertEqual(f0, Fraction(1, 6))
     f0 = Fraction(1, 2) / Fraction(3)
     self.assertEqual(f0, Fraction(1, 6))
     f1 = Fraction(5, 7) / Fraction(3, 9)
     self.assertEqual(f1, Fraction(45, 21))
     f2 = Fraction(-5, 7) / Fraction(3, -9)
     self.assertEqual(f2, f1)
     f3 = Fraction(5, 7) / 0.5
     self.assertEqual(f3, 10.0 / 7.0)
Exemple #17
0
    def render(self):
        """
        Creates MIDI data from the path and chord types.
        
        @rtype: midi.EventStream
        @return: an event stream containing all the midi events
        
        """
        mid = EventStream()
        mid.add_track()

        # Set the tempo at the beginning
        tempo = SetTempoEvent()
        tempo.tempo = self.tempo
        mid.add_event(tempo)

        # Set the instrument at the beginning
        instr = ProgramChangeEvent()
        instr.value = self.instrument
        mid.add_event(instr)

        beat_length = mid.resolution
        # Work out when each root change occurs
        time = Fraction(0)
        root_times = []
        for root, length in self.path:
            root_times.append((root, time))
            time += length

        def _root_at_time(time):
            current_root = root_times[0][0]
            for root, rtime in root_times[1:]:
                # Move through root until we get the first one that
                #  occurs after the previous time
                if rtime > time:
                    return current_root
                current_root = root
            # If we're beyond the time of the last root, use that one
            return current_root

        # Add each chord
        time = Fraction(0)
        bass_events = []
        bass = self.bass_root is not None
        for chord_type, length in self.chord_types:
            tick_length = length * beat_length - 10
            tick_time = time * beat_length
            # Find out what root we're on at this time
            root = _root_at_time(time)
            # Add all the necessary events for this chord
            chord_events = events_for_chord(
                root,
                chord_type,
                int(tick_time),
                int(tick_length),
                equal_temperament=self.equal_temperament,
                root_octave=self.root_octave,
                double_root=(self.double_root or bass))
            if bass:
                # Add the bass note to the bass track
                bass_events.extend([copy.copy(ev) for ev in chord_events[-1]])
            if bass and not self.double_root:
                # Remove the doubled root that we got for the bass line
                chord_events = sum(chord_events[:-1], [])
            # Add the main chord notes to the midi track
            for ev in chord_events:
                mid.add_event(ev)
            time += length

        if bass:
            bass_channel = 1
            # Add another track to the midi file for the bass notes
            mid.add_track()
            # Select a bass instrument - picked bass
            instr = ProgramChangeEvent()
            instr.value = 33
            instr.channel = bass_channel
            mid.add_event(instr)
            # Add all the bass notes
            for ev in bass_events:
                ev.channel = bass_channel
                mid.add_event(ev)
        return mid
Exemple #18
0
 def test_create_fraction(self):
     """ Simplest instantiation: fraction """
     f = Fraction(9, 10)
Exemple #19
0
 def test_neg(self):
     """ Try negating Fractions """
     f0 = Fraction(5, 7)
     self.assertEqual(-f0, Fraction(-5, 7))
     f1 = Fraction("5 4/5")
     self.assertEqual(-f1, Fraction("-5 4/5"))
Exemple #20
0
 def test_equal(self):
     """ Test that equal Fractions evaluate as equal """
     from random import randint
     for i in range(10):
         n = randint(0, 100)
         d = randint(1, 100)
         self.assertEqual(Fraction(n, d), Fraction(n, d))
     self.assertEqual(Fraction(50, 4), Fraction("12 1/2"))
     self.assertEqual(Fraction(50, 4), Fraction(25, 2))
     self.assertEqual(Fraction(7, 6), --Fraction(7, 6))
     f = Fraction(7, 19)
     self.assertEqual(f, f / Fraction(6, 17) * Fraction(12, 34))
Exemple #21
0
def path_to_tones(path, tempo=120, chord_types=None, root_octave=0, 
        double_root=False, equal_temperament=False, timings=False):
    """
    Takes a tonal space path, given as a list of coordinates, and 
    generates the tones of the roots.
    
    @type path: list of (3d-coordinate,length) tuples
    @param path: coordinates of the points in the sequence and the length 
        of each, in beats
    @type tempo: int
    @param tempo: speed in beats per second (Maelzel's metronome)
    @type chord_types: list of (string,length)
    @param chord_types: the type of chord to use for each tone and the 
        time spent on that chord type, in beats. See 
        L{CHORD_TYPES} keys for possible values.
    @type equal_temperament: bool
    @param equal_temperament: render all the pitches as they would be 
        played in equal temperament.
    @rtype: L{ToneMatrix}
    @return: a tone matrix that can be used to render the sound
    
    """
    # Use this envelope for all notes
    envelope = piano_envelope()
    
    sample_rate = DEFAULT_SAMPLE_RATE
    
    beat_length = 60.0 / tempo
    if timings:
        root_times = path
    else:
        # Work out when each root change occurs
        time = Fraction(0)
        root_times = []
        for root,length in path:
            root_times.append((root,time))
            time += length
    def _root_at_time(time):
        current_root = root_times[0][0]
        for root,rtime in root_times[1:]:
            # Move through root until we get the first one that 
            #  occurs after the previous time
            if rtime > time:
                return current_root
            current_root = root
        # If we're beyond the time of the last root, use that one
        return current_root
    
    if chord_types is None:
        # Default to just pure tones
        chord_types = [('prime',length) for __,length in path]
        
    if equal_temperament:
        _pitch_ratio = tonal_space_et_pitch
    else:
        _pitch_ratio = tonal_space_pitch_2d
    
    # Build the tone matrix by adding the tones one by one
    matrix = ToneMatrix(sample_rate=sample_rate)
    time = Fraction(0)
    for ctype,length in chord_types:
        coord = _root_at_time(time)
        pitch_ratio = _pitch_ratio(coord)
        duration = beat_length * float(length)
        # We want all enharmonic equivs of I to come out close to I, 
        #  not an octave above
        if not equal_temperament and coordinate_to_et_2d(coord) == 0 \
                and pitch_ratio > 1.5:
            pitch_ratio /= 2.0
        # Use a sine tone for each note
        tone = SineChordEvent(220*pitch_ratio, chord_type=ctype, duration=duration, envelope=envelope, root_octave=root_octave, root_weight=1.2, double_root=double_root)
        matrix.add_tone(beat_length * float(time), tone)
        time += length
    return matrix
Exemple #22
0
 def test_create_int(self):
     """ Simplest instantiation: int """
     f = Fraction(9)
     self.assertEqual(f, 9)