Эксперимент 23. Темп, длительность и паузы

Если в прошлом эксперименте ты попробовал выполнить дополнительное задание и записать мелодию, то, вероятно, понял, что это не просто, учитывая, что нужно описывать и ноты и их длительности и паузы между ними. А если после написания такой мелодии потребуется изменить ее темп, то придется пересчитывать все паузы. Должен быть другой, более удобный способ записывать мелодии.

Для этого запишем мелодию, последовательность ее нот, в массив, а длительности этих нот в другой. С помощью оператора цикла будем получать эти данные и исполнять. Для записи темпа заведем отдельную переменную, которая будет учитываться в расчете длительностей.

Схема эксперимента

Схему эксперимента оставим прежней, займемся программой.

Рисунок 1. Электрическая принципиальная схема эксперимента

Рисунок 2. Монтажная схема эксперимента

Программный код эксперимента

Exp23.py
  1. from machine import Pin, PWM
  2. import time
  3. _init()
  4.  
  5. tempo = 2
  6.  
  7. tones = {
  8. 'c': 262,
  9. 'd': 294,
  10. 'e': 330,
  11. 'f': 349,
  12. 'g': 392,
  13. 'a': 440,
  14. 'b': 494,
  15. 'C': 523
  16. }
  17.  
  18. speaker = PWM(Pin(15, Pin.OUT))
  19.  
  20. melody = 'abcdefgC'
  21. rhythm = [8, 2, 1, 8, 3, 4, 6, 8]
  22.  
  23. for tone, length in zip(melody, rhythm):
  24. speaker.duty(512)
  25. speaker.freq(tones[tone])
  26. time.sleep(tempo/length)
  27. speaker.duty(0)
  28. time.sleep(tempo/length/4)

Мелодию мы записали строкой abcdefgC, а ритм массивом [8, 2, 1, 8, 3, 4, 6, 8]. С помощью цикла for и оператора in проходим по всем элементам мелодии. Для этого мы использовали оператор zip. Он нужен для одновременного перебора сразу двух массивов и получения их элементов в переменные tone и length. Так на первой итерации в переменной tone окажется a, а в length8. На второй итерации b и 2 соответственно.

Здесь внимательный читатель заметит, что melody не является массивом, а является строкой. Почему же мы говорим о ней как о массиве и работаем как с массивом. Оказывается в Python любую строку можно представить как массив символов и обращаться к ним по индексу, что мы и делаем.

Получив ноту и ее длительность настраиваем частоту и скважность. Нота начинает звучать:

  1. speaker.duty(512)
  2. speaker.freq(tones[tone])

Нота звучит, пока мы ждем время, равное ее длительности. В расчете учитывается темп:

  1. time.sleep(tempo/length)

Чтобы ноты не сливались, мы делаем между ними маленькие паузы. Паузы между нотами также зависят от темпа и длительности ноты, но в 4 раза короче.

  1. speaker.duty(0)
  2. time.sleep(tempo/length/4)

Дополнительное задание

  • Измени темп мелодии и длительности отдельных нот.