qiuxiang / react-native-recording

React Native audio recording module used for DSP with Android + iOS
MIT License
110 stars 62 forks source link

startRecording() called on an uninitialized AudioRecord #10

Open ridozaen opened 6 years ago

ridozaen commented 6 years ago

i got error when first trying to use this library based on example.

startRecording() called on an uninitialized AudioRecord

handlerStart() {
    Recording.init({
      bufferSize: 4096,
      sampleRate: 44100
    });
    Recording.start();
    Recording.on('recording', data => {
      console.log(data)
    })
  }

  render() {
    return (
      <View>
        <Text onPress={this.handlerStart}>Recording</Text>
      </View>
    );
  }
qiuxiang commented 6 years ago

Have you allowed microphone permission on your app?

navrajkambo commented 6 years ago

I got this error when using the android simulator. It's important to remember that the android simulator doesn't have a microphone (correct me if i'm wrong). Did you try debugging on an actual device?

qiuxiang commented 6 years ago

For android, I mainly test on real devices.

speggos commented 6 years ago

I am getting this error on a specific device (my other two devices run the code just fine!). The device is a little older, looking to see if you have any insight on this.

Device: ZTE Blade C321 Android Version: 4.4.2 'KitKat'

Code:

this.Recorder = require('react-native-recording').default;

this.Recorder.init({
    2048,
    44100
    16,
    1,
});

this.Recorder.addRecordingEventListener((data) => {
    const result = this.Detector.onNewBuffer(data);

    if (result && this.state.isRecording) {
        this.stopRecording();
    }
});
navrajkambo commented 6 years ago

Check the sample rate of your device.

speggos commented 6 years ago

Is there a way to check if the recording object was set up successfully? Is there a way to programatically check the sample rate of the device? Haven't discovered any libraries supporting that functionality.

The app being developed requires support for as many older devices as possible

navrajkambo commented 6 years ago

In Java, you could write a loop that tries to instantiate an AudioRecord object with different sample rates.

public void getValidSampleRates() {
    for (int rate : new int[] {8000, 11025, 16000, 22050, 44100}) {  // add the rates you wish to check against
        int bufferSize = AudioRecord.getMinBufferSize(rate, AudioFormat.CHANNEL_CONFIGURATION_DEFAULT, AudioFormat.ENCODING_PCM_16BIT);
        if (bufferSize > 0) {
            // buffer size is valid, Sample rate supported

        }
    }
}

You could then add this functionality into a react-native package. For iOS, i'm not 100% sure, but I think all of the sample rates are the same.

speggos commented 6 years ago

Trying the looping method. I've discovered that the device works when the sample rate is set to 22050. Here is my current code, which is not working:

let potentialSampleRates = [44100, 22050, 16000];

for (let i=0; i<potentialSampleRates.length; i++) {
    try {
        this.Recorder.init({
            2048
            potentialSampleRates[i],
            16,
            1,
        });
        this.Recorder.start();

    } catch (error) {
        console.log('Error!', error);
        continue;
    }

    break;
}

What happens is that even though I try to start recording inside of a try block, I still get the red screen of death (ie it is not caught).

What I need to do is one of two things:

  1. Be able to start recording on a buffer which has been initialized incorrectly, and then try another initialization.
  2. Be able to tell if a recording instance has been initialized correctly BEFORE starting recording.

Any help to achieve either is greatly appreciated. I could not find anything within the recording object to satisfy option 2

speggos commented 6 years ago

Update: Got this working with my code. I had to fork this repo and make some changes which applies the looping process as stated by @navrajkambo (thank you!), except instead of checking bufferSize being >0, I check the audiorecord state.

Here is how I got it working:

int initializedCorrectly = -1;
int sampleRateInHz = 44100;

for (int rate : new int[] {44100, 22050, 16000, 11025, 8000}) {
        sampleRateInHz = rate;
        audioRecord = new AudioRecord(
                MediaRecorder.AudioSource.MIC,
                sampleRateInHz,
                channelConfig,
                audioFormat,
                this.bufferSize * 2
        );

        initializedCorrectly = audioRecord.getState();

        if (initializedCorrectly == AudioRecord.STATE_INITIALIZED) {
                break;
        }
}

Forked repo can be found here:

https://github.com/speggos/react-native-recording.git

Keepo12 commented 5 years ago

I also tried to run the example from the library but got the error below:

TypeError: undefined is not an object (evaluating 'Recording.init')

This error is located at:
    in App (at withExpoRoot.js:22)
    in RootErrorBoundary (at withExpoRoot.js:21)
    in ExpoRootComponent (at renderApplication.js:34)
    in RCTView (at View.js:44)
    in RCTView (at View.js:44)
    in AppContainer (at renderApplication.js:33)

I'm using an Android device with the Expo app for testing and I set microphone permission to be on for Expo.

speggos commented 5 years ago

I'm unsure that you can use this library with Expo. You might want to look into that (I may be wrong).

If you cannot, you must eject the app, or use a different library (expo has one built in)

sandeepReddyG commented 5 years ago

I also tried to run the example from the library but got the error below: TypeError: undefined is not an object (evaluating 'Recording.init')

This error is located at: in App (at withExpoRoot.js:22) in RootErrorBoundary (at withExpoRoot.js:21) in ExpoRootComponent (at renderApplication.js:34) in RCTView (at View.js:44) in RCTView (at View.js:44) in AppContainer (at renderApplication.js:33)

I'm using an Android device with the Expo app for testing and I set microphone permission to be on for Expo.

I am also facing same issue . I added permission in manifest file But still facing the issue. How to solve it?