写我的程序,但它不能很好地工作,我不知道我错在哪里。在此之前我使用byte []来存储来自wav的数据(它工作得很好但很吵)所以我切换到short [],但结果非常糟糕。
这是我的代码:
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;
}
}
你能帮我吗?非常感谢你!答案 0 :(得分: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;
}
看起来你正在接受原始字节并简单地将它们转换为短路,但每个短路需要文件中两个字节的数据。 (请参阅shortArrayToByteArray函数中的处理方法)。从文件读取原始短路的最简单方法是使用DataInputStream。不幸的是,您还需要担心字节顺序,因此您需要从guava获取LittleEndianDataInputStream,或者您可以编写自己的类来执行相同的操作,例如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,或者更好地获取媒体数据的大小,并使用它来构建一个正确大小的数组。但是,这些都不会确保您仍然可以执行操作,因为您尝试将整个文件放在内存中。相反,尝试阅读每个文件的较小的chucnks,并混合它们,然后读取下一个块。
但是在你开始工作之前我不会担心这一切。