summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--media/java/android/media/audiofx/DynamicsProcessing.java699
1 files changed, 422 insertions, 277 deletions
diff --git a/media/java/android/media/audiofx/DynamicsProcessing.java b/media/java/android/media/audiofx/DynamicsProcessing.java
index d09c9a895e0c..4c17ae1d93b3 100644
--- a/media/java/android/media/audiofx/DynamicsProcessing.java
+++ b/media/java/android/media/audiofx/DynamicsProcessing.java
@@ -16,10 +16,11 @@
package android.media.audiofx;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.media.AudioTrack;
import android.media.MediaPlayer;
import android.media.audiofx.AudioEffect;
-import android.media.audiofx.DynamicsProcessing.Settings;
import android.util.Log;
import java.nio.ByteBuffer;
@@ -90,66 +91,18 @@ public final class DynamicsProcessing extends AudioEffect {
private final static String TAG = "DynamicsProcessing";
- /**
- * Config object used to initialize and change effect parameters at runtime.
- */
- private Config mConfig = null;
-
-
// These parameter constants must be synchronized with those in
// /system/media/audio_effects/include/audio_effects/effect_dynamicsprocessing.h
-
- private static final int PARAM_GET_CHANNEL_COUNT = 0x0;
- private static final int PARAM_EQ_BAND_COUNT = 0x1;
- private static final int PARAM_MBC_BAND_COUNT = 0x2;
- private static final int PARAM_INPUT_GAIN = 0x3;
- private static final int PARAM_PRE_EQ_ENABLED = 0x10;
- private static final int PARAM_PRE_EQ_BAND_ENABLED = 0x11;
- private static final int PARAM_PRE_EQ_BAND_FREQUENCY = 0x12;
- private static final int PARAM_PRE_EQ_BAND_GAIN = 0x13;
- private static final int PARAM_EQ_FREQUENCY_RANGE = 0x22;
- private static final int PARAM_EQ_GAIN_RANGE = 0x23;
- private static final int PARAM_MBC_ENABLED = 0x30;
- private static final int PARAM_MBC_BAND_ENABLED = 0x31;
- private static final int PARAM_MBC_BAND_FREQUENCY = 0x32;
- private static final int PARAM_MBC_BAND_ATTACK_TIME = 0x33;
- private static final int PARAM_MBC_BAND_RELEASE_TIME = 0x34;
- private static final int PARAM_MBC_BAND_RATIO = 0x35;
- private static final int PARAM_MBC_BAND_THRESHOLD = 0x36;
- private static final int PARAM_MBC_BAND_KNEE_WIDTH = 0x37;
- private static final int PARAM_MBC_BAND_NOISE_GATE_THRESHOLD = 0x38;
- private static final int PARAM_MBC_BAND_EXPANDER_RATIO = 0x39;
- private static final int PARAM_MBC_BAND_GAIN_PRE = 0x3A;
- private static final int PARAM_MBC_BAND_GAIN_POST = 0x3B;
- private static final int PARAM_MBC_FREQUENCY_RANGE = 0x42;
- private static final int PARAM_MBC_ATTACK_TIME_RANGE = 0x43;
- private static final int PARAM_MBC_RELEASE_TIME_RANGE = 0x44;
- private static final int PARAM_MBC_RATIO_RANGE = 0x45;
- private static final int PARAM_MBC_THRESHOLD_RANGE = 0x46;
- private static final int PARAM_MBC_KNEE_WIDTH_RANGE = 0x47;
- private static final int PARAM_MBC_NOISE_GATE_THRESHOLD_RANGE = 0x48;
- private static final int PARAM_MBC_EXPANDER_RATIO_RANGE = 0x49;
- private static final int PARAM_MBC_GAIN_RANGE = 0x4A;
- private static final int PARAM_POST_EQ_ENABLED = 0x50;
- private static final int PARAM_POST_EQ_BAND_ENABLED = 0x51;
- private static final int PARAM_POST_EQ_BAND_FREQUENCY = 0x52;
- private static final int PARAM_POST_EQ_BAND_GAIN = 0x53;
- private static final int PARAM_LIMITER_ENABLED = 0x60;
- private static final int PARAM_LIMITER_LINK_GROUP = 0x61;
- private static final int PARAM_LIMITER_ATTACK_TIME = 0x62;
- private static final int PARAM_LIMITER_RELEASE_TIME = 0x63;
- private static final int PARAM_LIMITER_RATIO = 0x64;
- private static final int PARAM_LIMITER_THRESHOLD = 0x65;
- private static final int PARAM_LIMITER_GAIN_POST = 0x66;
- private static final int PARAM_LIMITER_ATTACK_TIME_RANGE = 0x72;
- private static final int PARAM_LIMITER_RELEASE_TIME_RANGE = 0x73;
- private static final int PARAM_LIMITER_RATIO_RANGE = 0x74;
- private static final int PARAM_LIMITER_THRESHOLD_RANGE = 0x75;
- private static final int PARAM_LIMITER_GAIN_RANGE = 0x76;
- private static final int PARAM_VARIANT = 0x100;
- private static final int PARAM_VARIANT_DESCRIPTION = 0x101;
- private static final int PARAM_VARIANT_COUNT = 0x102;
- private static final int PARAM_SET_ENGINE_ARCHITECTURE = 0x200;
+ private static final int PARAM_GET_CHANNEL_COUNT = 0x10;
+ private static final int PARAM_INPUT_GAIN = 0x20;
+ private static final int PARAM_ENGINE_ARCHITECTURE = 0x30;
+ private static final int PARAM_PRE_EQ = 0x40;
+ private static final int PARAM_PRE_EQ_BAND = 0x45;
+ private static final int PARAM_MBC = 0x50;
+ private static final int PARAM_MBC_BAND = 0x55;
+ private static final int PARAM_POST_EQ = 0x60;
+ private static final int PARAM_POST_EQ_BAND = 0x65;
+ private static final int PARAM_LIMITER = 0x70;
/**
* Index of variant that favors frequency resolution. Frequency domain based implementation.
@@ -226,12 +179,13 @@ public final class DynamicsProcessing extends AudioEffect {
* Config object that suits your needs. A null cfg parameter will create and use a default
* configuration for the effect
*/
- public DynamicsProcessing(int priority, int audioSession, Config cfg) {
+ public DynamicsProcessing(int priority, int audioSession, @Nullable Config cfg) {
super(EFFECT_TYPE_DYNAMICS_PROCESSING, EFFECT_TYPE_NULL, priority, audioSession);
if (audioSession == 0) {
Log.w(TAG, "WARNING: attaching a DynamicsProcessing to global output mix is"
+ "deprecated!");
}
+ final Config config;
mChannelCount = getChannelCount();
if (cfg == null) {
//create a default configuration and effect, with the number of channels this effect has
@@ -239,21 +193,33 @@ public final class DynamicsProcessing extends AudioEffect {
new DynamicsProcessing.Config.Builder(
CONFIG_DEFAULT_VARIANT,
mChannelCount,
- true /*use preEQ*/, 6 /*pre eq bands*/,
- true /*use mbc*/, 6 /*mbc bands*/,
- true /*use postEQ*/, 6 /*postEq bands*/,
- true /*use Limiter*/);
- mConfig = builder.build();
+ CONFIG_DEFAULT_USE_PREEQ,
+ CONFIG_DEFAULT_PREEQ_BANDS,
+ CONFIG_DEFAULT_USE_MBC,
+ CONFIG_DEFAULT_MBC_BANDS,
+ CONFIG_DEFAULT_USE_POSTEQ,
+ CONFIG_DEFAULT_POSTEQ_BANDS,
+ CONFIG_DEFAULT_USE_LIMITER);
+ config = builder.build();
} else {
- //validate channels are ok. decide what to do: replicate channels if more, or fail, or
- mConfig = new DynamicsProcessing.Config(mChannelCount, cfg);
+ //validate channels are ok. decide what to do: replicate channels if more
+ config = new DynamicsProcessing.Config(mChannelCount, cfg);
+ }
+
+ //configure engine
+ setEngineArchitecture(config.getVariant(),
+ config.getPreferredFrameDuration(),
+ config.isPreEqInUse(),
+ config.getPreEqBandCount(),
+ config.isMbcInUse(),
+ config.getMbcBandCount(),
+ config.isPostEqInUse(),
+ config.getPostEqBandCount(),
+ config.isLimiterInUse());
+ //update all the parameters
+ for (int ch = 0; ch < mChannelCount; ch++) {
+ updateEngineChannelByChannelIndex(ch, config.getChannelByChannelIndex(ch));
}
-
- setEngineArchitecture(mConfig.getVariant(),
- mConfig.isPreEqInUse(), mConfig.getPreEqBandCount(),
- mConfig.isMbcInUse(), mConfig.getMbcBandCount(),
- mConfig.isPostEqInUse(), mConfig.getPostEqBandCount(),
- mConfig.isLimiterInUse());
}
/**
@@ -261,11 +227,51 @@ public final class DynamicsProcessing extends AudioEffect {
* @return Config Current Config object used to setup this DynamicsProcessing effect.
*/
public Config getConfig() {
- return mConfig;
+ //Query engine architecture to create config object
+ Number[] params = { PARAM_ENGINE_ARCHITECTURE };
+ Number[] values = { 0 /*0 variant */,
+ 0.0f /* 1 preferredFrameDuration */,
+ 0 /*2 preEqInUse */,
+ 0 /*3 preEqBandCount */,
+ 0 /*4 mbcInUse */,
+ 0 /*5 mbcBandCount*/,
+ 0 /*6 postEqInUse */,
+ 0 /*7 postEqBandCount */,
+ 0 /*8 limiterInUse */};
+ byte[] paramBytes = numberArrayToByteArray(params);
+ byte[] valueBytes = numberArrayToByteArray(values); //just interest in the byte size.
+ getParameter(paramBytes, valueBytes);
+ byteArrayToNumberArray(valueBytes, values);
+ DynamicsProcessing.Config.Builder builder =
+ new DynamicsProcessing.Config.Builder(
+ values[0].intValue(),
+ mChannelCount,
+ values[2].intValue() > 0 /*use preEQ*/,
+ values[3].intValue() /*pre eq bands*/,
+ values[4].intValue() > 0 /*use mbc*/,
+ values[5].intValue() /*mbc bands*/,
+ values[6].intValue() > 0 /*use postEQ*/,
+ values[7].intValue()/*postEq bands*/,
+ values[8].intValue() > 0 /*use Limiter*/).
+ setPreferredFrameDuration(values[1].floatValue());
+ Config config = builder.build();
+ for (int ch = 0; ch < mChannelCount; ch++) {
+ Channel channel = queryEngineByChannelIndex(ch);
+ config.setChannelTo(ch, channel);
+ }
+ return config;
}
- private static final int CONFIG_DEFAULT_VARIANT = 0; //favor frequency
+ private static final int CONFIG_DEFAULT_VARIANT = VARIANT_FAVOR_FREQUENCY_RESOLUTION;
+ private static final boolean CONFIG_DEFAULT_USE_PREEQ = true;
+ private static final int CONFIG_DEFAULT_PREEQ_BANDS = 6;
+ private static final boolean CONFIG_DEFAULT_USE_MBC = true;
+ private static final int CONFIG_DEFAULT_MBC_BANDS = 6;
+ private static final boolean CONFIG_DEFAULT_USE_POSTEQ = true;
+ private static final int CONFIG_DEFAULT_POSTEQ_BANDS = 6;
+ private static final boolean CONFIG_DEFAULT_USE_LIMITER = true;
+
private static final float CHANNEL_DEFAULT_INPUT_GAIN = 0; // dB
private static final float CONFIG_PREFERRED_FRAME_DURATION_MS = 10.0f; //milliseconds
@@ -1276,7 +1282,7 @@ public final class DynamicsProcessing extends AudioEffect {
mChannel = new Channel[mChannelCount];
//check if channelconfig is null or has less channels than channel count.
//options: fill the missing with default options.
- // or fail?
+ // or fail?
for (int ch = 0; ch < mChannelCount; ch++) {
if (ch < channel.length) {
mChannel[ch] = new Channel(channel[ch]); //copy create
@@ -1331,7 +1337,7 @@ public final class DynamicsProcessing extends AudioEffect {
* Class constructor for Config
* @param cfg Configuration object copy constructor
*/
- public Config(Config cfg) {
+ public Config(@NonNull Config cfg) {
this(cfg.mChannelCount, cfg);
}
@@ -1763,138 +1769,115 @@ public final class DynamicsProcessing extends AudioEffect {
}
//=== CHANNEL
public Channel getChannelByChannelIndex(int channelIndex) {
- return mConfig.getChannelByChannelIndex(channelIndex);
+ return queryEngineByChannelIndex(channelIndex);
}
public void setChannelTo(int channelIndex, Channel channel) {
- mConfig.setChannelTo(channelIndex, channel);
+ updateEngineChannelByChannelIndex(channelIndex, channel);
}
public void setAllChannelsTo(Channel channel) {
- mConfig.setAllChannelsTo(channel);
+ for (int ch = 0; ch < mChannelCount; ch++) {
+ setChannelTo(ch, channel);
+ }
}
//=== channel params
public float getInputGainByChannelIndex(int channelIndex) {
- //TODO: return info from engine instead of cached config
- return mConfig.getInputGainByChannelIndex(channelIndex);
+ return getTwoFloat(PARAM_INPUT_GAIN, channelIndex);
}
public void setInputGainbyChannel(int channelIndex, float inputGain) {
- mConfig.setInputGainByChannelIndex(channelIndex, inputGain);
- //TODO: communicate change to engine
+ setTwoFloat(PARAM_INPUT_GAIN, channelIndex, inputGain);
}
public void setInputGainAllChannelsTo(float inputGain) {
- mConfig.setInputGainAllChannelsTo(inputGain);
- //TODO: communicate change to engine
+ for (int ch = 0; ch < mChannelCount; ch++) {
+ setInputGainbyChannel(ch, inputGain);
+ }
}
//=== PreEQ
public Eq getPreEqByChannelIndex(int channelIndex) {
- //TODO: return info from engine instead of cached config
- return mConfig.getPreEqByChannelIndex(channelIndex);
+ return queryEngineEqByChannelIndex(PARAM_PRE_EQ, channelIndex);
}
-
public void setPreEqByChannelIndex(int channelIndex, Eq preEq) {
- mConfig.setPreEqByChannelIndex(channelIndex, preEq);
- //TODO: communicate change to engine
+ updateEngineEqByChannelIndex(PARAM_PRE_EQ, channelIndex, preEq);
}
-
public void setPreEqAllChannelsTo(Eq preEq) {
- mConfig.setPreEqAllChannelsTo(preEq);
- //TODO: communicate change to engine
+ for (int ch = 0; ch < mChannelCount; ch++) {
+ setPreEqByChannelIndex(ch, preEq);
+ }
}
-
public EqBand getPreEqBandByChannelIndex(int channelIndex, int band) {
- //TODO: return info from engine instead of cached config
- return mConfig.getPreEqBandByChannelIndex(channelIndex, band);
+ return queryEngineEqBandByChannelIndex(PARAM_PRE_EQ_BAND, channelIndex, band);
}
-
public void setPreEqBandByChannelIndex(int channelIndex, int band, EqBand preEqBand) {
- mConfig.setPreEqBandByChannelIndex(channelIndex, band, preEqBand);
- //TODO: communicate change to engine
+ updateEngineEqBandByChannelIndex(PARAM_PRE_EQ_BAND, channelIndex, band, preEqBand);
}
-
public void setPreEqBandAllChannelsTo(int band, EqBand preEqBand) {
- mConfig.setPreEqBandAllChannelsTo(band, preEqBand);
- //TODO: communicate change to engine
+ for (int ch = 0; ch < mChannelCount; ch++) {
+ setPreEqBandByChannelIndex(ch, band, preEqBand);
+ }
}
//=== MBC
public Mbc getMbcByChannelIndex(int channelIndex) {
- //TODO: return info from engine instead of cached config
- return mConfig.getMbcByChannelIndex(channelIndex);
+ return queryEngineMbcByChannelIndex(channelIndex);
}
-
public void setMbcByChannelIndex(int channelIndex, Mbc mbc) {
- mConfig.setMbcByChannelIndex(channelIndex, mbc);
- //TODO: communicate change to engine
+ updateEngineMbcByChannelIndex(channelIndex, mbc);
}
-
public void setMbcAllChannelsTo(Mbc mbc) {
- mConfig.setMbcAllChannelsTo(mbc);
- //TODO: communicate change to engine
+ for (int ch = 0; ch < mChannelCount; ch++) {
+ setMbcByChannelIndex(ch, mbc);
+ }
}
-
public MbcBand getMbcBandByChannelIndex(int channelIndex, int band) {
- //TODO: return info from engine instead of cached config
- return mConfig.getMbcBandByChannelIndex(channelIndex, band);
+ return queryEngineMbcBandByChannelIndex(channelIndex, band);
}
-
public void setMbcBandByChannelIndex(int channelIndex, int band, MbcBand mbcBand) {
- mConfig.setMbcBandByChannelIndex(channelIndex, band, mbcBand);
- //TODO: communicate change to engine
+ updateEngineMbcBandByChannelIndex(channelIndex, band, mbcBand);
}
-
public void setMbcBandAllChannelsTo(int band, MbcBand mbcBand) {
- mConfig.setMbcBandAllChannelsTo(band, mbcBand);
- //TODO: communicate change to engine
+ for (int ch = 0; ch < mChannelCount; ch++) {
+ setMbcBandByChannelIndex(ch, band, mbcBand);
+ }
}
//== PostEq
public Eq getPostEqByChannelIndex(int channelIndex) {
- //TODO: return info from engine instead of cached config
- return mConfig.getPostEqByChannelIndex(channelIndex);
+ return queryEngineEqByChannelIndex(PARAM_POST_EQ, channelIndex);
}
-
public void setPostEqByChannelIndex(int channelIndex, Eq postEq) {
- mConfig.setPostEqByChannelIndex(channelIndex, postEq);
- //TODO: communicate change to engine
+ updateEngineEqByChannelIndex(PARAM_POST_EQ, channelIndex, postEq);
}
-
public void setPostEqAllChannelsTo(Eq postEq) {
- mConfig.setPostEqAllChannelsTo(postEq);
- //TODO: communicate change to engine
+ for (int ch = 0; ch < mChannelCount; ch++) {
+ setPostEqByChannelIndex(ch, postEq);
+ }
}
-
public EqBand getPostEqBandByChannelIndex(int channelIndex, int band) {
- //TODO: return info from engine instead of cached config
- return mConfig.getPostEqBandByChannelIndex(channelIndex, band);
+ return queryEngineEqBandByChannelIndex(PARAM_POST_EQ_BAND, channelIndex, band);
}
-
public void setPostEqBandByChannelIndex(int channelIndex, int band, EqBand postEqBand) {
- mConfig.setPostEqBandByChannelIndex(channelIndex, band, postEqBand);
- //TODO: communicate change to engine
+ updateEngineEqBandByChannelIndex(PARAM_POST_EQ_BAND, channelIndex, band, postEqBand);
}
-
public void setPostEqBandAllChannelsTo(int band, EqBand postEqBand) {
- mConfig.setPostEqBandAllChannelsTo(band, postEqBand);
- //TODO: communicate change to engine
+ for (int ch = 0; ch < mChannelCount; ch++) {
+ setPostEqBandByChannelIndex(ch, band, postEqBand);
+ }
}
//==== Limiter
public Limiter getLimiterByChannelIndex(int channelIndex) {
- //TODO: return info from engine instead of cached config
- return mConfig.getLimiterByChannelIndex(channelIndex);
+ return queryEngineLimiterByChannelIndex(channelIndex);
}
-
public void setLimiterByChannelIndex(int channelIndex, Limiter limiter) {
- mConfig.setLimiterByChannelIndex(channelIndex, limiter);
- //TODO: communicate change to engine
+ updateEngineLimiterByChannelIndex(channelIndex, limiter);
}
-
public void setLimiterAllChannelsTo(Limiter limiter) {
- mConfig.setLimiterAllChannelsTo(limiter);
- //TODO: communicate change to engine
+ for (int ch = 0; ch < mChannelCount; ch++) {
+ setLimiterByChannelIndex(ch, limiter);
+ }
}
/**
@@ -1905,165 +1888,327 @@ public final class DynamicsProcessing extends AudioEffect {
return getOneInt(PARAM_GET_CHANNEL_COUNT);
}
- private void setEngineArchitecture(int variant, boolean preEqInUse, int preEqBandCount,
- boolean mbcInUse, int mbcBandCount, boolean postEqInUse, int postEqBandCount,
- boolean limiterInUse) {
- int[] values = { variant, (preEqInUse ? 1 : 0), preEqBandCount,
- (mbcInUse ? 1 : 0), mbcBandCount, (postEqInUse ? 1 : 0), postEqBandCount,
+ //=== Engine calls
+ private void setEngineArchitecture(int variant, float preferredFrameDuration,
+ boolean preEqInUse, int preEqBandCount, boolean mbcInUse, int mbcBandCount,
+ boolean postEqInUse, int postEqBandCount, boolean limiterInUse) {
+
+ Number[] params = { PARAM_ENGINE_ARCHITECTURE };
+ Number[] values = { variant /* variant */,
+ preferredFrameDuration,
+ (preEqInUse ? 1 : 0),
+ preEqBandCount,
+ (mbcInUse ? 1 : 0),
+ mbcBandCount,
+ (postEqInUse ? 1 : 0),
+ postEqBandCount,
(limiterInUse ? 1 : 0)};
- //TODO: enable later setIntArray(PARAM_SET_ENGINE_ARCHITECTURE, values);
+ setNumberArray(params, values);
+ }
+
+ private void updateEngineEqBandByChannelIndex(int param, int channelIndex, int bandIndex,
+ @NonNull EqBand eqBand) {
+ Number[] params = {param,
+ channelIndex,
+ bandIndex};
+ Number[] values = {(eqBand.isEnabled() ? 1 : 0),
+ eqBand.getCutoffFrequency(),
+ eqBand.getGain()};
+ setNumberArray(params, values);
+ }
+ private Eq queryEngineEqByChannelIndex(int param, int channelIndex) {
+
+ Number[] params = {param == PARAM_PRE_EQ ? PARAM_PRE_EQ : PARAM_POST_EQ,
+ channelIndex};
+ Number[] values = {0 /*0 in use */,
+ 0 /*1 enabled*/,
+ 0 /*2 band count */};
+ byte[] paramBytes = numberArrayToByteArray(params);
+ byte[] valueBytes = numberArrayToByteArray(values); //just interest in the byte size.
+ getParameter(paramBytes, valueBytes);
+ byteArrayToNumberArray(valueBytes, values);
+ int bandCount = values[2].intValue();
+ Eq eq = new Eq(values[0].intValue() > 0 /* in use */,
+ values[1].intValue() > 0 /* enabled */,
+ bandCount /*band count*/);
+ for (int b = 0; b < bandCount; b++) {
+ EqBand eqBand = queryEngineEqBandByChannelIndex(param == PARAM_PRE_EQ ?
+ PARAM_PRE_EQ_BAND : PARAM_POST_EQ_BAND, channelIndex, b);
+ eq.setBand(b, eqBand);
+ }
+ return eq;
+ }
+ private EqBand queryEngineEqBandByChannelIndex(int param, int channelIndex, int bandIndex) {
+ Number[] params = {param,
+ channelIndex,
+ bandIndex};
+ Number[] values = {0 /*0 enabled*/,
+ 0.0f /*1 cutoffFrequency */,
+ 0.0f /*2 gain */};
+
+ byte[] paramBytes = numberArrayToByteArray(params);
+ byte[] valueBytes = numberArrayToByteArray(values); //just interest in the byte size.
+ getParameter(paramBytes, valueBytes);
+
+ byteArrayToNumberArray(valueBytes, values);
+
+ return new EqBand(values[0].intValue() > 0 /* enabled */,
+ values[1].floatValue() /* cutoffFrequency */,
+ values[2].floatValue() /* gain*/);
+ }
+ private void updateEngineEqByChannelIndex(int param, int channelIndex, @NonNull Eq eq) {
+ int bandCount = eq.getBandCount();
+ Number[] params = {param,
+ channelIndex};
+ Number[] values = { (eq.isInUse() ? 1 : 0),
+ (eq.isEnabled() ? 1 : 0),
+ bandCount};
+ setNumberArray(params, values);
+ for (int b = 0; b < bandCount; b++) {
+ EqBand eqBand = eq.getBand(b);
+ updateEngineEqBandByChannelIndex(param == PARAM_PRE_EQ ?
+ PARAM_PRE_EQ_BAND : PARAM_POST_EQ_BAND, channelIndex, b, eqBand);
+ }
+ }
+
+ private Mbc queryEngineMbcByChannelIndex(int channelIndex) {
+ Number[] params = {PARAM_MBC,
+ channelIndex};
+ Number[] values = {0 /*0 in use */,
+ 0 /*1 enabled*/,
+ 0 /*2 band count */};
+ byte[] paramBytes = numberArrayToByteArray(params);
+ byte[] valueBytes = numberArrayToByteArray(values); //just interest in the byte size.
+ getParameter(paramBytes, valueBytes);
+ byteArrayToNumberArray(valueBytes, values);
+ int bandCount = values[2].intValue();
+ Mbc mbc = new Mbc(values[0].intValue() > 0 /* in use */,
+ values[1].intValue() > 0 /* enabled */,
+ bandCount /*band count*/);
+ for (int b = 0; b < bandCount; b++) {
+ MbcBand mbcBand = queryEngineMbcBandByChannelIndex(channelIndex, b);
+ mbc.setBand(b, mbcBand);
+ }
+ return mbc;
+ }
+ private MbcBand queryEngineMbcBandByChannelIndex(int channelIndex, int bandIndex) {
+ Number[] params = {PARAM_MBC_BAND,
+ channelIndex,
+ bandIndex};
+ Number[] values = {0 /*0 enabled */,
+ 0.0f /*1 cutoffFrequency */,
+ 0.0f /*2 AttackTime */,
+ 0.0f /*3 ReleaseTime */,
+ 0.0f /*4 Ratio */,
+ 0.0f /*5 Threshold */,
+ 0.0f /*6 KneeWidth */,
+ 0.0f /*7 NoiseGateThreshold */,
+ 0.0f /*8 ExpanderRatio */,
+ 0.0f /*9 PreGain */,
+ 0.0f /*10 PostGain*/};
+
+ byte[] paramBytes = numberArrayToByteArray(params);
+ byte[] valueBytes = numberArrayToByteArray(values); //just interest in the byte size.
+ getParameter(paramBytes, valueBytes);
+
+ byteArrayToNumberArray(valueBytes, values);
+
+ return new MbcBand(values[0].intValue() > 0 /* enabled */,
+ values[1].floatValue() /* cutoffFrequency */,
+ values[2].floatValue()/*2 AttackTime */,
+ values[3].floatValue()/*3 ReleaseTime */,
+ values[4].floatValue()/*4 Ratio */,
+ values[5].floatValue()/*5 Threshold */,
+ values[6].floatValue()/*6 KneeWidth */,
+ values[7].floatValue()/*7 NoiseGateThreshold */,
+ values[8].floatValue()/*8 ExpanderRatio */,
+ values[9].floatValue()/*9 PreGain */,
+ values[10].floatValue()/*10 PostGain*/);
+ }
+ private void updateEngineMbcBandByChannelIndex(int channelIndex, int bandIndex,
+ @NonNull MbcBand mbcBand) {
+ Number[] params = { PARAM_MBC_BAND,
+ channelIndex,
+ bandIndex};
+ Number[] values = {(mbcBand.isEnabled() ? 1 : 0),
+ mbcBand.getCutoffFrequency(),
+ mbcBand.getAttackTime(),
+ mbcBand.getReleaseTime(),
+ mbcBand.getRatio(),
+ mbcBand.getThreshold(),
+ mbcBand.getKneeWidth(),
+ mbcBand.getNoiseGateThreshold(),
+ mbcBand.getExpanderRatio(),
+ mbcBand.getPreGain(),
+ mbcBand.getPostGain()};
+ setNumberArray(params, values);
+ }
+
+ private void updateEngineMbcByChannelIndex(int channelIndex, @NonNull Mbc mbc) {
+ int bandCount = mbc.getBandCount();
+ Number[] params = { PARAM_MBC,
+ channelIndex};
+ Number[] values = {(mbc.isInUse() ? 1 : 0),
+ (mbc.isEnabled() ? 1 : 0),
+ bandCount};
+ setNumberArray(params, values);
+ for (int b = 0; b < bandCount; b++) {
+ MbcBand mbcBand = mbc.getBand(b);
+ updateEngineMbcBandByChannelIndex(channelIndex, b, mbcBand);
+ }
+ }
+
+ private void updateEngineLimiterByChannelIndex(int channelIndex, @NonNull Limiter limiter) {
+ Number[] params = { PARAM_LIMITER,
+ channelIndex};
+ Number[] values = {(limiter.isInUse() ? 1 : 0),
+ (limiter.isEnabled() ? 1 : 0),
+ limiter.getLinkGroup(),
+ limiter.getAttackTime(),
+ limiter.getReleaseTime(),
+ limiter.getRatio(),
+ limiter.getThreshold(),
+ limiter.getPostGain()};
+ setNumberArray(params, values);
+ }
+
+ private Limiter queryEngineLimiterByChannelIndex(int channelIndex) {
+ Number[] params = {PARAM_LIMITER,
+ channelIndex};
+ Number[] values = {0 /*0 in use (int)*/,
+ 0 /*1 enabled (int)*/,
+ 0 /*2 link group (int)*/,
+ 0.0f /*3 attack time (float)*/,
+ 0.0f /*4 release time (float)*/,
+ 0.0f /*5 ratio (float)*/,
+ 0.0f /*6 threshold (float)*/,
+ 0.0f /*7 post gain(float)*/};
+
+ byte[] paramBytes = numberArrayToByteArray(params);
+ byte[] valueBytes = numberArrayToByteArray(values); //just interest in the byte size.
+ getParameter(paramBytes, valueBytes);
+ byteArrayToNumberArray(valueBytes, values);
+
+ return new Limiter(values[0].intValue() > 0 /*in use*/,
+ values[1].intValue() > 0 /*enabled*/,
+ values[2].intValue() /*linkGroup*/,
+ values[3].floatValue() /*attackTime*/,
+ values[4].floatValue() /*releaseTime*/,
+ values[5].floatValue() /*ratio*/,
+ values[6].floatValue() /*threshold*/,
+ values[7].floatValue() /*postGain*/);
+ }
+
+ private Channel queryEngineByChannelIndex(int channelIndex) {
+ float inputGain = getTwoFloat(PARAM_INPUT_GAIN, channelIndex);
+ Eq preEq = queryEngineEqByChannelIndex(PARAM_PRE_EQ, channelIndex);
+ Mbc mbc = queryEngineMbcByChannelIndex(channelIndex);
+ Eq postEq = queryEngineEqByChannelIndex(PARAM_POST_EQ, channelIndex);
+ Limiter limiter = queryEngineLimiterByChannelIndex(channelIndex);
+
+ Channel channel = new Channel(inputGain,
+ preEq.isInUse(), preEq.getBandCount(),
+ mbc.isInUse(), mbc.getBandCount(),
+ postEq.isInUse(), postEq.getBandCount(),
+ limiter.isInUse());
+ channel.setInputGain(inputGain);
+ channel.setPreEq(preEq);
+ channel.setMbc(mbc);
+ channel.setPostEq(postEq);
+ channel.setLimiter(limiter);
+ return channel;
+ }
+
+ private void updateEngineChannelByChannelIndex(int channelIndex, @NonNull Channel channel) {
+ //send things with as few calls as possible
+ setTwoFloat(PARAM_INPUT_GAIN, channelIndex, channel.getInputGain());
+ Eq preEq = channel.getPreEq();
+ updateEngineEqByChannelIndex(PARAM_PRE_EQ, channelIndex, preEq);
+ Mbc mbc = channel.getMbc();
+ updateEngineMbcByChannelIndex(channelIndex, mbc);
+ Eq postEq = channel.getPostEq();
+ updateEngineEqByChannelIndex(PARAM_POST_EQ, channelIndex, postEq);
+ Limiter limiter = channel.getLimiter();
+ updateEngineLimiterByChannelIndex(channelIndex, limiter);
}
//****** convenience methods:
//
- private int getOneInt(int paramGet) {
- int[] param = new int[1];
- int[] result = new int[1];
+ private int getOneInt(int param) {
+ final int[] params = { param };
+ final int[] result = new int[1];
- param[0] = paramGet;
- checkStatus(getParameter(param, result));
+ checkStatus(getParameter(params, result));
return result[0];
}
- private int getTwoInt(int paramGet, int paramA) {
- int[] param = new int[2];
- int[] result = new int[1];
+ private void setTwoFloat(int param, int paramA, float valueSet) {
+ final int[] params = { param, paramA };
+ final byte[] value;
- param[0] = paramGet;
- param[1] = paramA;
- checkStatus(getParameter(param, result));
- return result[0];
- }
-
- private int getThreeInt(int paramGet, int paramA, int paramB) {
- //have to use bytearrays, with more than 2 parameters.
- byte[] paramBytes = concatArrays(intToByteArray(paramGet),
- intToByteArray(paramA),
- intToByteArray(paramB));
- byte[] resultBytes = new byte[4]; //single int
-
- checkStatus(getParameter(paramBytes, resultBytes));
-
- return byteArrayToInt(resultBytes);
- }
-
- private void setOneInt(int paramSet, int valueSet) {
- int[] param = new int[1];
- int[] value = new int[1];
-
- param[0] = paramSet;
- value[0] = valueSet;
- checkStatus(setParameter(param, value));
- }
-
- private void setTwoInt(int paramSet, int paramA, int valueSet) {
- int[] param = new int[2];
- int[] value = new int[1];
-
- param[0] = paramSet;
- param[1] = paramA;
- value[0] = valueSet;
- checkStatus(setParameter(param, value));
- }
-
- private void setThreeInt(int paramSet, int paramA, int paramB, int valueSet) {
- //have to use bytearrays, with more than 2 parameters.
- byte[] paramBytes = concatArrays(intToByteArray(paramSet),
- intToByteArray(paramA),
- intToByteArray(paramB));
- byte[] valueBytes = intToByteArray(valueSet);
-
- checkStatus(setParameter(paramBytes, valueBytes));
- }
-
- private void setOneFloat(int paramSet, float valueSet) {
- int[] param = new int[1];
- byte[] value;
-
- param[0] = paramSet;
- value = floatToByteArray(valueSet);
- checkStatus(setParameter(param, value));
- }
-
- private void setTwoFloat(int paramSet, int paramA, float valueSet) {
- int[] param = new int[2];
- byte[] value;
-
- param[0] = paramSet;
- param[1] = paramA;
value = floatToByteArray(valueSet);
- checkStatus(setParameter(param, value));
+ checkStatus(setParameter(params, value));
}
- private void setThreeFloat(int paramSet, int paramA, int paramB, float valueSet) {
- //have to use bytearrays, with more than 2 parameters.
- byte[] paramBytes = concatArrays(intToByteArray(paramSet),
- intToByteArray(paramA),
- intToByteArray(paramB));
- byte[] valueBytes = floatToByteArray(valueSet);
-
- checkStatus(setParameter(paramBytes, valueBytes));
- }
- private byte[] intArrayToByteArray(int[] values) {
- int expectedBytes = values.length * 4;
+ private byte[] numberArrayToByteArray(Number[] values) {
+ int expectedBytes = 0;
+ for (int i = 0; i < values.length; i++) {
+ if (values[i] instanceof Integer) {
+ expectedBytes += Integer.BYTES;
+ } else if (values[i] instanceof Float) {
+ expectedBytes += Float.BYTES;
+ } else {
+ throw new IllegalArgumentException("unknown value type " +
+ values[i].getClass());
+ }
+ }
ByteBuffer converter = ByteBuffer.allocate(expectedBytes);
converter.order(ByteOrder.nativeOrder());
- for (int k = 0; k < values.length; k++) {
- converter.putFloat(values[k]);
+ for (int i = 0; i < values.length; i++) {
+ if (values[i] instanceof Integer) {
+ converter.putInt(values[i].intValue());
+ } else if (values[i] instanceof Float) {
+ converter.putFloat(values[i].floatValue());
+ }
}
return converter.array();
}
- private void setIntArray(int paramSet, int[] paramArray) {
- //have to use bytearrays, with more than 2 parameters.
- byte[] paramBytes = intToByteArray(paramSet);
- byte[] valueBytes = intArrayToByteArray(paramArray);
- checkStatus(setParameter(paramBytes, valueBytes));
+ private void byteArrayToNumberArray(byte[] valuesIn, Number[] valuesOut) {
+ int inIndex = 0;
+ int outIndex = 0;
+ while (inIndex < valuesIn.length && outIndex < valuesOut.length) {
+ if (valuesOut[outIndex] instanceof Integer) {
+ valuesOut[outIndex++] = byteArrayToInt(valuesIn, inIndex);
+ inIndex += Integer.BYTES;
+ } else if (valuesOut[outIndex] instanceof Float) {
+ valuesOut[outIndex++] = byteArrayToFloat(valuesIn, inIndex);
+ inIndex += Float.BYTES;
+ } else {
+ throw new IllegalArgumentException("can't convert " +
+ valuesOut[outIndex].getClass());
+ }
+ }
+ if (outIndex != valuesOut.length) {
+ throw new IllegalArgumentException("only converted " + outIndex +
+ " values out of "+ valuesOut.length + " expected");
+ }
}
- private float getOneFloat(int paramGet) {
- int[] param = new int[1];
- byte[] result = new byte[4];
-
- param[0] = paramGet;
- checkStatus(getParameter(param, result));
- return byteArrayToFloat(result);
+ private void setNumberArray(Number[] params, Number[] values) {
+ byte[] paramBytes = numberArrayToByteArray(params);
+ byte[] valueBytes = numberArrayToByteArray(values);
+ checkStatus(setParameter(paramBytes, valueBytes));
}
- private float getTwoFloat(int paramGet, int paramA) {
- int[] param = new int[2];
- byte[] result = new byte[4];
+ private float getTwoFloat(int param, int paramA) {
+ final int[] params = { param, paramA };
+ final byte[] result = new byte[4];
- param[0] = paramGet;
- param[1] = paramA;
- checkStatus(getParameter(param, result));
+ checkStatus(getParameter(params, result));
return byteArrayToFloat(result);
}
- private float getThreeFloat(int paramGet, int paramA, int paramB) {
- //have to use bytearrays, with more than 2 parameters.
- byte[] paramBytes = concatArrays(intToByteArray(paramGet),
- intToByteArray(paramA),
- intToByteArray(paramB));
- byte[] resultBytes = new byte[4]; //single float
-
- checkStatus(getParameter(paramBytes, resultBytes));
-
- return byteArrayToFloat(resultBytes);
- }
-
- private float[] getOneFloatArray(int paramGet, int expectedSize) {
- int[] param = new int[1];
- byte[] result = new byte[4 * expectedSize];
-
- param[0] = paramGet;
- checkStatus(getParameter(param, result));
- float[] returnArray = new float[expectedSize];
- for (int k = 0; k < expectedSize; k++) {
- returnArray[k] = byteArrayToFloat(result, 4 * k);
- }
- return returnArray;
- }
/**
* @hide
* The OnParameterChangeListener interface defines a method called by the DynamicsProcessing