From 1c3f90aef078b921c75ccda3595ab1328b1a0a10 Mon Sep 17 00:00:00 2001 From: Ahmet Inan Date: Thu, 15 Jan 2015 00:32:39 +0100 Subject: [PATCH] added spectrum view to present spectrogram --- app/src/main/java/xdsopl/robot36/Decoder.java | 15 +++++- .../java/xdsopl/robot36/MainActivity.java | 1 + .../java/xdsopl/robot36/SpectrumView.java | 15 ++---- app/src/main/res/layout/activity_main.xml | 22 +++++---- app/src/main/res/values/strings.xml | 1 + app/src/main/rs/exports.rsh | 1 + app/src/main/rs/initialization.rsh | 4 +- app/src/main/rs/state.rsh | 1 + app/src/main/rs/stft.rsh | 49 ++++++++++++++----- 9 files changed, 72 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/xdsopl/robot36/Decoder.java b/app/src/main/java/xdsopl/robot36/Decoder.java index df0cf39..05e93f9 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 SpectrumView spectrogram; private final VUMeterView meter; private final AudioRecord audio; private final int audioSource = MediaRecorder.AudioSource.MIC; @@ -39,6 +40,7 @@ public class Decoder { private final short[] audioBuffer; private final int[] pixelBuffer; private final int[] spectrumBuffer; + private final int[] spectrogramBuffer; private final int[] currentMode; private final int[] savedBuffer; private final int[] savedWidth; @@ -49,6 +51,7 @@ public class Decoder { private final Allocation rsDecoderAudioBuffer; private final Allocation rsDecoderPixelBuffer; private final Allocation rsDecoderSpectrumBuffer; + private final Allocation rsDecoderSpectrogramBuffer; private final Allocation rsDecoderValueBuffer; private final Allocation rsDecoderCurrentMode; private final Allocation rsDecoderSavedBuffer; @@ -78,6 +81,7 @@ public class Decoder { image.drawCanvas(); if(enableAnalyzer) { spectrum.drawCanvas(); + spectrogram.drawCanvas(); meter.drawCanvas(); } } @@ -87,13 +91,15 @@ public class Decoder { } }; - public Decoder(MainActivity activity, SpectrumView spectrum, ImageView image, VUMeterView meter) { + public Decoder(MainActivity activity, SpectrumView spectrum, SpectrumView spectrogram,ImageView image, VUMeterView meter) { this.image = image; + this.spectrogram = spectrogram; 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()]; + spectrogramBuffer = new int[spectrogram.bitmap.getWidth() * spectrogram.bitmap.getHeight()]; int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); int bufferSizeInSamples = bufferSizeInBytes / 2; @@ -118,6 +124,7 @@ public class Decoder { rsDecoderValueBuffer = Allocation.createSized(rs, Element.U8(rs), valueBufferLength, Allocation.USAGE_SCRIPT); rsDecoderPixelBuffer = Allocation.createSized(rs, Element.I32(rs), pixelBuffer.length, Allocation.USAGE_SHARED | Allocation.USAGE_SCRIPT); rsDecoderSpectrumBuffer = Allocation.createSized(rs, Element.I32(rs), spectrumBuffer.length, Allocation.USAGE_SHARED | Allocation.USAGE_SCRIPT); + rsDecoderSpectrogramBuffer = Allocation.createSized(rs, Element.I32(rs), spectrogramBuffer.length, Allocation.USAGE_SHARED | Allocation.USAGE_SCRIPT); 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); @@ -128,6 +135,7 @@ public class Decoder { rsDecoder.bind_value_buffer(rsDecoderValueBuffer); rsDecoder.bind_pixel_buffer(rsDecoderPixelBuffer); rsDecoder.bind_spectrum_buffer(rsDecoderSpectrumBuffer); + rsDecoder.bind_spectrogram_buffer(rsDecoderSpectrogramBuffer); rsDecoder.bind_current_mode(rsDecoderCurrentMode); rsDecoder.bind_saved_width(rsDecoderSavedWidth); rsDecoder.bind_saved_height(rsDecoderSavedHeight); @@ -135,7 +143,8 @@ public class Decoder { rsDecoder.bind_saved_buffer(rsDecoderSavedBuffer); rsDecoder.invoke_initialize(sampleRate, valueBufferLength, image.bitmap.getWidth(), image.bitmap.getHeight(), - spectrum.bitmap.getWidth(), spectrum.bitmap.getHeight()); + spectrum.bitmap.getWidth(), spectrum.bitmap.getHeight(), + spectrogram.bitmap.getWidth(), spectrogram.bitmap.getHeight()); thread.start(); } @@ -261,6 +270,8 @@ public class Decoder { if (enableAnalyzer) { rsDecoderSpectrumBuffer.copyTo(spectrumBuffer); spectrum.bitmap.setPixels(spectrumBuffer, 0, spectrum.bitmap.getWidth(), 0, 0, spectrum.bitmap.getWidth(), spectrum.bitmap.getHeight()); + rsDecoderSpectrogramBuffer.copyTo(spectrogramBuffer); + spectrogram.bitmap.setPixels(spectrogramBuffer, 0, spectrogram.bitmap.getWidth(), 0, 0, spectrogram.bitmap.getWidth(), spectrogram.bitmap.getHeight()); } } } \ No newline at end of file diff --git a/app/src/main/java/xdsopl/robot36/MainActivity.java b/app/src/main/java/xdsopl/robot36/MainActivity.java index 18989f9..5d87867 100644 --- a/app/src/main/java/xdsopl/robot36/MainActivity.java +++ b/app/src/main/java/xdsopl/robot36/MainActivity.java @@ -123,6 +123,7 @@ public class MainActivity extends Activity { changeLayoutOrientation(getResources().getConfiguration()); decoder = new Decoder(this, (SpectrumView)findViewById(R.id.spectrum), + (SpectrumView)findViewById(R.id.spectrogram), (ImageView)findViewById(R.id.image), (VUMeterView)findViewById(R.id.meter) ); diff --git a/app/src/main/java/xdsopl/robot36/SpectrumView.java b/app/src/main/java/xdsopl/robot36/SpectrumView.java index 5f485ef..6a8aaef 100644 --- a/app/src/main/java/xdsopl/robot36/SpectrumView.java +++ b/app/src/main/java/xdsopl/robot36/SpectrumView.java @@ -37,7 +37,7 @@ public class SpectrumView extends SurfaceView implements SurfaceHolder.Callback holder = getHolder(); holder.addCallback(this); paint = new Paint(Paint.FILTER_BITMAP_FLAG); - bitmap = Bitmap.createBitmap(256, 32, Bitmap.Config.ARGB_8888); + bitmap = Bitmap.createBitmap(256, 64, Bitmap.Config.ARGB_8888); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { @@ -76,17 +76,12 @@ public class SpectrumView extends SurfaceView implements SurfaceHolder.Callback } void drawBitmap(Canvas canvas) { - float scale; - if (bitmap.getWidth() * canvasHeight < canvasWidth * bitmap.getHeight()) - scale = (float)canvasHeight / bitmap.getHeight(); - else - scale = (float)canvasWidth / bitmap.getWidth(); - float px = (canvasWidth - scale * bitmap.getWidth()) / 2.0f; - float py = (canvasHeight - scale * bitmap.getHeight()) / 2.0f; canvas.drawColor(Color.BLACK); canvas.save(); - canvas.scale(scale, scale, px, py); - canvas.drawBitmap(bitmap, px, py, paint); + float sx = (float)canvasWidth / bitmap.getWidth(); + float sy = (float)canvasHeight / bitmap.getHeight(); + canvas.scale(sx, sy, 0, 0); + canvas.drawBitmap(bitmap, 0, 0, paint); canvas.restore(); } } \ 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 dc3f71a..8d563a1 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -4,10 +4,6 @@ android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent" - android:paddingBottom="@dimen/activity_vertical_margin" - android:paddingLeft="@dimen/activity_horizontal_margin" - android:paddingRight="@dimen/activity_horizontal_margin" - android:paddingTop="@dimen/activity_vertical_margin" android:keepScreenOn="true" tools:context=".MainActivity" android:orientation="vertical"> @@ -24,22 +20,28 @@ android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_weight="10" - android:weightSum="10"> + android:layout_weight="10"> + android:contentDescription="@string/spectrum_view" + android:layout_weight="100" /> + + + android:contentDescription="@string/meter_view" + android:layout_weight="190" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b12c8dd..23a9685 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -20,6 +20,7 @@ Toggle Scaling Decoder View Spectrum View + Spectrogram View VU Meter View diff --git a/app/src/main/rs/exports.rsh b/app/src/main/rs/exports.rsh index 718d3b7..127d841 100644 --- a/app/src/main/rs/exports.rsh +++ b/app/src/main/rs/exports.rsh @@ -21,6 +21,7 @@ short *audio_buffer; uchar *value_buffer; uchar4 *pixel_buffer; uchar4 *spectrum_buffer; +uchar4 *spectrogram_buffer; uchar4 *saved_buffer; int *saved_width; int *saved_height; diff --git a/app/src/main/rs/initialization.rsh b/app/src/main/rs/initialization.rsh index 0905404..34a62ae 100644 --- a/app/src/main/rs/initialization.rsh +++ b/app/src/main/rs/initialization.rsh @@ -22,7 +22,7 @@ limitations under the License. #include "modes.rsh" #include "stft.rsh" -void initialize(float rate, int length, int iw, int ih, int sw, int sh) +void initialize(float rate, int length, int iw, int ih, int sw, int sh, int sgw, int sgh) { sample_rate = rate; buffer_length = length; @@ -33,7 +33,7 @@ void initialize(float rate, int length, int iw, int ih, int sw, int sh) for (int i = 0; i < iw * ih; ++i) pixel_buffer[i] = 0; - init_analyzer(sw, sh); + init_analyzer(sw, sh, sgw, sgh); automatic_mode_detection = 1; debug_mode = 0; diff --git a/app/src/main/rs/state.rsh b/app/src/main/rs/state.rsh index fc96d96..9e35f7d 100644 --- a/app/src/main/rs/state.rsh +++ b/app/src/main/rs/state.rsh @@ -37,6 +37,7 @@ static int buffer_cleared; static int bitmap_width, bitmap_height; static int maximum_width, maximum_height; static int spectrum_width, spectrum_height; +static int spectrogram_width, spectrogram_height; static int sync_length, sync_counter, vpos, hpos; static int seperator_counter, seperator_length; static int u_sep_begin, u_sep_end, v_sep_begin, v_sep_end; diff --git a/app/src/main/rs/stft.rsh b/app/src/main/rs/stft.rsh index fa18605..c7b1bf3 100644 --- a/app/src/main/rs/stft.rsh +++ b/app/src/main/rs/stft.rsh @@ -35,28 +35,42 @@ static inline uchar4 rainbow(float v) static void freq_marker(int freq) { - int i = (radix2_N * freq + sample_rate / 2) / sample_rate; - spectrum_buffer[i] = rgb(255, 255, 255); + int sgi = (spectrogram_width * freq + sample_rate / 4) / (sample_rate / 2); + spectrogram_buffer[sgi] |= rgb(64, 64, 64); + + int si = (spectrum_width * freq + sample_rate / 4) / (sample_rate / 2); + for (int j = 0; j < spectrum_height; ++j) + spectrum_buffer[spectrum_width * j + si] |= rgb(64, 64, 64); } static void show_rainbow() { - for (int j = 0; j < spectrum_height; ++j) - for (int i = 0; i < spectrum_width; ++i) - spectrum_buffer[spectrum_width * j + i] = rainbow((float)i / spectrum_width); + for (int j = 0; j < spectrogram_height; ++j) + for (int i = 0; i < spectrogram_width; ++i) + spectrogram_buffer[spectrogram_width * j + i] = rainbow((float)i / spectrogram_width); } static void clear_spectrum() { for (int i = 0; i < spectrum_height * spectrum_width; ++i) spectrum_buffer[i] = 0; + for (int i = 0; i < spectrogram_height * spectrogram_width; ++i) + spectrogram_buffer[i] = 0; } -static void init_analyzer(int sw, int sh) +static void fade_spectrum() +{ + for (int i = 0; i < spectrum_height * spectrum_width; ++i) + spectrum_buffer[i] = 0xff000000 | (0x00fefefe & (int)spectrum_buffer[i]) >> 1; +} + +static void init_analyzer(int sw, int sh, int sgw, int sgh) { disable_analyzer = 0; spectrum_width = sw; spectrum_height = sh; + spectrogram_width = sgw; + spectrogram_height = sgh; show_rainbow(); } @@ -108,15 +122,24 @@ static void spectrum_analyzer(int amplitude) radix2(output, input, radix2_N, 1, 0); for (int i = 0; i < radix2_N; ++i) input[i] = 0.0f; - for (int j = spectrum_height - 1; 0 < j; --j) - for (int i = 0; i < spectrum_width; ++i) - spectrum_buffer[spectrum_width * j + i] = spectrum_buffer[spectrum_width * (j-1) + i]; - for (int i = 0; i < spectrum_width; ++i) { - int b = (i * (radix2_N / 2)) / spectrum_width; - float power = clamp(pown(cabs(output[b]) / 127.0f, 2), 0.0f, 1.0f); + for (int j = spectrogram_height - 1; 0 < j; --j) + for (int i = 0; i < spectrogram_width; ++i) + spectrogram_buffer[spectrogram_width * j + i] = spectrogram_buffer[spectrogram_width * (j-1) + i]; + for (int i = 0; i < spectrogram_width; ++i) { + int b = (i * (radix2_N / 2)) / spectrogram_width; + float power = min(pown(cabs(output[b]) / 127.0f, 2), 1.0f); float dB = 10.0f * log10(max(0.000001f, power)); float v = clamp((60.0f + dB) / 60.0f, 0.0f, 1.0f); - spectrum_buffer[i] = rainbow(v); + spectrogram_buffer[i] = rainbow(v); + } + fade_spectrum(); + for (int b = 0; b < radix2_N / 2; ++b) { + float power = min(pown(cabs(output[b]) / 127.0f, 2), 1.0f); + float dB = 10.0f * log10(max(0.000001f, power)); + float v = clamp((60.0f + dB) / 60.0f, 0.0f, 1.0f); + int i = (b * spectrum_width) / (radix2_N / 2); + int j = (spectrum_height - 1) - (spectrum_height - 1) * v; + spectrum_buffer[spectrum_width * j + i] = rgb(255, 255, 255); } freq_marker(1100 * M); freq_marker(1300 * M);