Java swing实现支持录音等功能的钢琴程序

如何实现Java Swing支持录音等功能的钢琴程序?

  1. 导入所需库文件

实现这个功能的Java库有很多,我们可以使用Java Sound API、Java Media Framework、JLGui和JLayer。为了方便起见,我们在这里使用Java Sound API来实现这个功能。我们需要导入下面的库文件:

<dependency>
    <groupId>javax.sound</groupId>
    <artifactId>javax.sound.sampled</artifactId>
    <version>1.0.3</version>
</dependency>
  1. 创建GUI

创建Java Swing GUI界面,以及添加相应的组件,例如钢琴键和录音按钮等。

示例代码:

// 导入Swing库
import javax.swing.*;

public class PianoProgram extends JFrame {

    // 定义录音按钮
    private JButton recordButton;

    public PianoProgram() {
        // 设置标题
        super("Java Swing Piano Program");

        // 创建录音按钮,并添加点击事件监听器
        recordButton = new JButton("Record");
        recordButton.addActionListener(new RecordButtonListener());

        // 把钢琴键和录音按钮添加到界面上
        getContentPane().add(PianoKeysPanel.createPanel());
        getContentPane().add(recordButton);

        // 设置布局管理器
        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));

        // 设置窗口大小
        setSize(500, 300);

        // 设置关闭窗口时的行为
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // 设置窗口可见
        setVisible(true);
    }

    // 录音按钮的事件监听器
    private class RecordButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO: 开始录音
        }
    }

    public static void main(String[] args) {
        new PianoProgram();
    }

}
  1. 配置录音

现在,我们需要在“Record”按钮的事件监听器中添加录音的代码。首先,我们需要找到“TargetDataLine”和“AudioFormat”:

// 查找支持录音的MixerDevice,初始化AudioFormat
Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
for (Mixer.Info info : mixerInfo) {
    Mixer mixer = AudioSystem.getMixer(info);
    Line.Info[] lineInfos = mixer.getTargetLineInfo();
    for (Line.Info lineInfo : lineInfos) {
        Line line = null;
        boolean opened = true;
        try {
            line = mixer.getLine(lineInfo);
            opened = line.isOpen() || line instanceof Clip;
            if (!opened) {
                line.open();
            }
            AudioFormat[] formats = line.getFormats();
            for (AudioFormat format : formats) {
                if (format.getSampleSizeInBits() == 16
                    && format.getChannels() == 1
                    && format.getEncoding() == AudioFormat.Encoding.PCM_SIGNED) {
                        // 找到支持的目标格式
                        AudioFormat dataFormat = format;
                        TargetDataLine targetDataLine;
                        targetDataLine = (TargetDataLine) mixer.getLine(
                            new DataLine.Info(TargetDataLine.class, dataFormat));
                    }
            }
        } catch (LineUnavailableException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // Ignore
        } finally {
            if (line != null && !opened) {
                line.close();
            }
        }
    }
}
  1. 开始录音

现在,我们已经找到了“TargetDataLine”和“AudioFormat”,接下来我们可以编写代码开始录音。我们可以使用线程来执行录音。

// 开始录音
RecordThread recordThread = new RecordThread(targetDataLine, dataFormat);
recordThread.start();

示例代码:

private void startRecording() {
    try {
        // 查找支持录音的MixerDevice,初始化AudioFormat
        Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
        for (Mixer.Info info : mixerInfo) {
            Mixer mixer = AudioSystem.getMixer(info);
            Line.Info[] lineInfos = mixer.getTargetLineInfo();
            for (Line.Info lineInfo : lineInfos) {
                Line line = null;
                boolean opened = true;
                try {
                    line = mixer.getLine(lineInfo);
                    opened = line.isOpen() || line instanceof Clip;
                    if (!opened) {
                        line.open();
                    }
                    AudioFormat[] formats = line.getFormats();
                    for (AudioFormat format : formats) {
                        if (format.getSampleSizeInBits() == 16 && format.getChannels() == 1
                                && format.getEncoding() == AudioFormat.Encoding.PCM_SIGNED) {
                            // 找到支持的目标格式
                            AudioFormat dataFormat = format;
                            TargetDataLine targetDataLine;
                            targetDataLine = (TargetDataLine) mixer.getLine(
                                    new DataLine.Info(TargetDataLine.class, dataFormat));
                            RecordThread recordThread = new RecordThread(targetDataLine, dataFormat);
                            recordThread.start();
                        }
                    }
                } catch (LineUnavailableException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    // Ignore
                } finally {
                    if (line != null && !opened) {
                        line.close();
                    }
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  1. 实现录音线程

现在,我们需要实现一个线程来执行录音。这个线程将录制用户的声音,然后将它保存到一个 WAV 文件中。

实现录音的线程示例代码:

public class RecordThread extends Thread {
    private TargetDataLine targetDataLine;
    private AudioFormat dataFormat;

    public RecordThread(TargetDataLine targetDataLine, AudioFormat dataFormat) {
        this.targetDataLine = targetDataLine;
        this.dataFormat = dataFormat;
    }

    public void run() {
        AudioInputStream audioStream = new AudioInputStream(targetDataLine);
        File audioFile = new File("record.wav");
        try {
            AudioSystem.write(audioStream, AudioFileFormat.Type.WAVE, audioFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  1. 结束录音

确认录音已经完成后,我们需要停止录音线程并保存录音。

示例代码:

private void stopRecording() {
    targetDataLine.stop();
    targetDataLine.close();
}

示例代码:

// 停止录音
StopRecording stopRecording = new StopRecording(targetDataLine);
stopRecording.start();
public class StopRecording extends Thread {
    private TargetDataLine targetDataLine;

    public StopRecording(TargetDataLine targetDataLine) {
        this.targetDataLine = targetDataLine;
    }

    public void run() {
        // 打断线程
        targetDataLine.stop();
        targetDataLine.close();

        // TODO: 保存录音
    }
}
  1. 保存录音

我们已经准备好了录音,现在我们需要将它保存到文件中。

示例代码:

private void saveRecording() {
    FileDialog fileDialog = new FileDialog(this, "Save Recording", FileDialog.SAVE);
    fileDialog.setFile("record.wav");
    fileDialog.setVisible(true);
    String filename = fileDialog.getFile();
    if (filename != null) {
        try {
            File selectedFile = new File(fileDialog.getDirectory() + "/" + fileDialog.getFile());
            FileInputStream fileInputStream = new FileInputStream("record.wav");
            FileOutputStream fileOutputStream = new FileOutputStream(selectedFile);
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = fileInputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, bytesRead);
            }
            fileInputStream.close();
            fileOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

至此,我们已经实现了Java Swing支持录音等功能的钢琴程序。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java swing实现支持录音等功能的钢琴程序 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • 详解Java中Method的Invoke方法

    详解Java中Method的Invoke方法 在Java中,我们可以对方法进行反射获取并执行。Method类的invoke方法可以用来执行通过反射获取到的方法。 Method类的基本概念 Method类是Java的反射机制中的一个类,它用于描述类的方法信息,例如方法名、参数类型、返回值类型等,同时也包含了方法的访问控制信息。 我们可以通过Class类中的 g…

    Java 2023年5月26日
    00
  • 如何使用java写Student类的功能

    下面详细讲解如何使用Java写Student类的功能的完整攻略,过程中包含两条示例说明。 1. 定义Student类 首先,我们需要定义一个Student类,代码如下: public class Student { private String name; private int age; public Student(String name, int ag…

    Java 2023年5月26日
    00
  • JSP Spring ApplicationContext的国际化支持

    JSP Spring ApplicationContext的国际化支持是一种让应用程序可以在不修改源代码的情况下,动态切换不同语言版本的功能。下面就详细讲解一下该功能的实现步骤: 第一步:准备资源文件 在项目的src/main/resources目录下创建多个.properties文件,每个文件对应一个语言版本。例如,可以创建messages.propert…

    Java 2023年6月15日
    00
  • jsp中如何实现按下回车键自动提交表单

    在JSP中实现按下回车键自动提交表单,可以采用两种方式来实现: 利用JavaScript 利用form表单属性 下面我将给出详细的步骤以及示例说明。 利用JavaScript 在jsp页面中嵌入JavaScript代码段 <script type="text/javascript"> window.onload=functio…

    Java 2023年6月15日
    00
  • bootstrap weebox 支持ajax的模态弹出框

    Bootstrap是一套UI框架,其中Weebox是一个基于Bootstrap的模态弹出框插件,支持AJAX加载内容。本攻略将详细介绍如何使用Bootstrap Weebox插件实现AJAX加载内容的模态弹出框。 准备工作 引入Bootstrap和jQuery库。 <link rel="stylesheet" href="…

    Java 2023年6月16日
    00
  • 让javascript加载速度倍增的方法(解决JS加载速度慢的问题)

    下面是一份详细讲解“让 JavaScript 加载速度倍增的方法”的攻略,希望能够帮助到你。 为什么要关注 JavaScript 的加载速度 JavaScript 是网页的重要组成部分之一,但是在加载过程中可能会带来用户体验的负面影响。如果加载速度过慢,会导致页面变得卡顿,用户体验不佳,同时也会对网站的排名和转化率造成不良影响。因此,关注 JavaScrip…

    Java 2023年6月15日
    00
  • 深入剖析Java之String字符串

    深入剖析Java之String字符串 介绍 在Java中,String是最常用的数据类型之一,它表示了一个由字符组成的不可变字符串。在实际编程过程中,我们经常需要进行字符串的操作,比如拼接、截取、替换等操作。本文将从基本数据结构说起,深入剖析Java String字符串的特点、常用方法以及相关注意事项。 基本数据结构 在Java中String本质上是一个字符…

    Java 2023年5月26日
    00
  • Java 8中字符串拼接新姿势StringJoiner详解

    Java 8中字符串拼接新姿势StringJoiner详解 在Java 8中,使用StringJoiner类可以更方便地进行字符串拼接。这个类可以让我们无需显式地使用字符串缓冲区或分隔符,并且支持指定开头和结尾的字符串,还可以在一些场景下避免空值引起的问题。 StringJoiner的用法 构造函数 首先,我们需要知道StringJoiner类的构造函数有如…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部