Getting back original signal using JTransform method realInverse - java

I was playing with JTransforms realForwardFull and RealInverse to test how they work.
My understanding is that after you pass say an audio signal to realForwardFull and then apply RealInverse, you should get back the same signal.
So here is what I am doing.
double[] a1 = getAudioSignal();
DoubleDDT_1D fft = new DoubleFFT_1D(a1.length);
double[] fftData = new double[a1.length * 2];
for(int i=0; i<fftData.length; i++) {
fftData[i] = a1[i]; // real part
fftData[fftData.length+i] = 0; // imaginary parts
}
fft.realForwardFull(fftData);
//Do an inverse to get back the signal
fft.realInverse(fftData, false);
My question is should the fftData after the inverse fft (realInverse) contain the same data as in a1, the original audio signal?
I tested this and checked if all the even indexes (real part) fftData[2k] was the same as indexes in a1, its not so.
for(int k=0; k<a1.length; k++) {
if(a[k] == fftData[2k]) {
printSame();
} else {
printDiff();
}
I see that the output in the array after realInverse is very different.
How do I get the original signal back?

As per the javadoc of realForwardFull you need to call complexInverse to recover the original signal. Since you want the original points you should enable scaling which will divide the values by N:
fft.realForwardFull(fftData);
//Do an inverse to get back the signal
fft.complexInverse(fftData, true);
Also your checking logic is broken. You cannot check double equality like that because of rounding errors. You should check it like this using an epsilon error tolerance:
for(int k=0; k<a1.length; k++) {
if(Math.abs(a1[k] - fftData[2*k]) < 1e-6) {
printSame();
} else {
printDiff();
}

Related

Returning value from method and "The Value Assigned Is Never Used" [duplicate]

This question already has answers here:
What does the "Assigned value is never used" warning mean?
(5 answers)
Closed 3 months ago.
I'm following Princeton's introductory computer science course (I'm not a student, just teaching myself). I working on this assignment.
Main is calling two methods: amplify and reverse, both of which return an array. Amplify multiplies all values in the array by a constant alpha. Reverse returns an array that lists the original array values in reverse order, ex. {1,2,3} -> {3,2,1}.
Amplify works fine, but nothing happens when I call reverse and I get a bug that states: The Value Assigned Is Never Used
public class audiocollage {
// Returns a new array that rescales a[] by a factor of alpha.
public static double[] amplify(double[] a, double alpha) {
for (int i = 0; i < a.length; i++) {
a[i] = a[i] * alpha;
}
return a;
}
// Returns a new array that is the reverse of a[].
public static double[] reverse(double[] a) {
double[] b = new double[a.length];
for (int i = a.length - 1, j = 0; i >= 0; i--, j++) {
b[j] = a[i];
}
return b;
}
// Creates an audio collage and plays it on standard audio.
public static void main(String[] args) {
double[] samples = StdAudio.read("cow.wav");
double alpha = 2.0;
samples = amplify(samples, alpha);
samples = reverse(samples);
}
}
It sounds like you have two questions:
Why doesn't anything happen when I call reverse(samples)?
The code you're showing does nothing with the result of reverse(samples) other than store it in the variable samples (overwriting its previous value). You will need to do something with samples after that to observe the new array (like printing samples, which should now appear to be reversed).
Which leads into the next question:
Why do I get a warning about "the value assigned to samples is never used"?
This is a warning saying that the code you wrote doesn't do anything.
Dead store to local variable is the first line of the warning, which describes what's happening: the value stored to samples is "dead" -- it is never used again, and so we may as well have skipped that line altogether. That causes your compiler (or extension) to give us a warning because it's almost certain that the code you wrote is not doing what you intended, so in many cases that warning can be helpful for spotting mistakes.
This warning can be resolved by using samples somehow, such as by printing it, calling another function with it, etc.
The previous line
samples = amplify(samples, alpha);
doesn't generate that warning because it's output is used in the following call to reverse():
samples = reverse(samples);
// ^ usage of `samples` variable!
This is made even clearer by using different variables for all your arrays:
public static void main(String[] args) {
// No warning; samplesRaw used later
double[] samplesRaw = StdAudio.read("cow.wav");
double alpha = 2.0;
// No warning; samplesAmplified used later
samplesAmplified = amplify(samplesRaw, alpha);
// WARNING! samplesReversed is never used!
samplesReversed = reverse(samplesAmplified);
}
If the hint is related to the last line, it means you have a local variables samples which has not used ( you assigned a value but never read it)

How to look for exact same color in an array in Java

I have an array of 24 colors. Occasionally when I generate it I get colors that have the exact same RGB values. What I want to do is find the duplicates in the array and change the value of the match by like 1 or 2. Just so that it doesn't match anymore.
Here is my array of colors. Notice that there are 3 of the exact shade of red. I want each one to be slightly different from each other. Keep the R channel the same but change the G and or B channels to be like 1 or 2 numbers higher.
Color Array: [java.awt.Color[r=255,g=194,b=23], java.awt.Color[r=255,g=0,b=0], java.awt.Color[r=255,g=0,b=0], java.awt.Color[r=0,g=67,b=255], java.awt.Color[r=0,g=255,b=175], java.awt.Color[r=255,g=13,b=10], java.awt.Color[r=255,g=115,b=43], java.awt.Color[r=2,g=92,b=255], java.awt.Color[r=241,g=219,b=255], java.awt.Color[r=255,g=194,b=0], java.awt.Color[r=231,g=210,b=255], java.awt.Color[r=0,g=43,b=255], java.awt.Color[r=255,g=80,b=0], java.awt.Color[r=255,g=205,b=27], java.awt.Color[r=255,g=0,b=9], java.awt.Color[r=205,g=199,b=255], java.awt.Color[r=0,g=44,b=255], java.awt.Color[r=255,g=0,b=0], java.awt.Color[r=21,g=255,b=219], java.awt.Color[r=255,g=199,b=51], java.awt.Color[r=255,g=82,b=2], java.awt.Color[r=215,g=198,b=255], java.awt.Color[r=0,g=255,b=203], java.awt.Color[r=255,g=98,b=28]]
What I was thinking was iterating through the array.
for(int i = 0; i < colorArray.length; i++){
if(colorArray[i] == //not sure what this would be equal to as it will be checking all the values in the array ) {
colorArray[i].getBlue() = matchingColor.getBlue() += 1;
colorArray[i].getGreen() matchingColor.getGreen() += 2; //These are example values just to make sure that they have no match
}
}
Learning the APIs of the Classes you use is really helpful.
for(int i = 0; i < colorArray.length; i++) {
// use while in case the color is black/white. (May thrash for few iterations)
while (colorArray[i].equals(matchingColor)) {
colorArray[i] = (Math.random() < 0.5)?colorArray[i].brighter():colorArray[i].darker();
}
}
Here is a solution using a Set to maintain uniqueness. This saves re-inventing all the functionality to check for duplicates. It takes advantage of the fact that the add method of the Set interface returns true if the object has been added to the set. Under the covers, of course, it uses the equals method of Color.
In the event that a duplicate is found, we repeatedly try modifying the Color a little, by doing a bitwise exclusive-or of its three components, until we come to a unique one.
public void deduplicate(Color[] colors) {
Set<Color> uniqueColors = new HashSet<>();
for (int which = 0; which < colors.length; which++) {
Color originalColor = colors[which];
boolean unique = uniqueColors.add(originalColor);
for (int modifyBy = 1; !unique ; modifyBy++) {
colors[which] = new Color(
originalColor.getRed() ^ modifyBy,
originalColor.getGreen() ^ modifyBy,
originalColor.getBlue() ^ modifyBy);
unique = uniqueColors.add(colors[which]);
}
}
}

How to find missing audio segments

I am writing my own audio format as part of a game console project. Part of the project requires me to write an emulator so I know exactly how to implement it's functions in hardware. I am currently writing the DSP portion, but I am having trouble writing a decoding algorithm. Before I go further, I'll explain my format.
DST (Dingo Sound Track) Audio format
The audio format only records to pieces of data per sample: the amplitude and the number of frames since the last sample. I'll explain. When converting an audio file (WAV for example), it compares the current sample with the previous one. If it detects that the current sample switches amplitude direction in relation to the previous sample, it records the previous sample and the number of frames since the last record. It keeps going until the end of the file. Here is a diagram to explain further:
What I need to do
I need my "DSP" to figure out the data between each sample, as accurately as possible using only the given information. I don't think it's my encoding algorithm, because when I play the file in Audacity, I can sort of make out the original song. But when I try to play it with my decoding algorithm, I get scattered clicks. I am able to play WAV files directly with a few mods to the algorithm with almost no quality drop, so I know it's definitely the algorithm and not the rest of the DSP.
The Code
So now I got all of the basic info out of the way, here is my code (only the important parts).
Encoding algorithm:
FileInputStream s = null;
BufferedWriter bw;
try {
int bytes;
int previous = 0;
int unsigned;
int frames = 0;
int size;
int cursor = 0;
boolean dir = true;
int bytes2;
int previous2 = 0;
int unsigned2;
int frames2 = 0;
boolean dir2 = true;
s = new FileInputStream(selectedFile);
size = (int)s.getChannel().size();
File f = new File(Directory.getPath() + "\\" + (selectedFile.getName().replace(".wav", ".dts")));
System.out.println(f.getPath());
if(!f.exists()){
f.createNewFile();
}
bw = new BufferedWriter(new FileWriter(f));
try (BufferedInputStream b = new BufferedInputStream(s)) {
byte[] data = new byte[128];
b.skip(44);
System.out.println("Loading...");
while ((bytes = b.read(data)) > 0) {
// do something
for(int i=1; i<bytes; i += 4) {
unsigned = data[i] & 0xFF;
if (dir) {
if (unsigned < previous) {
bw.write(previous);
bw.write(frames);
dir = !dir;
frames = 0;
}else{
frames ++;
}
} else {
if (unsigned > previous) {
bw.write(previous);
bw.write(frames);
dir = !dir;
frames = 0;
}else{
frames ++;
}
}
previous = unsigned;
cursor ++;
unsigned2 = data[i + 2] & 0xFF;
if (dir2) {
if (unsigned2 < previous2) {
bw.write(previous2);
bw.write(frames2);
dir2 = !dir2;
frames2 = 0;
}else{
frames2 ++;
}
} else {
if (unsigned2 > previous2) {
bw.write(previous2);
bw.write(frames2);
dir2 = !dir2;
frames2 = 0;
}else{
frames2 ++;
}
}
previous2 = unsigned2;
cursor ++;
progress.setValue((int)(((float)(cursor / size)) * 100));
}
}
b.read(data);
}
bw.flush();
bw.close();
System.out.println("Done");
convert.setEnabled(true);
status.setText("finished");
} catch (Exception ex) {
status.setText("An error has occured");
ex.printStackTrace();
convert.setEnabled(true);
}
finally {
try {
s.close();
} catch (Exception ex) {
status.setText("An error has occured");
ex.printStackTrace();
convert.setEnabled(true);
}
}
The progress and status objects can be ignored for they are part of the GUI of my converter tool. This algorithm converts WAV files to my format (DST).
Decoding algorithm:
int start = bufferSize * (bufferNumber - 1);
short current;
short frames;
short count = 1;
short count2 = 1;
float jump;
for (int i = 0; i < bufferSize; i ++) {
current = RAM.read(start + i);
i++;
frames = RAM.read(start + i);
if (frames == 0) {
buffer[count - 1] = current;
count ++;
} else {
jump = current / frames;
for (int i2 = 1; i2 < frames; i2++) {
buffer[(2 * i2) - 1] = (short) (jump * i2);
count ++;
}
}
i++;
current = RAM.read(start + i);
i++;
frames = RAM.read(start + i);
if (frames == 0) {
buffer[count2] = current;
count2 ++;
} else {
jump = current / frames;
for (int i2 = 1; i2 < frames; i2++) {
buffer[2 * i2] = (short) (jump * i2);
count2 ++;
}
}
}
bufferNumber ++;
if(bufferNumber > maxBuffer){
bufferNumber = 1;
}
The RAM object is just a byte array. bufferNumber and maxBuffer refer to the amount of processing buffers the DSP core uses. buffer is the object that the resulting audio is written to. This algorithm set is designed to convert stereo tracks, which works the same way in my format but each sample will contain two sets of data, one for each track.
The Question
How do I figure out the missing audio between each sample, as accurately as possible, and how accurate will the approach be? I would love to simply use the WAV format, but my console is limited on memory (RAM). This format halves the RAM space required to process audio. I am also planning on implementing this algorithm in an ARM microcontroller, which will be the console's real DSP. The algorithm should also be fast, but accuracy is more important. If I need to clarify or explain anything further, let me know since this is my first BIG question and I am sure I forgot something. Code samples would be nice, but aren't needed that much.
EDIT:
I managed to get the DSP to output a song, but it's sped up and filled with static. The sped up part is due to a glitch in it not splitting the track into stereo (I think). And the static is due to the initial increment being too steep. Here is a picture of what I'm getting:
Here is the new code used in the DSP:
if (frames == 0) {
buffer[i - 1] = current;
//System.out.println(current);
} else {
for (int i2 = 1; i2 < frames + 1; i2++) {
jump = (float)(previous + ((float)(current - previous) / (frames - i2 + 1)));
//System.out.println((short)jump);
buffer[(2 * i2) - 1] = (short)(jump);
}
}
previous = current;
I need a way to smooth out those initial increments, and I'd prefer not to use complex arithmetic because I am limited on performance when I port this to hardware (preferably something that can operate on a 100MHZ ARM controller while being able to keep a 44.1KHZ sample rate). Edit: the result wave should actually be backwards. Sorry.
Second Edit:
I got the DSP to output in stereo, but unfortunately that didn't fix anything else like I hoped it would. I also fixed some bugs with the encoder so now it takes 8 bit unsigned audio. This has become more of a math issue so I think I'll post a similar question in Mathematics Stack Exchange. Well that was a waste of time. It got put on fhold near instantly.
You have basically a record of the signal's local extrema and want to reconstruct the signal. The most straight-forward way would be to use some monotonic interpolation scheme. You can try if this fits your needs. But I guess, the result would be very inaccurate because the characteristics of the signal are ignored.
I am not an audio engineer, so my assumptions could be wrong. But maybe, you get somewhere with these thoughts.
The signal is basically a mixture of sines. Calculating a sine function for any segment between two key frames is quite easy. The period is given by twice their distance. The amplitude is given by half the amplitude difference. This will give you a sine that hits the two key samples exactly. Furthermore, it will give you a C1-continuous signal because the derivatives at the connection points are zero. For a nice signal, you probably need even more smoothness. So you could start to interpolate the two sines around a key frame with an appropriate window function. I would start with a simple triangle window but others may give better results. This procedure will preserve the extrema.
It is probably easier to tackle this problem visually (with a plot of the signal), so you can see the results.
If it's all about size, then maybe you want to look into established audio compression methods. They usually give much better compression ratio than 1:2. Also, I don't understand why this method saves RAM because you'll have to calculate all samples when decoding. Of course, this assumes that not the complete data are loaded into RAM but streamed in pieces.

Wrong values in calculating Frequency using FFT

I'm getting wrong frequency, I don't understand why i'm getting wrong values.since i have calculating as per instructions followed by stackoverflow.
I've used FFT from
http://introcs.cs.princeton.edu/java/97data/FFT.java.html
and complex from
http://introcs.cs.princeton.edu/java/97data/Complex.java.html
audioRec.startRecording();
audioRec.read(bufferByte, 0,bufferSize);
for(int i=0;i<bufferSize;i++){
bufferDouble[i]=(double)bufferByte[i];
}
Complex[] fftArray = new Complex[bufferSize];
for(int i=0;i<bufferSize;i++){
fftArray[i]=new Complex(bufferDouble[i],0);
}
FFT.fft(fftArray);
double[] magnitude=new double[bufferSize];
for(int i=0;i<bufferSize;i++){
magnitude[i] = Math.sqrt((fftArray[i].re()*fftArray[i].re()) + (fftArray[i].im()*fftArray[i].im()));
}
double max = 0.0;
int index = -1;
for(int j=0;j<bufferSize;j++){
if(max < magnitude[j]){
max = magnitude[j];
index = j;
}
}
final int peak=index * sampleRate/bufferSize;
Log.v(TAG2, "Peak Frequency = " + index * sampleRate/bufferSize);
handler.post(new Runnable() {
public void run() {
textView.append("---"+peak+"---");
}
});
i'm getting values like 21000,18976,40222,30283 etc...
Please help me.....
Thank you..
Your source code is almost fine. The only problem is that you search for the peaks through the full spectrum, i.e. from 0 via Fs/2 to Fs.
For any real-valued input signal (which you have) the spectrum between Fs/2 and Fs (=sample frequency) is an exact mirror of the spectrum between 0 and Fs/2 (I found this nice background explanation). Thus, for each frequency there exist two peaks with almost identical amplitude. I'm writing 'almost' because due to limited machine precision they are not necessarily exactly identical. So, you randomly find the peak in the first half of the spectrum which contains the frequencies below the Nyquist frequency (=Fs/2) or in the second half of the spectrum with the frequencies above the Nyquist frequency.
If you want to correct the mistake yourself, stop reading here. Otherwise continue:
Just replace
for(int j=0;j<bufferSize;j++){
with
for(int j=0;j<=bufferSize/2;j++){
in the source code you presented.
P.S.: Typically, it is better to apply a window function to the analysis buffer (e.g. a Hamming window) but for your application of peak picking it won't change results very much.

How to pass array values to and from Android RenderScript using Allocations

I've been working with RenderScript recently with the intent of creating an API that a programmer can use with ease, similar to the way that Microsoft Accelerator works.
The trouble I'm stuck with at the moment as that I want to pass values to and from the RenderScript layer and have everything run in the most efficient way possible, this is an extract of my source code so far:
int[] A = new int[10];
int[] B = new int[10];
for (int i = 0; i < 10; i++) {
A[i] = 2;
B[i] = i;
}
intAdd(A, B);
This just creates two basic arrays and fills them with values and calls the functions that will send them to RenderScript.
private void intAdd(int[] A, int[] B) {
RenderScript rs = RenderScript.create(this);
ScriptC_rsintadd intaddscript = new ScriptC_rsintadd(rs, getResources(), R.raw.rsintadd);
mScript = intaddscript;
for(int i = 0; i < A.length; i++) {
setNewValues(mScript, A[i], B[i]);
intaddscript.invoke_intAdd();
int C = getResult(mScript);
notifyUser.append(" " + C);
}
}
public void setNewValues(Script script, int A, int B) {
mScript.set_numberA(A);
mScript.set_numberB(B);
}
public int getResult(Script script) {
int C = mScript.get_numberC();
return C;
}
This will send a pair of values to the following RenderScript code:
int numberA;
int numberB;
int numberC;
void intAdd() {
/*Add the two together*/
numberC = numberA + numberB;
/*Send their values to the logcat*/
rsDebug("Current Value", numberC);
}
But there are two problems with this, the first one is the Asynchronous nature of RenderScript means that when the Java layer requests the value, the script either hasn't done the operation yet, or it's already done it, destroyed the value of the output and started on the next one. And thanks to the low debugging visibility of RenderScript there's no way of telling.
The other problem is that it's not very efficient, the code is constantly calling the RenderScript function to add two numbers together. Ideally I'd want to pass the array to RenderScript and store it in a struct and have the entire operation done in one script call rather than many. But in order to get it back I reckon I'll need to user the rsSendtoClient function, but I've not found any material on how to use it. And preferably I'd like to use the rsForEach strategy, but again information is scare.
If anyone has any ideas I'd be very grateful. Thanks.
Will Scott-Jackson
I'm not sure if this will be of help to you at this point but since I know how much of a pain it can be to work through RenderScript, here is the help I can offer. In order to use the rsSendToClient function, you need to instruct the RenderScript instance you created where to send messages to. This is accomplished by something such as:
private void intAdd(int[] A, int[] B) {
RenderScript rs = RenderScript.create(this);
MySubclassedRSMessageHandler handler = new MySubclassedRSMessageHandler();
rs.setMessageHandler(handler);
ScriptC_rsintadd intaddscript = new ScriptC_rsintadd(rs, getResources(), R.raw.rsintadd);
mScript = intaddscript;
for(int i = 0; i < A.length; i++) {
setNewValues(mScript, A[i], B[i]);
intaddscript.invoke_intAdd();
int C = getResult(mScript);
notifyUser.append(" " + C);
}
}
It will be necessary to subclass RenderScript.RSMessageHandler and override the run() method. See http://developer.android.com/reference/android/renderscript/RenderScript.RSMessageHandler.html if you havn't already. Basically there is no way to get around the asynchronous nature which I find to be a double edged sword.
As for the inefficiency, I would consider creating a RenderScript instance, leave it running (you can pause it when not needed, will stay in memory but stop the threads, thus not incurring the construction cost each time you call a function). From here you can have your structures and then use invoke_myFunction(some arguments here) from the reflected Java layer.
Hopefully this helps at least a little bit.
I had the same problem.
The problem with your program is that doesn't know when the add function in rs file should run
,try this it should work
public void setNewValues(Script script, int A, int B) {
mScript.set_numberA(A);
mScript.set_numberB(B);
mscript.invoke_intAdd();
}
I had the same problem with you. I think rsSendtoClient function is not useful and creates many bugs. Instead, using a pointer and allocate it a memory to bring result back to you is much easier.
I recommend the solution of your problem like this:
In rsintadd.rs use this snippet:
int32_t *a;
int32_t *b;
int32_t *c;
void intAdd() {
for(int i = 0; i<10;i++){
c[i] = a[i] + b[i];
}
In your JAVA code use this snippet:
int[] B = new int[10];
int[] A = new int[10];
for (int i = 0; i < 10; i++) {
A[i] = 2;
B[i] = 1;
}
// provide memory for b using data in B
Allocation b = Allocation.createSized(rs, Element.I32(rs), B.length);
b.copyFrom(B);
inv.bind_b(b);
// provide memory for a using data in A
Allocation a = Allocation.createSized(rs, Element.I32(rs), A.length);
a.copyFrom(A);
inv.bind_a(a);
// create blank memory for c
inv.bind_c(Allocation.createSized(rs, Element.I32(rs), 10));
// call intAdd function
inv.invoke_intAdd();
// get result
int[] C = new int[10];
inv.get_c().copyTo(C);
for (int i = 0; i < C.length; i++) {
System.out.println(C[i]);
}
And this is your result on Logcat:
Your first question is about Asynchronous, you can use thread to wait result. In this example, the function is fast enough and instantly gives the output to C array so result can show on logcat.
Your second question is about implement intAdd() function without recalling it. The code above is the answer. You can access any part of int array in Java until the method is done ( different from root() function ).
Hope this can help someone :)

Categories

Resources