2017-02-14 96 views
1

我遇到了JFugue 5.0.7的一個問題:我正在編寫一個無限期播放音樂的實時應用程序,但jfugue庫提供的RealtimePlayer將樂器相互混合。JFugue RealtimePlayer無法同時播放多個樂器

我有以下代碼

public class HelloJFugue { 

    public static int BPM = 150; 
    public static int SIGNATURE = 3; 
    public static boolean RANDOM = false; 

    public static void main(String[] args) throws MidiUnavailableException { 
     RealtimePlayer player = new RealtimePlayer(); 
     BlockingQueue<Pattern> queue = new SynchronousQueue<>(); 

     List<PatternProducer> pProducers = createPatternProducers(); 

     Thread pConsumer = new Thread(new PatternConsumer(player, queue)); 
     Thread pProducer = new Thread(new PatternMediator(queue, pProducers)); 

     pConsumer.start(); 
     pProducer.start(); 
    } 

    private static List<PatternProducer> createPatternProducers() { 
     Random rand = new Random(); 

     PatternProducer rightHand = new PatternProducer() { 
      int counter = 0; 
      String[] patterns = { 
       "Rq Rq E6i D#6i", 
       "E6i D#6i E6i B5i D6i C6i", 
       "A5q Ri C5i E5i A5i", 
       "B5q Ri E5i G#5i B5i", 
       "C6q Ri E5i E6i D#6i", 
       "E6i D#6i E6i B5i D6i C6i", 
       "A5q Ri C5i E5i A5i", 
       "B5q Ri E5i C6i B5i", 
       "A5q Ri E5i E6i D#6i" 
      }; 

      @Override 
      public Pattern getPattern() { 
       Pattern p = new Pattern(patterns[RANDOM ? rand.nextInt(patterns.length - 1) + 1 : counter]) 
         .setVoice(0) 
         .setInstrument("Piano"); 
       counter++; 
       if (counter >= patterns.length) { 
        counter = 1; 
       } 
       return p; 
      } 
     }; 

     PatternProducer leftHand = new PatternProducer() { 
      int counter = 0; 
      String[] patterns = { 
       "Rq Rq Rq", 
       "Rq Rq Rq", 
       "A3i E4i A4i Ri Rq", 
       "E3i E4i G#4i Ri Rq", 
       "A3i E4i A4i Ri Rq", 
       "Rq Rq Rq", 
       "A3i E4i A4i Ri Rq", 
       "E3i E4i G#4i Ri Rq", 
       "A3i E4i A4i Ri Rq" 
      }; 

      @Override 
      public Pattern getPattern() { 
       Pattern p = new Pattern(patterns[RANDOM ? rand.nextInt(patterns.length - 1) + 1 : counter]) 
         .setVoice(1) 
         .setInstrument("Guitar"); 
       counter++; 
       if (counter >= patterns.length) { 
        counter = 1; 
       } 
       return p; 
      } 
     }; 

     return new ArrayList<PatternProducer>() { 
      { 
       add(rightHand); 
       add(leftHand); 
      } 
     }; 
    } 
} 

public class PatternMediator implements Runnable { 

    private BlockingQueue<Pattern> queue; 
    private List<PatternProducer> producers; 

    public PatternMediator(BlockingQueue<Pattern> queue, List<PatternProducer> producers) { 
     this.queue = queue; 
     this.producers = producers; 
    } 

    private void fillQueue() throws InterruptedException { 
     Pattern p = new Pattern(); 
     for (PatternProducer producer : producers) { 
      p.add(producer.getPattern().setTempo(HelloJFugue.BPM)); 
     } 
     this.queue.put(p); 
    } 

    @Override 
    public void run() { 
     while (true) { 
      try { 
       fillQueue(); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(PatternMediator.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    } 
} 

public class PatternConsumer implements Runnable { 

    private RealtimePlayer player; 
    private BlockingQueue<Pattern> queue; 

    public PatternConsumer(RealtimePlayer player, BlockingQueue<Pattern> queue) { 
     this.player = player; 
     this.queue = queue; 
    } 

    private void playFromQueue() throws InterruptedException { 
     player.play(queue.take()); 
    } 

    @Override 
    public void run() { 
     while (true) { 
      try { 
       playFromQueue(); 
       Thread.sleep(HelloJFugue.SIGNATURE * 60000/HelloJFugue.BPM); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(PatternConsumer.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    } 
} 

的問題是,打兩個樂器(吉他和鋼琴)時搞混,兩者不能simultanously播放。相反,玩家隨意地在兩個樂器之間變化,因此一次只能聽到一個演奏兩種樂器的樂器。

+0

我意識到,'sleep'是同步可怕的方式。這是我只是嘗試了JFugue –

+1

的功能我看到這裏發生了什麼:聲音和樂器正從你的左右手模式混合在一起。 JFugue需要的是一種識別語音+圖層+樂器+將連音符識別爲單個原子音樂元素的方法。在你的例子的驅動下,我正在研究一個新類「Atom」和一個pattern.atomize()方法(以及一個新的AtomSubparser)。我的目標是你可以使用和你一樣的代碼,並添加一個pattern.atomize()調用。我會保持發佈,並在其工作時回答這個問題。 –

+0

感謝David Koelle,太棒了。 –

回答