0

我正在尝试将(捕获)音频数据记录到新的 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 个样本时它才能正常工作。

4

1 回答 1

1

这是一种将双簧管输入流录制到 C++ for Android 中的 .Wav 文件的方法: https ://github.com/reuniware/OboeAudioRecorder/blob/master/app/src/main/cpp/OboeAudioRecorder.cpp

于 2020-07-05T16:24:06.150 回答