Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Comminos <andrewcomminos@gmail.com>2013-11-26 11:34:00 +0400
committerAndrew Comminos <andrewcomminos@gmail.com>2013-11-26 11:34:00 +0400
commit2961a81d8fd62393924a24415a4b2a496845b1f1 (patch)
tree1b92d5e101b273e517269d4bd1fa2adf06dce4d6 /src/main/java
parent2e87d8c8d23f377f8fd51a5bd27584e4cf6cce13 (diff)
Implemented methods to swap between transmit modes.
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/com/morlunk/jumble/JumbleService.java66
-rw-r--r--src/main/java/com/morlunk/jumble/audio/AudioInput.java14
-rw-r--r--src/main/java/com/morlunk/jumble/audio/AudioOutput.java3
-rw-r--r--src/main/java/com/morlunk/jumble/audio/AudioOutputSpeech.java35
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() {