Тема 6 из 6

Звук и заставка

Звук и музыка

music = pyglet.media.load("music.ogg")                    # длинный файл читается с диска по частям
shot = pyglet.media.load("shot.wav", streaming=False)     # короткий эффект — целиком в памяти

shot.play()                         # сыграть эффект (можно много раз подряд)

player = pyglet.media.Player()
player.queue(music)                 # поставить в очередь
player.play()
player.pause()
player.volume = 0.5                 # от 0.0 (тишина) до 1.0
print(player.time)                  # сколько секунд уже играет
player.loop = True                  # повторять текущий трек
player.next_source()                # перейти к следующему в очереди

WAV pyglet читает сам; для MP3 и OGG использует кодеки системы или установленный FFmpeg.

Звук можно и синтезировать — без файлов:

from pyglet.media import synthesis

beep = synthesis.Sine(0.1, 880)      # синусоида 880 Гц длиной 0.1 секунды
beep.play()

В задачах курса используется именно синтез — так программы работают без скачивания музыки.

Такт

Темп музыки задают в BPM — ударах в минуту. Зная темп, анимацию можно привязать к музыке:

beats = t * BPM / 60         # сколько ударов прошло с начала (дробное число)
beat = int(beats)            # номер текущего удара
phase = beats - beat         # доля текущего удара: от 0 до 1
flash = 1 - phase            # вспышка в момент удара, потом гаснет

Время t лучше брать из player.time — тогда анимация не разъедется со звуком, даже если программа подтормозит.

Сцены

Заставку собирают из сцен, идущих одна за другой. Зная длительности сцен, по общему времени находят текущую сцену и время внутри неё — дальше каждая сцена анимирует свои объекты по своему прогрессу (из прошлой темы).

На границе сцен важно решить, какая сцена «главнее». Обычно — следующая: в момент 2.0 первая сцена уже кончилась, а вторая только началась.

Плейлист

Несколько треков подряд — та же задача, что и сцены. Добавляются две вещи:

  • повтор: t %= total — остаток от деления на общую длину;
  • затухание: громкость плавно растёт в начале трека и падает в конце, чтобы треки не обрывались.

Итог

  • pyglet.media.load, streaming=False для эффектов, Player: queue, play, pause, volume, time;
  • pyglet.media.synthesis.Sine(длительность, частота) — звук без файла;
  • удар int(t * BPM / 60), вспышка 1 - доля;
  • сцены и треки подряд: найти текущий по накопленному времени; повтор — %; затухание — min(1, pos / fade, (length - pos) / fade).

Вы собрали все части заставки: фигуры, время, управление, плавность и музыку. Попробуйте объединить их в одной программе — например, логотип из первой темы, который проявляется и пульсирует в такт.