简体   繁体   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");
        }
        
    }
    
}

this is the code I used to play different piano note wav files one by one to create a music, but when I make the Thread.sleep less than 1000, the music note will jam up, it will skipped or play some notes together, is there anyway I can play these files one by one in order, or is there other way I can use to create a music editor that allows me to combine different music notes together to play songs using java?`enter code here.这是我用来逐个播放不同钢琴音符wav文件以创建音乐的代码,但是当我使Thread.sleep小于1000时,音符会卡住,它会跳过或一起播放一些音符,是无论如何,我可以按顺序一个一个地播放这些文件,或者还有其他方法可以用来创建一个音乐编辑器,允许我将不同的音符组合在一起使用 java 播放歌曲?`在此处输入代码。

So, you're basic problem is, you're closing the clip before it's either had a chance to play or play completely.所以,你的基本问题是,你在它有机会播放或完全播放之前关闭剪辑。

Rather than relying on Thread.sleep , which won't take into account the variable nature of the playback (ie the source clips been different lengths or the sound system needing more time) you should be trying to use a more imperial measurement.而不是依赖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);
        }
    }
}

Now, if you run this, you'll find one particular problem.现在,如果你运行它,你会发现一个特殊的问题。 They "seem" to all play at once (like smashing you hands on the keyboard)... not pretty.他们“似乎”同时演奏(就像在键盘上砸你的手)......不漂亮。

So, instead, we need to know more information, specifically, when the clip actually completes.因此,相反,我们需要了解更多信息,特别是剪辑实际完成的时间。

So, I added a LineListener to the Clip and used a ReentrantLock to "wait" till the clip had "stopped", for example...因此,我向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);
    }
}

This ensures that each note is played immediately after the last note has completed.这可确保在最后一个音符完成后立即播放每个音符。

Now, if you prefer to have a little "overlap" of the notes, then simply, don't close the clip, let it play.现在,如果您希望音符有一点“重叠”,那么简单地说,不要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);
    }
}

If needed, you could use the LineListener to close the clip instead如果需要,您可以使用LineListenerclose剪辑

nb: I sourced my note files from https://sound.stackexchange.com/questions/22769/are-there-free-records-of-separate-piano-notes-in-wav-files-for-instance , specifically, http://www.mediafire.com/download/zp8brp1f6q777b1/Midi_Notes.rar andhttp://www.mediafire.com/download/zd1mqtazulgv28a/mp3_Notes.rar .注意:我的笔记文件来自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 I used the MP3 files and converted them to wav files我使用了 MP3 文件并将它们转换为 wav 文件

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

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