he `quarterLengthDivisors` provides a flexible way to provide quantization
settings. For example, (2,) will snap all events to eighth note grid.
(4, 3) will snap events to sixteenth notes and eighth note triplets,
whichever is closer. (4, 6) will snap events to sixteenth notes and
sixteenth note triplets.  If quarterLengthDivisors is not specified then
defaults.quantizationQuarterLengthDivisors is used.  The default is (4, 3).

`processOffsets` determines whether the Offsets are quantized.

`processDurations` determines whether the Durations are quantized.

Both are set to True by default.  Setting both to False does nothing to the Stream.

if `inPlace` is True, then the quantization is done on the Stream itself.  If False
(default) then a new quantized Stream of the same class is returned.

If `recurse` is True, then all substreams are also quantized.
If False (default), then only the highest level of the Stream is quantized.

* Changed in v7:
   - `recurse` defaults False
   - look-ahead approach to choosing divisors to avoid gaps when processing durations

>>> n = note.Note()
>>> n.quarterLength = 0.49
>>> s = stream.Stream()
>>> s.repeatInsert(n, [0.1, 0.49, 0.9])
>>> nShort = note.Note()
>>> nShort.quarterLength = 0.26
>>> s.repeatInsert(nShort, [1.49, 1.76])

>>> s.quantize((4,), processOffsets=True, processDurations=True, inPlace=True)
>>> [e.offset for e in s]
[0.0, 0.5, 1.0, 1.5, 1.75]
>>> [e.duration.quarterLength for e in s]
[0.5, 0.5, 0.5, 0.25, 0.25]

The error in quantization is set in the editorial attribute for the note in
two places `.offsetQuantizationError` and `.quarterLengthQuantizationError`:

>>> [e.editorial.offsetQuantizationError for e in s.notes]
[0.1, -0.01, -0.1, -0.01, 0.01]
>>> [e.editorial.quarterLengthQuantizationError for e in s.notes]
[-0.01, -0.01, -0.01, 0.01, 0.01]

With default quarterLengthDivisors:

>>> s = stream.Stream()
>>> s.repeatInsert(n, [0.1, 0.49, 0.9])
>>> nShort = note.Note()
>>> nShort.quarterLength = 0.26
>>> s.repeatInsert(nShort, [1.49, 1.76])
>>> quantized = s.quantize(processOffsets=True, processDurations=True, inPlace=False)
>>> [e.offset for e in quantized]
[0.0, 0.5, 1.0, 1.5, 1.75]
>>> [e.duration.quarterLength for e in quantized]
[0.5, 0.5, 0.5, 0.25, 0.25]

Set `recurse=True` to quantize elements in substreams such as parts, measures, voices:

>>> myPart = converter.parse('tinynotation: c32 d32 e32 f32')
>>> myPart.quantize(inPlace=True)
>>> [e.offset for e in myPart.measure(1).notes]  # no change!
[0.0, 0.125, 0.25, 0.375]

>>> myPart.quantize(inPlace=True, recurse=True)
>>> [e.offset for e in myPart.measure(1).notes]
[0.0, 0.0, 0.25, Fraction(1, 3)]

* New in v7: if both `processDurations` and `processOffsets` are True, then
  the next note's quantized offset is taken into account when quantizing the
  duration of the current note. This is to prevent unnecessary gaps from applying
  different quantization units to adjacent notes:

>>> s2 = stream.Stream()
>>> nOddLength = note.Note(quarterLength=0.385)
>>> s2.repeatInsert(nOddLength, [0, 0.5, 1, 1.5])
>>> s2.show('t', addEndTimes=True)
    {0.0 - 0.385} <music21.note.Note C>
    {0.5 - 0.885} <music21.note.Note C>
    {1.0 - 1.385} <music21.note.Note C>
    {1.5 - 1.885} <music21.note.Note C>

Before v.7, this would have yielded four triplet-eighths (separated by 1/6 QL rests):

>>> s2.quantize(processOffsets=True, processDurations=True, inPlace=True)
>>> s2.show('text', addEndTimes=True)
    {0.0 - 0.5} <music21.note.Note C>
    {0.5 - 1.0} <music21.note.Note C>
    {1.0 - 1.5} <music21.note.Note C>
    {1.5 - 1.8333} <music21.note.Note C>

OMIT_FROM_DOCS

Test changing defaults, running, and changing back:

>>> dd = defaults.quantizationQuarterLengthDivisors
>>> defaults.quantizationQuarterLengthDivisors = (3,)

>>> u = s.quantize(processOffsets=True, processDurations=True, inPlace=False)
>>> [e.offset for e in u]
[0.0, Fraction(1, 3), 1.0, Fraction(4, 3), Fraction(5, 3)]
>>> [e.duration.quarterLength for e in u]
[Fraction(1, 3), Fraction(1, 3), Fraction(1, 3), Fraction(1, 3), Fraction(1, 3)]

Original unchanged because inPlace=False:

>>> [e.offset for e in s]
[Fraction(1, 10), Fraction(49, 100), Fraction(9, 10), Fraction(149, 100), Fraction(44, 25)]

>>> defaults.quantizationQuarterLengthDivisors = dd
>>> v = s.quantize(processOffsets=True, processDurations=True, inPlace=False)
>>> [e.offset for e in v]
[0.0, 0.5, 1.0, 1.5, 1.75]
>>> [e.duration.quarterLength for e in v]
[0.5, 0.5, 0.5, 0.25, 0.25]
Tc