package omrecorder;

import android.media.AudioRecord;
import android.os.Build;
import android.util.Log;

/**
 * An {@code PullableSource} represents {@link Source} which is Pullable
 *
 * @author Kailash Dabhi
 * @date 01-07-2017
 */
public interface PullableSource extends Source {
  /**
   * @return number of bytes to be read from @{@link Source}
   */
  int pullSizeInBytes();

  void isEnableToBePulled(boolean enabledToBePulled);

  boolean isEnableToBePulled();

  AudioRecord preparedToBePulled();

  class Base implements PullableSource {
    private final PullableSource pullableSource;

    Base(PullableSource pullableSource) {
      this.pullableSource = pullableSource;
    }

    @Override
    public AudioRecord audioRecord() {
      return pullableSource.audioRecord();
    }

    @Override
    public AudioRecordConfig config() {
      return pullableSource.config();
    }

    @Override
    public int minimumBufferSize() {
      return pullableSource.minimumBufferSize();
    }

    @Override
    public int pullSizeInBytes() {
      return pullableSource.pullSizeInBytes();
    }

    @Override
    public void isEnableToBePulled(boolean enabledToBePulled) {
      pullableSource.isEnableToBePulled(enabledToBePulled);
    }

    @Override
    public boolean isEnableToBePulled() {
      return pullableSource.isEnableToBePulled();
    }

    @Override
    public AudioRecord preparedToBePulled() {
      return pullableSource.preparedToBePulled();
    }
  }

  class Default extends Source.Default implements PullableSource {
    private final int pullSizeInBytes;
    private volatile boolean pull;

    public Default(AudioRecordConfig config, int pullSizeInBytes) {
      super(config);
      this.pullSizeInBytes = pullSizeInBytes;
    }

    public Default(AudioRecordConfig config) {
      super(config);
      this.pullSizeInBytes = minimumBufferSize();
    }

    @Override
    public int pullSizeInBytes() {
      return pullSizeInBytes;
    }

    @Override
    public void isEnableToBePulled(boolean enabledToBePulled) {
      this.pull = enabledToBePulled;
    }

    @Override
    public boolean isEnableToBePulled() {
      return pull;
    }

    @Override
    public AudioRecord preparedToBePulled() {
      final AudioRecord audioRecord = audioRecord();
      audioRecord.startRecording();
      isEnableToBePulled(true);
      return audioRecord;
    }
  }

  class NoiseSuppressor extends Base {
    public NoiseSuppressor(PullableSource pullableSource) {
      super(pullableSource);
    }

    @Override
    public AudioRecord preparedToBePulled() {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        if (android.media.audiofx.NoiseSuppressor.isAvailable()) {
          android.media.audiofx.NoiseSuppressor noiseSuppressor = android.media.audiofx.NoiseSuppressor
              .create(audioRecord().getAudioSessionId());
          if (noiseSuppressor != null) {
            noiseSuppressor.setEnabled(true);
            Log.i(getClass().getSimpleName(), "NoiseSuppressor ON");
          } else {
            Log.i(getClass().getSimpleName(), "NoiseSuppressor failed :(");
          }
        } else {
          Log.i(getClass().getSimpleName(), "This device don't support NoiseSuppressor");
        }
      } else {
        Log.i(getClass().getSimpleName(),
            "For this effect, Android api should be higher than or equals 16");
      }
      return super.preparedToBePulled();
    }
  }
}
@@ -3461,10 +3461,1135 @@
    %7D%0A  %7D
+%0A%0A  class AutomaticGainControl extends Base %7B%0A    public AutomaticGainControl(PullableSource pullableSource) %7B%0A      super(pullableSource);%0A    %7D%0A%0A    @Override%0A    public AudioRecord preparedToBePulled() %7B%0A      if (Build.VERSION.SDK_INT %3E= Build.VERSION_CODES.JELLY_BEAN) %7B%0A        if (android.media.audiofx.AutomaticGainControl.isAvailable()) %7B%0A          android.media.audiofx.AutomaticGainControl automaticGainControl = android.media.audiofx.AutomaticGainControl%0A              .create(audioRecord().getAudioSessionId());%0A          if (automaticGainControl != null) %7B%0A            automaticGainControl.setEnabled(true);%0A            Log.i(getClass().getSimpleName(), %22AutomaticGainControl ON%22);%0A          %7D else %7B%0A            Log.i(getClass().getSimpleName(), %22AutomaticGainControl failed :(%22);%0A          %7D%0A        %7D else %7B%0A          Log.i(getClass().getSimpleName(), %22This device don't support AutomaticGainControl%22);%0A        %7D%0A      %7D else %7B%0A        Log.i(getClass().getSimpleName(),%0A            %22For this effect, Android api should be higher than or equals 16%22);%0A      %7D%0A      return super.preparedToBePulled();%0A    %7D%0A  %7D
 %0A%7D

Add AutomaticGainControl implementation of PullableSource