繁体   English   中英

关于如何创建一个音乐播放器,可以一个一个播放不同的文件来创建音乐

[英]About how to create a music player that could play different file one by one to create a music

import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import javax.sound.sampled.*;
public class Main{
        
       static File [] arr= new File[100];
     
        static String[] arrNote = new String[100];
        public void play(File filename)throws UnsupportedAudioFileException, IOException,InterruptedException,
    LineUnavailableException{
            AudioInputStream audioStream = AudioSystem.getAudioInputStream(filename);
                    Clip clip = AudioSystem.getClip();
                    clip.open(audioStream);
                    clip.start();
                Thread.sleep(500); 
                clip.close();
        }
        
        
    
    public static void main(String[]args) throws UnsupportedAudioFileException, IOException,InterruptedException,
    LineUnavailableException{
        Scanner scanner = new Scanner(System.in);
        String response = "";
        Main a = new Main();
        int numItems = 0;
         System.out.println("Store music notes, type in Alphabate + number for example(E3) for the music note you want to store in the array, type Q when finished");    
        while(!response.equals("Q")){
            response = scanner.next();
            response.toUpperCase();
            switch(response){
                case("B3"): 
                arr[numItems] = new File("C:\\Users\\westg\\OneDrive\\Desktop\\piano.wav\\B3.wav");
                arrNote[numItems] = "B3";
                numItems++;
                break;
                case("C3"):
                arr[numItems] = new File("C:\\Users\\westg\\OneDrive\\Desktop\\piano.wav\\C3.wav");
                arrNote[numItems] = "C3";
                numItems++;
                break;
                case("D3"):
                arr[numItems] = new File("C:\\Users\\westg\\OneDrive\\Desktop\\piano.wav\\D3.wav");
                arrNote[numItems] = "D3";
                numItems++;
                break;
                case("E3"):
                arr[numItems] = new File("C:\\Users\\westg\\OneDrive\\Desktop\\piano.wav\\E3.wav");
                arrNote[numItems] = "E3";
                numItems++;
                break;
                case("F3"): 
                arr[numItems] = new File("C:\\Users\\westg\\OneDrive\\Desktop\\piano.wav\\F3.wav");
                arrNote[numItems] = "F3";
                numItems++;
                break;
                case("Q"): 
                break; 
                default: System.out.println("Not a valid response");
            }
            
        }
        System.out.println("Your music note sequence: ");
        for (int x = 0; x < numItems; x ++){
            System.out.print(x + 1 + "." + arrNote[x] + " ");          
        }
        System.out.println("If you want to play your music, click any key to continue");
        response = scanner.next();
        while(!response.equals("Q")){
            System.out.println("P = play, S = Stop, R= Reset, Q = Quit");
            System.out.print("Enter your choice: ");
            response = scanner.next();
            response = response.toUpperCase();
            
            switch (response) { 
                
                case("P"): 
                for (int i = 0; i < numItems; i++){
                  a.play(arr[i]);
                }
                    
                default: System.out.println("Not a valid response");
            }
            System.out.println("Bye");
        }
        
    }
    
}

这是我用来逐个播放不同钢琴音符wav文件以创建音乐的代码,但是当我使Thread.sleep小于1000时,音符会卡住,它会跳过或一起播放一些音符,是无论如何,我可以按顺序一个一个地播放这些文件,或者还有其他方法可以用来创建一个音乐编辑器,允许我将不同的音符组合在一起使用 java 播放歌曲?`在此处输入代码。

所以,你的基本问题是,你在它有机会播放或完全播放之前关闭剪辑。

而不是依赖Thread.sleep ,它不会考虑播放的可变性质(即源剪辑的长度不同或音响系统需要更多时间),您应该尝试使用更英制的测量。

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Test {

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

    public enum Note {
        A3_MINOR(Note.class.getResource("/notes/a-3.wav")),
        A4_MINOR(Note.class.getResource("/notes/a-4.wav")),
        A5_MINOR(Note.class.getResource("/notes/a-5.wav")),
        A3(Note.class.getResource("/notes/a3.wav")),
        A4(Note.class.getResource("/notes/a4.wav")),
        A5(Note.class.getResource("/notes/a5.wav")),
        B3(Note.class.getResource("/notes/b3.wav")),
        B4(Note.class.getResource("/notes/b4.wav")),
        B5(Note.class.getResource("/notes/b5.wav")),
        C3_MINOR(Note.class.getResource("/notes/c-3.wav")),
        C4_MINOR(Note.class.getResource("/notes/c-4.wav")),
        C5_MINOR(Note.class.getResource("/notes/c-5.wav")),
        C3(Note.class.getResource("/notes/c3.wav")),
        C4(Note.class.getResource("/notes/c4.wav")),
        C5(Note.class.getResource("/notes/c5.wav")),
        D3_MINOR(Note.class.getResource("/notes/d-3.wav")),
        D4_MINOR(Note.class.getResource("/notes/d-4.wav")),
        D5_MINOR(Note.class.getResource("/notes/d-5.wav")),
        D3(Note.class.getResource("/notes/d3.wav")),
        D4(Note.class.getResource("/notes/d4.wav")),
        D5(Note.class.getResource("/notes/d5.wav")),
        E3(Note.class.getResource("/notes/e3.wav")),
        E4(Note.class.getResource("/notes/e4.wav")),
        E5(Note.class.getResource("/notes/e5.wav")),
        F3_MINOR(Note.class.getResource("/notes/f-3.wav")),
        F4_MINOR(Note.class.getResource("/notes/f-4.wav")),
        F5_MINOR(Note.class.getResource("/notes/f-5.wav")),
        F3(Note.class.getResource("/notes/f3.wav")),
        F4(Note.class.getResource("/notes/f4.wav")),
        F5(Note.class.getResource("/notes/f5.wav")),
        G3_MINOR(Note.class.getResource("/notes/g-3.wav")),
        G4_MINOR(Note.class.getResource("/notes/g-4.wav")),
        G5_MINOR(Note.class.getResource("/notes/g-5.wav")),
        G3(Note.class.getResource("/notes/g3.wav")),
        G4(Note.class.getResource("/notes/g4.wav")),
        G5(Note.class.getResource("/notes/g5.wav")),;

        private URL source;

        private Note(URL source) {
            this.source = source;
        }

        public URL getSource() {
            return source;
        }

    }

    public Test() {
        List<Note> notes = new ArrayList<>(16);
        notes.add(Note.A3_MINOR);
        notes.add(Note.A4_MINOR);
        notes.add(Note.A5_MINOR);
        notes.add(Note.A3);
        notes.add(Note.A4);
        notes.add(Note.A5);
        play(notes);
    }

    protected void play(List<Note> notes) {
        for (Note note : notes) {
            System.out.println("Play " + note + "; " + note.getSource());
            try {
                AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(note.getSource());
                Clip clip = AudioSystem.getClip();
                clip.open(audioInputStream);
                clip.start();
                clip.drain();
            } catch (UnsupportedAudioFileException | IOException | LineUnavailableException ex) {
                Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

现在,如果你运行它,你会发现一个特殊的问题。 他们“似乎”同时演奏(就像在键盘上砸你的手)......不漂亮。

因此,相反,我们需要了解更多信息,特别是剪辑实际完成的时间。

因此,我向Clip添加了LineListener并使用ReentrantLock来“等待”直到剪辑“停止”,例如......

protected void play(List<Note> notes) {
    ReentrantLock waitLock = new ReentrantLock();
    Condition waitCondition = waitLock.newCondition();
    for (Note note : notes) {
        System.out.println("Play " + note + "; " + note.getSource());
        try {
            AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(note.getSource());
            Clip clip = AudioSystem.getClip();
            clip.addLineListener(new LineListener() {
                @Override
                public void update(LineEvent event) {
                    if (event.getType().equals(LineEvent.Type.STOP)) {
                        waitLock.lock();
                        try {
                            waitCondition.signal();
                        } finally {
                            waitLock.unlock();
                        }
                    }
                }
            });
            clip.open(audioInputStream);
            clip.start();
            clip.drain();
            waitLock.lock();
            try {
                waitCondition.await();
            } catch (InterruptedException ex) {
                //Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
                waitLock.unlock();
            }
            clip.close();
        } catch (UnsupportedAudioFileException | IOException | LineUnavailableException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    try {
        Thread.sleep(500);
    } catch (InterruptedException ex) {
        Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
    }
}

这可确保在最后一个音符完成后立即播放每个音符。

现在,如果您希望音符有一点“重叠”,那么简单地说,不要close剪辑,让它播放。

protected void play(List<Note> notes) {
    ReentrantLock waitLock = new ReentrantLock();
    Condition waitCondition = waitLock.newCondition();
    for (Note note : notes) {
        System.out.println("Play " + note + "; " + note.getSource());
        try {
            AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(note.getSource());
            Clip clip = AudioSystem.getClip();
            clip.open(audioInputStream);
            clip.start();
            clip.drain();
            Thread.sleep(125);
        } catch (UnsupportedAudioFileException | IOException | LineUnavailableException | InterruptedException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    try {
        Thread.sleep(500);
    } catch (InterruptedException ex) {
        Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
    }
}

如果需要,您可以使用LineListenerclose剪辑

注意:我的笔记文件来自https://sound.stackexchange.com/questions/22769/are-there-free-records-of-separate-piano-notes-in-wav-files-for-instance ,具体来说, http://www.mediafire.com/download/zp8brp1f6q777b1/Midi_Notes.rarhttp://www.mediafire.com/download/zd1mqtazulgv28a/mp3_Notes.r 我使用了 MP3 文件并将它们转换为 wav 文件

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM