[英]Mix two files audio wav on android use short array
編寫我的程序,但是效果不是很好,我不知道自己哪里寫錯了。 在此之前,我使用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;
}
}
你能幫助我嗎。 非常感謝你!
您的主要問題在於此功能:
/**
* 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,或者如果您不想導入整個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,或者更好地獲取媒體數據的大小,並首先使用它來構建正確大小的數組。 但是,所有這些都不能確保您仍可以執行該操作,因為您正在嘗試將整個文件放入內存中。 取而代之的是,嘗試讀取每個文件的較小塊,並將其混合,然后讀取下一個塊。
但是在您開始工作之前,我不會擔心所有這些。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.