android剪切合并MP3音乐

/ Android / 没有评论 / 1473浏览

android剪切合并MP3音乐

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

package com.cdu.hhmusic.utils;  

import java.io.File;  
import java.io.FileInputStream;  
import java.io.FileNotFoundException;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.RandomAccessFile;  
import java.util.ArrayList;  
import java.util.List;  
/** 
 * 使用注意事项 
 * @作者 胡楠启 
 * 在android中操作肯定需要操作SD卡的权限的。 
 *调用顺序: 
 *1、fenLiData//只要调用了它就会产生中间文件 
 *2、initMP3Frame 
 *3、CutingMp3 
 *4、在调用端,切割完毕后删除中间产生的垃圾文件 
 *String fenLiData = CutingMp3.fenLiData(str1); 
 *File file=new File(fenLiData); 
 *if(file.exists())file.delete(); 
 *原因是在工具端删除中间文件时,这个删除失败。懒得继续画精力去找 ,所以必须在调用端切割完毕后删除, 
 *一避免垃圾文件占用内存 
 */  
public class CaoZuoMp3Utils {  
    /** 
     * 返回分离出MP3文件中的数据帧的文件路径 
     * 
     * @作者 胡楠启 
     * 
     */  
    public static String fenLiData(String path) throws IOException {  
        File file = new File(path);// 原文件  
        File file1 = new File(path + "01");// 分离ID3V2后的文件,这是个中间文件,最后要被删除  
        File file2 = new File(path + "001");// 分离id3v1后的文件  
        RandomAccessFile rf = new RandomAccessFile(file, "rw");// 随机读取文件  
        FileOutputStream fos = new FileOutputStream(file1);  
        byte ID3[] = new byte[3];  
        rf.read(ID3);  
        String ID3str = new String(ID3);  
        // 分离ID3v2  
        if (ID3str.equals("ID3")) {  
            rf.seek(6);  
            byte[] ID3size = new byte[4];  
            rf.read(ID3size);  
            int size1 = (ID3size[0] & 0x7f) << 21;  
            int size2 = (ID3size[1] & 0x7f) << 14;  
            int size3 = (ID3size[2] & 0x7f) << 7;  
            int size4 = (ID3size[3] & 0x7f);  
            int size = size1 + size2 + size3 + size4 + 10;  
            rf.seek(size);  
            int lens = 0;  
            byte[] bs = new byte[1024*4];  
            while ((lens = rf.read(bs)) != -1) {  
                fos.write(bs, 0, lens);  
            }  
            fos.close();  
            rf.close();  
        } else {// 否则完全复制文件  
            int lens = 0;  
            rf.seek(0);  
            byte[] bs = new byte[1024*4];  
            while ((lens = rf.read(bs)) != -1) {  
                fos.write(bs, 0, lens);  
            }  
            fos.close();  
            rf.close();  
        }  
        RandomAccessFile raf = new RandomAccessFile(file1, "rw");  
        byte TAG[] = new byte[3];  
        raf.seek(raf.length() - 128);  
        raf.read(TAG);  
        String tagstr = new String(TAG);  
        if (tagstr.equals("TAG")) {  
            FileOutputStream fs = new FileOutputStream(file2);  
            raf.seek(0);  
            byte[] bs=new byte[(int)(raf.length()-128)];  
            raf.read(bs);  
            fs.write(bs);  
            raf.close();  
            fs.close();  
        } else {// 否则完全复制内容至file2  
            FileOutputStream fs = new FileOutputStream(file2);  
            raf.seek(0);  
            byte[] bs = new byte[1024*4];  
            int len = 0;  
            while ((len = raf.read(bs)) != -1) {  
                fs.write(bs, 0, len);  
            }  
            raf.close();  
            fs.close();  
        }  
        if (file1.exists())// 删除中间文件  
        {  
            file1.delete();  

        }  
        return file2.getAbsolutePath();  
    }  

    /** 
     * 分离出数据帧每一帧的大小并存在list数组里面 
     *失败则返回空 
     * @param path 
     * @return 
     * @throws IOException 
     */  
    public static List<Integer> initMP3Frame(String path)  {  
        File file = new File(path);  
        List<Integer> list = new ArrayList<>();  
        /*  int framSize=0; 
            RandomAccessFile rad = new RandomAccessFile(file, "rw"); 
            byte[] head = new byte[4]; 
            rad.seek(framSize); 
            rad.read(head); 
            int bitRate = getBitRate((head[2] >> 4) & 0x0f) * 1000; 
            int sampleRate = getsampleRate((head[2] >> 2) & 0x03); 
            int paing = (head[2] >> 1) & 0x01; 
            int len = 144 * bitRate / sampleRate + paing; 
            for(int i=0,lens=(int)(file.length())/len;i<lens;i++){ 
                list.add(len);// 将数据帧的长度添加进来 
            }*/  
        int framSize = 0;  
        RandomAccessFile rad = null;  
        try {  
            rad = new RandomAccessFile(file, "rw");  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        }  
        while (framSize < file.length()) {  
            byte[] head = new byte[4];  
            try {  
                rad.seek(framSize);  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            try {  
                rad.read(head);  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            int bitRate = getBitRate((head[2] >> 4) & 0x0f) * 1000;  
            int sampleRate = getsampleRate((head[2] >> 2) & 0x03);  
            int paing = (head[2] >> 1) & 0x01;  
            if(bitRate==0||sampleRate==0)return null;  
            int len = 144 * bitRate / sampleRate + paing;  
            list.add(len);// 将数据帧的长度添加进来  
            framSize += len;  
        }  
        return list;  
    }  

    /** 
     * 返回切割后的MP3文件的路径 返回null则切割失败 开始时间和结束时间的整数部分都是秒,以秒为单位 
     * 
     * 
     * @param list 
     * @param startTime 
     * @param stopTime 
     * @return 
     * @throws IOException 
     */  
    public static String CutingMp3(String path, String name,  
                                   List<Integer> list, double startTime, double stopTime)  
        throws IOException {  
        File file = new File(path);  
        String luJing="/storage/emulated/0/"+"HH音乐播放器/切割/";  
        File f=new File(luJing);  
        f.mkdirs();  
        int start = (int) (startTime / 0.026);  
        int stop = (int) (stopTime / 0.026);  
        if ((start > stop) || (start < 0) || (stop < 0) || (stop > list.size())) {  
            return null;  
        } else {  
            long seekStart = 0;// 开始剪切的字节的位置  
            for (int i = 0; i < start; i++) {  
                seekStart += list.get(i);  
            }  
            long seekStop = 0;// 结束剪切的的字节的位置  
            for (int i = 0; i < stop; i++) {  
                seekStop += list.get(i);  
            }  
            RandomAccessFile raf = new RandomAccessFile(file, "rw");  
            raf.seek(seekStart);  
            File file1 = new File(luJing + name + "(HH切割).mp3");  
            FileOutputStream out = new FileOutputStream(file1);  
            byte[] bs=new byte[(int)(seekStop-seekStart)];  
            raf.read(bs);  
            out.write(bs);  
            raf.close();  
            out.close();  
            File filed=new File(path);  
            if(filed.exists())  
                filed.delete();  
            return file1.getAbsolutePath();  
        }  

    }  

    private static int getBitRate(int i) {  
        int a[] = {0,32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224,  
                   256, 320,0 };  
        return a[i];  
    }  

    private static int getsampleRate(int i) {  
        int a[] = { 44100, 48000, 32000,0 };  
        return a[i];  
    }  
    /** 
     * 返回合并后的文件的路径名,默认放在第一个文件的目录下 
     * @param path 
     * @param path1 
     * @param name 
     * @return 
     * @throws IOException 
     */  
    public static String heBingMp3(String path,String path1,String name) throws IOException{  
        String fenLiData = fenLiData(path);  
        String fenLiData2 = fenLiData(path1);  
        File file=new File(fenLiData);  
        File file1=new File(fenLiData2);  
        String luJing="/storage/emulated/0/"+"HH音乐播放器/合并/";  
        File f=new File(luJing);  
        f.mkdirs();  
        //生成处理后的文件  
        File file2=new File(luJing+name+"(HH合并).mp3");  
        FileInputStream in=new FileInputStream(file);  
        FileOutputStream out=new FileOutputStream(file2);  
        byte bs[]=new byte[1024*4];  
        int len=0;  
        //先读第一个  
        while((len=in.read(bs))!=-1){  
            out.write(bs,0,len);  
        }  
        in.close();  
        out.close();  
        //再读第二个  
        in=new FileInputStream(file1);  
        out=new FileOutputStream(file2,true);//在文件尾打开输出流  
        len=0;  
        byte bs1[]=new byte[1024*4];  
        while((len=in.read(bs1))!=-1){  
            out.write(bs1,0,len);  
        }  
        in.close();  
        out.close();  
        if(file.exists())file.delete();  
        if(file1.exists())file1.delete();  
        return file2.getAbsolutePath();  
    }  
}  

作用就是可以剪切合并音乐,各种路劲需要根据实际情况修改。

用法:剪切

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);

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