1

自分のプログラムを書くことはできませんが、うまく機能しません。どこが間違っていたのかわかりません。その前に、バイト [] を使用して wav からのデータを格納していました (かなりうまく機能しますが、ノイズが多い)。そのため、短い [] に切り替えましたが、結果は非常に悪かったです。

この私のコード:

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

}

手伝って頂けますか。どうもありがとうございました!

4

1 に答える 1

1

あなたの主な問題は、この関数にあります:

/**
 * 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;
}

生のバイトを取得して単にショートにキャストしているようですが、各ショートにはファイル内の 2 バイトのデータが必要です。( shortArrayToByteArray 関数でこれを正しく処理した方法を参照してください)。ファイルから raw short を読み取る最も簡単な方法は、DataInputStream を使用することです。残念ながら、バイトオーダーについても心配する必要があるため、 guava から LittleEndianDataInputStream を取得する必要がありますまたは、guavaライブラリ全体をインポートしたくない場合は、thisのように、独自のクラスを記述して同じことを行うこともできます。これを試してください(テストされていないため、微調整する必要があるかもしれません):

/**
 * 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;
}

補足として、すべてのデータをリストに格納してから配列に転送するのは、かなり非効率的です (そして混乱を招きます)。単に ArrayList を使用するか、メディア データのサイズを取得し、それを使用して最初に正しいサイズの配列を作成することを検討する必要があります。ただし、ファイル全体をメモリに入れようとしているため、操作を実行できることを保証するものはありません。代わりに、各ファイルの小さなチャンクを読み取り、それらを混合してから、次のチャンクを読み取ってみてください。

しかし、あなたがこれを機能させるまで、私はそのすべてについて心配することはありません.

于 2013-05-31T14:59:16.750 に答える