如何捕获音频数据并保存到WAV文件?

时间:2018-12-21 20:22:32

标签: android file wav audio-recording oboe

我正在尝试将音频数据记录(捕获)到新的wav文件中。 我正在使用Oboe c ++根据此Example code

缓冲音频

这是我将音频数据从混音器捕获到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;
    }
}

结果非常接近,但是质量很差。 有人知道我在做什么错吗? btw只有当我每个演奏1个样本时,它才能很好地工作。

1 个答案:

答案 0 :(得分:1)

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