gpt4 book ai didi

java - 在 Android 上合并两个 WAVE 文件(连接)

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:30:00 25 4
gpt4 key购买 nike

我已经尝试在 Android 上合并两个 WAVE 文件很长一段时间了,但似乎真的无法让它正常工作。

一切看起来都很好,文件被读取并写入输出文件,该文件在稍后阶段也是可读的,并且具有我希望看到的文件大小。

应用程序完成合并后立即出现问题。此消息将显示在日志中:error occurred in updateListener, recording is aborted 这是来自 extAudioRecorder 的消息并在 OnRecordPositionUpdateListener 到达 catch 子句时出现(异常具有以下 detailMessage:写入失败:EBADF(错误文件编号))。这似乎没有破坏任何东西,所以我不太担心这一点。

当我尝试创建一个 MediaPlayer 时真正的问题出现了并调用setDataSource(String path)在 MediaPlayer 实例上。每当我对合并文件执行此操作时,日志中都会显示以下错误消息:无法创建媒体播放器(抛出的 IOException 包含以下 detailMessage:< strong>setDataSourceFD 失败。: status=0x80000000)。请注意,文件第一次可以完美播放(第一个文件不是由 combineWaveFiles() 方法制作的)。该错误消息似乎表明音频文件的格式不正确和/或 MediaPlayer 无法读取。

我的问题是,是否有人发现下面的代码有任何真正的问题(我知道它在很多方面都不是最优的,但我更愿意先让它工作,然后再担心性能)。

public static String MergeRecordings(String cumulativeFile, String recordFile, int sampleRate, int bpp, int bufferSize, int channels) {
if (cumulativeFile == null) {
return recordFile;
} else if (recordFile == null) {
return cumulativeFile;
}

String outputFile = FileUtils.getFilePath(null, MDSettings.shared().getMainActivity());
FileUtils.combineWaveFiles(cumulativeFile, recordFile, outputFile, sampleRate, bpp, bufferSize, channels);

//FileUtils.removeFile(cumulativeFile);
//FileUtils.removeFile(recordFile);

return outputFile;
}

//creates a new file containing file1 + file2 stuck together as such.
private static void combineWaveFiles(String file1, String file2, String outputFile, int sampleRate, int bpp, int bufferSize, int channels) {
FileInputStream in1 = null, in2 = null;
FileOutputStream out = null;
long longSampleRate = sampleRate;
long byteRate = sampleRate * channels * bpp / 8;

byte[] data;

try {
try {
in1 = new FileInputStream(file1);
} catch (Exception e) { }

try {
in2 = new FileInputStream(file2);
} catch (FileNotFoundException e) { }

out = new FileOutputStream(outputFile);

long file1Size = 0;
long file2Size = 0;

if (in1 != null) { file1Size = in1.getChannel().size() - 44; }
if (in2 != null) { file2Size = in2.getChannel().size() - 44; }

long totalAudioLen = file1Size + file2Size;
long totalDataLen = totalAudioLen + 36;

FileUtils.writeWaveFileHeader(out, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate, bpp);

if (in1 != null) {
in1.skip(44);
data = new byte[bufferSize];

if (file1Size < bufferSize) {
data = new byte[(int)file1Size];
}

while (in1.read(data) != -1) {
out.write(data);

file1Size -= bufferSize;

if (file1Size <= 0) {
break;
} else if (file1Size < bufferSize) {
data = new byte[(int)file1Size];
}
}
}

if (in2 != null) {
in2.skip(44);
data = new byte[bufferSize];

if (file2Size < bufferSize) {
data = new byte[(int)file2Size];
}

while (in2.read(data) != -1) {
out.write(data);

file2Size -= bufferSize;

if (file2Size <= 0) {
break;
} else if (file2Size < bufferSize) {
data = new byte[(int)file2Size];
}
}
}

out.close();
if (in1 != null) { in1.close(); }
if (in2 != null) { in2.close(); }
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

private static void writeWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen, long longSampleRate, int channels, long byteRate, int bpp)
throws IOException {

byte[] header = new byte[44];

header[0] = 'R';
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte)(totalDataLen & 0xff);
header[5] = (byte)((totalDataLen >> 8) & 0xff);
header[6] = (byte)((totalDataLen >> 16) & 0xff);
header[7] = (byte)((totalDataLen >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f';
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16;
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = 1;
header[21] = 0;
header[22] = (byte) channels;
header[23] = 0;
header[24] = (byte)(longSampleRate & 0xff);
header[25] = (byte)((longSampleRate >> 8) & 0xff);
header[26] = (byte)((longSampleRate >> 16) & 0xff);
header[27] = (byte)((longSampleRate >> 24) & 0xff);
header[28] = (byte)(byteRate & 0xff);
header[29] = (byte)((byteRate >> 8) & 0xff);
header[30] = (byte)((byteRate >> 16) & 0xff);
header[31] = (byte)((byteRate >> 24) & 0xff);
header[32] = (byte)(channels * bpp); //(2 * 16 / 8);
header[33] = 0;
header[34] = (byte)bpp;
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte)(totalAudioLen & 0xff);
header[41] = (byte)((totalAudioLen >> 8) & 0xff);
header[42] = (byte)((totalAudioLen >> 16) & 0xff);
header[43] = (byte)((totalAudioLen >> 24) & 0xff);

out.write(header, 0, 44);
}

此代码的大部分来自 this answer .

最佳答案

我在我的 Android 应用程序中正是这样做的。我根据用户选择合并多个文件,而不是两个。我使用 AsyncTask 在后台合并样本。在这里看看。只需过滤您需要的部分。如果你对我的应用程序感到好奇,它叫做 Sound Recorder + Pro ,除了合并,我还混合,添加回声和放大样本:

    @Override
protected Void doInBackground(Void... params) {

isProcessingOn=true;
try {
DataOutputStream amplifyOutputStream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(Environment.getExternalStorageDirectory() + "/Soundrecpluspro/" + year +"-"+ month +"-"+ date +"-"+ hour+"-" + min +"-"+ sec+"ME.wav")));
DataInputStream[] mergeFilesStream = new DataInputStream[selection.size()];
long[] sizes=new long[selection.size()];
for(int i=0; i<selection.size(); i++) {
File file = new File(Environment.getExternalStorageDirectory() + "/Soundrecpluspro/" +selection.get(i));
sizes[i] = (file.length()-44)/2;
}
for(int i =0; i<selection.size(); i++) {
mergeFilesStream[i] =new DataInputStream(new BufferedInputStream(new FileInputStream(Environment.getExternalStorageDirectory() + "/Soundrecpluspro/" +selection.get(i))));

if(i == selection.size()-1) {
mergeFilesStream[i].skip(24);
byte[] sampleRt = new byte[4];
mergeFilesStream[i].read(sampleRt);
ByteBuffer bbInt = ByteBuffer.wrap(sampleRt).order(ByteOrder.LITTLE_ENDIAN);
RECORDER_SAMPLERATE = bbInt.getInt();
mergeFilesStream[i].skip(16);
}
else {
mergeFilesStream[i].skip(44);
}

}

for(int b=0; b<selection.size(); b++) {
for(int i=0; i<(int)sizes[b]; i++) {
byte[] dataBytes = new byte[2];
try {
dataBytes[0] = mergeFilesStream[b].readByte();
dataBytes[1] = mergeFilesStream[b].readByte();
}
catch (EOFException e) {
amplifyOutputStream.close();
}
short dataInShort = ByteBuffer.wrap(dataBytes).order(ByteOrder.LITTLE_ENDIAN).getShort();
float dataInFloat= (float) dataInShort/37268.0f;


short outputSample = (short)(dataInFloat * 37268.0f);
byte[] dataFin = new byte[2];
dataFin[0] = (byte) (outputSample & 0xff);
dataFin[1] = (byte)((outputSample >> 8) & 0xff);
amplifyOutputStream.write(dataFin, 0 , 2);

}
}
amplifyOutputStream.close();
for(int i=0; i<selection.size(); i++) {
mergeFilesStream[i].close();
}

} catch (FileNotFoundException e) {

e.printStackTrace();
} catch (IOException e) {

e.printStackTrace();
}
long size =0;
try {
FileInputStream fileSize = new FileInputStream(Environment.getExternalStorageDirectory() + "/Soundrecpluspro/"+year +"-"+ month +"-"+ date +"-"+ hour+"-" + min +"-"+ sec+"ME.wav");
size = fileSize.getChannel().size();
fileSize.close();
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


final int RECORDER_BPP = 16;

long datasize=size+36;
long byteRate = (RECORDER_BPP * RECORDER_SAMPLERATE)/8;
long longSampleRate = RECORDER_SAMPLERATE;
byte[] header = new byte[44];


header[0] = 'R'; // RIFF/WAVE header
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte) (datasize & 0xff);
header[5] = (byte) ((datasize >> 8) & 0xff);
header[6] = (byte) ((datasize >> 16) & 0xff);
header[7] = (byte) ((datasize >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f'; // 'fmt ' chunk
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16; // 4 bytes: size of 'fmt ' chunk
header[17] = 0;
header[18] = 0;
header[19] = 0;
header[20] = 1; // format = 1
header[21] = 0;
header[22] = (byte) 1;
header[23] = 0;
header[24] = (byte) (longSampleRate & 0xff);
header[25] = (byte) ((longSampleRate >> 8) & 0xff);
header[26] = (byte) ((longSampleRate >> 16) & 0xff);
header[27] = (byte) ((longSampleRate >> 24) & 0xff);
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
header[32] = (byte) ((RECORDER_BPP) / 8); // block align
header[33] = 0;
header[34] = RECORDER_BPP; // bits per sample
header[35] = 0;
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
header[40] = (byte) (size & 0xff);
header[41] = (byte) ((size >> 8) & 0xff);
header[42] = (byte) ((size >> 16) & 0xff);
header[43] = (byte) ((size >> 24) & 0xff);
// out.write(header, 0, 44);

try {
RandomAccessFile rFile = new RandomAccessFile(Environment.getExternalStorageDirectory() + "/Soundrecpluspro/" +year +"-"+ month +"-"+ date +"-"+ hour+"-" + min +"-"+ sec+ "ME.wav", "rw");
rFile.seek(0);
rFile.write(header);
rFile.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


return null;
}

关于java - 在 Android 上合并两个 WAVE 文件(连接),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18750892/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com