2017-02-23 2 views
0

이것은 매우 수용 가능한 질문이 아니지만 나는이 시점에서 필사적이다.동기식 미디어 플레이어 javafx

빠른 탐색 및 균형 수정을 사용하는 동기식 Java 미디어 플레이어가 필요합니다.

시나리오 :

내가 루프에서 매우 짧은 (50 ~ 100 밀리 초) 미디어 파일을 재생 가지고 자바 FX 프로젝트가 있습니다. 것은 다시 시작하기 전에 기다려야하는 요구 사항입니다.

짧게 : 재생 사운드 - 특정 요구 사항이 충족 (잔액이 수정 됨) (120ms마다) -> 소리가 들리면 처음부터 재생 재생.

javafx는 내가 수정 한 미디어 플레이어를 제공합니다. 아직 더 효율성이 필요 : 사람이 올바른 방향으로 (내가 놓친 라이브러리/일)을 날 지점 수 있다면

// this method is just to show how the modified mediaplayer class is called 
public void updateSoundBalance(double currentTimeInCycle) { 
    // control the balance of the sound 
    if(playingSound && mediaPlayer != null) 
    { 
     long b = System.nanoTime(); 

     // 0 <= balance < 4. balance represents the cycle phase. 
     double balance = currentTimeInCycle % RADIANCE_FULL_CYCLE/RADIANCE_QUARTER_CYCLE; 
     boolean firstHalfCycle = balance < 2; 

     double quarterCycleIndex = Math.floor(balance); 

     long a = System.nanoTime(); 
     if(swingingSound) 
      mediaPlayer.setBalance(firstHalfCycle ? 1 - balance : balance - 3); 
     else 
      mediaPlayer.setBalance(balance > 1 && balance < 3? -1 : 1); 
     System.out.println("C ::: sound balance = " + (System.nanoTime() - a)); 

     if ((quarterCycleIndex == 1 | quarterCycleIndex == 3) && 
      balance - quarterCycleIndex <= Settings.DEFAULT_PATTERN_SMOOTHNESS) 
     { 
      a = System.nanoTime(); 

      if (mediaDone){ 
       mediaPlayer.reset(); 
       mediaDone = false; 
      } 
      System.out.println("B ::: call reset = " + (System.nanoTime() - a)); 
     } 
     System.out.println("A ::: total time = " + (System.nanoTime() - b)); 
    } 
} 

import java.util.concurrent.ScheduledThreadPoolExecutor; 

import javafx.scene.media.Media; 
import javafx.scene.media.MediaPlayer; 
import javafx.util.Duration; 


public class MultiMediaPlayer 
{ 
private MediaPlayer mp1, mp2; 
private boolean usingMp1 = true; 

private ScheduledThreadPoolExecutor seekService = new ScheduledThreadPoolExecutor(2); 
private Runnable seekRun = new Runnable() { 
    @Override 
    public void run() { 
     try 
     { 
      long a = System.nanoTime(); 
      if(usingMp1) { 
       usingMp1 = false; 
       mp1.stop(); 
       mp2.play(); 
       mp1.seek(new Duration(0)); 
      } else { 
       usingMp1 = true; 
       mp2.stop(); 
       mp1.play(); 
       mp2.seek(new Duration(0)); 
      } 
      System.out.println("D ::: reset sound time taken = " + (System.nanoTime() - a)); 
     } 
     catch (Exception e){ 
      e.printStackTrace(); 
     } 
    } 
}; 

public MultiMediaPlayer(Media value) 
{ 
    mp1 = new MediaPlayer(value); 
    mp2 = new MediaPlayer(value); 

    mp1.balanceProperty().bindBidirectional(mp2.balanceProperty()); 
    mp1.onEndOfMediaProperty().bindBidirectional(mp2.onEndOfMediaProperty()); 
} 

public void setBalance(double value){ 
    mp1.setBalance(value); 
} 

public void reset(){ 
    seekService.execute(seekRun); 
} 

public void play(){ 
    if(usingMp1) { 
     mp1.play(); 
    } else { 
     mp2.play(); 
    } 
} 

public void stop(){ 
    mp1.stop(); 
    mp2.stop(); 
} 

public void pause(){ 
    mp1.pause(); 
    mp2.pause(); 
} 

public void setOnEndOfMedia(Runnable r) { 
    mp1.setOnEndOfMedia(r); 
} 
} 

내가 감사

PS 것이 허용되는 자바 버전은 가장입니다 최신 가능

답변

0

감사 올로프 Kohlhaas,하지만 난 내 특정 문제에 대한 더 나은 해결책을 찾은 것 같아요, 그리고 자바 FX의의 AudioClip를 사용합니다. 그러나, knowladge 부족으로 인해, 나는 웨이브 및 기타 특정 형식 만 지원하는 파일의 길이를 얻는 기본적인 방법을 사용했습니다. 이 클래스가 변경되면 javafx의 미디어 패키지가 지원하는 형식으로 작동합니다.

import java.io.IOException; 
import java.net.URL; 

import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.Clip; 
import javax.sound.sampled.DataLine; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.UnsupportedAudioFileException; 

import javafx.beans.property.ReadOnlyBooleanProperty; 
import javafx.beans.property.SimpleBooleanProperty; 
import javafx.beans.property.SimpleObjectProperty; 
import javafx.scene.media.AudioClip; 
import javafx.scene.media.Media; 
import javafx.scene.media.MediaPlayer; 

/** 
* 
* this class is to optimize sound pattern playing 
* 
* reasoning: 
* - audio clips are for short repetitive files that don't need live changes to balance 
* - media players are for long files that will have the ability to swing with the visual patted 
* by updating the balance whenever needed (every few updates) 
*/ 
public class AudioPlayer 
{ 
    public enum Controller{ 
     MEDIA_PLAYER, AUDIO_CLIP; 
    } 

    /** 
    * this class is to help other classes keep track of this particular state of the AudioPlayer 
    */ 
    public class ControllerProperty extends SimpleObjectProperty<Controller>{ 
     SimpleBooleanProperty isMediaPlayerProperty = new SimpleBooleanProperty(); 

     @Override 
     public void set(Controller newValue) { 
      super.set(newValue); 
      if (newValue == Controller.MEDIA_PLAYER) 
       isMediaPlayerProperty.set(true); 
      else 
       isMediaPlayerProperty.set(false); 
     } 

     public ReadOnlyBooleanProperty isMediaPlayerProperty() { 
      return isMediaPlayerProperty; 
     } 
    } 
    // different controllers used 
    private Media media; 
    private MediaPlayer mediaPlayer; 
    private AudioClip audioClip; 

    // controllerProperty property indicator 
    private ControllerProperty controllerProperty = new ControllerProperty(); 

    private boolean mediaDonePlaying = true; 
    private double durationMillis; 

    /** 
    * Constructor. This will be the place where you can 
    * @param srcUrl 
    */ 
    public AudioPlayer(String srcUrl) { 
     boolean formatSupported = true; 
     try { 
      durationMillis = getLength(srcUrl); 
     } catch (IOException | LineUnavailableException e) { 
      e.printStackTrace(); 
     } catch (UnsupportedAudioFileException e) { 
      formatSupported = false; 
     } 
     // if file is long or format unsupported (not one of these: AudioSystem.getAudioFileTypes()) 
     if (durationMillis > 400 | !formatSupported){ 
      media = new Media(srcUrl); 
      mediaPlayer = new MediaPlayer(media); 
      controllerProperty.set(Controller.MEDIA_PLAYER); 
      mediaPlayer.setOnEndOfMedia(() -> mediaDonePlaying = true); 
     } 
     else { 
      audioClip = new AudioClip(srcUrl); 
      controllerProperty.set(Controller.AUDIO_CLIP); 
     } 
    } 

    /** 
    * gets the audio duration of the provided source in milliseconds 
    * @param path url string representation of the path 
    * @return the length in milliseconds 
    * @throws IOException 
    * @throws UnsupportedAudioFileException 
    * @throws LineUnavailableException 
    */ 
    public static double getLength(String path) throws IOException, UnsupportedAudioFileException, LineUnavailableException 
    { 
     AudioInputStream stream; 
     stream = AudioSystem.getAudioInputStream(new URL(path)); 
     AudioFormat format = stream.getFormat(); 
     if (format.getEncoding() != AudioFormat.Encoding.PCM_SIGNED) { 
      format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, format 
       .getSampleRate(), format.getSampleSizeInBits() * 2, format 
       .getChannels(), format.getFrameSize() * 2, format 
       .getFrameRate(), true); // big endian 
      stream = AudioSystem.getAudioInputStream(format, stream); 
     } 
     DataLine.Info info = new DataLine.Info(Clip.class, stream.getFormat(), 
      ((int) stream.getFrameLength() * format.getFrameSize())); 
     Clip clip = (Clip) AudioSystem.getLine(info); 
     clip.close(); 
     return clip.getBufferSize() 
      /(clip.getFormat().getFrameSize() * clip.getFormat() 
      .getFrameRate()); 
    } 

    public void stop(){ 
     switch (controllerProperty.get()) 
     { 
      case AUDIO_CLIP: 
       if (audioClip != null) 
        audioClip.stop(); 
       break; 

      case MEDIA_PLAYER: 
       if (mediaPlayer != null && media != null){ 
        mediaPlayer.stop(); 
        mediaDonePlaying = true; 
       } 
       break; 
     } 
    } 

    public void play(){ 
     switch (controllerProperty.get()) 
     { 
      case AUDIO_CLIP: 
       if (audioClip != null) 
        if(!audioClip.isPlaying()){ 
         audioClip.play(); 
        } 
       break; 

      case MEDIA_PLAYER: 
       if (mediaPlayer != null && media != null){ 
        mediaPlayer.play(); 
        mediaDonePlaying = false; 
       } 
       break; 
     } 
    } 

    public void pause(){ 
     switch (controllerProperty.get()) 
     { 
      case AUDIO_CLIP: 
       if (audioClip != null) 
        audioClip.stop(); 
       break; 

      case MEDIA_PLAYER: 
       if (mediaPlayer != null && media != null) 
        mediaPlayer.pause(); 
       break; 
     } 
    } 

    /** 
    * sets the balance of the player, if the controller is an {@link AudioClip}, the balance is 
    * updated at the next play cycle, if the controller is a {@link MediaPlayer} the balance is 
    * updated at the next time the {@link MediaPlayer} has Status.READY (read 
    * {@link MediaPlayer#setBalance(double)} for more details) 
    * @param balance 
    */ 
    public void setBalance(double balance){ 
     switch (controllerProperty.get()) 
     { 
      case AUDIO_CLIP: 
       if (audioClip != null) 
        audioClip.setBalance(balance); 
       break; 

      case MEDIA_PLAYER: 
       if (mediaPlayer != null && media != null) 
        mediaPlayer.setBalance(balance); 
       break; 
     } 
    } 

    public String getSource(){ 
     switch (controllerProperty.get()) 
     { 
      case AUDIO_CLIP: 
       if (audioClip != null) 
        return audioClip.getSource(); 
       break; 

      case MEDIA_PLAYER: 
       if (mediaPlayer != null && media != null) 
        return media.getSource(); 
       break; 
     } 
     return null; 
    } 

    /** 
    * @return if the file is done 
    */ 
    public boolean isDonePlaying(){ 
     switch (controllerProperty.get()) 
     { 
      case AUDIO_CLIP: 
       if (audioClip != null) 
        return !audioClip.isPlaying(); 
       break; 

      case MEDIA_PLAYER: 
       if (mediaPlayer != null && media != null) 
        return mediaDonePlaying; 
       break; 
     } 
     throw new IllegalStateException("Internal Error"); 
    } 

    public ControllerProperty controllerProperty() { 
     return controllerProperty; 
    } 
} 
0

이 경우 더 낮은 수준의 Java Sound API를 사용하는 것이 좋습니다. 이미 표준 API의 일부입니다. 당신은 매우 짧은 오디오 신호를 가지고 있다고 언급했습니다. 따라서 메모리에 버퍼링 한 다음 여러 번 개요로 작성할 수 있습니다. 언뜻보기에 팬이 균형 대신 올바른 선택이 될 수 있습니다. 다음 예제는 균형 및 팬을 최대 및 최소로 전환하는 방법을 보여줍니다. Java Sound API는 기본적으로 WAVE 및 AIFF와 함께 작동합니다. 다른 파일 형식을 사용하는 경우 mp3spi 및 vorbisspi와 같은 Java Sound API FormatConversionProviders를 살펴 봐야합니다.

import java.io.File; 
import java.io.IOException; 

import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.DataLine; 
import javax.sound.sampled.FloatControl; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.SourceDataLine; 
import javax.sound.sampled.UnsupportedAudioFileException; 

public class Main { 

    public static void main(String[] args) { 

     try { 
      int loops = 20; 

      File waveFile = new File(yourWaveFilePath); 

      AudioInputStream stream = AudioSystem.getAudioInputStream(waveFile); 
      AudioFormat format = stream.getFormat(); 

      // reading complete audio file into memory 
      byte[] frames = new byte[format.getFrameSize() * (int) stream.getFrameLength()]; 
      stream.read(frames, 0, frames.length); 

      DataLine.Info lineInfo = new DataLine.Info(SourceDataLine.class, format); 
      SourceDataLine line = (SourceDataLine) AudioSystem.getLine(lineInfo); 
      line.open(format); 
      line.start(); 

      FloatControl balance = (FloatControl) line.getControl(FloatControl.Type.BALANCE); 
      FloatControl pan = (FloatControl) line.getControl(FloatControl.Type.PAN); 

      for (int i = 0; i < loops; i++) { 
       // switching balance and pan with every iteration 
       if (i % 2 == 0) { 
        balance.setValue(balance.getMinimum()); 
        pan.setValue(pan.getMinimum()); 
       } else { 
        balance.setValue(balance.getMaximum()); 
        pan.setValue(pan.getMaximum()); 
       } 

       // playing complete audio file 
       line.write(frames, 0, frames.length); 

       System.out.println("iteration: " + i + ", balance: " + balance.getValue() + ", pan: " + pan.getValue()); 
      } 

      line.drain(); 
      line.close(); 
      stream.close(); 

     } catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) { 
      e.printStackTrace(); 
     } 
    } 

}