Coder Social home page Coder Social logo

Comments (4)

navrajkambo avatar navrajkambo commented on May 27, 2024 2

From matlab, I figured out that the data needs to be treated as datatype int16 instead of double, or float. The noise was caused by playing the data as datatype double. Audio is crystal clear with datatype int16! Incase anyone is wondering, below is my matlab test code and some modifications I made to your android module to test my theory...

playback.m matlab file for testing audi playback of recorded samples

Fs = 44100;
fid=fopen('record.pcm');
sig=double(fread(fid,inf,'int16')).'; % it's noisy
fclose(fid);

sig=int16(sig); % make it clean

player = audioplayer(sig,Fs);
player.play()

RecordingModule.java android java file for exporting pcm byte file to be played in audacity, and used in matlab

package cn.qiuxiang.react.recording;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;


import java.io.File; //added by Navraj Kambo
import java.io.FileInputStream; //added by Navraj Kambo
import java.io.FileNotFoundException; //added by Navraj Kambo
import java.io.FileOutputStream; //added by Navraj Kambo
import java.io.IOException; //added by Navraj Kambo
import android.os.Environment; //added by Navraj Kambo

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.modules.core.DeviceEventManagerModule;

class RecordingModule extends ReactContextBaseJavaModule {
    private static AudioRecord audioRecord;
    private final ReactApplicationContext reactContext;
    private DeviceEventManagerModule.RCTDeviceEventEmitter eventEmitter;
    private boolean running;
    private int bufferSize;
    private Thread recordingThread;

    RecordingModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    @Override
    public String getName() {
        return "Recording";
    }

    @ReactMethod
    public void init(ReadableMap options) {
        if (eventEmitter == null) {
            eventEmitter = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
        }

        if (running || (recordingThread != null && recordingThread.isAlive())) {
            return;
        }

        if (audioRecord != null) {
            audioRecord.stop();
            audioRecord.release();
        }

        // for parameter description, see
        // https://developer.android.com/reference/android/media/AudioRecord.html

        int sampleRateInHz = 44100;
        if (options.hasKey("sampleRate")) {
            sampleRateInHz = options.getInt("sampleRate");
        }

        int channelConfig = AudioFormat.CHANNEL_IN_MONO;
        if (options.hasKey("channelsPerFrame")) {
            int channelsPerFrame = options.getInt("channelsPerFrame");

            // every other case --> CHANNEL_IN_MONO
            if (channelsPerFrame == 2) {
                channelConfig = AudioFormat.CHANNEL_IN_STEREO;
            }
        }

        // we support only 8-bit and 16-bit PCM
        int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
        if (options.hasKey("bitsPerChannel")) {
            int bitsPerChannel = options.getInt("bitsPerChannel");

            if (bitsPerChannel == 8) {
                audioFormat = AudioFormat.ENCODING_PCM_8BIT;
            }
        }

        if (options.hasKey("bufferSize")) {
            this.bufferSize = options.getInt("bufferSize");
        } else {
            this.bufferSize = 8192;
        }

        audioRecord = new AudioRecord(
                MediaRecorder.AudioSource.MIC,
                sampleRateInHz,
                channelConfig,
                audioFormat,
                this.bufferSize * 2);

        recordingThread = new Thread(new Runnable() {
            public void run() {
                recording();
            }
        }, "RecordingThread");
    }

    @ReactMethod
    public void start() {
        if (!running && audioRecord != null && recordingThread != null) {
            running = true;
            audioRecord.startRecording();
            recordingThread.start();
        }
    }

    @ReactMethod
    public void stop() {
        if (audioRecord != null) {
            running = false;
            audioRecord.stop();
            audioRecord.release();
            audioRecord = null;
        }
    }
    private byte[] short2byte(short[] sData) { //added by Navraj Kambo
        int shortArrsize = sData.length; //added by Navraj Kambo
        byte[] bytes = new byte[shortArrsize * 2]; //added by Navraj Kambo
        for (int i = 0; i < shortArrsize; i++) { //added by Navraj Kambo
            bytes[i * 2] = (byte) (sData[i] & 0x00FF); //added by Navraj Kambo
            bytes[(i * 2) + 1] = (byte) (sData[i] >> 8); //added by Navraj Kambo
            sData[i] = 0; //added by Navraj Kambo
        } //added by Navraj Kambo
        return bytes; //added by Navraj Kambo
    } //added by Navraj Kambo
	
    private void recording() {
        short buffer[] = new short[bufferSize];
	String filepath = Environment.getExternalStorageDirectory().getPath(); //added by Navraj Kambo
        FileOutputStream os = null; //added by Navraj Kambo
        try { //added by Navraj Kambo
	    os = new FileOutputStream(filepath+"/download/record.pcm"); //added by Navraj Kambo
        } catch (FileNotFoundException e) { //added by Navraj Kambo
	    e.printStackTrace(); //added by Navraj Kambo
        } //added by Navraj Kambo
        while (running && !reactContext.getCatalystInstance().isDestroyed()) {
            WritableArray data = Arguments.createArray();
            audioRecord.read(buffer, 0, bufferSize);
            for (float value : buffer) {
                data.pushInt((int) value);
            }
            eventEmitter.emit("recording", data);
	    byte bdata[] = short2byte(buffer); //added by Navraj Kambo
	    try { //added by Navraj Kambo
                os.write(bdata, 0, bufferSize * 2); //added by Navraj Kambo
            } catch (IOException e) { //added by Navraj Kambo
                e.printStackTrace(); //added by Navraj Kambo
            } //added by Navraj Kambo
        }
	try { //added by Navraj Kambo
            os.close(); //added by Navraj Kambo
        } catch (IOException e) { //added by Navraj Kambo
            e.printStackTrace(); //added by Navraj Kambo
        } //added by Navraj Kambo
    }
}

Note: I also verified this with the streamed data from javascript/react-native

from react-native-recording.

qiuxiang avatar qiuxiang commented on May 27, 2024

raw data can't play directly before encoded to some audio format (wav, mp3 etc.)

from react-native-recording.

navrajkambo avatar navrajkambo commented on May 27, 2024

I played the file by importing the raw data into my Matlab workspace, and then used the sound(y,Fs) function in Matlab. I'll try an encode the data into a wav file using some third party software, and upload my results. Maybe the Matlab sound() requires something other than pcm 16 audio?

from react-native-recording.

qiuxiang avatar qiuxiang commented on May 27, 2024

I have not used matlab. But if you already encoded into wav file, you should be able to play it with an audio player.

from react-native-recording.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.