diff --git a/app/src/main/java/xdsopl/robot36/Decoder.java b/app/src/main/java/xdsopl/robot36/Decoder.java index a8fdf48..379055b 100644 --- a/app/src/main/java/xdsopl/robot36/Decoder.java +++ b/app/src/main/java/xdsopl/robot36/Decoder.java @@ -30,6 +30,7 @@ public class Decoder { private final MainActivity activity; private final ImageView image; private final SpectrumView spectrum; + private final VUMeterView meter; private final AudioRecord audio; private final int audioSource = MediaRecorder.AudioSource.MIC; private final int channelConfig = AudioFormat.CHANNEL_IN_MONO; @@ -42,6 +43,7 @@ public class Decoder { private final int[] savedBuffer; private final int[] savedWidth; private final int[] savedHeight; + private final int[] volume; private final RenderScript rs; private final Allocation rsDecoderAudioBuffer; @@ -52,6 +54,7 @@ public class Decoder { private final Allocation rsDecoderSavedBuffer; private final Allocation rsDecoderSavedWidth; private final Allocation rsDecoderSavedHeight; + private final Allocation rsDecoderVolume; private final ScriptC_decoder rsDecoder; private final int mode_raw = 0; @@ -73,7 +76,10 @@ public class Decoder { return; if (drawImage) { image.drawCanvas(); - spectrum.drawCanvas(); + if(enableAnalyzer) { + spectrum.drawCanvas(); + meter.drawCanvas(); + } } } decode(); @@ -81,9 +87,10 @@ public class Decoder { } }; - public Decoder(MainActivity activity, SpectrumView spectrum, ImageView image) { + public Decoder(MainActivity activity, SpectrumView spectrum, ImageView image, VUMeterView meter) { this.image = image; this.spectrum = spectrum; + this.meter = meter; this.activity = activity; pixelBuffer = new int[image.bitmap.getWidth() * image.bitmap.getHeight()]; spectrumBuffer = new int[spectrum.bitmap.getWidth() * spectrum.bitmap.getHeight()]; @@ -103,6 +110,7 @@ public class Decoder { currentMode = new int[1]; savedWidth = new int[1]; savedHeight = new int[1]; + volume = new int[1]; savedBuffer = new int[pixelBuffer.length]; rs = RenderScript.create(activity.getApplicationContext()); @@ -113,6 +121,7 @@ public class Decoder { rsDecoderCurrentMode = Allocation.createSized(rs, Element.I32(rs), 1, Allocation.USAGE_SHARED | Allocation.USAGE_SCRIPT); rsDecoderSavedWidth = Allocation.createSized(rs, Element.I32(rs), 1, Allocation.USAGE_SHARED | Allocation.USAGE_SCRIPT); rsDecoderSavedHeight = Allocation.createSized(rs, Element.I32(rs), 1, Allocation.USAGE_SHARED | Allocation.USAGE_SCRIPT); + rsDecoderVolume = Allocation.createSized(rs, Element.I32(rs), 1, Allocation.USAGE_SHARED | Allocation.USAGE_SCRIPT); rsDecoderSavedBuffer = Allocation.createSized(rs, Element.I32(rs), savedBuffer.length, Allocation.USAGE_SHARED | Allocation.USAGE_SCRIPT); rsDecoder = new ScriptC_decoder(rs); rsDecoder.bind_audio_buffer(rsDecoderAudioBuffer); @@ -122,6 +131,7 @@ public class Decoder { rsDecoder.bind_current_mode(rsDecoderCurrentMode); rsDecoder.bind_saved_width(rsDecoderSavedWidth); rsDecoder.bind_saved_height(rsDecoderSavedHeight); + rsDecoder.bind_volume(rsDecoderVolume); rsDecoder.bind_saved_buffer(rsDecoderSavedBuffer); rsDecoder.invoke_initialize(sampleRate, valueBufferLength, image.bitmap.getWidth(), image.bitmap.getHeight(), @@ -238,6 +248,9 @@ public class Decoder { rsDecoderCurrentMode.copyTo(currentMode); switch_mode(currentMode[0]); + rsDecoderVolume.copyTo(volume); + meter.volume = volume[0] / 1023.0f; + rsDecoderSavedHeight.copyTo(savedHeight); if (savedHeight[0] > 0) { rsDecoderSavedWidth.copyTo(savedWidth); diff --git a/app/src/main/java/xdsopl/robot36/MainActivity.java b/app/src/main/java/xdsopl/robot36/MainActivity.java index fbc0948..f503224 100644 --- a/app/src/main/java/xdsopl/robot36/MainActivity.java +++ b/app/src/main/java/xdsopl/robot36/MainActivity.java @@ -125,7 +125,8 @@ public class MainActivity extends Activity { changeLayoutOrientation(getResources().getConfiguration()); decoder = new Decoder(this, (SpectrumView)findViewById(R.id.spectrum), - (ImageView)findViewById(R.id.image) + (ImageView)findViewById(R.id.image), + (VUMeterView)findViewById(R.id.meter) ); manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); showNotification(); @@ -165,9 +166,9 @@ public class MainActivity extends Activity { private void changeLayoutOrientation(Configuration config) { boolean horizontal = config.orientation == Configuration.ORIENTATION_LANDSCAPE; - View spectrum = findViewById(R.id.spectrum); - spectrum.setVisibility(enableAnalyzer ? View.VISIBLE : View.GONE); - spectrum.setLayoutParams( + View spectrum_meter = findViewById(R.id.spectrum_meter); + spectrum_meter.setVisibility(enableAnalyzer ? View.VISIBLE : View.GONE); + spectrum_meter.setLayoutParams( new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, horizontal ? 1.0f : 10.0f)); diff --git a/app/src/main/java/xdsopl/robot36/VUMeterView.java b/app/src/main/java/xdsopl/robot36/VUMeterView.java new file mode 100644 index 0000000..49ec0cf --- /dev/null +++ b/app/src/main/java/xdsopl/robot36/VUMeterView.java @@ -0,0 +1,78 @@ +/* + Copyright 2015 Ahmet Inan + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +package xdsopl.robot36; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +public class VUMeterView extends SurfaceView implements SurfaceHolder.Callback { + private int canvasWidth = -1, canvasHeight = -1; + private boolean cantTouchThis = true; + private final SurfaceHolder holder; + private final Paint paint; + public float volume = 0.0f; + + public VUMeterView(Context context, AttributeSet attrs) { + super(context, attrs); + holder = getHolder(); + holder.addCallback(this); + paint = new Paint(); + paint.setColor(Color.GREEN); + } + + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + synchronized (holder) { + canvasWidth = width; + canvasHeight = height; + } + drawCanvas(); + } + + public void surfaceCreated(SurfaceHolder holder) { + synchronized (holder) { + cantTouchThis = false; + } + } + + public void surfaceDestroyed(SurfaceHolder holder) { + synchronized (holder) { + cantTouchThis = true; + } + } + + void drawCanvas() { + synchronized (holder) { + if (cantTouchThis) + return; + Canvas canvas = null; + try { + canvas = holder.lockCanvas(null); + canvas.drawColor(Color.BLACK); + canvas.drawRect(0, canvasHeight - volume * canvasHeight, canvasWidth, canvasHeight, paint); + } finally { + if (canvas != null) + holder.unlockCanvasAndPost(canvas); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index e10a722..c026239 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -19,11 +19,27 @@ android:layout_weight="1" android:contentDescription="@string/decoder_view" /> - + android:weightSum="10"> + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 959240c..b12c8dd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -20,5 +20,6 @@ Toggle Scaling Decoder View Spectrum View + VU Meter View diff --git a/app/src/main/rs/decoder.rs b/app/src/main/rs/decoder.rs index 79222ac..68e9f23 100644 --- a/app/src/main/rs/decoder.rs +++ b/app/src/main/rs/decoder.rs @@ -214,6 +214,7 @@ void decode(int samples) { int amp = audio_buffer[sample]; float avg_rms = filter(&avg_amplitude, amp * amp); float avg_amp = sqrt(2.0f * avg_rms); + *volume = clamp(avg_amp / 32.0f, 0.0f, 1023.0f); if (avg_amp < 16.0f) continue; float norm_amp = amp / avg_amp; diff --git a/app/src/main/rs/exports.rsh b/app/src/main/rs/exports.rsh index ff7bca7..a1ed8df 100644 --- a/app/src/main/rs/exports.rsh +++ b/app/src/main/rs/exports.rsh @@ -25,5 +25,6 @@ uchar4 *saved_buffer; int *saved_width; int *saved_height; int *current_mode; +int *volume; #endif \ No newline at end of file