chipweinberger / flutter_pcm_sound

A flutter plugin for playing raw PCM audio data (16-bit integer)
Other
16 stars 7 forks source link

corrupts problem #5

Closed baigua closed 9 months ago

baigua commented 11 months ago

I try to make a piano roll, that let users to arrange their own midi sequences. I use both flutter_pcm_sound.dart and dart_melty_soundfont.dart


//data struture for notes:
class Note {
  int note;
  int startTime;
  int duration;
  int channel;
  int preset;
  bool isPlayed;

  // play midi function
  void playNotes(){
        // wait for note start
        Future.delayed(Duration(milliseconds: note.startTime), () {
               _startNoteTimer(
                note.channel, note.preset, note.note, note.duration);
          })
 }

void _startNoteTimer(int channel, int preset, int note, int duration) {
     FlutterPcmSound.play();
    _synth!.selectPreset(channel: channel, preset: preset);
    _synth!.noteOn(channel: channel, key: note, velocity: 120);
    /////////// feed buffer 
   ArrayInt16 buffer =
        ArrayInt16.zeros(numShorts: sampleRate ~/ 10); 
    _synth!.renderMonoInt16(buffer);
    FlutterPcmSound.feed(PcmArrayInt16(bytes: buffer.bytes));
   /////// wait for it's end 
   Future.delayed(Duration(milliseconds: duration), () {
          _synth!.noteOff(channel: channel, key: note);
          FlutterPcmSound.stop();
    }
}

I don't know if that are better ways to do this, because when I use the pre feed buffer way, I can't hear voice from the second channel.

when I run my program, error reports:

E/AndroidRuntime( 8773): FATAL EXCEPTION: Thread-5
E/AndroidRuntime( 8773): Process: com.example.detect_sound, PID: 8773
E/AndroidRuntime( 8773): java.lang.NullPointerException: Attempt to invoke virtual method 'java.nio.ByteBuffer java.nio.ByteBuffer.duplicate()' on a null object reference
E/AndroidRuntime( 8773):        at com.lib.flutter_pcm_sound.FlutterPcmSoundPlugin.lambda$startPlaybackThread$1$com-lib-flutter_pcm_sound-FlutterPcmSoundPlugin(FlutterPcmSoundPlugin.java:271)
E/AndroidRuntime( 8773):        at com.lib.flutter_pcm_sound.FlutterPcmSoundPlugin$$ExternalSyntheticLambda1.run(Unknown Source:2)
E/AndroidRuntime( 8773):        at java.lang.Thread.run(Thread.java:1012)
I/Process ( 8773): Sending signal. PID: 8773 SIG: 9

it seems in FlutterPcmSoundPlugin.java here should be modified like this:

                  while (mSamplesIsEmpty() == false) {
                                 // ByteBuffer data = mSamplesPop().duplicate();
                                ByteBuffer data = mSamplesPop();
                                if (data != null && mAudioTrack != null) {
                                    ByteBuffer dataCopy = data.duplicate();
                                    mAudioTrack.write(data, data.remaining(), AudioTrack.WRITE_BLOCKING);
                                }
chipweinberger commented 11 months ago

thanks

if we already check mSamplesIsEmpty why do we also need another null check?

please open a PR

baigua commented 11 months ago

it's strange that after I modified that part, my program don't corrupts again. but it was also probably because I rebuilt my program.

to get each note listen clearly, I have them apply memory every 100 milliseconds like this:

var timer = Timer.periodic(const Duration(milliseconds: 100), (timer) {
          _feedAudioData();
      });

void _feedAudioData() {
    ArrayInt16 buffer =
        ArrayInt16.zeros(numShorts: sampleRate ~/ 10);
    _synth!.renderMonoInt16(buffer);
    FlutterPcmSound.feed(PcmArrayInt16(bytes: buffer.bytes));
  }

so when there are hundreds of notes to play, the program is very busy.