Интересный Python #13: играем "Имперский марш"

В прошлых постах было слишком много слов «работаем». Поэтому сегодняшний пост будет про то, как играть. Причём играть не что-то там, а музыку. Причём музыку не какую-то там, а «Имперский марш» из «Звёздных войн». Так что, товарищи Дарты Вейдеры, отвлекитесь на пару минут от удушения очередного офицера и насладитесь чудесными звуками.

Интересный Python #13: играем "Имперский марш" Python, Программирование, IT, Обучение, Star Wars, Имперский марш, Урок, Длиннопост

Для воспроизведения звуков будем использовать модуль winsound из стандартной библиотеки Python. Устанавливать ничего не нужно, он уже идёт в комплекте с интерпретатором.

В нём есть функция Beep(), с помощью которой можно воспроизвести звук заданной частоты и заданной длительности.


Важно: модуль работает только под Windows. Господа линуксоиды, сегодня вы в пролёте :(


Дальше в посте будет много кода в виде скриншотов. Забрать его в виде текста можно здесь.
Интересный Python #13: играем "Имперский марш" Python, Программирование, IT, Обучение, Star Wars, Имперский марш, Урок, Длиннопост

Также понадобится модуль time, с помощью которого будем создавать паузы.

Интересный Python #13: играем "Имперский марш" Python, Программирование, IT, Обучение, Star Wars, Имперский марш, Урок, Длиннопост

Каждой ноте соответствует определённая частота звука, выраженная в герцах. Таблицу можно увидеть здесь или здесь.


Составим список необходимых нот:

Интересный Python #13: играем "Имперский марш" Python, Программирование, IT, Обучение, Star Wars, Имперский марш, Урок, Длиннопост

Ключ - это название ноты, а значение - это частота.

Запишем мелодию в виде набора нот.

Интересный Python #13: играем "Имперский марш" Python, Программирование, IT, Обучение, Star Wars, Имперский марш, Урок, Длиннопост

1/4, 3/16 и прочее - это длительность каждой ноты.

Интересный Python #13: играем "Имперский марш" Python, Программирование, IT, Обучение, Star Wars, Имперский марш, Урок, Длиннопост

Нам понадобятся 2 функции: одна для воспроизведения конкретной ноты, а вторая - для воспроизведения всей мелодии.

Воспроизводим ноту

Интересный Python #13: играем "Имперский марш" Python, Программирование, IT, Обучение, Star Wars, Имперский марш, Урок, Длиннопост

Воспроизводим мелодию

Интересный Python #13: играем "Имперский марш" Python, Программирование, IT, Обучение, Star Wars, Имперский марш, Урок, Длиннопост

Наслаждаемся результатами

Оригинальный темп мелодии - 103 BPM.

Интересный Python #13: играем "Имперский марш" Python, Программирование, IT, Обучение, Star Wars, Имперский марш, Урок, Длиннопост

Забрать полный код в текстовом виде можно здесь.

Программирование на python

686 постов11.9K подписчиков

Правила сообщества

Публиковать могут пользователи с любым рейтингом. Однако!


Приветствуется:

• уважение к читателям и авторам

• конструктивность комментариев

• простота и информативность повествования

• тег python2 или python3, если актуально

• код публиковать в виде цитаты, либо ссылкой на специализированный сайт


Не рекомендуется:

• допускать оскорбления и провокации

• распространять вредоносное ПО

• просить решить вашу полноценную задачу за вас

• нарушать правила Пикабу

1
Автор поста оценил этот комментарий

Код картинками, боже ж ты мой.

раскрыть ветку (1)
3
Автор поста оценил этот комментарий

На Пикабу можно выкладывать код не картинками, я чего-то не знаю?)


А вообще в самом начале и в самом конце поста написано: "Код в виде текста можно забрать ЗДЕСЬ". В самом начале даже цитатой выделил, чтобы заметнее было.

показать ответы
2
Автор поста оценил этот комментарий

Здравствуйте, такая проблема, решил послушать через пайчарм, и звуки как-то отрывками воспроизводятся. Поначалу вроде похоже на имперский марш, а потом и вовсе мелодия теряется. Где-то как-будто бы пропуски нот идут, непонятно(

раскрыть ветку (1)
2
Автор поста оценил этот комментарий

Кстати, ещё вариант: код целиком скопировали, элементы кортежа нигде не потеряли?

показать ответы
2
Автор поста оценил этот комментарий

Здравствуйте, такая проблема, решил послушать через пайчарм, и звуки как-то отрывками воспроизводятся. Поначалу вроде похоже на имперский марш, а потом и вовсе мелодия теряется. Где-то как-будто бы пропуски нот идут, непонятно(

раскрыть ветку (1)
2
Автор поста оценил этот комментарий

Здравствуйте) Сложно сказать, может быть, где-то дебаггер тормозит выполнение или ещё что-нибудь. Попробуйте через терминал запустить, без лишних обвесов: python [путь_к_файлу].py

2
Автор поста оценил этот комментарий
*режим душнилы on* марш имперский, а штурмовик на картинке из Первого ордена - постимперский.
*режим душнилы off*
раскрыть ветку (1)
2
Автор поста оценил этот комментарий

*душит душнилу, хрипло посвистывая сквозь маску*

1
Автор поста оценил этот комментарий
Так его ещё и запускать как то надо? 😂 Я ж не программист)
раскрыть ветку (1)
1
Автор поста оценил этот комментарий

Ну да) Это же пост в сообществе "Программирование на Python" из серии "Изучаем интересные возможности языка программирования Python".

2
DELETED
Автор поста оценил этот комментарий

Офигеть! Дайте две!


Каждый раз поражаюсь сколько гитик умеет Питон "из коробки".


Хотя, казалось бы, зачем это ему?

Ну пусть будет, прикольно.


Вопрос появился, но не питоновский.

# Не будем слишком подробно останавливаться

# на механике перевода BPM в миллисекунды

duration = int(value * 4 * 1000 * (60 / bpm))

Реквестирую подробности по поводу длительности.

Ведь если нота целая, то она и длится один такт, то есть 1 Beat, который Per Second, разве не так?

И тогда умножение на 4 вроде бы и не нужно. А так получается мы из четвертных целые делаем?

В музыкальной теории нерюх, прошу понять и простить.


Буду благодарен за разъяснения.

раскрыть ветку (1)
1
Автор поста оценил этот комментарий
Реквестирую подробности по поводу длительности.

Там всё чуть сложнее. Всё музыкальное произведение разделяется на такты, а один из самых распространённых размеров такта - это 4/4. В том числе, в таком размере написан и "Имперский марш":


Соответственно, 1 такт = 4 бита.


Для работы с другими размерами такта нужно модифицировать функцию play_melody, но это и код бы усложнило (+1 аргумент и соответствующая логика в теле), и ненужные вопросы за собой повлекло. Так что решил использовать 4\4 по умолчанию, благо в подавляющем большинстве случаев именно он и используется)

Иллюстрация к комментарию
показать ответы
Автор поста оценил этот комментарий

>"Код в виде текста можно забрать ЗДЕСЬ"

Не заметил, лол.

раскрыть ветку (1)
1
Автор поста оценил этот комментарий
Shit happens)
1
Автор поста оценил этот комментарий

Классно пропикало :)

А "Мурку" так сможешь? :)

раскрыть ветку (1)
1
Автор поста оценил этот комментарий

Вообще без проблем, там несложная мелодия)

Иллюстрация к комментарию
показать ответы
2
Автор поста оценил этот комментарий

судя по всему этот модуль для винды.

раскрыть ветку (1)
1
Автор поста оценил этот комментарий

Да, забыл это указать. Добавил информацию в начало поста, спасибо за подсказку.

2
Автор поста оценил этот комментарий

С козырей решили зайти ))

раскрыть ветку (1)
1
Автор поста оценил этот комментарий

21-й пост, пора бы и козыри выложить :)

показать ответы
1
DELETED
Автор поста оценил этот комментарий

Все просто: я Питон знаю очень плохо, и первое, что приходит в голову -- это RuntimeError.

В какой-то момент вспомнил, что вроде есть более подходящий ValueError, но исправить в остальных местах забыл.

раскрыть ветку (1)
Автор поста оценил этот комментарий

Понял, спасибо)

1
DELETED
Автор поста оценил этот комментарий

Пара исправлений:

https://www.online-python.com/GMn6aveDKL

раскрыть ветку (1)
Автор поста оценил этот комментарий

Солидно! :)


Кстати, интересно стало: а почему бросаете именно `RuntimeError` в `get_note_frequency()`? Понимаю, что проект игрушечный, но всё же ждал здесь `ValueError`, а оно вот как получилось. Если это не опечатка, а осознанный выбор, то расскажите, пожалуйста, почему так?

показать ответы
1
Автор поста оценил этот комментарий
Блин, я стойко читал то, в чем понял едва ли четверть. Не понял где можно прослушать и пришлось прочесть ещё раз. Но прослушать у меня так и не вышло. Чувствую себя обманутым)
раскрыть ветку (1)
Автор поста оценил этот комментарий

Не совсем понял - код не запустился или что?

показать ответы