package im.actor.sdk.controllers.calls.view; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioRecord; import android.media.MediaRecorder; import java.util.ArrayList; import java.util.Arrays; import im.actor.runtime.Log; import im.actor.runtime.actors.Actor; import im.actor.runtime.actors.messages.PoisonPill; import im.actor.sdk.core.audio.OpusEncoderActor; import im.actor.sdk.core.audio.VoiceBuffers; public class AudioStreamVolumeValueActor extends Actor { private static final int BUFFER_SIZE = 16 * 1024; private int delay; private AudioRecord audioRecord; boolean inited = false; public AudioStreamVolumeValueActor() { } ArrayList<VolumeValueListener> callbacks = new ArrayList<VolumeValueListener>(); @Override public void preStart() { delay = 10; } private void subscribeForVolume(VolumeValueListener callback){ if(audioRecord == null){ int minBufferSize = AudioRecord.getMinBufferSize(16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); int bufferSize = 16 * minBufferSize; audioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, 16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); audioRecord.startRecording(); } callbacks.add(callback); if(!inited){ inited = true; schedule(new Check(), delay); } } private void unsubscribeFromVolume(VolumeValueListener callback){ callbacks.remove(callback); audioRecord.stop(); audioRecord.release(); audioRecord = null; self().send(PoisonPill.INSTANCE); } private void check(){ if(audioRecord!=null){ byte[] buffer = VoiceBuffers.getInstance().obtainBuffer(BUFFER_SIZE); int len = audioRecord.read(buffer, 0, buffer.length); if (len > 0) { int i = getMax(buffer) - getMin(buffer); for (VolumeValueListener c:callbacks) { c.onVolumeValue(i); } } else { VoiceBuffers.getInstance().releaseBuffer(buffer); } } self().send(new Check()); } byte getMax(byte[] array){ byte max = array[0]; for (int i = 1; i < array.length; i++) { if (array[i] > max) { max = array[i]; } } return max; } byte getMin(byte[] array){ byte min = array[0]; for (int i = 1; i < array.length; i++) { if (array[i] < min) { min = array[i]; } } return min; } @Override public void onReceive(Object message) { if(message instanceof Check){ check(); }else if(message instanceof Subscribe){ subscribeForVolume(((Subscribe) message).getCallback()); }else if(message instanceof Unsubscribe){ unsubscribeFromVolume(((Unsubscribe) message).getCallback()); } } interface VolumeValueListener{ void onVolumeValue(int val); } public static class Subscribe{ VolumeValueListener callback; public Subscribe(VolumeValueListener callback) { this.callback = callback; } public VolumeValueListener getCallback() { return callback; } } public static class Unsubscribe{ VolumeValueListener callback; public Unsubscribe(VolumeValueListener callback) { this.callback = callback; } public VolumeValueListener getCallback() { return callback; } } private static class Check{} }