小言_互联网的博客

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

204人阅读  评论(0)

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

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

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

演奏视频


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上,欢迎大家玩!传送门


转载:https://blog.csdn.net/m0_51517236/article/details/128509090
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场