0

I'm trying to record (Capture) audio data to a new wav file. I'm using Oboe c++ for buffering the audio according to this Example code

This is how I capture audio data from the mixer to RecordBuffer array:

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;
            }
        }
    }
}

Stop record and get the short array to Java code

jshortArray Mixer::getRecordingData(JNIEnv *env) {
    recording = false;
    jshortArray result = env->NewShortArray(recordFrames);
    env->SetShortArrayRegion(result,0,recordFrames,recordBuffer);
    return result;
}

Then in Java code, I create the wav file:

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;
    }
}

The results are pretty close, but the quality is very bad. Does anyone know what am I doing wrong? btw It works well only if I played 1 sample each.

Matan
  • 296
  • 5
  • 24
  • 1
    WHy are you generating the data in C and writing it to a file in Java? It would make more sense to do both in one spot, and reduce the incidence of silly bugs (like one side writing with 8 bits per sample and one at 16, or one stereo and one mono). And sending data back and forth fromn Java to C isn't exactly efficient. – Gabe Sechan Dec 21 '18 at 20:56
  • Agree with Gabe. You'd be better off using something like [libsndfile](https://github.com/erikd/libsndfile/blob/master/Building-for-Android.md) for writing WAV files in C – donturner Dec 27 '18 at 17:33

1 Answers1

1

Here is a way to record a Oboe input stream to a .Wav file in C++ for Android : https://github.com/reuniware/OboeAudioRecorder/blob/master/app/src/main/cpp/OboeAudioRecorder.cpp

KotlinIsland
  • 799
  • 1
  • 6
  • 25