2014-04-28 1 views
0

JLayer를 사용하여 Java로 미디어 플레이어를 만들었으며 mp3 파일을 사용할 수 있습니다. 사용자가 해당 노래를 재생하면 특정 노래에 대한 가사가 표시되지만, 이제는 가라오케처럼 노래에서 들리는 가사의 텍스트 색상을 강조하거나 변경하려고합니다. 하나의 노래에 대해서만이 작업을 수행하면됩니다. 이미 프로그램에서 가사를 구현할 것입니다. 이미이 작업을 수행하는 방법을 검색했지만 찾고있는 것을 정확하게 찾을 수없는 것 같습니다. 아래에서는 음악 파일을 재생하는 클래스에 코드를 추가했습니다. 고마워요!JLayer를 사용하여 mp3 파일 재생 (가라오케처럼)으로 가사를 강조 표시하는 방법

public class PlayMusic { 

/** 
* Global variables. FileInputStream obtains input bytes from a file system 
* and reads streas of raw bytes. BufferedInputStream adds functionality 
* to the fis, and creates an internal buffer array. 
*/ 
private String filename; 
private Player player; 
private boolean canResume; 
private boolean valid; 
private int total; 
private int stopped; 
FileInputStream fis; 
BufferedInputStream bis; 


/** 
* Constructor the takes in the path of the mp3 file to be played. 
* @param filename - path of the mp3 file 
*/ 
public PlayMusic(String filename) { 
    this.filename = filename; 
    this.canResume = false; 
    this.valid = false; 
    this.total = 0; 
    this.stopped = 0; 
    this.fis = null; 
    this.bis = null; 
} 

/** 
* Function called to stop a song altogether as opposed to pausing. 
*/ 
public void close() { 
    if (player != null) 
     player.close(); 
    stopped = 0; 
    fis = null; 
    bis = null; 
    player = null; 
    canResume = false; 
    } 


/** 
* Function called to pause a song. Fis.available() is a method that returns 
* the number of remaining bytes that can be read from the input stream. 
*/ 
public void pause(){ 
    try { 
     if (fis!=null) 
      stopped = fis.available(); 
     if (player!= null) 
      player.close(); 
     fis = null; 
     bis = null; 
     player = null; 
     if(valid) 
      canResume = true; 
    } catch (IOException e) { 

    } 


} 

/** 
* Function called when we want to resume a song from where it left off 
* after being paused. 
*/ 
public void resume() 
{ 
    if(!canResume) 
     return; 
    if(play(total-stopped)) 
     canResume = false; 
} 

/** 
* Function called to play the song and keep track of where in the song the 
* user presses stop in order for the resume button to work properly. Fis.skip 
* skips over and discards pos bytes of data from fis. 
* @param pos - The position of the song in which we want to resume play 
* @return 
*/ 
public boolean play(int pos) { 
    valid = true; 
    canResume = false; 
    try { 
     fis = new FileInputStream(filename); 
     total = fis.available(); 
     if(pos> -1) 
      fis.skip(pos); 
     bis = new BufferedInputStream(fis); 
     player = new Player(bis); 

    } 
    catch (Exception e) { 
     System.out.println("Problem playing file " + filename); 
     System.out.println(e); 
    } 



    /** 
    * Run the play button in a new thread so the music plays in the background. 
    */ 
    new Thread() { 
     public void run() { 
      try { player.play(); } 
      catch (Exception e) { System.out.println(e); valid = false; } 
     } 
    }.start(); 


    return valid; 

} 

}

+0

하나의 노래에 대해서만 연주해야하는 경우 비디오 편집기를 사용하여 적절한 시간에 나타나는 하이라이트 가사의 비디오를 만드는 것이 좋습니다. – DJClayworth

+0

[.srt] (http://en.wikipedia.org/wiki/SubRip#SubRip_text_file_format) 파일 형식과 같은 것을 사용하고 있습니까? – ggovan

+0

@DJClayworth는 확실히 쉽게 할 수 있지만 프로그래밍 클래스의 최종 프로젝트를 진행하고 있으며 코딩을 통해이를 수행 할 수 있기를 원합니다. – user3078608

답변

2

당신은 (쉽게 최소한으로) 노래에서 노래되고 있는지 단어 감지 할 수 있지만하지 않습니다 당신은 파일에있는 노래의 가사가 있고 경우 노래의 사운드 파일을 가지고 있다면 노래에 가사의 단어가 노래 될 때 그 가사 파일에 추가 정보를 추가하여지도를 만들 수있는 것처럼 들리 네요.

예를 들어 노래 Jingle Bells을 사용하여 이것을 수행하려는 경우 가사가 포함 된 탭 구분 파일이있을 수 있습니다. 한 줄은 한 단어이고 노래 시작과 관련된 시작 및 종료 시간이 있습니다 밀리 초 단위.

jingle 0 1000 
bells 1001 1500 
jingle 1501 2500 
bells 2501 3000 
... and so on 

노래가 재생 된 시간을 추적하는 코드 작성법을 설명하는 편집. 라는 인스턴스 변수를 만들 수

두 가지 방법 totalTimeSongHasBeenPlaying

  1. 난 당신이 사운드 파일을 재생 밖으로 추상화 얼마나 확실하지 않다,라고,하지만 당신은 그런 다음 Sound 클래스에 그를 추상화 말 당신은 당신이 잡을 수있는 soundStarted를 호출 할 수있는 사운드를 재생의 시작에서 다음 세 가지 방법, sound.soundStarted, sound.soundStopped, sound.soundRestarted을 할 수있는 System.nanoTime 또는 System.currentTimeMillissoundStopped에, 당신은 다시 잡고 차이를 가지고 totalTimeSongHasBeenPlaying에 추가 할 수 있습니다 및에totalTimeSongHasBeenPlaying을 0으로 설정할 수 있습니다.

  2. 프레임 위치와 비교하여 현재 재생중인 사운드와 해당 파일의 초당 프레임 수를 비교합니다. JLayer에 대한 정확한 라이브러리를 알지 못합니다. 사용한지 얼마되지 않았습니다.하지만이 방법은 파일의 길이가 얼마나 먼지 알려줄 것입니다.

그 후, 사운드 클래스는 다음 totalTimeSongHasBeenPlaying에 보이는 방법 등 currentWordBeingSung()을 가지고 있고, 가사가 건설 중에 파일 오프 만든 조회 테이블을 사용하고 고유 특정 단어를 반환 할 수 (수 있습니다 중복). 귀하의 GUI를 작성할 때 JLyricsViewer라고 말하면 Sound 오브젝트에 인스턴스를 보유 할 수 있으며 SwingTimer을 사용하여 50㎳ 정도마다 다시 칠할 수 있습니다. paintComponent 메소드에서 currentWordBeingSung()을 찾습니다.

+0

의미가 있습니다. 노래가 재생되는 동안 내 프로그램에 무언가를 추가하면 (밀리 초> 0 및 밀리 초 <1000) "징글"이 표시되는지 확인합니다. – user3078608

+0

사운드 파일을 어떻게 추상화했는지 모르겠지만 Sound 클래스에 추상화했다고 가정하면 sound.soundStarted, sound.soundStopped, sound.soundRestarted의 세 가지 메서드를 사용할 수 있습니다. 사운드 재생을 시작하면 SoundStarted를 호출하여 System.nanoTime 또는 System.currentTimeMillis를 잡고 soundStopped에서 다시 잡아서 차이를 가져와 totalTimeSongHasBeenPlaying에 추가하고 soundRestart에 totalTimeSongHasBeenPlaying을 0으로 설정할 수 있습니다. – NESPowerGlove

+0

또한 Sound 클래스는 totalTimeSongHasBeenPlaying을보고 작성 중에 가사 파일에서 만든 찾아보기 테이블을 사용하고 특정 단어를 고유하게 반환하는 currentWordBeingSung()과 같은 메서드를 가질 수 있습니다 (중복 일 수 있음). 귀하의 GUI를 만들 때 JLyricsViewer가 Sound 객체에 인스턴스를 보유 할 수 있으며 SwingTimer를 사용하여 매 50ms마다 다시 칠할 수 있습니다. paintComponent 메서드에서 currentWordBeingSung()을 찾습니다. – NESPowerGlove