Android版卡拉OK,歌词同步程序

1. [图片] 2012-08-21-13-07-10.png    

2. [代码][Java]代码    跳至[2][3][4][全屏预览]

001package my.android.karaoke.media;
002 
003import java.io.FileDescriptor;
004import java.io.FileInputStream;
005import java.io.IOException;
006import java.io.InputStream;
007import java.util.ArrayList;
008import java.util.List;
009 
010import my.android.karaoke.bean.LyricSentence;
011import my.android.karaoke.bean.LyricText;
012import my.android.karaoke.bean.LyricWord;
013 
014import android.content.Context;
015import android.content.res.AssetFileDescriptor;
016import android.content.res.AssetManager;
017import android.media.MediaPlayer;
018import android.os.Handler;
019import android.os.Message;
020import android.util.Log;
021 
022 
023public class KaraokeMedia {
024 
025private static KaraokeMedia karaokeMedia=new KaraokeMedia();
026   
027    //文章每个段落的起始和结束时间段
028    private static List<Integer> sentencesTimes=null;
029    private static MediaPlayer mp3Player = new MediaPlayer();
030   
031    private static int currentSentence_index ; //当前段落索引
032    private static int currentWord_index;//当前段落单个字的字数索引
033    private static int showWord_index;//当前段落单个字的显示字数索引
034   
035    private static List<LyricSentence> sentences;
036   
037    private KaraokeMedia(){}
038   
039    public static KaraokeMedia getInstance() {
040        return karaokeMedia;
041    }
042   
043    //开始播放文章
044    public static void playArticleMedia(LyricText lyricText,Context context) {
045       
046        karaokeMedia.prepareSentencesTimes(lyricText);
047       
048        currentSentence_index=0;
049        currentWord_index=0;
050       
051        mMode = RUNNING;
052        karaokeMedia.update();
053       
054        AssetManager asset = context.getAssets();
055        FileDescriptor fd = null;
056        try {
057            fd = asset.openFd(lyricText.getSound_path()).getFileDescriptor();
058        } catch (IOException e1) {
059            // TODO Auto-generated catch block
060            e1.printStackTrace();
061        }
062         
063        if(fd == null){
064            return;
065        }
066       
067        try {
068            //mp3Player.setDataSource(article.getSound_path());
069            mp3Player.setDataSource(fd);
070            mp3Player.prepare();
071        } catch (IllegalArgumentException e) {
072            // TODO Auto-generated catch block
073            e.printStackTrace();
074        } catch (SecurityException e) {
075            // TODO Auto-generated catch block
076            e.printStackTrace();
077        } catch (IllegalStateException e) {
078            // TODO Auto-generated catch block
079            e.printStackTrace();
080        } catch (IOException e) {
081            // TODO Auto-generated catch block
082            e.printStackTrace();
083        }      
084 
085        mp3Player.start();
086       
087        //Log.v("KaraokeMedia playArticleMedia() Duration:", ""+mp3Player.getDuration());
088    }
089   
090    //开始播放某个文章段落
091    public static void seekToArticleMedia(int seekTotSentence_index) {
092       
093        currentSentence_index=seekTotSentence_index;
094        mMode = PAUSE;
095       
096        int seekToTime = sentencesTimes.get(currentSentence_index);
097       
098        if(mp3Player.isPlaying()){
099           
100            mp3Player.seekTo(seekToTime);
101           
102        } else {       
103 
104            mp3Player.start();
105            mp3Player.seekTo(seekToTime);
106        }
107       
108        mMode = RUNNING;
109        karaokeMedia.update();
110    }
111   
112    //暂停播放文章,如果暂停成功则返回true
113    public static boolean pauseArticleMedia() {
114       
115        if(mp3Player.isPlaying()){
116            mp3Player.pause();
117            mMode = PAUSE;
118           
119            return true;
120        } else {
121            return false;
122        }
123    }
124   
125    //恢复播放文章,如果恢复成功则返回true
126    public static boolean reStartoArticleMedia() {
127       
128        if(!mp3Player.isPlaying()){    
129            mp3Player.start();
130            mMode = RUNNING;
131            karaokeMedia.update();
132           
133            return true;
134        } else {
135            return false;
136        }
137    }
138   
139    //初始化文章音频LRC时间段
140    private void prepareSentencesTimes(LyricText lyricText){
141       
142        sentences = lyricText.getSentences();
143        int Sentences_size = sentences.size();
144       
145        if(sentencesTimes!=null){
146            sentencesTimes.clear();
147        }
148       
149        sentencesTimes = new ArrayList<Integer>(Sentences_size);
150        for(LyricSentence sentence : sentences){
151           
152            Integer time = sentence.getSentence_offset();
153            sentencesTimes.add(time);
154        }
155    }
156   
157    private static int mMediaDelay = 10;
158   
159    private static int mMode;
160    public static final int PAUSE = 0;
161    public static final int READY = 1;
162    public static final int RUNNING = 2;
163    public static final int STOP = 3;
164   
165    //定时器,每mMediaDelay时间循环一次,判断当前音频是否更换段落
166    //update在RUNNING状态的更新间隔为此方法执行时间+mMediaDelay,因为经过测试,该方式执行时间大概为100MS,所以间隔时间为100MS左右+mMediaDelay
167    //有一定误差
168    private void update() {
169        if (mMode == RUNNING) {
170           
171            int now = mp3Player.getCurrentPosition();
172 
173            //Log.v("ArticleMedia update() now:", ""+now);
174           
175            if(currentSentence_index < (sentencesTimes.size()))  {
176               
177                //判断歌词段落的移动
178                if (now >= sentencesTimes.get(currentSentence_index)) {
179                   
180                //  Log.v("ArticleMedia update():", ""+currentSentence_index);                 
181                    mOnSentenceChangeListener.OnSentenceChange(currentSentence_index);
182                    currentSentence_index++;   
183                    currentWord_index=0;
184                    showWord_index=0;
185                }              
186            }
187           
188            if(currentSentence_index <= (sentencesTimes.size())) {
189                //判断歌词单个字的移动
190                int sentenceIndex4word = currentSentence_index-1;
191                LyricSentence currentSentence = sentences.get(sentenceIndex4word);
192                List<LyricWord> words = currentSentence.getWords();
193               
194                if(currentWord_index < words.size()) {
195                   
196                    LyricWord word = words.get(currentWord_index);
197                    if (now >= word.getWord_offset()) {
198                       
199                //      Log.v("KaraokeMedia update():", ""+currentWord_index+"/"+words.size());
200                       
201                        showWord_index = showWord_index + word.getWord().length();
202                       
203                        mOnSentenceChangeListener.OnWordChange(showWord_index);                    
204                        currentWord_index++;
205                    }
206                }
207            }
208           
209            mRedrawHandler.sleep(mMediaDelay);
210        }
211 
212    }
213   
214    private RefreshHandler mRedrawHandler = new RefreshHandler();
215 
216    class RefreshHandler extends Handler {
217 
218        @Override
219        public void handleMessage(Message msg) {
220            karaokeMedia.update();
221        }
222 
223        public void sleep(long delayMillis) {
224            this.removeMessages(0);
225            sendMessageDelayed(obtainMessage(0), delayMillis);
226        }
227    };
228   
229    public void SetOnSentenceChangeListener(
230            OnSentenceChangeListener l) {
231        mOnSentenceChangeListener = l;
232    }
233   
234    OnSentenceChangeListener mOnSentenceChangeListener = null;
235   
236    public interface OnSentenceChangeListener {
237        void OnSentenceChange(int currentSentence_index);
238        void OnWordChange(int showWord_index);
239    }
240   
241    //停止播放文章
242    public static void stopArticleMedia() {
243       
244        mMode=STOP;
245       
246        if(mp3Player!=null) {
247            mp3Player.stop();
248            mp3Player.release();
249            mp3Player=null;
250        }      
251    }
252}

3. [代码][Java]代码    跳至[2][3][4][全屏预览]

001package my.android.karaoke.parse;
002 
003import java.io.BufferedReader;
004import java.io.FileInputStream;
005import java.io.FileNotFoundException;
006import java.io.IOException;
007import java.io.InputStream;
008import java.io.InputStreamReader;
009import java.io.StringReader;
010 
011import org.xmlpull.v1.XmlPullParser;
012import org.xmlpull.v1.XmlPullParserException;
013import org.xmlpull.v1.XmlPullParserFactory;
014 
015import android.content.Context;
016import android.content.res.AssetManager;
017import android.util.Log;
018 
019public class XmlPullFactory {
020   
021    private final static String CODING_TYPE="utf-8";
022 
023    public static XmlPullParser CreateXppFromAssets(String xmlPath,Context context) throws IOException {
024        AssetManager asset = context.getAssets();
025        //return asset.openXmlResourceParser(xmlPath);
026        InputStream inputStream = null ;
027        
028          try {
029        
030           inputStream = asset.open(xmlPath);
031        
032          } catch (IOException e) {
033        
034           Log.e ("tag", e.getMessage());
035        
036          }
037 
038          XmlPullParser xpp = null;
039 
040            try {
041                XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
042               
043                factory.setNamespaceAware(true);
044                xpp = factory.newPullParser();
045 
046            } catch (XmlPullParserException e1) {          
047                e1.printStackTrace();
048            }       
049           
050            String xmltext = "";
051           
052            try {          
053                InputStreamReader inStreamReader = new InputStreamReader(inputStream,CODING_TYPE);             
054                BufferedReader br = new BufferedReader(inStreamReader);
055               
056                String data = null;
057               
058                while((data = br.readLine())!=null)
059                {
060                    xmltext = xmltext + data;
061                }
062               
063                inStreamReader.close();
064                inputStream.close();
065                br.close();
066 
067                StringReader strReader = new StringReader(xmltext);
068                xpp.setInput(strReader);
069               
070            //  strReader.close();
071            } catch (FileNotFoundException e) {        
072                e.printStackTrace();
073            } catch(XmlPullParserException e) {
074                e.printStackTrace();
075            } catch (IOException e) {          
076                e.printStackTrace();
077            }
078           
079            return xpp;
080       
081    }
082   
083    public static XmlPullParser CreateXppFromXml(String xmlPath) {
084       
085        XmlPullParser xpp = null;
086 
087        try {
088            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
089           
090            factory.setNamespaceAware(true);
091            xpp = factory.newPullParser();
092 
093        } catch (XmlPullParserException e1) {          
094            e1.printStackTrace();
095        }       
096       
097        String xmltext = "";
098       
099        try {          
100            FileInputStream fileInStream = new FileInputStream(xmlPath);
101            InputStreamReader inStreamReader = new InputStreamReader(fileInStream,CODING_TYPE);            
102            BufferedReader br = new BufferedReader(inStreamReader);
103           
104            String data = null;
105           
106            while((data = br.readLine())!=null)
107            {
108                xmltext = xmltext + data;
109            }
110           
111            inStreamReader.close();
112            fileInStream.close();
113            br.close();
114 
115            StringReader strReader = new StringReader(xmltext);
116            xpp.setInput(strReader);
117           
118        //  strReader.close();
119        } catch (FileNotFoundException e) {        
120            e.printStackTrace();
121        } catch(XmlPullParserException e) {
122            e.printStackTrace();
123        } catch (IOException e) {          
124            e.printStackTrace();
125        }
126       
127        return xpp;
128    }  
129   
130    public static String getAttrValueByName(String name, XmlPullParser xpp){
131        String valueStr = "";
132       
133        int attrCount = xpp.getAttributeCount();
134        for(int i=0 ; i<attrCount ; i++) {
135            if(name.equals(xpp.getAttributeName(i))){
136                valueStr = xpp.getAttributeValue(i);
137                break;
138            }
139        }
140       
141        return valueStr;
142    }
143}

4. [代码][Java]代码    跳至[2][3][4][全屏预览]

001package my.android.karaoke.parse;
002 
003import java.io.IOException;
004import java.util.ArrayList;
005import java.util.List;
006 
007import org.xmlpull.v1.XmlPullParser;
008import org.xmlpull.v1.XmlPullParserException;
009 
010import my.android.karaoke.bean.LyricSentence;
011import my.android.karaoke.bean.LyricText;
012import my.android.karaoke.bean.LyricWord;
013import android.content.Context;
014import android.util.Log;
015import android.widget.Toast;
016 
017public class LyricParse {
018   
019    /**加载的歌词内容**/
020    public static LyricText getLyricTextNew(String lyricpath,Context context) {    
021        LyricText lyricText = null;    
022        try {
023                String lyricContent = getLyricContent(lyricpath,context); //获取歌词lyric内容字符串
024                Log.v("lrcText",lyricContent );
025                if ( lyricContent != null && lyricContent != "")
026                {
027                    lyricText = new LyricText();
028                    lyricText = getLyricTextFromString(context,lyricContent);
029                    String soundPath = lyricpath.replace(".xml", ".mp3"); //lrc必须要小写
030                    lyricText.setSound_path(soundPath);
031                }
032                //smartText_map.put(textpath, smartText);
033               
034            } catch (Exception e) {
035               e.printStackTrace();
036               //Toast.makeText(context, "无法解析文件:" + textpath, Toast.LENGTH_LONG).show();
037               return null;
038           }
039        //}
040        return lyricText;
041    }
042   
043    public static String getLyricContent(String lyricpath,Context context) throws XmlPullParserException, IOException{
044       
045        String lyricContent="";
046       
047        XmlPullParser xpp = XmlPullFactory.CreateXppFromAssets(lyricpath,context);
048        //XmlPullParser xpp = XmlPullFactory.CreateXppFromXml(lyricpath);
049        int eventType = xpp.getEventType();
050       
051        while(eventType != XmlPullParser.END_DOCUMENT) {
052            if(eventType == XmlPullParser.START_TAG) {
053                String tagName = xpp.getName();
054                if("Lyric_1".equals(tagName)) {
055                    lyricContent = XmlPullFactory.getAttrValueByName("LyricContent",xpp);
056                }
057            }
058            eventType = xpp.next();
059        }
060        return lyricContent;
061    }
062   
063    /**从解密后得到的string解析lrc(直接从内存中解析,不必再写临时文件)*/
064    public static LyricText getLyricTextFromString(Context context,String lrcText) {
065       
066        LyricText lyricText = new LyricText();
067       
068         try {
069            
070            String[] lrcList = lrcText.split("\\["); //将字符串按 [ 拆分为数组
071            List<LyricSentence> sentences = new ArrayList<LyricSentence>(); //歌词段落时间点标签
072            int count = lrcList.length;
073            int sentence_id=0;
074           
075            for (int i = 0 ; i < count; i ++) {
076               
077                if (lrcList[i].trim() != ""){
078                   
079                    String[] lrc_str = lrcList[i].split("\\]");
080                   
081                    //判断是否为歌词部分还是信息部分
082                    if(lrc_str.length<2){
083                       
084                        String[] lrc_info = lrc_str[0].split(":");
085                       
086                        if("ti".equals(lrc_info[0])) {
087                            lyricText.setLyric_ti(lrc_info[1]);
088                            continue;
089                        }
090                       
091                        if("ar".equals(lrc_info[0])) {
092                            lyricText.setLyric_ar(lrc_info[1]);
093                            continue;
094                        }
095                       
096                        if("al".equals(lrc_info[0])) {
097                            lyricText.setLyric_al(lrc_info[1]);
098                            continue;
099                        }
100                       
101                        if("by".equals(lrc_info[0])) {
102                            lyricText.setLyric_by(lrc_info[1]);
103                            continue;
104                        }
105                       
106                        if("offset".equals(lrc_info[0])) {
107                            lyricText.setLyric_offset(lrc_info[1]);
108                            continue;
109                        }
110                       
111                    } else {                       
112                       
113                        LyricSentence sentence = new LyricSentence();
114                        sentence.setSentence_id(sentence_id);                      
115                        sentence_id++;
116                       
117                        String[] lrc_time = lrc_str[0].split(",");
118                        int sentence_offset = Integer.parseInt(lrc_time[0]);
119                        sentence.setSentence_offset(sentence_offset);
120                       
121                        int sentence_duration = Integer.parseInt(lrc_time[1]);
122                        sentence.setSentence_duration(sentence_duration);
123 
124                        parseLyricWord(sentence,lrc_str[1]);
125                       
126                        sentences.add(sentence);
127                    }
128                }
129            }
130            lyricText.setSentences(sentences);
131            Log.v("sentences.size()", ""+sentences.size());
132        }
133        catch (Exception e) {
134            Toast.makeText(context, "处理解析歌词部分出错", Toast.LENGTH_LONG).show();
135            return null;
136       }
137        return lyricText;
138    }
139   
140    public static void parseLyricWord(LyricSentence sentence,String original_sentence){
141       
142        List<LyricWord> words = new ArrayList<LyricWord>();
143        String sentence_str="";
144       
145        String[] words_str = original_sentence.split("\\)");
146        int count = words_str.length;
147       
148        for (int i = 0 ; i < count; i ++) {
149           
150            if(words_str[i].trim() != ""){
151                String[] word_str = words_str[i].split("\\(");             
152                LyricWord word = new LyricWord();
153               
154                word.setWord(word_str[0]);
155                sentence_str = sentence_str+word_str[0];
156               
157                String[] word_time = word_str[1].split(",");
158                int word_offset = Integer.parseInt(word_time[0]);
159                word.setWord_offset(word_offset);
160               
161                int word_duration = Integer.parseInt(word_time[1]);
162                word.setWord_duration(word_duration);
163               
164                words.add(word);
165            }          
166        }
167       
168        sentence.setSentence(sentence_str);
169        sentence.setWords(words);
170    }

5. [文件]Karaoke4Mobile.rar ~ 210KB        下载(405)        [全屏预览

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值