- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我已经尝试在 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/
我想修复我网站上 WAVE 工具中的错误:http://human2.com.pl/错误是: [网址= https://gifyu.com/image/sUbw][img]https://s1.gif
波浪是否仅限于共享文本信息 (HTML),或者我是否正确地假设波浪可以包含任意数据(以 XML 表示),只要它还包含以有意义的方式呈现它所需的 javascript? 我问是因为Google I/O视
我的理解是 Google wave 是一种通信和协作工具。但它仅限于 IM/Twitter 类型的界面还是可以做得更多?它可以是与自上而下的对话格式完全不同的东西吗? 假设我想使用 google wa
如何链接到 Google Wave,例如在网站或电子邮件中,例如 Hey, just have a look to this new Wave I created. ,在哪里???正是我要找的。 最佳
有没有办法部署使用 H2O wave 创建的应用程序? 我最近制作了一个数据可视化应用程序,希望人们能够快速轻松地演示它。 我试过关注这个话题:Deploy H2O Wave application
Google Wave 中使用的操作转换 Material 具有相当奇特的文档格式。文档基本上只是一个 xml 子集文档 - 字符、开始标签和结束标签。除此之外,文档还有“注释”,它们是与范围相关的元
我想知道是否有可用的工具/框架支持在 Google Wave 之外测试 Google Wave 小工具。 我知道这两个模拟器(1 和 2),但我仍然必须为每次调试运行上传我的小工具。 我正在寻找一种工
我真的是编程新手,所以你们的任何帮助都会很有帮助,我将非常感激。顺便说一下,这是 C++。我有一个 wave 文件,我成功地读取了它的标题。我想创建另一个 wave 文件,将第一个 wave 文件的所
我有一个原始立体声音频文件。 它是树莓派上噪声消除系统的一部分,麦克风 1 将主要声音记录到左声道,麦克风 2 将周围的噪音记录到右声道。目标是从左 channel 中减去右 channel 。我将写
我正在尝试学习一些有关音频编程的知识,因此我决定看看是否可以弄清楚如何生成正弦波并将其写入 .wav 文件。来自引用 here ,我认为每个 channel 只是在文件末尾的数据 block 中交错。
接收错误在 @waves/waves-crypto 中找不到 crypto-js。我尝试通过 npm 卸载并重新安装模块,并使用 *wavesCrypto 导入模块,但模块本身文件 index.d.t
我正在寻找一种方法,可以使用 python 将多个 wave 文件组合成一个 wave 文件并在 linux 上运行它。除了默认的 shell 命令行和默认的 python 模块之外,我不想使用任何附
这让我头疼了一天,但既然我已经弄明白了,我想把它贴在某个地方以防它有帮助。 我正在使用 python 的 wave 模块将数据写入 wave 文件。我没有使用 scipy.io.wavfile,因为数
此代码生成的 WAV 文件在许多应用程序中不起作用。 当我 checkin RIFFVIEWER 应用程序时,它提示 RIFF 长度无效。 BWFMetaEdit 声称文件已被截断。一些宽容的应用程序
(在我问我的问题之前;我真的不知道是否有人可以回答我的问题,因为 Z-wave 协议(protocol)应该是 secret 信息,但如果它确实违反了任何类型的法规,那么我会觉得免费删除此帖子。) 我
数字声音正在使用DirectSound设备播放。像模拟设备一样,必须以分贝显示声音事件。 从WAVE PCM数据(44100 Hz,16位)计算声压的正确方法是什么? 最佳答案 如果您只需要一个“理想
我一直在研究试图理解声音和正弦波的工作方式,尤其是和弦。到目前为止,我的理解如下: b(t) = sin(Api(t)) 是频率为 A 的和弦的基音。 T(t) = sin(5/4piA(t)) 是基
img{ width: 150px; height:150px; float:left; } var img = undefined, section = documen
我想“设计”google wave 并在我的博客/网站上试用它?是否可以修改 Google Wave 的源代码?它在哪里可用? 有没有人做过这样的事情? 最佳答案 如前所述,您可能想要 embed a
所以基本上我试图读取波形文件的信息,以便我可以获取字节信息并创建时间->幅度点的数组。 import wave class WaveFile: # `filename` is the name
我是一名优秀的程序员,十分优秀!