Source code for birdears.prequestion
"""This module implements pre-questions' progressions.
Pre questions are chord progressions or notes played before the question is
played, so to affirmate the sound of the question's key.
For example a common cadence is chords I-IV-V-I from the diatonic scale, which
in a key of `C` is `CM-FM-GM-CM` and in a key of `A` is `AM-DM-EM-AM`.
Pre-question methods should be decorated with `register_prequestion_method`
decorator, so that they will be registered as a valid pre-question method.
"""
from .sequence import Sequence
from functools import wraps
PREQUESTION_METHODS = {}
# http://stackoverflow.com/questions/5910703/howto-get-all-methods-of-a-pyt\
# hon-class-with-given-decorator
# http://stackoverflow.com/questions/5707589/calling-functions-by-array-ind\
# ex-in-python/5707605#5707605
[docs]def register_prequestion_method(f, *args, **kwargs):
"""Decorator for prequestion method functions.
Functions decorated with this decorator will be registered in the
`PREQUESTION_METHODS` global dict.
"""
@wraps(f)
def decorator(*args, **kwargs):
return f(*args, **kwargs)
PREQUESTION_METHODS.update({f.__name__: f})
return decorator
[docs]class PreQuestion:
def __init__(self, method, question):
"""This class implements methods for different types of pre-question
progressions.
Args:
method (str): The method used in the pre question.
question (obj): Question object from which to generate the
pre-question sequence.
"""
self.METHOD = PREQUESTION_METHODS[method]
self.question = question
def __call__(self, *args, **kwargs):
"""Calls the resolution method and pass arguments to it.
Returns a `birdears.Sequence` object with the pre-question generated by
the method.
"""
return self.METHOD(question=self.question, *args, **kwargs)
[docs]@register_prequestion_method
def none(question, *args, **kwargs):
"""Pre-question method that return an empty sequence with no delay.
Args:
question (obj): Question object from which to generate the
pre-question sequence. (this is provided by the `Resolution` class
when it is `__call__`ed)
"""
return Sequence(elements=[], duration=0, delay=0, pos_delay=0)
[docs]@register_prequestion_method
def tonic_only(question, *args, **kwargs):
"""Pre-question method that only play's the question tonic note before the
question.
Args:
question (object): Question object from which to generate the
pre-question sequence. (this is provided by the `Resolution` class
when it is `__call__`ed)
"""
tonic_pitch = question.tonic_pitch
duration = question.durations['preq']['duration']
delay = question.durations['preq']['delay']
pos_delay = question.durations['preq']['pos_delay']
sequence = Sequence(elements=[tonic_pitch], duration=duration,
delay=delay, pos_delay=pos_delay)
return sequence
[docs]@register_prequestion_method
def progression_i_iv_v_i(question, *args, **kwargs):
"""Pre-question method that play's a chord progression with triad chords
built on the grades I, IV, V the I of the question key.
Args:
question (obj): Question object from which to generate the
pre-question sequence. (this is provided by the `Resolution` class
when it is `__call__`ed)
"""
# tonic_pitch = question.tonic_pitch
# is_scale_descending = question
tonic_index = 0 if not question.scale.is_descending else -1
tonic_pitch = question.scale[tonic_index]
mode = question.mode
duration = question.durations['preq']['duration']
delay = question.durations['preq']['delay']
pos_delay = question.durations['preq']['pos_delay']
degrees = [1, 4, 5, 1]
sequence = Sequence(duration=duration, delay=delay,
pos_delay=pos_delay)
sequence.make_chord_progression(tonic_pitch=tonic_pitch, mode=mode,
degrees=degrees)
return sequence