我正在尝试将(捕获)音频数据记录到新的 wav 文件中。我正在使用 Oboe c++ 根据此示例代码缓冲音频
这就是我将音频数据从混音器捕获到 RecordBuffer 数组的方式:
void Mixer::renderAudio(int16_t *audioData, int32_t numFrames) {
int32_t count = numFrames * kChannelCount;
// Zero out the incoming container array
for (int j = 0; j < count; ++j) {
audioData[j] = 0;
}
for (int i = 0; i < mNextFreeTrackIndex; ++i) {
mTracks[i]->renderAudio(mixingBuffer, numFrames);
for (int j = 0; j < count; ++j) {
data = mixingBuffer[j];
data*= volume;
audioData[j] += data;
if(recording && recordFrames < kMaxRecordSize){
if(data != 0)
recordBuffer[recordFrames++] = data;
}
}
}
}
停止记录并获取 Java 代码的短数组
jshortArray Mixer::getRecordingData(JNIEnv *env) {
recording = false;
jshortArray result = env->NewShortArray(recordFrames);
env->SetShortArrayRegion(result,0,recordFrames,recordBuffer);
return result;
}
然后在 Java 代码中,我创建了 wav 文件:
public class Wave {
private final int LONGINT = 4;
private final int SMALLINT = 2;
private final int INTEGER = 4;
private final int ID_STRING_SIZE = 4;
private final int WAV_RIFF_SIZE = LONGINT+ID_STRING_SIZE;
private final int WAV_FMT_SIZE = (4*SMALLINT)+(INTEGER*2)+LONGINT+ID_STRING_SIZE;
private final int WAV_DATA_SIZE = ID_STRING_SIZE+LONGINT;
private final int WAV_HDR_SIZE = WAV_RIFF_SIZE+ID_STRING_SIZE+WAV_FMT_SIZE+WAV_DATA_SIZE;
private final short PCM = 1;
private final int SAMPLE_SIZE = 2;
int cursor, nSamples;
byte[] output;
int sampleRate = 48000;
short channels = 2;
public Wave( short[] data, int start, int end) {
nSamples=end-start+1;
cursor=0;
output=new byte[nSamples*SMALLINT+WAV_HDR_SIZE];
buildHeader(sampleRate,channels);
writeData(data,start,end);
}
private void buildHeader(int sampleRate, short nChannels) {
write("RIFF");
write(output.length);
write("WAVE");
writeFormat(sampleRate, nChannels);
}
public void writeFormat(int sampleRate, short nChannels){
write("fmt ");
write(WAV_FMT_SIZE-WAV_DATA_SIZE);
write(PCM);
write(nChannels);
write(sampleRate);
write(nChannels * sampleRate * SAMPLE_SIZE);
write((short)(nChannels * SAMPLE_SIZE));
write((short)16);
}
public void writeData(short[] data, int start, int end)
{
write("data");
write(nSamples*SMALLINT);
for(int i=start; i<=end; write(data[i++]));
}
private void write(byte b) {
output[cursor++]=b;
}
private void write(String id) {
if(id.length()!=ID_STRING_SIZE) {}
else {
for(int i=0; i<ID_STRING_SIZE; ++i) write((byte)id.charAt(i));
}
}
private void write(int i) {
write((byte) (i&0xFF)); i>>=8;
write((byte) (i&0xFF)); i>>=8;
write((byte) (i&0xFF)); i>>=8;
write((byte) (i&0xFF));
}
private void write(short i) {
write((byte) (i&0xFF)); i>>=8;
write((byte) (i&0xFF));
}
public boolean wroteToFile() {
boolean ok;
try {
File path = FileManager.generateNewFile(String.valueOf(sampleRate + " " + channels));
FileOutputStream outFile = new FileOutputStream(path);
outFile.write(output);
outFile.close();
ok=true;
} catch (FileNotFoundException e) {
e.printStackTrace();
ok=false;
} catch (IOException e) {
ok=false;
e.printStackTrace();
}
return ok;
}
}
结果非常接近,但质量很差。有谁知道我做错了什么?顺便说一句,只有当我每个播放 1 个样本时它才能正常工作。