混合在Android中使用的短阵两个文件的音频WAV [英] Mix two files audio wav on android use short array

查看:244
本文介绍了混合在Android中使用的短阵两个文件的音频WAV的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给我写的程序,但它不工作这么好,我不知道我错了。在此之前,我用的byte []存储从WAV数据(它的工作原理pretty不错,但嘈杂的),所以我切换到短[],但结果​​是非常糟糕的。

to write my programs, but it does not work so well, I do not know where I was wrong. Before that I used byte [] to store data from wav (it works pretty good but noisy) so I switched to short [], but the results were very bad.

这是我的code:

public class Mix extends Activity {


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    try {
        mixSound();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

private void mixSound() throws IOException {

    in1 = getResources().openRawResource(R.raw.media_b); //16-bit little-endian, 1411kbps, 44100Hz, 2 channels 
    in2 = getResources().openRawResource(R.raw.media_c); //16-bit little-endian, 1411kbps, 44100Hz, 2 channels 

    List<Short> music1  =  createMusicArray(in1);
    List<Short> music2  =  createMusicArray(in2);

    completeStreams(music1, music2);

    short[] arrayMusic1 = buildShortArray(music1);;
    short[] arrayMusic2 = buildShortArray(music2);

    output = new short[arrayMusic1.length];

    for (int i = 0; i < output.length; i++) {


    }

    saveToFile();
}




/**
 * createMusicArray reads the stream and returns a list of short objects (the samples)
 */
public List<Short> createMusicArray (InputStream ins) throws IOException {
    List<Short> musicList = new ArrayList<Short>();

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] byteArray           = new byte[50*1024];
    int i = Integer.MAX_VALUE;
    while ((i = ins.read(byteArray, 0, byteArray.length)) > 0) {
        baos.write(byteArray, 0, i);
    }

    for (int j = 0; j < byteArray.length; j++) {
        short objShort = (short)(byteArray[j]); 
        musicList.add(objShort);
    }

    return musicList;

}

/**
 * completeStreams normalizes the streams by adding  a series of '0' shorts at the end of smaller files. At the end the 2 files have all the same length.
 */
public void completeStreams(List<Short> mListShort_1, List<Short> mListShort_2) {
    //TODO: check length
    int size_a = mListShort_1.size();
    int size_b = mListShort_2.size();

    if (size_a > size_b){
        // adding series of '0'
        for (int i = size_b+1; i <= size_a; i++) {
            mListShort_2.set(i, (short) 0);
        }
    } else if (size_a < size_b) {
        for (int i = size_a+1; i <= size_b; i++) {
            mListShort_1.set(i, (short) 0);
        }
    } else {
        //do nothing
    }
}




private byte[] shortArrayToByteArray(short[] shortArr) {
    /**
    int index;
    int iterations = shortArr.length;
    ByteBuffer byteBuffer = ByteBuffer.allocate(shortArr.length * 2);

    for(index = 0; index != iterations; ++index){
      byteBuffer.putShort(shortArr[index]);    
    }

    return byteBuffer.array();
    */

    int short_index, byte_index;
    int iterations = shortArr.length;

    byte [] buffer = new byte[shortArr.length * 2];

    short_index = byte_index = 0;

    for(/*NOP*/; short_index != iterations; /*NOP*/) {
        buffer[byte_index]      =   (byte) (shortArr[short_index] & 0x00FF); 
        buffer[byte_index + 1]  =   (byte) ((shortArr[short_index] & 0xFF00) >> 8);

        ++short_index; byte_index += 2;
    }

    return buffer;
}

private byte[] intToByteArray(int i) {
    byte[] b = new byte[4];
    b[0]     = (byte) (i & 0x00FF);
    b[1]     = (byte) ((i >> 8)  & 0x000000FF);
    b[2]     = (byte) ((i >> 16) & 0x000000FF);
    b[3]     = (byte) ((i >> 24) & 0x000000FF);
    return b;
}

private byte[] shortToByteArray(short data) {
    byte[] b = new byte[2];
    b[0] = (byte) (data & 0xff);
    b[1] = (byte) ((data >> 8) & 0xff);
    return b;
}

public static long byteArrayToLong(byte[] b) {
    int  start = 0;
    int      i = 0;
    int    len = 4;
    int    cnt = 0;
    byte[] tmp = new byte[len];
    for (i = start; i < (start + len); i++) {
        tmp[cnt] = b[i];
        cnt++;
    }
    long accum = 0;
    i = 0;
    for (int shiftBy = 0; shiftBy < 32; shiftBy += 8) {
        accum |= ((long) (tmp[i] & 0xff)) << shiftBy;
        i++;
    }
    return accum;
}

}

你能帮助我。非常感谢你!

Can you help me. Thank you very much!

推荐答案

您的主要问题是在这个函数:

Your main problem is in this function:

/**
 * createMusicArray reads the stream and returns a list of short objects (the samples)
 */
public List<Short> createMusicArray (InputStream ins) throws IOException {
    List<Short> musicList = new ArrayList<Short>();

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] byteArray           = new byte[50*1024];
    int i = Integer.MAX_VALUE;
    while ((i = ins.read(byteArray, 0, byteArray.length)) > 0) {
        baos.write(byteArray, 0, i);
    }

    for (int j = 0; j < byteArray.length; j++) {
        short objShort = (short)(byteArray[j]); 
        musicList.add(objShort);
    }

    return musicList;
}

看来你正在服用的原始字节,并简单地将它们转换为短裤,但每个短需要的数据ROM两个字节的文件中。 (看你如何在shortArrayToByteArray功能正确处理这一点)。读取原始短裤掀起了文件的最简单方法是使用一个DataInputStream。不幸的是,你还需要担心字节顺序,所以你需要从番石榴得到LittleEndianDataInputStream ,或者你可以写自己的课上做同样的事情,像<一个href=\"http://stackoverflow.com/questions/8028094/java-datainputstream-replacement-for-endianness\">this,如果你不想导入整个番石榴库。试试这个(未经测试,所以你可能需要调整它):

It seems you are taking raw bytes and simply casting them to shorts, but each short needs the data rom two bytes in the file. (see how you handled this correctly in your shortArrayToByteArray function). The easiest way to read raw shorts off a file is with a DataInputStream. Unfortunately, you also need to worry about byte order, so you need to get LittleEndianDataInputStream from guava, or you could write your own class to do the same thing, like this, if you don't want to import the whole guava library. Try this (untested, so you might have to tweak it):

/**
 * createMusicArray reads the stream and returns a list of short objects (the samples)
 */
public List<Short> createMusicArray (InputStream ins) throws IOException {
    LittleEndianDataInputStream dis = new LittleEndianDataInputStream(ins);

    while (true) {
        try {
            short d = dis.readShort();
            musicList.add(d);
        } catch( EOFException e ) {
            break;
        }
    }

    return musicList;
}

作为一个侧面说明,它是pretty低效(和混乱)来存储在列表中的所有数据,然后将其转移到一个数组。你应该考虑只使用一个ArrayList,或者更好的获取媒体数据的大小和使用,要建立正确的尺寸摆在首位的数组。然而,没有这些东西将确保,因为你正试图把整个文件在内存中,你仍然可以执行的操作。相反,尝试读取每个文件的小chucnks,和混合这些,然后读取下一个块。

As a side note, it's pretty inefficient (and confusing) to store all that data in list and then transfer it to an array. You should consider just using an ArrayList, or better yet getting the size of the media data and using that to build an array of the correct size in the first place. However, none of those things will ensure that you can still perform the operation because you are trying to put the whole file in memory. Instead, try reading smaller chucnks of each file, and mixing those, and then reading the next chunk.

但我不会担心这一切,直到你得到这个工作。

But I wouldn't worry about all that until you get this working.

这篇关于混合在Android中使用的短阵两个文件的音频WAV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆