diff options
author | Andrew Comminos <andrewcomminos@gmail.com> | 2013-11-26 11:34:00 +0400 |
---|---|---|
committer | Andrew Comminos <andrewcomminos@gmail.com> | 2013-11-26 11:34:00 +0400 |
commit | 2961a81d8fd62393924a24415a4b2a496845b1f1 (patch) | |
tree | 1b92d5e101b273e517269d4bd1fa2adf06dce4d6 /src/main/java | |
parent | 2e87d8c8d23f377f8fd51a5bd27584e4cf6cce13 (diff) |
Implemented methods to swap between transmit modes.
Diffstat (limited to 'src/main/java')
4 files changed, 72 insertions, 46 deletions
diff --git a/src/main/java/com/morlunk/jumble/JumbleService.java b/src/main/java/com/morlunk/jumble/JumbleService.java index 3d12457..827f429 100644 --- a/src/main/java/com/morlunk/jumble/JumbleService.java +++ b/src/main/java/com/morlunk/jumble/JumbleService.java @@ -56,6 +56,7 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1); } + /** Intent to connect to a Mumble server. See extras. **/ public static final String ACTION_CONNECT = "com.morlunk.jumble.CONNECT"; public static final String EXTRAS_SERVER = "server"; public static final String EXTRAS_SHOW_CHAT_NOTIFICATION = "show_chat_notifications"; @@ -101,27 +102,28 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon @Override public void onTalkStateChanged(final boolean talking) { - if(!isConnected()) - return; - - new Handler(getMainLooper()).post(new Runnable() { - @Override - public void run() { - final User currentUser = getUserHandler().getUser(getSession()); - currentUser.setTalkState(talking ? User.TalkState.TALKING : User.TalkState.PASSIVE); - notifyObservers(new ObserverRunnable() { - @Override - public void run(IJumbleObserver observer) throws RemoteException { - observer.onUserTalkStateUpdated(currentUser); - } - }); - } - }); - } - - @Override - public void onVADStateUpdate(float prob) { + try { + if(!isConnected()) + return; + + final User currentUser = getBinder().getSessionUser(); + + new Handler(getMainLooper()).post(new Runnable() { + @Override + public void run() { + currentUser.setTalkState(talking ? User.TalkState.TALKING : User.TalkState.PASSIVE); + notifyObservers(new ObserverRunnable() { + @Override + public void run(IJumbleObserver observer) throws RemoteException { + observer.onUserTalkStateUpdated(currentUser); + } + }); + } + }); + } catch (RemoteException e) { + e.printStackTrace(); + } } }; @@ -216,6 +218,26 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon } @Override + public void setTransmitMode(int transmitMode) throws RemoteException { + mTransmitMode = transmitMode; + mAudioInput.setTransmitMode(mTransmitMode); + + // Reconfigure audio input/output to accommodate for change in transmit mode. + if(mConnection != null && mConnection.isConnected()) { + if(transmitMode == Constants.TRANSMIT_CONTINUOUS || transmitMode == Constants.TRANSMIT_VOICE_ACTIVITY) + mAudioInput.startRecording(); + else + mAudioInput.stopRecording(); + } + } + + @Override + public void setVADThreshold(float threshold) throws RemoteException { + if(mAudioInput != null) + mAudioInput.setVADThreshold(threshold); + } + + @Override public boolean isTalking() throws RemoteException { return mAudioInput.isRecording(); } @@ -384,6 +406,10 @@ public class JumbleService extends Service implements JumbleConnection.JumbleCon Mumble.UserState.Builder usb = Mumble.UserState.newBuilder(); usb.setSelfMute(mute); usb.setSelfDeaf(deaf); + if(!mute && (mTransmitMode == Constants.TRANSMIT_CONTINUOUS || mTransmitMode == Constants.TRANSMIT_VOICE_ACTIVITY)) + mAudioInput.startRecording(); // Resume recording when unmuted for PTT. + else + mAudioInput.stopRecording(); // Stop recording when muted. mConnection.sendTCPMessage(usb.build(), JumbleTCPMessageType.UserState); } diff --git a/src/main/java/com/morlunk/jumble/audio/AudioInput.java b/src/main/java/com/morlunk/jumble/audio/AudioInput.java index 5c55892..e5f8580 100644 --- a/src/main/java/com/morlunk/jumble/audio/AudioInput.java +++ b/src/main/java/com/morlunk/jumble/audio/AudioInput.java @@ -57,12 +57,6 @@ public class AudioInput extends ProtocolHandler implements Runnable { public void onFrameEncoded(byte[] data, int length, JumbleUDPMessageType messageType); public void onTalkStateChanged(boolean talking); - - /** - * Called after a frame is passed into the speex preprocessor. - * @param prob The probability of speech, from 0 to 1. - */ - public void onVADStateUpdate(float prob); } private static final int[] SAMPLE_RATES = { 48000, 44100, 22050, 160000, 11025, 8000 }; @@ -140,6 +134,14 @@ public class AudioInput extends ProtocolHandler implements Runnable { mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, mInputSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, mMinBufferSize); } + public void setVADThreshold(float threshold) { + mVADThreshold = threshold; + } + + public void setTransmitMode(int transmitMode) { + mTransmitMode = transmitMode; + } + /** * Initializes and configures the Speex preprocessor. * Based off of Mumble project's AudioInput method resetAudioProcessor(). diff --git a/src/main/java/com/morlunk/jumble/audio/AudioOutput.java b/src/main/java/com/morlunk/jumble/audio/AudioOutput.java index 680e3a0..8c75ea1 100644 --- a/src/main/java/com/morlunk/jumble/audio/AudioOutput.java +++ b/src/main/java/com/morlunk/jumble/audio/AudioOutput.java @@ -97,7 +97,8 @@ public class AudioOutput extends ProtocolHandler implements Runnable, AudioOutpu boolean play = mix(mix, mix.length); if(play) { mAudioTrack.write(mix, 0, mix.length); - } else if(System.nanoTime()-mLastPacket > SLEEP_THRESHOLD) { + } + else if(System.nanoTime()-mLastPacket > SLEEP_THRESHOLD) { Log.v(Constants.TAG, "Pausing audio output thread."); synchronized (mInactiveLock) { try { diff --git a/src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java b/src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java index 95f086e..da0a7c0 100644 --- a/src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java +++ b/src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java @@ -53,6 +53,7 @@ public class AudioOutputSpeech { // State-specific private float[] mBuffer; + private float[] mOut; private float[] mFadeOut; private float[] mFadeIn; private Queue<byte[]> mFrames = new ConcurrentLinkedQueue<byte[]>(); @@ -90,7 +91,8 @@ public class AudioOutputSpeech { break; } - mBuffer = new float[mAudioBufferSize*2]; // Leave room for an extra frame in the buffer, this saves buffer resize operations at runtime normally. + mBuffer = new float[mAudioBufferSize*2]; // Make initial buffer size larger so we can save performance by not resizing at runtime. + mOut = new float[mAudioBufferSize]; mFadeIn = new float[Audio.FRAME_SIZE]; mFadeOut = new float[Audio.FRAME_SIZE]; @@ -152,7 +154,6 @@ public class AudioOutputSpeech { if(mBufferFilled >= num) return mLastAlive; - float[] out = new float[mAudioBufferSize]; boolean nextAlive = mLastAlive; while(mBufferFilled < num) { @@ -160,7 +161,7 @@ public class AudioOutputSpeech { resizeBuffer(mBufferFilled + mAudioBufferSize); if(!mLastAlive) - Arrays.fill(out, 0); + Arrays.fill(mOut, 0); else { IntPointer avail = new IntPointer(1); avail.put(0); @@ -244,18 +245,18 @@ public class AudioOutputSpeech { CELT7.celt_decode_float(mCELTAlphaDecoder, data, data.length, - out); + mOut); } else if(mCodec == JumbleUDPMessageType.UDPVoiceCELTBeta) { CELT11.celt_decode_float(mCELTBetaDecoder, data, data.length, - out, + mOut, Audio.FRAME_SIZE); } else if(mCodec == JumbleUDPMessageType.UDPVoiceOpus) { decodedSamples = Opus.opus_decode_float(mOpusDecoder, data, data.length, - out, + mOut, mAudioBufferSize, 0); } else { // Speex @@ -266,7 +267,7 @@ public class AudioOutputSpeech { // Speex.speex_decode(mSpeexDecoder, mSpeexBits, out); // } for(int i = 0; i < Audio.FRAME_SIZE; i++) - out[i] *= (1.0f / 32767.f); + mOut[i] *= (1.0f / 32767.f); } if(mFrames.isEmpty()) @@ -278,11 +279,11 @@ public class AudioOutputSpeech { nextAlive = false; } else { if(mCodec == JumbleUDPMessageType.UDPVoiceCELTAlpha) - CELT7.celt_decode_float(mCELTAlphaDecoder, null, 0, out); + CELT7.celt_decode_float(mCELTAlphaDecoder, null, 0, mOut); else if(mCodec == JumbleUDPMessageType.UDPVoiceCELTBeta) - CELT11.celt_decode_float(mCELTBetaDecoder, null, 0, out, Audio.FRAME_SIZE); + CELT11.celt_decode_float(mCELTBetaDecoder, null, 0, mOut, Audio.FRAME_SIZE); else if(mCodec == JumbleUDPMessageType.UDPVoiceOpus) - decodedSamples = Opus.opus_decode_float(mOpusDecoder, null, 0, out, Audio.FRAME_SIZE, 0); + decodedSamples = Opus.opus_decode_float(mOpusDecoder, null, 0, mOut, Audio.FRAME_SIZE, 0); // else { // Speex.speex_decode(mSpeexDecoder, null, out); // for(int i = 0; i < Audio.FRAME_SIZE; i++) @@ -292,11 +293,11 @@ public class AudioOutputSpeech { if (!nextAlive) { for (int i = 0; i < Audio.FRAME_SIZE; i++) { - out[i] *= mFadeOut[i]; + mOut[i] *= mFadeOut[i]; } } else if (ts == 0) { for (int i = 0; i < Audio.FRAME_SIZE; i++) { - out[i] *= mFadeIn[i]; + mOut[i] *= mFadeIn[i]; } } @@ -306,7 +307,7 @@ public class AudioOutputSpeech { } } - System.arraycopy(out, 0, mBuffer, mBufferFilled, decodedSamples); + System.arraycopy(mOut, 0, mBuffer, mBufferFilled, decodedSamples); mBufferFilled += decodedSamples; } @@ -338,12 +339,8 @@ public class AudioOutputSpeech { } public void resizeBuffer(int newSize) { - if(newSize > mBuffer.length) { - float[] n = new float[newSize]; - if(mBuffer != null) - System.arraycopy(mBuffer, 0, n, 0, mBuffer.length); - mBuffer = n; - } + if(newSize > mBuffer.length) + mBuffer = Arrays.copyOf(mBuffer, newSize); } public float[] getBuffer() { |