python自动演奏Freepiano【双手合奏】

news2024/11/23 8:24:55

文章编写背景

玩了N久的Freepiano,碍于本人没有天赋,左右手一直没法协调。
于是,突然奇想,也是代码设计的思路:

用多线程的方式,开两个线程,然后通过按键模拟的方式,分别模拟左右手去演奏。觉得可行,于是开干

依赖

import time
import pyautogui
import keyboard
from threading import Thread

大致分析

在这里插入图片描述

按键模拟

首先要研究按键模拟,就是获取所有键盘的Mapping值。然后发现很多坑:
1、部分依赖不支持小键盘(键盘最右边)
2、部分按键不能模拟(menu,right crtl等)
3、键盘上的按键是不一样的,但是他们的mapping值是一样的(home page up 等)

这时候需要分两步走,获取所有按键对应的mapping值,然后配置一个Mapping 常量,我们可以借助下面的片段:

import keyboard
# keyboard.press_and_release('num lock')  # 小键盘锁键
def on_key_press(event):
    print("按键:", event.name)

keyboard.on_press(on_key_press)
keyboard.wait()

运行后,任意按键会打印对应的Mapping值,这里注意的是小键盘的锁切换后会不一样
然后得到一个mapping常量(按自身实际配置):

left_hand_mapping = {
    '1': 'q',
    '111': '8',
    '2': 'w',
    "222": "9",
    '3': 'e',
    '33': '3',
    '4': 'r',
    '44': '4',
    '5': 't',
    '55': '5',
    '6': 'y',
    '66': '6',
    '7': 'u',
    '77': '7',
    'P': ' '
}

right_hand_mapping = {
    '1': 'end',
    '2': 'down',
    '3': 'pagedown',
    '333': 'alt',
    '4': 'left',
    '5': 'clear',
    '555': "f2",
    '6': 'right',
    '666': 'f1',
    '666#': 'backspace',
    '7': 'home',
    'P': ' '
}

综合上面的坑,要对freepiano进行键位修改,这里的思路是放弃小键盘的锁键,还有HOME等功能键,见下图:
在这里插入图片描述
PS:这里要注意新按键的通道,因为左右手的力度是不一样的。

线程模拟

开始编码模拟左右手,因为左右手的演奏速度是不一样的,所以这里要做区分。
左手按键与松开:

def play_left_hand(melody):
    for note in melody:
        if note == "-":
            time.sleep(stop_note)
        press_key(note, 'left')
        time.sleep(note_duration_left)
        release_key_left(note)

def release_key_left(note):
    if note in left_hand_mapping:
        keyboard.release(left_hand_mapping[note])

右手按键与松开:

def play_right_hand(melody):
    for note in melody:
        if note == "-":
            time.sleep(stop_note)
        press_key(note, 'right')
        time.sleep(note_duration_right)
        release_key_right(note)
def release_key_right(note):
    if note in right_hand_mapping:
        keyboard.release(right_hand_mapping[note])

按键方法:

def press_key(note, hand):
    if hand == 'left' and note in left_hand_mapping:
        left_hand_key = left_hand_mapping[note]
        keyboard.press(left_hand_key)

    if hand == 'right' and note in right_hand_mapping:
        right_hand_key = right_hand_mapping[note]
        keyboard.press(right_hand_key)

乐谱设计

这里是最重要的,这里我们用两个列表分别存左右手的音符。具体字符需要根据实际mapping值来设计

 left_hand_melody = ['33', '66', '77', '111', '-', '44', '66', '77', '111', '-', '55', '66', '222', '111', '77']
    right_hand_melody = ["666", "666", "666", "-", "666", "666#", "666#", "666#", "555", "555", "555", "-", "555",
                         "333", "333", "333", "333"]

这是一段某游戏登录前奏。乐谱地址:简谱

具体效果

效果不理想,休止音符和节奏没设计好,下版本更新。。。。
具体效果:

python演奏Freepiano(双手合奏)DEMO1


。TBD

完整代码

key_mapping.py:

left_hand_mapping = {
    '1': 'q',
    '111': '8',
    '2': 'w',
    "222": "9",
    '3': 'e',
    '33': '3',
    '4': 'r',
    '44': '4',
    '5': 't',
    '55': '5',
    '6': 'y',
    '66': '6',
    '7': 'u',
    '77': '7',
    'P': ' '
}

right_hand_mapping = {
    '1': 'end',
    '2': 'down',
    '3': 'pagedown',
    '333': 'alt',
    '4': 'left',
    '5': 'clear',
    '555': "f2",
    '6': 'right',
    '666': 'f1',
    '666#': 'backspace',
    '7': 'home',
    'P': ' '
}

piano.py

import time
import pyautogui
import keyboard
from threading import Thread
from key_mapping import *


def play_left_hand(melody):
    for note in melody:
        if note == "-":
            time.sleep(stop_note)
        press_key(note, 'left')
        time.sleep(note_duration_left)
        release_key_left(note)


def play_right_hand(melody):
    for note in melody:
        if note == "-":
            time.sleep(stop_note)
        press_key(note, 'right')
        time.sleep(note_duration_right)
        release_key_right(note)


def press_key(note, hand):
    if hand == 'left' and note in left_hand_mapping:
        left_hand_key = left_hand_mapping[note]
        keyboard.press(left_hand_key)

    if hand == 'right' and note in right_hand_mapping:
        right_hand_key = right_hand_mapping[note]
        keyboard.press(right_hand_key)


def release_key_left(note):
    if note in left_hand_mapping:
        keyboard.release(left_hand_mapping[note])


def release_key_right(note):
    if note in right_hand_mapping:
        keyboard.release(right_hand_mapping[note])


if __name__ == '__main__':
    repeat = True
    right_first = True
    left_hand_melody = ['33', '66', '77', '111', '-', '44', '66', '77', '111', '-', '55', '66', '222', '111', '77']
    right_hand_melody = ["666", "666", "666", "-", "666", "666#", "666#", "666#", "555", "555", "555", "-", "555",
                         "333", "333", "333", "333"]

    note_duration_left = 0.4  # 每个音符的持续时间(秒) 左手
    note_duration_right = 0.3  # 每个音符的持续时间(秒) 左手
    stop_note = 0.1  # 休止音符
    # 切换到FreePiano界面
    time.sleep(2)
    freepiano_window = pyautogui.getWindowsWithTitle("FreePiano")[0]
    freepiano_window.activate()
    # 简谱是否重复
    if repeat:
        left_hand_melody.append("-")
        left_hand_melody += left_hand_melody
        right_hand_melody.append("-")
        right_hand_melody += right_hand_melody
    # 启动左手伴奏和右手主旋律线程
    left_hand_thread = Thread(target=play_left_hand, args=(left_hand_melody,))
    right_hand_thread = Thread(target=play_right_hand, args=(right_hand_melody,))

    left_hand_thread.start()
    right_hand_thread.start()

    left_hand_thread.join()
    right_hand_thread.join()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/579889.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式网络通信框架(一)——集群和分布式

单机聊天服务器 缺点: 受限于硬件资源,服务器所能承受的用户并发量不够大; 任意模块修改,都会导致整个项目代码重新编译、部署; 系统中,有些模块是CPU密集型,有些是IO密集型,造成…

计算机网络五 传输层

传输层 概念 传输层是指ISO/OSI模型中的第四层,在计算机网络中起着非常重要的作用。它负责数据在网络中的传输,管理数据传输的可靠性和流量控制,保证数据在网络中不会丢失或重复。 提供的服务 传输层提供的主要服务有两种,分别…

《数据库应用系统实践》------ 包裹信息管理系统

系列文章 《数据库应用系统实践》------ 包裹信息管理系统 文章目录 系列文章一、需求分析1、系统背景2、 系统功能结构(需包含功能结构框图和模块说明)3.系统功能简介 二、概念模型设计1.基本要素(符号介绍说明&…

9. Linux下实现简单的UDP请求

本文简单介绍了UDP传输层协议,并在Linux下实现简单的socket通讯 一、UDP UDP(User Datagram Protocol,用户数据报协议)是一种无连接的传输层协议,它不保证数据包的可靠性和顺序。UDP在IP协议的基础上增加了简单的差错…

阿里云服务器配置CPU内存、带宽和系统盘选择方法

阿里云服务器配置怎么选择?CPU内存、公网带宽和系统盘怎么选择?个人用户选择轻量应用服务器或ECS通用算力型u1云服务器,企业用户选择ECS计算型c7、通用型g7云服务器,阿里云服务器网分享阿里云服务器配置选择方法: 目录…

大数据周会-本周学习内容总结015

开会时间:2023.05.28 15:30 线下会议 目录 01【fhzny项目】 02【Spark】 03【调研-数仓构建】 3.1【数仓构建,流程图、架构图、使用场景】 场景选择 组件设计 构建流程 04【专利】 05【导师点评】 01【fhzny项目】 GitLabMyBatis-PlusSpringbo…

Java001——基本的Dos命令

打开CMD的方式 1、win10:开始->系统->命令提示符 win11:开始->windows工具->命令提示符 2、Win键R输入cmd 打开控制台 3、进入文件夹,按住shift键鼠标右键点击,在此…

路径规划算法:基于萤火虫优化的路径规划算法- 附代码

路径规划算法:基于萤火虫优化的路径规划算法- 附代码 文章目录 路径规划算法:基于萤火虫优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要:本文主要介绍利用智能优化算法…

[第一章 web入门]SQL注入-1

拿到题目是一篇日记,是GET型请求方式,我们可以直接在url栏中注入数据 判断注入类型,页面有回显所以不是整型注入 id 1 and 1 2 id 1 页面无回显,判断为字符型注入,闭合符应该就是单引号 id 1 order by 4-- 无回显&…

C#,码海拾贝(26)——求解“一般带状线性方程组”之C#源代码,《C#数值计算算法编程》源代码升级改进版

using System; namespace Zhou.CSharp.Algorithm { /// <summary> /// 求解线性方程组的类 LEquations /// 原作 周长发 /// 改编 深度混淆 /// </summary> public static partial class LEquations { /// <summary> /…

Reorder buffer and Reservation station

Reoder buffer(ROB) 为了解决异常问题 instruction 的decode阶段被写入缓冲区的条目&#xff0c;指令完成的话&#xff0c;向缓冲区写入结果&#xff0c;最早decode的指令&#xff08;程序顺序&#xff09;如果没有被标记异常的话&#xff0c;写入reg file register rename …

基于STM32的IIC驱动协议实现

目录 1.简介 2.特点 3.协议细节 1.简介 IIC(Inter&#xff0d;Integrated Circuit)总线是一种由 PHILIPS 公司开发的两线式串行线&#xff0c;用于连接微控制器及其外围设备。它是由数据线 SDA 和时钟 SCL 构成的串行总线&#xff0c;可发送和接收数据。在 CPU 与被控 IC 之…

第一部分-基础篇-第一章:PSTN与VOIP(下篇)

文章目录 序言上一篇文章&#xff1a;1.6 电路交换与分组交换1.6.1 电路交换1.6.2 分组交换 1.7 VoIP1.8 IMS1.8.1 什么是IMS1.8.2 IMS的特点1.8.3 IMS核心网元&#xff08;1 &#xff09; CSCF&#xff08;2 &#xff09; MGCF&#xff08;3 &#xff09; IM-MGW&#xff08;5…

【数据结构】--单链表力扣面试题⑤链表分割

目录 一、有相对顺序的链表分割 二、无相对顺序的链表分割 一、有相对顺序的链表分割 题述&#xff1a;现有一链表的头指针ListNode* phead,给一定值x,编写一段代码将所有<x的结点排在其余结点之前&#xff0c;且不能改变原来的数据顺序&#xff0c;返回重新排序后的链表的…

Three.js加载FBX模型并解析骨骼动画

通过Threejs先加载一个.FBX格式的三维模型文件&#xff0c;然后解析该文件中的骨骼动画信息。 FBX 加载器FBXLoader.js <!-- 引入fbx模型加载库FBXLoader --> <script src"http://www.yanhuangxueyuan.com/versions/threejsR92/examples/js/loaders/FBXLoader.…

Linux源码包的安装与升级

文章目录 Linux源码包的安装与升级什么是源代码、编译器与可执行文件什么是函数库什么是make与configure什么是Tarball的软件如何安装与升级软件 Linux源码包的安装与升级 如果你想在自己的Linux服务器上运行网站&#xff0c;就需要安装一个Web服务器软件&#xff0c;否则无法…

测试工程师 | 测试基础知识点速查

文章目录 1. 测试介绍2. 测试的分类2.1 按照测试阶段划分&#xff08;4种&#xff09;2.2 按照代码可见度划分&#xff08;3种&#xff09;2.3 是否运行代码&#xff08;2种&#xff09;2.4 是否按照自动化&#xff08;2种&#xff09;2.5 其它测试&#xff08;4种&#xff09;…

深入篇【C++】CC++内存管理:new/delete底层原理剖析+思维导图总结

深入篇【C】C&C内存管理&#xff1a;new/delete底层原理剖析思维导图总结 Ⅰ.C/C内存分布Ⅱ.C的内存管理Ⅲ.C的内存管理①.new/delete操作内置类型总结&#xff1a; ②.new/delete操作自定义类型总结: ③.operator new与operator delete总结&#xff1a; ④.new/delete底层…

【C++String类使用】万字详解保姆级教学,手把手教你使用string类。

string类的使用 什么是string类&#xff1f;string构造string();string (const char* s);string (const string& str);string (const string& str, size_t pos, size_t len npos);string (const char* s, size_t n);string (size_t n, char c);template < class In…

《The Element of Style》阅读笔记 —— 章节 III A Few Matters of Form

前言&#xff1a;本篇为书籍《The Element of Style》第三章的阅读笔记。 本书电子版链接&#xff1a;http://www.jlakes.org/ch/web/The-elements-of-style.pdf 章节 I Elementary Rules of Usage 阅读笔记&#xff1a;链接章节 II Elementary Principles of Composition 阅读…