Trivial debugging :o|

Hello folks! I am writing a piece of code that takes a .wav file, encoded with 16 bits/sample, and has to perform a "thersholding" operation in these samples. That is, that groups of samples that don't have enough mean energy, shall not be included in the new .wav file that will contain the thresholded sample (the whole process is a short of compression).

The problem is, that for some reason I haven't discovered yet, only half of the bytes of the original file are found in the final file! (But, the thresholding mechanism works well in these half samples :P)

Could you please check on my code? 15 javies for the one who gives me a solution! :)

Here goes my code...

[696 byte] By [miss_eleca] at [2007-11-27 11:35:23]
# 1

// 16bits/sample

// line 47 -> input .wav file

import java.io.*;

import javax.sound.sampled.*;

public class thresholding16 {

public thresholding16() {

try {

jbInit();

} catch (Exception ex) {

ex.printStackTrace();

}

}

AudioFormat audioFormat;

AudioInputStream audioInputStream;

//initial samples from File

byte buffer[] = new byte[10000000];

//thresholded samples ->to be written in a new File

byte newBuffer[] = new byte[10000000];

//the initial 2-byte samples will be represented as an integer (by merging the MSB,LSB of the sample)

int intArray[]=new int[5000000];

//mean energy of samples for every one of the 200000 groups of 25 samples

double energyArray[] = new double[200000];

public static void main(String args[]){

try{

thresholding16 thres=new thresholding16();

thres.moveToBuffer();

}

catch(Exception x){

System.out.println(x);

}

}

void moveToBuffer() {

int cnt=0;

try{

File soundFile =

new File("aFile0.wav"); //to arxeio eisodou pou 8a 'katwfliw8ei'

audioInputStream = AudioSystem.

getAudioInputStream(soundFile);

audioFormat = audioInputStream.getFormat();

System.out.println(audioFormat);

for(int h=0;h<10000000;h++){

buffer[h]=0;

}

while((cnt = audioInputStream.read(buffer,0,buffer.length)) != -1){

}

/*

System.out.println("Ta arxika deigmata ws bytes");

for(int j=0;j<10000;j++){

System.out.println(j+" "+buffer[j]);

}

*/

/*

//

FileWriter fistream = new FileWriter("16bitArxika.txt");

BufferedWriter outi = new BufferedWriter(fistream);

outi.write("Ta arxika deigmata ws bytes"+"\r\n");

for(int j=0;j<10000;j++){

outi.write(buffer[j]+"\r\n");

}

//Close the output stream

outi.close();

*/

//merge the 2 bytes of a sample int one integer

for(int j=0;j<5000000;j++){

int num=0;

int msb=0;

int lsb=0;

msb=buffer[j*2+1];

lsb=buffer[j*2];

int h=buffer[j*2+1];

if (h<0){

num=msb&lsb;

}

else{

num=msb^lsb;

}

intArray[j]=num;

}//end for

FileWriter fistream = new FileWriter("16bitArxika.txt");

BufferedWriter outi = new BufferedWriter(fistream);

outi.write("Ta arxika deigmata ws bytes"+"\r\n");

for(int j=0;j<200000;j++){

outi.write(intArray[j]+" ");

}

//Close the output stream

outi.close();

/*

System.out.println("Ena deigma -> enas integer");

for(int j=0;j<500;j++){

System.out.println(j+" "+intArray[j]);

}*/

for(int i=0;i<200000;i++){

energyArray[i]=0;

}

//Mean energy estimated from the type //Ε=10log(ε+1/ΝΣS^2(n))

for(int i=0;i<200000;i++){

for(int j=0;j<25;j++){

energyArray[i]=energyArray[i]+intArray[i*25+j]*intArray[i*25+j];

}

}

// System.out.println("Mesh Energeia ana omada");

for(int i=0;i<200000;i++){

double h=0;

h=Math.log(energyArray[i]/25+000000.1)/Math.log(10);

energyArray[i]=h;

}

//auxiliary array that tells which groups of bytes pass and //which do not

int booleanArray[] = new int[200000];

for(int j=0;j<200000;j++){

booleanArray[j]=0;

if (energyArray[j]>2.1){//the wanted threshold

booleanArray[j]=1;

}

}

for(int i=0;i<10000000;i++){

newBuffer[i]=buffer[i];

}

//I put 0 to the proper positions, depending on whether the //groups of bytes has passed the thresholding operation

for(int i=0;i<200000;i++){

if(booleanArray[i]==0){

for(int j=0;j<25;j++){

newBuffer[i*25+j*2]=0; // 0 at MSB

}

for(int j=1;j<26;j++){

newBuffer[i * 25 + j * 2 - 1] = 0; // 0 at LSB

}

}

}

FileWriter fstream = new FileWriter("16bitDeigmataKatwfliwmena.txt");

BufferedWriter out = new BufferedWriter(fstream);

out.write("Ta telika deigmata ws bytes"+"\r\n");

for(int j=0;j<10000000;j++){

out.write(newBuffer[j]+"\r\n");

}

//Close the output stream

out.close();

//the new .wav file

ByteArrayInputStream bis=new ByteArrayInputStream(newBuffer);

AudioInputStream ais=new AudioInputStream(bis,audioFormat,newBuffer.length/audioFormat.getFrameSize());

int cnt2;

cnt2 = audio system.write(ais,AudioFileFormat.Type.WAVE,new File("aFile0Thres.wav"));

System.out.println(" "+cnt2);

}

catch (Exception e) {

}

}//end of method moveToBuffer

private void jbInit() throws Exception {

}

}//end of class thresholding16

miss_eleca at 2007-7-29 17:02:32 > top of Java-index,Java Essentials,Java Programming...
# 2

Only had a chance to skim the code but here is what looks odd to me:

while((cnt = audioInputStream.read(buffer,0,buffer.length)) != -1){

}

The read() method may not get all the bytes the first time and since you are not using the cnt returned to specify where in the buffer to write, you could over-write bytes read the previous time.

Are you mixing streams with writers? Streams are for bytes but writers are for character data.

jbisha at 2007-7-29 17:02:32 > top of Java-index,Java Essentials,Java Programming...
# 3

I checked what you say and everything seems ok when I fill the byte array with the bytes from the original file.

miss_eleca at 2007-7-29 17:02:32 > top of Java-index,Java Essentials,Java Programming...
# 4

> I checked what you say and everything seems ok when I

> fill the byte array with the bytes from the original

> file.

It probably works most of the time when you are reading "real" files (as opposed to streams from sockets, urls, etc.); however, I don't believe it is a good practice.

What about my second comment on streams vs. writers?

jbisha at 2007-7-29 17:02:32 > top of Java-index,Java Essentials,Java Programming...
# 5

I didn't understand exactly your second comment..:P But it is sure that the problem lies in my code the selects which bytes shall pass to the new file (as a proof for that, without this part of the code I can make an exact copy of the original file)

What goes wrong in that part of the code,I don't know! I have checked it one hundred times :P

miss_eleca at 2007-7-29 17:02:32 > top of Java-index,Java Essentials,Java Programming...
# 6

> energyArray[ i ]=energyArray[ i ]+intArray[ i*25+j ]*intArray[ i*25+j ];

I'm going to abbreviate the above to:

d = d + i * i;

(where d is a double, and i is an int).

Are you aware of how it does the math? It first evaluates the expression

(i * i) -- since both parts of that expression are ints, the result is an int as well.

You may have overflowed the int range.

Then it evaluates (d + (result of above)), yielding a double value to put back into the variable.

I don't know, maybe the possible overflow is the problem.

warnerjaa at 2007-7-29 17:02:32 > top of Java-index,Java Essentials,Java Programming...
# 7

> I didn't understand exactly your second comment..:P

FileWriter fstream = new FileWriter("16bitDeigmataKatwfliwmena.txt");

BufferedWriter out = new BufferedWriter(fstream);

out.write("Ta telika deigmata ws bytes"+"\r\n");

for(int j=0;j<10000000;j++){

out.write(newBuffer[j]+"\r\n");

}

You are using a Writer (used to write character streams) to write an array of bytes - not sure how this will be handled. Writers are used to write characters using different encoding.

jbisha at 2007-7-29 17:02:32 > top of Java-index,Java Essentials,Java Programming...