android剪切合并MP3音乐

以前做过一个音乐播放器,基本的功能都有,什么在线播放,下载,歌词显示,分享等。下面是剪切合并代码,算法也有,结合算法才好看代码

[java]  view plain  copy
  1. package com.cdu.hhmusic.utils;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileNotFoundException;  
  6. import java.io.FileOutputStream;  
  7. import java.io.IOException;  
  8. import java.io.RandomAccessFile;  
  9. import java.util.ArrayList;  
  10. import java.util.List;  
  11. /** 
  12.  * 使用注意事项 
  13.  * @作者 胡楠启 
  14.  * 在android中操作肯定需要操作SD卡的权限的。 
  15.  *调用顺序: 
  16.  *1、fenLiData//只要调用了它就会产生中间文件 
  17.  *2、initMP3Frame 
  18.  *3、CutingMp3 
  19.  *4、在调用端,切割完毕后删除中间产生的垃圾文件 
  20.  *String fenLiData = CutingMp3.fenLiData(str1); 
  21.  *File file=new File(fenLiData); 
  22.  *if(file.exists())file.delete(); 
  23.  *原因是在工具端删除中间文件时,这个删除失败。懒得继续画精力去找 ,所以必须在调用端切割完毕后删除, 
  24.  *一避免垃圾文件占用内存 
  25.  */  
  26.   
  27. public class CaoZuoMp3Utils {  
  28.     /** 
  29.      * 返回分离出MP3文件中的数据帧的文件路径 
  30.      * 
  31.      * @作者 胡楠启 
  32.      * 
  33.      */  
  34.     public static String fenLiData(String path) throws IOException {  
  35.         File file = new File(path);// 原文件  
  36.         File file1 = new File(path + "01");// 分离ID3V2后的文件,这是个中间文件,最后要被删除  
  37.         File file2 = new File(path + "001");// 分离id3v1后的文件  
  38.         RandomAccessFile rf = new RandomAccessFile(file, "rw");// 随机读取文件  
  39.         FileOutputStream fos = new FileOutputStream(file1);  
  40.         byte ID3[] = new byte[3];  
  41.         rf.read(ID3);  
  42.         String ID3str = new String(ID3);  
  43.         // 分离ID3v2  
  44.         if (ID3str.equals("ID3")) {  
  45.             rf.seek(6);  
  46.             byte[] ID3size = new byte[4];  
  47.             rf.read(ID3size);  
  48.             int size1 = (ID3size[0] & 0x7f) << 21;  
  49.             int size2 = (ID3size[1] & 0x7f) << 14;  
  50.             int size3 = (ID3size[2] & 0x7f) << 7;  
  51.             int size4 = (ID3size[3] & 0x7f);  
  52.             int size = size1 + size2 + size3 + size4 + 10;  
  53.             rf.seek(size);  
  54.             int lens = 0;  
  55.             byte[] bs = new byte[1024*4];  
  56.             while ((lens = rf.read(bs)) != -1) {  
  57.                 fos.write(bs, 0, lens);  
  58.             }  
  59.             fos.close();  
  60.             rf.close();  
  61.         } else {// 否则完全复制文件  
  62.             int lens = 0;  
  63.             rf.seek(0);  
  64.             byte[] bs = new byte[1024*4];  
  65.             while ((lens = rf.read(bs)) != -1) {  
  66.                 fos.write(bs, 0, lens);  
  67.             }  
  68.             fos.close();  
  69.             rf.close();  
  70.         }  
  71.         RandomAccessFile raf = new RandomAccessFile(file1, "rw");  
  72.         byte TAG[] = new byte[3];  
  73.         raf.seek(raf.length() - 128);  
  74.         raf.read(TAG);  
  75.         String tagstr = new String(TAG);  
  76.         if (tagstr.equals("TAG")) {  
  77.             FileOutputStream fs = new FileOutputStream(file2);  
  78.             raf.seek(0);  
  79.             byte[] bs=new byte[(int)(raf.length()-128)];  
  80.             raf.read(bs);  
  81.             fs.write(bs);  
  82.             raf.close();  
  83.             fs.close();  
  84.         } else {// 否则完全复制内容至file2  
  85.             FileOutputStream fs = new FileOutputStream(file2);  
  86.             raf.seek(0);  
  87.             byte[] bs = new byte[1024*4];  
  88.             int len = 0;  
  89.             while ((len = raf.read(bs)) != -1) {  
  90.                 fs.write(bs, 0, len);  
  91.             }  
  92.             raf.close();  
  93.             fs.close();  
  94.         }  
  95.         if (file1.exists())// 删除中间文件  
  96.         {  
  97.             file1.delete();  
  98.   
  99.         }  
  100.         return file2.getAbsolutePath();  
  101.     }  
  102.   
  103.     /** 
  104.      * 分离出数据帧每一帧的大小并存在list数组里面 
  105.      *失败则返回空 
  106.      * @param path 
  107.      * @return 
  108.      * @throws IOException 
  109.      */  
  110.     public static List<Integer> initMP3Frame(String path)  {  
  111.             File file = new File(path);  
  112.             List<Integer> list = new ArrayList<>();  
  113.         /*  int framSize=0; 
  114.             RandomAccessFile rad = new RandomAccessFile(file, "rw"); 
  115.             byte[] head = new byte[4]; 
  116.             rad.seek(framSize); 
  117.             rad.read(head); 
  118.             int bitRate = getBitRate((head[2] >> 4) & 0x0f) * 1000; 
  119.             int sampleRate = getsampleRate((head[2] >> 2) & 0x03); 
  120.             int paing = (head[2] >> 1) & 0x01; 
  121.             int len = 144 * bitRate / sampleRate + paing; 
  122.             for(int i=0,lens=(int)(file.length())/len;i<lens;i++){ 
  123.                 list.add(len);// 将数据帧的长度添加进来 
  124.             }*/  
  125.         int framSize = 0;  
  126.         RandomAccessFile rad = null;  
  127.         try {  
  128.             rad = new RandomAccessFile(file, "rw");  
  129.         } catch (FileNotFoundException e) {  
  130.             e.printStackTrace();  
  131.         }  
  132.         while (framSize < file.length()) {  
  133.             byte[] head = new byte[4];  
  134.             try {  
  135.                 rad.seek(framSize);  
  136.             } catch (IOException e) {  
  137.                 e.printStackTrace();  
  138.             }  
  139.             try {  
  140.                 rad.read(head);  
  141.             } catch (IOException e) {  
  142.                 e.printStackTrace();  
  143.             }  
  144.             int bitRate = getBitRate((head[2] >> 4) & 0x0f) * 1000;  
  145.             int sampleRate = getsampleRate((head[2] >> 2) & 0x03);  
  146.             int paing = (head[2] >> 1) & 0x01;  
  147.             if(bitRate==0||sampleRate==0)return null;  
  148.             int len = 144 * bitRate / sampleRate + paing;  
  149.             list.add(len);// 将数据帧的长度添加进来  
  150.             framSize += len;  
  151.         }  
  152.             return list;  
  153.     }  
  154.   
  155.     /** 
  156.      * 返回切割后的MP3文件的路径 返回null则切割失败 开始时间和结束时间的整数部分都是秒,以秒为单位 
  157.      * 
  158.      * 
  159.      * @param list 
  160.      * @param startTime 
  161.      * @param stopTime 
  162.      * @return 
  163.      * @throws IOException 
  164.      */  
  165.     public static String CutingMp3(String path, String name,  
  166.                                    List<Integer> list, double startTime, double stopTime)  
  167.             throws IOException {  
  168.         File file = new File(path);  
  169.         String luJing="/storage/emulated/0/"+"HH音乐播放器/切割/";  
  170.         File f=new File(luJing);  
  171.         f.mkdirs();  
  172.         int start = (int) (startTime / 0.026);  
  173.         int stop = (int) (stopTime / 0.026);  
  174.         if ((start > stop) || (start < 0) || (stop < 0) || (stop > list.size())) {  
  175.             return null;  
  176.         } else {  
  177.             long seekStart = 0;// 开始剪切的字节的位置  
  178.             for (int i = 0; i < start; i++) {  
  179.                 seekStart += list.get(i);  
  180.             }  
  181.             long seekStop = 0;// 结束剪切的的字节的位置  
  182.             for (int i = 0; i < stop; i++) {  
  183.                 seekStop += list.get(i);  
  184.             }  
  185.             RandomAccessFile raf = new RandomAccessFile(file, "rw");  
  186.             raf.seek(seekStart);  
  187.             File file1 = new File(luJing + name + "(HH切割).mp3");  
  188.             FileOutputStream out = new FileOutputStream(file1);  
  189.             byte[] bs=new byte[(int)(seekStop-seekStart)];  
  190.             raf.read(bs);  
  191.             out.write(bs);  
  192.             raf.close();  
  193.             out.close();  
  194.             File filed=new File(path);  
  195.             if(filed.exists())  
  196.                  filed.delete();  
  197.             return file1.getAbsolutePath();  
  198.         }  
  199.   
  200.     }  
  201.   
  202.     private static int getBitRate(int i) {  
  203.         int a[] = {0,32404856648096112128160192224,  
  204.                 256320,0 };  
  205.         return a[i];  
  206.     }  
  207.   
  208.     private static int getsampleRate(int i) {  
  209.         int a[] = { 441004800032000,0 };  
  210.         return a[i];  
  211.     }  
  212.     /** 
  213.      * 返回合并后的文件的路径名,默认放在第一个文件的目录下 
  214.      * @param path 
  215.      * @param path1 
  216.      * @param name 
  217.      * @return 
  218.      * @throws IOException 
  219.      */  
  220.     public static String heBingMp3(String path,String path1,String name) throws IOException{  
  221.         String fenLiData = fenLiData(path);  
  222.         String fenLiData2 = fenLiData(path1);  
  223.         File file=new File(fenLiData);  
  224.         File file1=new File(fenLiData2);  
  225.         String luJing="/storage/emulated/0/"+"HH音乐播放器/合并/";  
  226.         File f=new File(luJing);  
  227.         f.mkdirs();  
  228.         //生成处理后的文件  
  229.         File file2=new File(luJing+name+"(HH合并).mp3");  
  230.         FileInputStream in=new FileInputStream(file);  
  231.         FileOutputStream out=new FileOutputStream(file2);  
  232.         byte bs[]=new byte[1024*4];  
  233.         int len=0;  
  234.         //先读第一个  
  235.         while((len=in.read(bs))!=-1){  
  236.             out.write(bs,0,len);  
  237.         }  
  238.         in.close();  
  239.         out.close();  
  240.         //再读第二个  
  241.         in=new FileInputStream(file1);  
  242.         out=new FileOutputStream(file2,true);//在文件尾打开输出流  
  243.         len=0;  
  244.         byte bs1[]=new byte[1024*4];  
  245.         while((len=in.read(bs1))!=-1){  
  246.             out.write(bs1,0,len);  
  247.         }  
  248.         in.close();  
  249.         out.close();  
  250.         if(file.exists())file.delete();  
  251.         if(file1.exists())file1.delete();  
  252.         return file2.getAbsolutePath();  
  253.     }  
  254. }  
 作用就是可以剪切合并音乐,各种路劲需要根据实际情况修改。

用法:剪切

 String fenLiData = CaoZuoMp3Utils.fenLiData(str);
                        final List<Integer> list = CaoZuoMp3Utils.initMP3Frame
                                (fenLiData);
                        if(list==null){
                            han.post(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(Cut_Mp3_Activity.this, "剪切失败",
                                            Toast.LENGTH_SHORT).show();
                                    prodiialog.dismiss();
                                }
                            });
                        }else{
                            final String path = CaoZuoMp3Utils.CutingMp3(fenLiData, cuting_name,
                                    list,
                                    start, stop);
                            final File file = new File(fenLiData);

合并:

 final String s = CaoZuoMp3Utils.heBingMp3(path, path1, name);

因为是耗时操作所以需要放在线程中进行。

猜你喜欢

转载自blog.csdn.net/laowu119119/article/details/70800144