Skip to content

Commit

Permalink
Create multiple encoders for each sound.
Browse files Browse the repository at this point in the history
  • Loading branch information
bivashy committed Jun 11, 2022
1 parent 5575b47 commit df174c7
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,12 @@ public interface ICodecHolder {
byte[] encode(byte[] data);

byte[] decode(byte[] data);

void resetEncoder();

void resetDecoder();

void closeEncoder();

void closeDecoder();
}
Original file line number Diff line number Diff line change
@@ -1,53 +1,65 @@
package com.ubivashka.plasmovoice.audio.codecs;

import javax.sound.sampled.AudioFormat;

import com.ubivashka.plasmovoice.function.MemoizingSupplier;
import com.ubivashka.plasmovoice.opus.OpusDecoder;
import com.ubivashka.plasmovoice.opus.OpusEncoder;

import de.maxhenkel.opus4j.Opus;

import javax.sound.sampled.AudioFormat;
import java.util.function.Supplier;

public class OpusCodecHolder extends AbstractCodecHolder {
private static final int MTU_SIZE = 1024;
private static final int JOPUS_MODE = Opus.OPUS_APPLICATION_VOIP;

private OpusEncoder encoder = new OpusEncoder(sampleRate, frameSize, MTU_SIZE, JOPUS_MODE);
private OpusDecoder decoder = new OpusDecoder(sampleRate, frameSize, MTU_SIZE);

public OpusEncoder getEncoder() {
return encoder;
}

public void setEncoder(OpusEncoder encoder) {
this.encoder = encoder;
}

public OpusDecoder getDecoder() {
return decoder;
}

public void setDecoder(OpusDecoder decoder) {
this.decoder = decoder;
}

@Override
public byte[] encode(byte[] data) {
return encoder.encode(data);
}

@Override
public byte[] decode(byte[] data) {
return decoder.decode(data);
}

@Override
public void setSampleRate(int sampleRate) {
this.sampleRate = sampleRate;
this.audioFormat = new AudioFormat(sampleRate, 16, 1, true, false);
this.frameSize = (sampleRate / 1000) * 2 * 20;

this.encoder = new OpusEncoder(sampleRate, frameSize, MTU_SIZE, JOPUS_MODE);
this.decoder = new OpusDecoder(sampleRate, frameSize, MTU_SIZE);
}
private static final int MTU_SIZE = 1024;
private static final int JOPUS_MODE = Opus.OPUS_APPLICATION_VOIP;

private Supplier<OpusEncoder> lazyEncoder = MemoizingSupplier.memoize(() -> new OpusEncoder(sampleRate, frameSize, MTU_SIZE, JOPUS_MODE));
private Supplier<OpusDecoder> lazyDecoder = MemoizingSupplier.memoize(() -> new OpusDecoder(sampleRate, frameSize, MTU_SIZE));

public OpusEncoder getEncoder() {
return lazyEncoder.get();
}

public OpusDecoder getDecoder() {
return lazyDecoder.get();
}

@Override
public byte[] encode(byte[] data) {
return getEncoder().encode(data);
}

@Override
public byte[] decode(byte[] data) {
return getDecoder().decode(data);
}

@Override
public void resetEncoder() {
getEncoder().reset();
}

@Override
public void closeEncoder() {
getEncoder().close();
}

public void resetDecoder() {
getDecoder().reset();
}

@Override
public void closeDecoder() {
getDecoder().close();
}

@Override
public void setSampleRate(int sampleRate) {
this.sampleRate = sampleRate;
this.audioFormat = new AudioFormat(sampleRate, 16, 1, true, false);
this.frameSize = (sampleRate / 1000) * 2 * 20;

lazyEncoder = MemoizingSupplier.memoize(() -> new OpusEncoder(sampleRate, frameSize, MTU_SIZE, JOPUS_MODE));
lazyDecoder = MemoizingSupplier.memoize(() -> new OpusDecoder(sampleRate, frameSize, MTU_SIZE));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public interface ISoundPlayer {
ISoundPlaySession playSound(ISound sound, IAudioSource audioSource, ISoundController soundController);

/**
* @return Возвращает кодек с которым можно сжимать и обратить этот процесс.
* @return Создаёт кодек с которым можно сжимать и обратить этот процесс.
*/
ICodecHolder getCodecHolder();
ICodecHolder createCodecHolder();
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,23 @@
import su.plo.voice.PlasmoVoice;

public class PlasmoVoiceSoundPlayer implements ISoundPlayer {
private final OpusCodecHolder opusCodecHolder = new OpusCodecHolder();

@Override
public ISoundPlaySession playSound(ISound sound, IAudioSource audioSource, ISoundController soundController) {
if (!(audioSource instanceof IPlayerAudioSource) || !(soundController instanceof PlasmoVoiceSoundController))
return null;
updateCodecHolder();
IPlayerAudioSource playerAudioSource = (IPlayerAudioSource) audioSource;
Player player = Bukkit.getPlayer(playerAudioSource.getPlayerUniqueId());
if (player == null)
return null;
return new PlasmoVoiceSoundPlaySession(sound, playerAudioSource, (PlasmoVoiceSoundController) soundController);
}

private void updateCodecHolder() {
opusCodecHolder.setSampleRate(PlasmoVoice.getInstance().getVoiceConfig().getSampleRate());
}

@Override
public ICodecHolder getCodecHolder() {
return opusCodecHolder;
public ICodecHolder createCodecHolder() {
ICodecHolder codecHolder = new OpusCodecHolder();
codecHolder.setSampleRate(PlasmoVoice.getInstance().getVoiceConfig().getSampleRate());
return codecHolder;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.ubivashka.plasmovoice.function;

import java.io.Serializable;
import java.util.function.Supplier;

public final class MemoizingSupplier<T> implements Supplier<T>, Serializable {

final Supplier<T> delegate;
transient volatile boolean initialized;
// "value" does not need to be volatile; visibility piggy-backs
// on volatile read of "initialized".
transient T value;

MemoizingSupplier(Supplier<T> delegate) {
this.delegate = delegate;
}

@Override
public T get() {
// A 2-field variant of Double Checked Locking.
if (!initialized) {
synchronized (this) {
if (!initialized) {
T t = delegate.get();
value = t;
initialized = true;
return t;
}
}
}
return value;
}

@Override
public String toString() {
return "Suppliers.memoize(" + delegate + ")";
}

private static final long serialVersionUID = 0;

public static <T> Supplier<T> memoize(Supplier<T> supplier) {
return new MemoizingSupplier<>(supplier);
}

}
9 changes: 4 additions & 5 deletions src/main/java/com/ubivashka/plasmovoice/opus/OpusEncoder.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package com.ubivashka.plasmovoice.opus;

import com.sun.jna.ptr.PointerByReference;
import com.ubivashka.plasmovoice.opus.utils.AudioUtils;
import de.maxhenkel.opus4j.Opus;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;

import com.sun.jna.ptr.PointerByReference;
import com.ubivashka.plasmovoice.opus.utils.AudioUtils;

import de.maxhenkel.opus4j.Opus;

public class OpusEncoder {
protected PointerByReference opusEncoder;
protected int sampleRate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public ISound build() throws UnsupportedAudioFileException, IOException {
switch (soundFormat) {
case WAV:
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(inputStream);
sound = new AudioStreamSound(audioInputStream, PLUGIN.getPlasmoVoiceSoundPlayer().getCodecHolder(), true);
sound = new AudioStreamSound(audioInputStream, PLUGIN.getPlasmoVoiceSoundPlayer().createCodecHolder(), true);
break;
case MP3:
sound = new MP3Sound(inputStream, PLUGIN.getPlasmoVoiceSoundPlayer());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public MP3Sound(InputStream musicInputStream, ISoundPlayer player) throws IOExce
baseFormat.getSampleRate(),
false);
audioInputStream = new MpegFormatConversionProvider().getAudioInputStream(targetFormat, audioInputStream);
convertedSound = new AudioStreamSound(audioInputStream, player.getCodecHolder(), true);
convertedSound = new AudioStreamSound(audioInputStream, player.createCodecHolder(), true);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class AudioStreamSound implements ISound {
* ICodecHolder
*/
public AudioStreamSound(AudioInputStream audioInputStream, ISoundPlayer soundPlayer) {
this(audioInputStream, soundPlayer.getCodecHolder(), false);
this(audioInputStream, soundPlayer.createCodecHolder(), false);
}

/**
Expand All @@ -33,7 +33,7 @@ public AudioStreamSound(AudioInputStream audioInputStream, ISoundPlayer soundPla
* получить из файла или InputStream используйте (Можно
* и другим способом):
* {@link javax.sound.sampled.AudioSystem}
* @param soundPlayer - Используется для сжатия звука
* @param codecHolder - Используется для сжатия звука
* @param convert - Решает конвертировать ли формат звука
*/
public AudioStreamSound(AudioInputStream audioInputStream, ICodecHolder codecHolder, boolean convert) {
Expand All @@ -45,6 +45,7 @@ public AudioStreamSound(AudioInputStream audioInputStream, ICodecHolder codecHol
try {
new AudioInputStreamReader(newAudioInputStream, (data) -> newDataList.add(codecHolder.encode(data)))
.read(codecHolder.getFrameSize());
codecHolder.closeEncoder();
} catch (IOException e) {
e.printStackTrace();
}
Expand Down

0 comments on commit df174c7

Please sign in to comment.