迎接2023,用JAVA演奏“新年”

news2024/11/15 4:29:52

😊你好,我是小航,一个正在变秃、变强的文艺倾年。
🔔2023年快要到来啦,再此祝大家诸事顺遂,所见所盼皆如愿。
🔔本文讲解如何使用Java演奏一首歌曲,一起卷起来叭!
在这里插入图片描述

众所周知,语言=算法+数据结构,那么音乐=曲谱+音质,曲谱定义了音的高低、长短,力度,我们常常又根据这些对歌曲常分为主奏和伴奏。因为一切皆文件嘛,凭借这些规则,我们通过编程将曲谱读取得到对应的音符的高低、长短、力度,然后依次调用音质文件,最后组成音乐。

先上视频演示,代码在文末:

演奏视频


目录

    • 1、音质
    • 2、编写主奏、伴奏曲谱
    • 3、编写项目

1、音质

主奏与伴奏中支持输入的35个音符:
“1–” ~ “7–”, “1-” ~ “7-”, “1” ~ “7”, “1+” ~ “7+”, “1++” ~ “7++” 分别代表倍低音、低音、中音、高音、倍高音一共35个音符

这里我们提前找到对应的音(音色可以自己找,上网一搜八十八个高音音频即可):

在这里插入图片描述

2、编写主奏、伴奏曲谱

2、分别在主奏(.note)与伴奏(.accompaniments)中输入需要自动弹奏的音符,定义规则如下:

  • 每个音符之间用空格隔开(任意多个空格,推荐每个音符包括空格共占用4个占位符,以便主奏和伴奏音符对齐)

  • 输入字符"0",则会使音长额外延长一倍;

  • 输入除了上面35个音符以及“0”以外的任意字符不会对弹奏起任何作用;

  • 如果需要换行填写,则需在上一行的末尾以及下一行的开头都加上空格;

  • 音长里输入每两个音符之间的间隔时长,单位是毫秒(ms)

这里我找了一份蜜雪冰城的谱子:
在这里插入图片描述
然后将它转化为咱们的规则:
主旋律:

 0     0 3+ 4+ 
 5+ 0 5+ 0 5+   0 0   6+ 
 5+ 0 3+ 0 1+   0 1+ 2+ 
 3+ 0 3+ 0 2+   0 2+ 0 
 1+ 0 0   0 1++ 0 0   0 

 3+ 0 5+ 0 5+ 0 0 6+ 
 5+ 0 3+ 0 1+ 0 1+ 2+ 
 3+ 0 3+ 0 2+ 0 1+ 0 
 2+ 0 0 0 0 0 0 0 

 3+ 0 5+ 0 5+ 0 0 6+ 
 5+ 0 3+ 0 1+ 0 1+ 2+ 
 3+ 0 3+ 0 2+ 0 2+ 0 
 1+ 0 0 0 0 0 0 0 

 4+ 0 0 0 4+ 0 0 0 
 4+ 0 6+ 0 0 0 0 0 
 5+ 0 0 0 5+ 0 3+ 0 
 2+ 0 0 0 0 0 0 0 

 3+ 0 5+ 0 5+ 0 0 6+ 
 5+ 0 3+ 0 1+ 0 1+ 2+ 
 3+ 0 3+ 0 2+ 0 2+ 0 
 1+ 0 0 0 0 0 0 0 

伴奏:

 0   0 0  0 
 1- 0 3- 0 1-  0 3- 0 
 1- 0 3- 0 1-  0 3- 0 
 1- 0 3- 0 5-- 0 2- 0 
 1- 0 3- 0 3-  0 0 0 

 1- 0 3- 0 1-  0 3- 0 
 1- 0 3- 0 1-  0 3- 0 
 1- 0 3- 0 1-  0 3- 0 
 5-- 0 2- 0 5-- 0 2- 0 

 1- 0 3- 0 1-  0 3- 0 
 1- 0 3- 0 1-  0 3- 0 
 1- 0 3- 0 5-- 0 2- 0 
 1- 0 3- 0 1- 0 3- 0 

 4-- 0 1- 0 4-- 0 1- 0 
 4-- 0 1- 0 4-- 0 1- 0 
 1- 0 3- 0 1- 0 3- 0 
 5-- 0 2- 0 5-- 0 2- 0 

 1- 0 3- 0 1- 0 3- 0 
 1- 0 3- 0 1- 0 3- 0 
 1- 0 3- 0 5-- 0 2- 0 
 1- 0 3- 0 1++ 0 0 0 

3、编写项目

我们新建Maven项目并将上述文件分别放到resoucres目录下:
在这里插入图片描述
导入需要的依赖:

		<dependency>
            <groupId>javazoom</groupId>
            <artifactId>jlayer</artifactId>
            <version>1.0.1</version>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-core</artifactId>
            <version>5.6.5</version>
        </dependency>

编写启动类,类名叫Happpy叭:

public class Happy {
    public static void main(String[] args) {
        String musicName = "蜜雪冰城";
        FileUtils.play(musicName);
    }
}

编写FileUtils(实现读取曲谱的功能)

public class FileUtils {
    static void play(String musicName) {
        System.out.println("载入歌曲:" + musicName);
        String path =
                new File("").getAbsolutePath() + File.separator + "src/main/resources/notes" + File.separator;
        String notesPath = path + musicName +  ".notes";
        String accompanimentsPath = path + musicName +  ".accompaniments";
        String notes = fileToStr(notesPath);
        String accompaniments = fileToStr(accompanimentsPath);
        new AudioPlay(180).loadNotes(notes).start();
        new AudioPlay(180).loadNotes(accompaniments).start();
        new Animation(180).loadNotes(notes).start();
    }

    static String fileToStr(String musicPath) {
        StringBuilder stringBuilder = new StringBuilder();
        try {
            BufferedReader reader = new BufferedReader(new FileReader(musicPath));
            String line = null;
            String ls = System.getProperty("line.separator");
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line);
                stringBuilder.append(ls);
            }
            // 删除最后一个新行分隔符
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            reader.close();
        } catch (Exception ignored) {}
        return stringBuilder.toString();
    }
}

规则编写:
新建AudioPlay类,将每个音符对应每个读取到的字符:

package com.example.demo.play;

import cn.hutool.core.io.FileUtil;

/**
 * @author xh
 * @Date 2022/12/27
 */
public class AudioPlay extends Thread{
    /** 音符 */
    private String[] notes;
    /** 间隔时间(单位:毫秒) */
    private int times;


    public AudioPlay(String[] notes, int times)
    {
        this.notes = notes;
        this.times = times;
    }

    public AudioPlay(String filePath, int times)
    {
        String content = FileUtil.readString(filePath,"UTF-8");
        this.notes = content.split(" ");
        this.times = times;
    }

    public AudioPlay(int times)
    {
        this.times = times;
    }


    public String[] getNotes()
    {
        return this.notes;
    }


    public void setNotes(String[] notes)
    {
        this.notes = notes;
    }
    public AudioPlay loadNotes(String notes)
    {
        this.notes = notes.split(" ");
        return this;
    }


    public int getTimes()
    {
        return this.times;
    }


    public void setTimes(int times)
    {
        this.times = times;
    }


    @Override
    public void run()
    {
        try
        {
            int times = this.times;
            new Audio("audio/test.mp3").start();
            sleep(1000);
            for (String note : notes) {
                if (note.length() < 1) {
                    continue;
                }
                switch (note) {
                    case "1--":
                        new Audio("audio/ll1.mp3").start();
                        sleep(times / 2);
                        break;
                    case "2--":
                        new Audio("audio/ll2.mp3").start();
                        sleep(times / 2);
                        break;
                    case "3--":
                        new Audio("audio/ll3.mp3").start();
                        sleep(times / 2);
                        break;
                    case "4--":
                        new Audio("audio/ll4.mp3").start();
                        sleep(times / 2);
                        break;
                    case "5--":
                        new Audio("audio/ll5.mp3").start();
                        sleep(times / 2);
                        break;
                    case "6--":
                        new Audio("audio/ll6.mp3").start();
                        sleep(times / 2);
                        break;
                    case "7--":
                        new Audio("audio/ll7.mp3").start();
                        sleep(times / 2);
                        break;
                    case "1-":
                        new Audio("audio/l1.mp3").start();
                        sleep(times / 2);
                        break;
                    case "2-":
                        new Audio("audio/l2.mp3").start();
                        sleep(times / 2);
                        break;
                    case "3-":
                        new Audio("audio/l3.mp3").start();
                        sleep(times / 2);
                        break;
                    case "4-":
                        new Audio("audio/l4.mp3").start();
                        sleep(times / 2);
                        break;
                    case "5-":
                        new Audio("audio/l5.mp3").start();
                        sleep(times / 2);
                        break;
                    case "6-":
                        new Audio("audio/l6.mp3").start();
                        sleep(times / 2);
                        break;
                    case "7-":
                        new Audio("audio/l7.mp3").start();
                        sleep(times / 2);
                        break;
                    case "1":
                        new Audio("audio/m1.mp3").start();
                        sleep(times / 2);
                        break;
                    case "2":
                        new Audio("audio/m2.mp3").start();
                        sleep(times / 2);
                        break;
                    case "3":
                        new Audio("audio/m3.mp3").start();
                        sleep(times / 2);
                        break;
                    case "4":
                        new Audio("audio/m4.mp3").start();
                        sleep(times / 2);
                        break;
                    case "5":
                        new Audio("audio/m5.mp3").start();
                        sleep(times / 2);
                        break;
                    case "6":
                        new Audio("audio/m6.mp3").start();
                        sleep(times / 2);
                        break;
                    case "7":
                        new Audio("audio/m7.mp3").start();
                        sleep(times / 2);
                        break;
                    case "1+":
                        new Audio("audio/h1.mp3").start();
                        sleep(times / 2);
                        break;
                    case "2+":
                        new Audio("audio/h2.mp3").start();
                        sleep(times / 2);
                        break;
                    case "3+":
                        new Audio("audio/h3.mp3").start();
                        sleep(times / 2);
                        break;
                    case "4+":
                        new Audio("audio/h4.mp3").start();
                        sleep(times / 2);
                        break;
                    case "5+":
                        new Audio("audio/h5.mp3").start();
                        sleep(times / 2);
                        break;
                    case "6+":
                        new Audio("audio/h6.mp3").start();
                        sleep(times / 2);
                        break;
                    case "7+":
                        new Audio("audio/h7.mp3").start();
                        sleep(times / 2);
                        break;
                    case "1++":
                        new Audio("audio/hh1.mp3").start();
                        sleep(times / 2);
                        break;
                    case "2++":
                        new Audio("audio/hh2.mp3").start();
                        sleep(times / 2);
                        break;
                    case "3++":
                        new Audio("audio/hh3.mp3").start();
                        sleep(times / 2);
                        break;
                    case "4++":
                        new Audio("audio/hh4.mp3").start();
                        sleep(times / 2);
                        break;
                    case "5++":
                        new Audio("audio/hh5.mp3").start();
                        sleep(times / 2);
                        break;
                    case "6++":
                        new Audio("audio/hh6.mp3").start();
                        sleep(times / 2);
                        break;
                    case "7++":
                        new Audio("audio/hh7.mp3").start();
                        sleep(times / 2);
                        break;
                    case "0":
                        sleep(times / 2);
                        break;
                    default:
                        continue;
                }
                sleep(times / 2);
                times = this.times;
            }

        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }

    }

}

读取曲谱文件并打印曲谱:

package com.example.demo.play;

/**
 * @author xh
 * @Date 2022/12/27
 */
public class Animation extends Thread{
    /** 音符 */
    private String[] notes;
    /** 间隔时间(单位:毫秒) */
    private int times;

    public Animation(int times) {
        this.times = times;
    }

    public Animation(String[] notes, int times) {
        this.notes = notes;
        this.times = times;
    }

    public String[] getNotes() {
        return this.notes;
    }

    public void setNotes(String[] notes) {
        this.notes = notes;
    }

    public int getTimes() {
        return this.times;
    }

    public void setTimes(int times) {
        this.times = times;
    }

    public Animation loadNotes(String notes) {
        this.notes = notes.split(" ");
        return this;
    }

    @Override
    public void run() {
        try {
            int times = this.times;
            new Audio("audio/test.mp3").start();
            sleep(1000);
            int no = 1;
            for (String note : this.notes) {
                if (note.length() < 1) {
                    continue;
                }
                // 3+ 0 3+ 3+ 3+ 3+ 0 3+ 3+ 3+ 4+ 2+ 0 2+ 2+ 2+ 2+ 0 2+ 2+ 2+ 3+ 1+
                String n = note.replace("+", "").replace("-", "");
                if ("\n".equals(n) || "\r".equals(n) || "\r\n".equals(n)) {
                    System.out.print("\n");
                    no++;
                    continue;
                }
                switch (n) {
                    case "0":
                        System.out.print("_");
                        break;
                    case "1":
                        System.out.print("▁");
                        break;
                    case "2":
                        System.out.print("▂");
                        break;
                    case "3":
                        System.out.print("▃");
                        break;
                    case "4":
                        System.out.print("▄");
                        break;
                    case "5":
                        System.out.print("▅");
                        break;
                    case "6":
                        System.out.print("▆");
                        break;
                    case "7":
                        System.out.print("▇");
                        break;
                }
                System.out.print(" ");
                sleep(times);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }

}

控制音频播放Audio类:

package com.example.demo.play;

import cn.hutool.core.io.resource.ResourceUtil;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;

import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author xh
 * @Date 2022/12/27
 */
public class Audio {
    private static InputStream is;
    private Player player;
    ExecutorService service = Executors.newCachedThreadPool();

    public Audio(String path)
    {
        is = ResourceUtil.getStream(path);
        try
        {
            player = new Player(is);
        }
        catch (JavaLayerException e)
        {
            e.printStackTrace();
        }
    }


    public void start()
    {
        service.submit(() -> {
            try
            {
                player.play();
            }
            catch (JavaLayerException ignored)
            {

            }
        });

    }
}

项目整体结构:
在这里插入图片描述

代码已经开源到Github上,欢迎大家玩!传送门

在这里插入图片描述

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

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

相关文章

【复习】计算机网络学习笔记

前言 本篇笔记方便本人用于复习回顾知识点&#xff0c;内容庞杂&#xff0c;见谅。含有目录方便大家跳转复习&#xff01; 此复习笔记总结于 湖科大教书匠出品&#xff1a;深入浅出计算机网络 微课视频 此笔记尚未完结&#xff0c;持续更新中… 文章目录前言第一章 概述1.1 …

高并发系统设计 -- 服务限流算法

常见的限流算法 漏桶算法 漏桶法的关键点在于漏桶始终按照固定的速率运行&#xff0c;但是它并不能很好的处理有大量突发请求的场景&#xff0c;毕竟在某些场景下我们可能需要提高系统的处理效率&#xff0c;而不是一味的按照固定速率处理请求。 关于漏桶的实现&#xff0c;u…

快速入门 .NET nanoFramework 开发 ESP32-Pico 应用

本文是一篇适合初学者的 .NET nanoFramework 保姆级入门教程&#xff0c;并提供了基本的入门程序并介绍了微雪的 ESP32-S2-Pico 使用 .NET nanoFramework 开发过程的基础知识。 目录 1. 背景 1.1 .NET IOT 与 .NET nanoFramework 1.2 微控制器 1.3 实验板介绍 2. 搭建 .NET…

移动Web【空间转换[空间位移、透视、空间旋转、立体呈现、3D导航、空间缩放]、动画、综合案例】

文章目录一、空间转换1.1 空间位移1.2 透视1.3 空间旋转1.4 立体呈现1.5 3D导航1.6 空间缩放二、动画2.1 动画的实现步骤2.2 动画属性三、综合案例2.1 走马灯一、空间转换 空间&#xff1a;是从坐标轴角度定义的。 x 、y 和z三条坐标轴构成了一个立体空间&#xff0c;z轴位置与…

Android实战进阶 - 拉取项目代码后多处报红?如资源找不到该如何处理?

近期参与了一个我很感兴趣的项目&#xff0c;项目内用到了很多新东西&#xff0c;例如组件化、模块化、ARouter路由、MVI框架、Kt高阶用法等等&#xff0c;感觉可以学一段时间… Gradle相关Blog Android Gradle - Gradle、Gradle plugin 基础认知Android Gradle - AndroidStud…

函数极限定义的理解

回顾一下非正式的极限定义法。当x从任意一侧(自左向右或自右向左)接近常量 c时&#xff0c;如果f(x)变得任意接近一个单独的值L, 则当x接近c时f(x)的极限值是L, 写作 咋一看&#xff0c;这个定义似乎非常技术化。即使这样&#xff0c;它仍然是非正式的&#xff0c;因为它没有给…

三、Django -视图

Django 提示&#xff1a;本文根据b站黑马python课整理 链接指引 > 黑马程序员python企业级开发项目-手把手从0到1开发《美多商城》 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录Django视图介绍和项目准备视图…

【数据集6】全球人工不透水面积GAIA(清华数据)

全球人工不透水面积&#xff08;lobal artificial impervious area, GAIA&#xff09; 人工不透水区是表征建成区和城市范围的重要覆盖类型&#xff0c;特别是在较细的空间分辨率下。 1 简介 原理&#xff1a; 由Landsat卫星图像和辅助数据集生成&#xff0c;如夜间灯光数据…

健康码识别[QT+OpenCV]

&#x1f482; 个人主页:风间琉璃&#x1f91f; 版权: 本文由【风间琉璃】原创、在CSDN首发、需要转载请联系博主&#x1f4ac; 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦目录 一、识别原理 1.二维码定位 2.颜色识别 二、部分源码 一、识别原理 二维…

matlab实现基本相位调制

相位调制&#xff08;PM&#xff09;是将信息编码为载波的瞬时相位变化的一种调制模式。 调相的基本表达式如下&#xff1b; 载波c(t)是一个标准正弦信号&#xff1b;m(t)是调制信号&#xff1b;调制以后是把m(t)的变化附加到了载波的相位变化上&#xff1b; 调相的基本示意如…

WPF中iconfont图标库的使用

总目录 文章目录总目录前言一、查找项目需要的图标二、图标的使用1.将下载的文件解压缩2.将ttf文件复制粘贴到自己的项目中3.使用总结前言 本文主要介绍在WPF中iconfont图标库的使用 一、查找项目需要的图标 首先进入阿里巴巴矢量图标库网站&#xff0c;登录自己的账号&#…

MySQL快速生成大量测试数据 (脚本一键生成分表数据)

生成128个分表的测试数据敲到手累&#xff1b; 生成的测试数据虽然有离散分布&#xff0c;但随着时间的增长数据量不增反降&#xff0c;不符合大多数线上业务的增长趋势&#xff1b; 生成的测试数据部分超过当前日期。 具体表现如下图所示&#xff1a; 我们直接看下脚本的用法…

月入8000+的steam/csgo搬砖项目(详细拆解)

大家好&#xff0c;我是阿阳 今天就给大家带来一个在steam游戏搬砖项目的拆解&#xff0c;目前这个项目我们团队也一直在带队实操&#xff0c;已经跑通了项目的整个流程&#xff0c;提炼出了完整的赚钱体系。 先给大家看看近期的收益情况&#xff1a; 近期的出售记录&#xf…

[ Azure - Database ] Azure Database for MySQL 配置Auditing并查看使用

传统MySQL的二进制日志binlog可以说是MySQL最重要的日志&#xff0c;它记录了所有的DDL和DML语句&#xff08;除了数据查询语句select&#xff09;&#xff0c;以事件形式记录&#xff0c;还包含语句所执行的消耗的时间。本文会讲解微软云Azure Database for MySQL的binlog相关…

i.MX8MP平台开发分享(IOMUX篇)- 硬件原理

专栏目录&#xff1a;专栏目录传送门 平台内核i.MX8MP5.15.71文章目录1.前言2.IOMUX原理3. 寄存器实例&#xff1a;UART1_RX3.1 PAD: UART1_RXD3.2 PAD: SD1_CMD3.3 PAD: SAI2_RXC3.4 Input select3.5 功能实现4.SION1.前言 我们都知道&#xff0c;芯片包含数量有限的引脚&am…

BeanFactory和Applicationcontext实现

1.容器接口 1.BeanFactory能做哪些事 1.什么是beanFactory 它是spring的核心容器 是ApplicationContext的父接口 ApplicationContext扩展实现都【组合了】beanFactory 2.BeanFactory的功能 明面上只有getBean()方法实际上控制反转、依赖注入、bean生命周期的各种功能都…

tslib-1.4在I.MX6ULL开发板上电容屏不能触摸问题

一、前言 在采用触摸屏的移动终端中&#xff0c;触摸屏性能的调试是个重要问题之一&#xff0c;因为电磁噪声的缘故&#xff0c;触摸屏容易存在点击不准确、有抖动等问题。Tslib是一个开源的程序&#xff0c;能够为触摸屏驱动获得的采样提供诸如滤波、去抖、校准等功能&#x…

ESP32-S3 >>> MicroPython 编程初探

今天买了一个ESP32-S3&#xff0c;打算试试在这上面进行MicroPython的编程&#xff08;附资料网址&#xff09;。 首先为了在ESP32上进行mp的编程&#xff0c;需要对其重新烧录固件。这就需要我们电脑安装好CH343驱动&#xff0c;然后找到适用于ESP32-S3的固件&#xff0c;利用…

Diffusion详解及PyTorch代码

首先附上几个大佬的讲解 lilianweng-diffusion-models 这篇博客借鉴了上述博客和视频&#xff0c;同时加上个人的理解整合了一下&#xff0c;整个推导过程非常详细&#xff0c;希望能使每个人都看懂 结合之前讲过的VAE和GAN模型&#xff0c;Diffusion Model和他们的区别就是…

Apache Struts2远程代码执行漏洞(S2-015)复现及修复方案

Apache Struts2远程代码执行漏洞(S2-015)介绍 Apache Struts 2是用于开发JavaEE Web应用程序的开源Web应用框架。Apache Struts 2.0.0至2.3.14.2版本中存在远程命令执行漏洞。远程攻击者可借助带有‘${}’和‘%{}’序列值&#xff08;可导致判断OGNL代码两次&#xff09;的请求…