Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Max number of operations? (Good WAVE converter program hangs with "long" input files)

Reply
Thread Tools

Max number of operations? (Good WAVE converter program hangs with "long" input files)

 
 
Alex Ochoa
Guest
Posts: n/a
 
      01-18-2005
Hi, I wrote a Java program that takes a stereo .wav file and turns it
into a mono .wav file by appropriately deleting the information on one
channel (it ask you which one you want to keep). I don't think the
details of the sound editing matter. I'm not interested in simply
converting the .wav files from stereo to mono (I have retail programs
that do that already), but I want to solve my problem just to be a
better programmer.

The point is that I load an input stream and operate on it (loading
other streams in between to change the format of the info I'm reading)
and then write to the original file. I ran the program on a 52-byte
..wav file and IT WORKED, but on the other files (around 30 KB each) the
program hangs. Moreover, I compiled it placing
System.out.println("everything is fine here") and variations to see how
far down the code the program would stop, and I saw that with long
enough files (30 KB) the program would stop after exactly 513
iterations of a while loop in it. I only had one 1 KB file I could
work with and for this one it would finish all the necesary while
iterations (because they were less than 513), but the program would
later hang when trying to write the final stream to the .wav file.

I can put the code here if you want, it's not too long, but probably
long enough for a forum. What I was wondering is if anybody knows a
priori how to fix this (in case it is a known and general issue with
programs that do a lot of operations) or is this a problem specific to
my code, which might look good but actually isn't.
Your help will be greatly appreciated.

 
Reply With Quote
 
 
 
 
Alex Ochoa
Guest
Posts: n/a
 
      01-18-2005
Here's the code of my program:

import java.awt.*;
import java.io.*;
import javax.sound.sampled.*;
import javax.swing.*;

public class StereoToMono extends Object{

public StereoToMono (File wavFile, boolean isLeft){

try{
AudioInputStream stereoStream =
AudioSystem.getAudioInputStream (wavFile);
AudioFormat oldFmt = stereoStream.getFormat();
AudioFormat newFmt = new AudioFormat(oldFmt.getEncoding(),
oldFmt.getSampleRate(), oldFmt.getSampleSizeInBits(), 1,
oldFmt.getFrameSize(), oldFmt.getFrameRate(), oldFmt.isBigEndian());

if (oldFmt.getChannels() != 2) System.out.println ("Source
file is not in stereo");
else{
// create a new PipedOutputStream with the bytes I
want, then feed to PipedInputStream, then make that into an
AudioInputStream with
// the first constructor here
http://java.sun.com/j2se/1.5.0/docs/...putStream.html
// Finally, use AudioSystem to turn this
AudioInputStream into the file.
PipedInputStream monoStream = new PipedInputStream();
PipedOutputStream streamOut = new
PipedOutputStream(monoStream);

int frameSize = oldFmt.getFrameSize();
byte[] frameStereo = new byte[frameSize];
int reading = stereoStream.read(frameStereo);

if (isLeft == true){
while (reading != -1){
for (int j = 0; j <= frameSize/2-1; j++)
streamOut.write(frameStereo[j]);
reading = stereoStream.read(frameStereo);
}
}
else{
while (reading != -1){
for (int j = frameSize/2; j <= frameSize-1;
j++) streamOut.write(frameStereo[j]);
reading = stereoStream.read(frameStereo);
}
}

AudioInputStream audioMonoStream = new
AudioInputStream(monoStream, newFmt, stereoStream.getFrameLength());

try{
AudioSystem.write(audioMonoStream,
AudioFileFormat.Type.WAVE, wavFile);
System.out.println("Stereo to mono conversion is
complete");
}
catch (IOException e){
System.out.println ("Destination file not
opened:\n" + e.toString());
}
monoStream.close();
}
stereoStream.close();

}
catch (IOException e){
System.out.println ("Source file not opened:\n" +
e.toString());
}
catch (UnsupportedAudioFileException e){
System.out.println ("Source file is not a valid audio
file:\n" + e.toString());
}
}

public static void main (String[] args){
boolean isLeftChosen;
JFileChooser chooser = new JFileChooser();
if (chooser.showOpenDialog(null) ==
JFileChooser.APPROVE_OPTION){
int leftChosen = (JOptionPane.showConfirmDialog(chooser,
"Do you want to keep the left channel?\n(Choosing No will keep the
right channel)"));
if (leftChosen == JOptionPane.CANCEL_OPTION);
else{
if (leftChosen == JOptionPane.YES_OPTION) isLeftChosen
= true;
else isLeftChosen = false;
StereoToMono converter = new StereoToMono
(chooser.getSelectedFile(), isLeftChosen);
}
}
System.exit(0);
}

}

 
Reply With Quote
 
 
 
 
Yu SONG
Guest
Posts: n/a
 
      01-18-2005
Alex Ochoa wrote:
> Hi, I wrote a Java program that takes a stereo .wav file and turns it
> into a mono .wav file by appropriately deleting the information on one
> channel (it ask you which one you want to keep). I don't think the
> details of the sound editing matter. I'm not interested in simply
> converting the .wav files from stereo to mono (I have retail programs
> that do that already), but I want to solve my problem just to be a
> better programmer.
>



I have not debugged your program, but I think something wrong with your
loop conditions.

I would suggest you to have a look at "tritonus" (especially
org.tritonus.share.sampled). My implementation can read/write "n" MB
audio file without any problem you mentioned.


--
Song

/* E-mail.c */
#define User "Yu.Song"
#define At '@'
#define Warwick "warwick.ac.uk"
int main() {
printf("Yu Song's E-mail: %s%c%s", User, At, Warwick);
return 0;}

Further Info. : http://www.dcs.warwick.ac.uk/~esubbn/
__________________________________________________ _____

 
Reply With Quote
 
pfalstad@gmail.com
Guest
Posts: n/a
 
      01-18-2005
you're writing to a PipedOutputStream, but you don't have anybody
reading from it until you're completely done. PipedOutputStream isn't
designed for this; it has a fairly small buffer size. It's intended to
be written in one thread and read in the other.

I think ByteArrayOutputStream can be used to write an arbitrarily large
amount of data. But do you really want to store the whole file in
memory? .wav files get really huge.

If I were doing this, I would create a new file immediately, read from
the old file and write to the new one, and then when I'm done, I would
rename the new file to the old one, overwriting it. That also solves
the problem of what happens if something bad happens when you're
writing the new file.. You don't want to destroy the old one until
you're done.

 
Reply With Quote
 
Gordon Beaton
Guest
Posts: n/a
 
      01-18-2005
On 18 Jan 2005 04:09:42 -0800, Alex Ochoa wrote:
> The point is that I load an input stream and operate on it (loading
> other streams in between to change the format of the info I'm reading)
> and then write to the original file. I ran the program on a 52-byte
> .wav file and IT WORKED, but on the other files (around 30 KB each) the
> program hangs. Moreover, I compiled it placing
> System.out.println("everything is fine here") and variations to see how
> far down the code the program would stop, and I saw that with long
> enough files (30 KB) the program would stop after exactly 513
> iterations of a while loop in it. I only had one 1 KB file I could
> work with and for this one it would finish all the necesary while
> iterations (because they were less than 513), but the program would
> later hang when trying to write the final stream to the .wav file.


There is no limit on the number of operations.

Your problem is that you are using a PipedStream to buffer all of the
intermediate data from the "read" part of your code, before you invoke
the "write" part.

PipedStreams are intended to be read and written (more or less) at the
same time, and the buffer space is therefore limited.

You have (at least) three options:

1. Start a separate thread for one of the two (read or write) parts,
and let the two operations proceed at the same time.

2. Replace the Piped streams. Write the intermediate data to a
suitably large byte array (possibly using a ByteArrayOutputStream).
Then create a ByteArrayInputStream using the same byte array, and
pass that instead of the PipedInputStream to the AudioInputStream.

3. Write a subclass of FilterInputStream and pass that to the
AudioInputStream. Your class can read and filter the data as it is
requested by the AudioInputStream, so you don't need to buffer any
significant amount of data and you don't need to use separate
threads for reading and writing.

/gordon

--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
superposition of a square wave over a sine wave Shiva VHDL 2 02-02-2009 02:49 PM
superposition of a square wave over a sine wave rara10 VHDL 0 01-30-2009 08:21 PM
How do i record and invert a sound wave in real time using Tkinter,tkSnack and wave modules? Karthik Python 0 09-05-2007 05:12 AM
square wave / sine wave generator red floyd C++ 5 06-21-2007 09:30 PM
Clear hangs up - & hangs up - & hangs up Sue Bilstein NZ Computing 26 03-07-2004 01:33 AM



Advertisments