WIP: added spectrum analyzer

there is something fishy going on :(
This commit is contained in:
Ahmet Inan 2015-01-06 21:14:47 +01:00
parent eca5873fec
commit b77e9c1b3d
17 changed files with 17028 additions and 41 deletions

View file

@ -27,7 +27,8 @@ import android.support.v8.renderscript.RenderScript;
public class Decoder {
private boolean drawImage = true, quitThread = false;
private final MainActivity activity;
private final ImageView view;
private final ImageView image;
private final SpectrumView spectrum;
private final AudioRecord audio;
private final int audioSource = MediaRecorder.AudioSource.MIC;
private final int channelConfig = AudioFormat.CHANNEL_IN_MONO;
@ -35,6 +36,7 @@ public class Decoder {
private final int sampleRate = 44100;
private final short[] audioBuffer;
private final int[] pixelBuffer;
private final int[] spectrumBuffer;
private final int[] currentMode;
private final int[] savedBuffer;
private final int[] savedWidth;
@ -43,6 +45,7 @@ public class Decoder {
private final RenderScript rs;
private final Allocation rsDecoderAudioBuffer;
private final Allocation rsDecoderPixelBuffer;
private final Allocation rsDecoderSpectrumBuffer;
private final Allocation rsDecoderValueBuffer;
private final Allocation rsDecoderCurrentMode;
private final Allocation rsDecoderSavedBuffer;
@ -67,18 +70,22 @@ public class Decoder {
synchronized (this) {
if (quitThread)
return;
if (drawImage)
view.drawCanvas();
if (drawImage) {
image.drawCanvas();
spectrum.drawCanvas();
}
}
decode();
}
}
};
public Decoder(ImageView view, MainActivity activity) {
this.view = view;
public Decoder(MainActivity activity, SpectrumView spectrum, ImageView image) {
this.image = image;
this.spectrum = spectrum;
this.activity = activity;
pixelBuffer = new int[view.bitmap.getWidth() * view.bitmap.getHeight()];
pixelBuffer = new int[image.bitmap.getWidth() * image.bitmap.getHeight()];
spectrumBuffer = new int[spectrum.bitmap.getWidth() * spectrum.bitmap.getHeight()];
int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
int bufferSizeInSamples = bufferSizeInBytes / 2;
@ -101,6 +108,7 @@ public class Decoder {
rsDecoderAudioBuffer = Allocation.createSized(rs, Element.I16(rs), audioBuffer.length, Allocation.USAGE_SHARED | Allocation.USAGE_SCRIPT);
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);
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);
@ -109,16 +117,19 @@ public class Decoder {
rsDecoder.bind_audio_buffer(rsDecoderAudioBuffer);
rsDecoder.bind_value_buffer(rsDecoderValueBuffer);
rsDecoder.bind_pixel_buffer(rsDecoderPixelBuffer);
rsDecoder.bind_spectrum_buffer(rsDecoderSpectrumBuffer);
rsDecoder.bind_current_mode(rsDecoderCurrentMode);
rsDecoder.bind_saved_width(rsDecoderSavedWidth);
rsDecoder.bind_saved_height(rsDecoderSavedHeight);
rsDecoder.bind_saved_buffer(rsDecoderSavedBuffer);
rsDecoder.invoke_initialize(sampleRate, valueBufferLength, view.bitmap.getWidth(), view.bitmap.getHeight());
rsDecoder.invoke_initialize(sampleRate, valueBufferLength,
image.bitmap.getWidth(), image.bitmap.getHeight(),
spectrum.bitmap.getWidth(), spectrum.bitmap.getHeight());
thread.start();
}
void toggle_scaling() { view.intScale ^= true; }
void toggle_scaling() { image.intScale ^= true; }
void softer_image() { rsDecoder.invoke_incr_blur(); }
void sharper_image() { rsDecoder.invoke_decr_blur(); }
void toggle_debug() { rsDecoder.invoke_toggle_debug(); }
@ -139,48 +150,48 @@ public class Decoder {
{
switch (mode) {
case mode_raw:
view.imageWidth = view.bitmap.getWidth();
view.imageHeight = view.bitmap.getHeight();
image.imageWidth = image.bitmap.getWidth();
image.imageHeight = image.bitmap.getHeight();
updateTitle(R.string.action_raw_mode);
break;
case mode_robot36:
view.imageWidth = 320;
view.imageHeight = 240;
image.imageWidth = 320;
image.imageHeight = 240;
updateTitle(R.string.action_robot36_mode);
break;
case mode_robot72:
view.imageWidth = 320;
view.imageHeight = 240;
image.imageWidth = 320;
image.imageHeight = 240;
updateTitle(R.string.action_robot72_mode);
break;
case mode_martin1:
view.imageWidth = 320;
view.imageHeight = 256;
image.imageWidth = 320;
image.imageHeight = 256;
updateTitle(R.string.action_martin1_mode);
break;
case mode_martin2:
view.imageWidth = 320;
view.imageHeight = 256;
image.imageWidth = 320;
image.imageHeight = 256;
updateTitle(R.string.action_martin2_mode);
break;
case mode_scottie1:
view.imageWidth = 320;
view.imageHeight = 256;
image.imageWidth = 320;
image.imageHeight = 256;
updateTitle(R.string.action_scottie1_mode);
break;
case mode_scottie2:
view.imageWidth = 320;
view.imageHeight = 256;
image.imageWidth = 320;
image.imageHeight = 256;
updateTitle(R.string.action_scottie2_mode);
break;
case mode_scottieDX:
view.imageWidth = 320;
view.imageHeight = 256;
image.imageWidth = 320;
image.imageHeight = 256;
updateTitle(R.string.action_scottieDX_mode);
break;
case mode_wrasseSC2_180:
view.imageWidth = 320;
view.imageHeight = 256;
image.imageWidth = 320;
image.imageHeight = 256;
updateTitle(R.string.action_wrasseSC2_180_mode);
break;
default:
@ -220,7 +231,7 @@ public class Decoder {
rsDecoderAudioBuffer.copyFrom(audioBuffer);
rsDecoder.invoke_decode(samples);
rsDecoderPixelBuffer.copyTo(pixelBuffer);
view.bitmap.setPixels(pixelBuffer, 0, view.bitmap.getWidth(), 0, 0, view.bitmap.getWidth(), view.bitmap.getHeight());
image.bitmap.setPixels(pixelBuffer, 0, image.bitmap.getWidth(), 0, 0, image.bitmap.getWidth(), image.bitmap.getHeight());
rsDecoderCurrentMode.copyTo(currentMode);
switch_mode(currentMode[0]);
@ -231,5 +242,8 @@ public class Decoder {
rsDecoderSavedBuffer.copyTo(savedBuffer);
activity.storeBitmap(Bitmap.createBitmap(savedBuffer, savedWidth[0], savedHeight[0], Bitmap.Config.ARGB_8888));
}
rsDecoderSpectrumBuffer.copyTo(spectrumBuffer);
spectrum.bitmap.setPixels(spectrumBuffer, 0, spectrum.bitmap.getWidth(), 0, 0, spectrum.bitmap.getWidth(), spectrum.bitmap.getHeight());
}
}

View file

@ -105,7 +105,10 @@ public class MainActivity extends Activity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
changeLayoutOrientation(getResources().getConfiguration());
decoder = new Decoder((ImageView)findViewById(R.id.image), this);
decoder = new Decoder(this,
(SpectrumView)findViewById(R.id.spectrum),
(ImageView)findViewById(R.id.image)
);
manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
showNotification();
}

View file

@ -0,0 +1,92 @@
/*
Copyright 2015 Ahmet Inan <xdsopl@googlemail.com>
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 SpectrumView extends SurfaceView implements SurfaceHolder.Callback {
private int canvasWidth = -1, canvasHeight = -1;
private boolean cantTouchThis = true;
private final SurfaceHolder holder;
public final Bitmap bitmap;
private final Paint paint;
public SpectrumView(Context context, AttributeSet attrs) {
super(context, attrs);
holder = getHolder();
holder.addCallback(this);
paint = new Paint(Paint.FILTER_BITMAP_FLAG);
bitmap = Bitmap.createBitmap(256, 32, Bitmap.Config.ARGB_8888);
}
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);
drawBitmap(canvas);
} finally {
if (canvas != null)
holder.unlockCanvasAndPost(canvas);
}
}
}
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);
canvas.restore();
}
}

View file

@ -18,7 +18,7 @@
android:layout_weight="1"
android:contentDescription="@string/decoder_view" />
<ImageView
<xdsopl.robot36.SpectrumView
android:id="@+id/spectrum"
android:layout_width="match_parent"
android:layout_height="match_parent"

View file

@ -29,13 +29,8 @@ limitations under the License.
#include "state.rsh"
#include "exports.rsh"
#include "blur.rsh"
static inline uchar4 rgb(uchar r, uchar g, uchar b) { return (uchar4){ b, g, r, 255 }; }
static inline uchar4 yuv(uchar y, uchar u, uchar v)
{
uchar4 bgra = rsYuvToRGBA_uchar4(y, u, v);
return rgb(bgra[0], bgra[1], bgra[2]);
}
#include "stft.rsh"
#include "utils.rsh"
static void reset_buffer()
{
@ -222,6 +217,8 @@ void decode(int samples) {
continue;
float norm_amp = amp / avg_amp;
spectrum_analyzer(norm_amp);
complex_t cnt_baseband = convert(&cnt_ddc, norm_amp);
complex_t dat_baseband = convert(&dat_ddc, norm_amp);

View file

@ -20,6 +20,7 @@ limitations under the License.
short *audio_buffer;
uchar *value_buffer;
uchar4 *pixel_buffer;
uchar4 *spectrum_buffer;
uchar4 *saved_buffer;
int *saved_width;
int *saved_height;

View file

@ -21,17 +21,22 @@ limitations under the License.
#include "state.rsh"
#include "modes.rsh"
void initialize(float rate, int length, int width, int height)
void initialize(float rate, int length, int iw, int ih, int sw, int sh)
{
sample_rate = rate;
buffer_length = length;
buffer_mask = length - 1;
maximum_width = width;
maximum_height = height;
maximum_width = iw;
maximum_height = ih;
spectrum_width = sw;
spectrum_height = sh;
for (int i = 0; i < width * height; ++i)
for (int i = 0; i < iw * ih; ++i)
pixel_buffer[i] = 0;
for (int i = 0; i < sw * sh; ++i)
spectrum_buffer[i] = 0;
automatic_mode_detection = 1;
debug_mode = 0;
vpos = 0;

View file

@ -0,0 +1,53 @@
/*
Copyright 2015 Ahmet Inan <xdsopl@googlemail.com>
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.
*/
#ifndef RADIX2_RSH
#define RADIX2_RSH
#include "complex.rsh"
#include "radix2_generated.rsh"
static void radix2(complex_t *out, complex_t *in, int N, int S, int L)
{
if (1 == N) {
out[0] = in[0];
return;
} else if (2 == N) {
out[0] = in[0] + in[S];
out[1] = in[0] - in[S];
return;
} else if (4 == N) {
complex_t w = radix2_z[1 << L];
out[0] = in[0] + in[S] + in[2 * S] + in[3 * S];
out[1] = in[0] + cmul(w, in[S]) - in[2 * S] - cmul(w, in[3 * S]);
out[2] = in[0] - in[S] + in[2 * S] - in[3 * S];
out[3] = in[0] - cmul(w, in[S]) - in[2 * S] + cmul(w, in[3 * S]);
return;
}
radix2(out, in, N / 2, 2 * S, L + 1);
radix2(out + N / 2, in + S, N / 2, 2 * S, L + 1);
for (int k = 0; k < N / 2; ++k) {
int ke = k;
int ko = k + N / 2;
complex_t even = out[ke];
complex_t odd = out[ko];
complex_t w = radix2_z[k << L];
out[ke] = even + cmul(w, odd);
out[ko] = even - cmul(w, odd);
}
}
#endif

View file

@ -0,0 +1,260 @@
/* code generated by 'utils/radix2.c' */
static const int radix2_N = 512;
static const complex_t radix2_z[256] = {
{ 1, -0 },
{ 0.999925, -0.0122715 },
{ 0.999699, -0.0245412 },
{ 0.999322, -0.0368072 },
{ 0.998795, -0.0490677 },
{ 0.998118, -0.0613207 },
{ 0.99729, -0.0735646 },
{ 0.996313, -0.0857973 },
{ 0.995185, -0.0980171 },
{ 0.993907, -0.110222 },
{ 0.99248, -0.122411 },
{ 0.990903, -0.134581 },
{ 0.989177, -0.14673 },
{ 0.987301, -0.158858 },
{ 0.985278, -0.170962 },
{ 0.983105, -0.18304 },
{ 0.980785, -0.19509 },
{ 0.978317, -0.207111 },
{ 0.975702, -0.219101 },
{ 0.97294, -0.231058 },
{ 0.970031, -0.24298 },
{ 0.966976, -0.254866 },
{ 0.963776, -0.266713 },
{ 0.960431, -0.27852 },
{ 0.95694, -0.290285 },
{ 0.953306, -0.302006 },
{ 0.949528, -0.313682 },
{ 0.945607, -0.32531 },
{ 0.941544, -0.33689 },
{ 0.937339, -0.348419 },
{ 0.932993, -0.359895 },
{ 0.928506, -0.371317 },
{ 0.92388, -0.382683 },
{ 0.919114, -0.393992 },
{ 0.91421, -0.405241 },
{ 0.909168, -0.41643 },
{ 0.903989, -0.427555 },
{ 0.898674, -0.438616 },
{ 0.893224, -0.449611 },
{ 0.88764, -0.460539 },
{ 0.881921, -0.471397 },
{ 0.87607, -0.482184 },
{ 0.870087, -0.492898 },
{ 0.863973, -0.503538 },
{ 0.857729, -0.514103 },
{ 0.851355, -0.52459 },
{ 0.844854, -0.534998 },
{ 0.838225, -0.545325 },
{ 0.83147, -0.55557 },
{ 0.824589, -0.565732 },
{ 0.817585, -0.575808 },
{ 0.810457, -0.585798 },
{ 0.803208, -0.595699 },
{ 0.795837, -0.605511 },
{ 0.788346, -0.615232 },
{ 0.780737, -0.624859 },
{ 0.77301, -0.634393 },
{ 0.765167, -0.643832 },
{ 0.757209, -0.653173 },
{ 0.749136, -0.662416 },
{ 0.740951, -0.671559 },
{ 0.732654, -0.680601 },
{ 0.724247, -0.689541 },
{ 0.715731, -0.698376 },
{ 0.707107, -0.707107 },
{ 0.698376, -0.715731 },
{ 0.689541, -0.724247 },
{ 0.680601, -0.732654 },
{ 0.671559, -0.740951 },
{ 0.662416, -0.749136 },
{ 0.653173, -0.757209 },
{ 0.643832, -0.765167 },
{ 0.634393, -0.77301 },
{ 0.624859, -0.780737 },
{ 0.615232, -0.788346 },
{ 0.605511, -0.795837 },
{ 0.595699, -0.803208 },
{ 0.585798, -0.810457 },
{ 0.575808, -0.817585 },
{ 0.565732, -0.824589 },
{ 0.55557, -0.83147 },
{ 0.545325, -0.838225 },
{ 0.534998, -0.844854 },
{ 0.52459, -0.851355 },
{ 0.514103, -0.857729 },
{ 0.503538, -0.863973 },
{ 0.492898, -0.870087 },
{ 0.482184, -0.87607 },
{ 0.471397, -0.881921 },
{ 0.460539, -0.88764 },
{ 0.449611, -0.893224 },
{ 0.438616, -0.898674 },
{ 0.427555, -0.903989 },
{ 0.41643, -0.909168 },
{ 0.405241, -0.91421 },
{ 0.393992, -0.919114 },
{ 0.382683, -0.92388 },
{ 0.371317, -0.928506 },
{ 0.359895, -0.932993 },
{ 0.348419, -0.937339 },
{ 0.33689, -0.941544 },
{ 0.32531, -0.945607 },
{ 0.313682, -0.949528 },
{ 0.302006, -0.953306 },
{ 0.290285, -0.95694 },
{ 0.27852, -0.960431 },
{ 0.266713, -0.963776 },
{ 0.254866, -0.966976 },
{ 0.24298, -0.970031 },
{ 0.231058, -0.97294 },
{ 0.219101, -0.975702 },
{ 0.207111, -0.978317 },
{ 0.19509, -0.980785 },
{ 0.18304, -0.983105 },
{ 0.170962, -0.985278 },
{ 0.158858, -0.987301 },
{ 0.14673, -0.989177 },
{ 0.134581, -0.990903 },
{ 0.122411, -0.99248 },
{ 0.110222, -0.993907 },
{ 0.0980171, -0.995185 },
{ 0.0857973, -0.996313 },
{ 0.0735646, -0.99729 },
{ 0.0613207, -0.998118 },
{ 0.0490677, -0.998795 },
{ 0.0368072, -0.999322 },
{ 0.0245412, -0.999699 },
{ 0.0122715, -0.999925 },
{ 6.12323e-17, -1 },
{ -0.0122715, -0.999925 },
{ -0.0245412, -0.999699 },
{ -0.0368072, -0.999322 },
{ -0.0490677, -0.998795 },
{ -0.0613207, -0.998118 },
{ -0.0735646, -0.99729 },
{ -0.0857973, -0.996313 },
{ -0.0980171, -0.995185 },
{ -0.110222, -0.993907 },
{ -0.122411, -0.99248 },
{ -0.134581, -0.990903 },
{ -0.14673, -0.989177 },
{ -0.158858, -0.987301 },
{ -0.170962, -0.985278 },
{ -0.18304, -0.983105 },
{ -0.19509, -0.980785 },
{ -0.207111, -0.978317 },
{ -0.219101, -0.975702 },
{ -0.231058, -0.97294 },
{ -0.24298, -0.970031 },
{ -0.254866, -0.966976 },
{ -0.266713, -0.963776 },
{ -0.27852, -0.960431 },
{ -0.290285, -0.95694 },
{ -0.302006, -0.953306 },
{ -0.313682, -0.949528 },
{ -0.32531, -0.945607 },
{ -0.33689, -0.941544 },
{ -0.348419, -0.937339 },
{ -0.359895, -0.932993 },
{ -0.371317, -0.928506 },
{ -0.382683, -0.92388 },
{ -0.393992, -0.919114 },
{ -0.405241, -0.91421 },
{ -0.41643, -0.909168 },
{ -0.427555, -0.903989 },
{ -0.438616, -0.898674 },
{ -0.449611, -0.893224 },
{ -0.460539, -0.88764 },
{ -0.471397, -0.881921 },
{ -0.482184, -0.87607 },
{ -0.492898, -0.870087 },
{ -0.503538, -0.863973 },
{ -0.514103, -0.857729 },
{ -0.52459, -0.851355 },
{ -0.534998, -0.844854 },
{ -0.545325, -0.838225 },
{ -0.55557, -0.83147 },
{ -0.565732, -0.824589 },
{ -0.575808, -0.817585 },
{ -0.585798, -0.810457 },
{ -0.595699, -0.803208 },
{ -0.605511, -0.795837 },
{ -0.615232, -0.788346 },
{ -0.624859, -0.780737 },
{ -0.634393, -0.77301 },
{ -0.643832, -0.765167 },
{ -0.653173, -0.757209 },
{ -0.662416, -0.749136 },
{ -0.671559, -0.740951 },
{ -0.680601, -0.732654 },
{ -0.689541, -0.724247 },
{ -0.698376, -0.715731 },
{ -0.707107, -0.707107 },
{ -0.715731, -0.698376 },
{ -0.724247, -0.689541 },
{ -0.732654, -0.680601 },
{ -0.740951, -0.671559 },
{ -0.749136, -0.662416 },
{ -0.757209, -0.653173 },
{ -0.765167, -0.643832 },
{ -0.77301, -0.634393 },
{ -0.780737, -0.624859 },
{ -0.788346, -0.615232 },
{ -0.795837, -0.605511 },
{ -0.803208, -0.595699 },
{ -0.810457, -0.585798 },
{ -0.817585, -0.575808 },
{ -0.824589, -0.565732 },
{ -0.83147, -0.55557 },
{ -0.838225, -0.545325 },
{ -0.844854, -0.534998 },
{ -0.851355, -0.52459 },
{ -0.857729, -0.514103 },
{ -0.863973, -0.503538 },
{ -0.870087, -0.492898 },
{ -0.87607, -0.482184 },
{ -0.881921, -0.471397 },
{ -0.88764, -0.460539 },
{ -0.893224, -0.449611 },
{ -0.898674, -0.438616 },
{ -0.903989, -0.427555 },
{ -0.909168, -0.41643 },
{ -0.91421, -0.405241 },
{ -0.919114, -0.393992 },
{ -0.92388, -0.382683 },
{ -0.928506, -0.371317 },
{ -0.932993, -0.359895 },
{ -0.937339, -0.348419 },
{ -0.941544, -0.33689 },
{ -0.945607, -0.32531 },
{ -0.949528, -0.313682 },
{ -0.953306, -0.302006 },
{ -0.95694, -0.290285 },
{ -0.960431, -0.27852 },
{ -0.963776, -0.266713 },
{ -0.966976, -0.254866 },
{ -0.970031, -0.24298 },
{ -0.97294, -0.231058 },
{ -0.975702, -0.219101 },
{ -0.978317, -0.207111 },
{ -0.980785, -0.19509 },
{ -0.983105, -0.18304 },
{ -0.985278, -0.170962 },
{ -0.987301, -0.158858 },
{ -0.989177, -0.14673 },
{ -0.990903, -0.134581 },
{ -0.99248, -0.122411 },
{ -0.993907, -0.110222 },
{ -0.995185, -0.0980171 },
{ -0.996313, -0.0857973 },
{ -0.99729, -0.0735646 },
{ -0.998118, -0.0613207 },
{ -0.998795, -0.0490677 },
{ -0.999322, -0.0368072 },
{ -0.999699, -0.0245412 },
{ -0.999925, -0.0122715 }
};

View file

@ -35,6 +35,7 @@ static int buffer_length, buffer_mask, buffer_pos;
static int buffer_cleared;
static int bitmap_width, bitmap_height;
static int maximum_width, maximum_height;
static int spectrum_width, spectrum_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;

66
app/src/main/rs/stft.rsh Normal file
View file

@ -0,0 +1,66 @@
/*
Copyright 2015 Ahmet Inan <xdsopl@googlemail.com>
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.
*/
#ifndef STFT_RSH
#define STFT_RSH
#include "state.rsh"
#include "exports.rsh"
#include "utils.rsh"
#include "complex.rsh"
#include "radix2.rsh"
#include "stft_generated.rsh"
static inline uchar4 rainbow(float v)
{
#if 1
float r = 4.0f * v - 2.0f;
float g = 2.0f - 4.0f * fabs(v - 0.5f);
float b = 2.0f - 4.0f * v;
#else
float r = v;
float g = v;
float b = v;
#endif
return rgb(255.0f * sqrt(r), 255.0f * sqrt(g), 255.0f * sqrt(b));
}
static void spectrum_analyzer(float amplitude)
{
static int n;
static complex_t input[radix2_N];
static complex_t output[radix2_N];
input[n&(radix2_N-1)] += complex(stft_w[n] * amplitude, 0.0f);
if (++n >= stft_N) {
n = 0;
// yep, were wasting 3x performance
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 dB = 20.0f * log10(cabs(output[b]));
float v = min(1.0f, max(0.0f, (60.0f + dB) / 60.0f));
spectrum_buffer[i] = rainbow(v);
}
}
}
#endif

File diff suppressed because it is too large Load diff

27
app/src/main/rs/utils.rsh Normal file
View file

@ -0,0 +1,27 @@
/*
Copyright 2015 Ahmet Inan <xdsopl@googlemail.com>
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.
*/
#ifndef UTILS_RSH
#define UTILS_RSH
static inline uchar4 rgb(uchar r, uchar g, uchar b) { return (uchar4){ b, g, r, 255 }; }
static inline uchar4 yuv(uchar y, uchar u, uchar v)
{
uchar4 bgra = rsYuvToRGBA_uchar4(y, u, v);
return rgb(bgra[0], bgra[1], bgra[2]);
}
#endif

2
utils/.gitignore vendored
View file

@ -1 +1,3 @@
blur
radix2
stft

View file

@ -1,7 +1,11 @@
CFLAGS = -std=gnu99 -W -Wall -O3
LDFLAGS = -lm
generate: blur
generate: blur radix2 stft
./blur > ../app/src/main/rs/blur_generated.rsh
./radix2 > ../app/src/main/rs/radix2_generated.rsh
./stft > ../app/src/main/rs/stft_generated.rsh
blur: blur.c
radix2: radix2.c
stft: stft.c

34
utils/radix2.c Normal file
View file

@ -0,0 +1,34 @@
/*
Copyright 2015 Ahmet Inan <xdsopl@googlemail.com>
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.
*/
#include <math.h>
#include <complex.h>
#include <stdio.h>
int main()
{
const int N = 512;
const int dir = -1;
printf("/* code generated by 'utils/radix2.c' */\n");
printf("static const int radix2_N = %d;\n", N);
printf("static const complex_t radix2_z[%d] = {\n", N / 2);
for (int n = 0; n < N / 2; n++) {
complex double z = cexp(dir * I * n * 2.0 * M_PI / N);
printf("\t{ %g, %g }%s\n", creal(z), cimag(z), n < (N/2-1) ? "," : "");
}
printf("};\n");
return 0;
}

40
utils/stft.c Normal file
View file

@ -0,0 +1,40 @@
/*
Copyright 2015 Ahmet Inan <xdsopl@googlemail.com>
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.
*/
#include <math.h>
#include <complex.h>
#include <stdio.h>
double gauss(double n, double N, double o)
{
return exp(- 1.0/2.0 * pow((n - (N - 1.0) / 2.0) / (o * (N - 1.0) / 2.0), 2.0));
}
int main()
{
const int N = 1 << 14;
printf("/* code generated by 'utils/stft.c' */\n");
printf("static const int stft_N = %d;\n", N);
printf("static const float stft_w[%d] = {\n", N);
double sum = 0.0;
for (int n = 0; n < N; n++)
sum += gauss(n, N|1, 0.2);
for (int n = 0; n < N; n++) {
printf("\t%g%s\n", gauss(n, N, 0.2) / sum, n < (N-1) ? "," : "");
}
printf("};\n");
return 0;
}