hi tried it with a pipedinputstream and pipedoutputstream but it still blocks. <p>t.input = (TargetDataLine) AudioSystem.getLine(targetInfo); AudioInputStream auin=new AudioInputStream(t.input); PipedOutputStream pout=new PipedOutputStream(); PipedInputStream pin=new PipedInputStream(pout); pcm2speex=new Pcm2SpeexAudioInputStream(pin, format, AudioSystem.NOT_SPECIFIED); [...] int n=auin.read(frame, 0, frame.length); System.out.println(""+n+" bytes read."); pout.write(frame); int m=pcm2speex.read(frame, 0, frame.length); System.out.println(""+m+" bytes read - 2."); <p>output: root@mainframe:/home/uls/eclipse/avrelay# java TestClient started. Opening connection to server. Connecting ... Session joined. Opening mic Mic opened Constructing speex encoder. Speex encoder constructed. *** Speex info: Bitrate: 8000 Frame size: 160 Complexity: 3 Mode: 3 Sampling rate: 8000 relative quality: 0.0 *** end of speex info everything ok in writer 1280 bytes read. root@mainframe:/home/uls/eclipse/avrelay# it reads everything correctly, but pcm2speex still blocks ... does it await a header ? can i pipe over the direct pcm data or does it wait for some sort header? <p>thanks, ulrich <p>Ulrich B. Staudinger wrote:> Hi Marc, > thanks for the quick reply. > > Marc Gimpel wrote: > >> It would appear the the 'pcm2speex.read(frame, 0, frame.length)' >> is blocking which means that it is waiting for data from the >> underlying inputstream (i.e.AudioInputStream(t.input)). If it could >> read sufficient data it would transcode it. If it recieved an EOF, it >> should do some zero padding and then transcode it. Are you sure that >> you are receiving data from the underlying inputstream??? > > > Yes, it can recieve data from the underlying input stream. > If i read directly from the audioinputstream with > > auin=new AudioInputStream(t.input); > //int n=pcm2speex.read(frame, 0, frame.length); > int n=auin.read(frame, 0, frame.length); > > i can read the specified frame length of bytes repetively. What else > could be the cause for blocking? I am really glad about every hint! > >> One point to note though is that is you are receiving 44kHz audio, >> it will try to encode this as UWB (i.e. pretending it's 32kHz >> sampling rate), which means that to encode 1 speex packet you are >> going to need 640 samples, or 1280 bytes (which should compress down >> to something like 29 bytes because the quality setting should be 3 by >> default). > > > what about piping the input streams? can't i manually read 640 samples > from my AudioInputStream (which works) and hand them to a pipe > (PipedInputStream connected with an PipedOutputStream) which ends in > an InputStream in the Pcm2Speex constructor? > >> Having said this, jspeex does provide an SPI interface so you >> should be able to ask JavaSound to give you directly a a Speex >> AudioInputStream. It's coded although I admit that I never got round >> to testing it so it might not work. It does work for the decoding, >> that I'm sure of in any case. > > > that's interesting ... i have to look into this, but am not really > that familiar with SPI ... more with Swing and user interfaces ;-) > > I attached my TestClient.java, maybe it's of help ... Just press > 'join' if you actually start it ... > > best regards, > ulrich > >------------------------------------------------------------------------ > >/* > * Created on Oct 20, 2003 > * > * AVRelay > * > */ > >/** > * write comment here > * > * @author uls > */ > >import java.awt.GridLayout; >import java.awt.event.ActionEvent; >import java.awt.event.ActionListener; >import java.io.DataInputStream; >import java.io.DataOutputStream; >import java.io.PipedInputStream; >import java.io.PipedOutputStream; >import java.net.Socket; >import java.util.Random; >import java.util.Vector; > >import javax.sound.sampled.AudioFormat; >import javax.sound.sampled.AudioSystem; >import javax.sound.sampled.AudioInputStream; >import javax.sound.sampled.DataLine; >import javax.sound.sampled.SourceDataLine; >import javax.sound.sampled.TargetDataLine; >import javax.swing.JButton; >import javax.swing.JFrame; >import javax.swing.JLabel; >import javax.swing.JTextField; > > >import org.xiph.speex.*; >import org.xiph.speex.spi.*; > >public class TestClient { > > > public SourceDataLine output=null; > public TargetDataLine input=null; > > public Vector playbackBuffer=new Vector(); > public Vector recordBuffer=new Vector(); > > public double amplevel=2; > > //44100 khz * 2 byte * 2 channels (stereo) = x bytes per second > > public int bufferlength=44100; > public int framelength=1280; > int frameduration=1000; > > //public int bufferlength=320; > > > JTextField nickname, channel; > > TestClient(){ > > System.out.println("started."); > JFrame f=new JFrame("Test Client"); > > f.getContentPane().setLayout(new GridLayout(5,5)); > > f.getContentPane().add(new JLabel("nick")); > nickname=new JTextField("Guest"+((int)Math.random()*100)); > f.getContentPane().add(nickname); > f.getContentPane().add(new JLabel("channel")); > channel=new JTextField("jdev@conference.jabber.org"); > f.getContentPane().add(channel); > > JButton b=new JButton("Join"); > b.addActionListener(new ActionListener(){ > public void actionPerformed(ActionEvent e){ > connect(); > } > }); > f.getContentPane().add(b); > JButton b1=new JButton("leave"); > b1.addActionListener(new ActionListener(){ > public void actionPerformed(ActionEvent e){ > leave(); > } > }); > f.getContentPane().add(b1); > f.getContentPane().add(new JLabel("Mute")); > JTextField mute=new JTextField("nick name to mute"); > f.getContentPane().add(mute); > JButton b2=new JButton("Mute!"); > > > JButton b3=new JButton("amp x 1"); > b3.addActionListener(new ActionListener(){ > public void actionPerformed(ActionEvent e){ > amplevel=1; > } > }); > JButton b4=new JButton("amp x 2"); > b4.addActionListener(new ActionListener(){ > public void actionPerformed(ActionEvent e){ > amplevel=1; > } > }); > JButton b5=new JButton("amp x 3"); > b5.addActionListener(new ActionListener(){ > public void actionPerformed(ActionEvent e){ > amplevel=1; > } > }); > > f.getContentPane().add(b2); > f.getContentPane().add(b3); > f.getContentPane().add(b4); > f.getContentPane().add(b5); > f.setSize(300,200); > f.setVisible(true); > > } > > > public void leave(){ > try{ > > > > w.stop();System.out.println("."); > r.stop();System.out.println("."); > s.close();System.out.println("."); > > > > System.out.println("Connection closed."); > } > catch(Exception e){ > e.printStackTrace(); > } > } > > Writer w; > Reader r; > Socket s; > > public void connect(){ > try > { > > > > System.out.println("Opening connection to server."); > //DataLine.Info targetInfo = new DataLine.Info(TargetDataLine.class, format, 44100); > > System.out.println("Connecting ... "); > > s=new Socket("jabberstudio.org", 9997); > > DataOutputStream dout=new DataOutputStream(s.getOutputStream()); > DataInputStream din=new DataInputStream(s.getInputStream()); > dout.writeBytes("SPX:"+framelength+":"+frameduration+"\n"); > dout.writeBytes(channel.getText()+"\n"); > dout.writeBytes("\n"); > String reply=din.readLine(); > > if(reply.equals("OK")){ > > PipedInputStream pin=new PipedInputStream(); > PipedOutputStream pout=new PipedOutputStream(); > pin.connect(pout); > //Loop l=new Loop(); > //l.start(); > > //Writer w=new Writer(this, new DataOutputStream(pout)); > w=new Writer(this, dout); > w.start(); > //Reader r=new Reader(this, new DataInputStream(pin)); >// r=new Reader(this, din); >// r.start(); > System.out.println("Session joined. "); > > } > else{ > System.out.println("ERROR: "+reply); > } > > } > catch (Exception e) > { > e.printStackTrace(); > } > > } > > public static void main(String[] args) { > TestClient tp=new TestClient(); > } >} > > >class Writer extends Thread{ > TestClient t; > public DataOutputStream dos; // the pipe to write to > > public static final String VERSION = "slay! ulrich staudinger - based on jspeex"; > > public static int mode = 0; > public static int quality = 8; > public static int complexity = 3; > public static int bitrate = -1; > public static int nframes = 1; > public static int sampleRate = 44100; > public static float vbr_quality = -1; > public static boolean vbr = false; > public static boolean vad = false; > public static boolean dtx = false; > public static int channels = 1; > > //speex > Pcm2SpeexAudioInputStream pcm2speex; > > /** > * CONSTRUCTOR > * @param t > * @param dos > */ > Writer(TestClient t, DataOutputStream dos){ > > this.t=t; > this.dos=dos; > > } > > public void run(){ > > try{ > System.out.println("Opening mic"); > > AudioInput ai=new AudioInput(t); > ai.start(); > > if(t.input==null){ > AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false); > DataLine.Info targetInfo = new DataLine.Info(TargetDataLine.class, format, 44100); > > t.input = (TargetDataLine) AudioSystem.getLine(targetInfo); > > t.input.open(format,44100); > System.out.println(" Mic opened"); > > t.input.start(); > AudioInputStream auin=new AudioInputStream(t.input); > System.out.println("Constructing speex encoder."); > pcm2speex=new Pcm2SpeexAudioInputStream(auin, format, AudioSystem.NOT_SPECIFIED); > System.out.println("Speex encoder constructed."); > System.out.println("*** Speex info: "); > System.out.println("Bitrate: "+pcm2speex.getEncoder().getBitRate()); > System.out.println("Frame size: "+pcm2speex.getEncoder().getFrameSize()); > System.out.println("Complexity: "+pcm2speex.getEncoder().getComplexity()); > System.out.println("Mode: "+pcm2speex.getEncoder().getMode()); > System.out.println("Sampling rate: "+pcm2speex.getEncoder().getSamplingRate()); > System.out.println("relative quality: "+pcm2speex.getEncoder().getRelativeQuality()); > System.out.println("*** end of speex info"); > > System.out.println("everything ok in writer"); > > > > //byte[] buffer=new byte[t.bufferlength]; > > > double ratio=t.bufferlength/t.framelength; > > byte[] frame=new byte[t.framelength]; > > while(true){ > > int n=pcm2speex.read(frame, 0, frame.length); > //int n=auin.read(frame, 0, frame.length); > System.out.println(""+n+" bytes read."); > > > /* > > //convert the byte array to an int array > int[] iarray=new int[buffer.length/2]; > for(int i=0;i<iarray.length/2;i++){ > iarray[i]=0; > iarray[i]+=buffer[i*2]*256; > iarray[i]+=buffer[(i*2)+1]; > > //compressed[(int)((double)i/ratio)]=(byte)(2*(buffer[i])); > } > //this int array contains 44100 (16bit) stereo samples > //convert to mono > int[] monoarray=new int[iarray.length/2]; > for(int i=0;i<monoarray.length;i++){ > monoarray[i]=(iarray[i]+iarray[i+2])/2; > } > //now we have a 44100 int array, we now have to downgrade to 8000 > //we just do a very straight forward downgrade > int[] eightK=new int[8000]; > for(int i=0;i<eightK.length;i++){ > eightK[i]=monoarray[i*5]; > eightK[i]=monoarray[(i*5)+1]; > eightK[i]=monoarray[(i*5)+2]; > eightK[i]=monoarray[(i*5)+3]; > eightK[i]=monoarray[(i*5)+4]; > eightK[i]/=5; > } > //now we have a 8k int[] mono buffer > > //coder. > > */ > > //buffer contains 44100 16 bit stereo, > //we have to downgrade to 8000 16 bit mono > //byte[] compressed=new byte[t.framelength+1]; > //for(int i=0;i<t.bufferlength;i++){ > //compressed[(int)((double)i/ratio)]=(byte)(2*(buffer[i])); > //} > > //compress > > > > /*//do post recording amplifying > for(int j=0;j<compressed.length;j++){ > compressed[j]=(byte)( ((int)compressed[j])*t.amplevel ); > byte b=compressed[j]; > int b1=b; > System.out.println(""+b1); > }*/ > > t.recordBuffer.addElement(frame); > } > } > } > catch(Exception e){ > e.printStackTrace(); > } > > } > >} > >class Reader extends Thread{ > TestClient t; > //DirectSoundWriter waveWriter; > //SpeexDecoder speexDecoder; > > /** > * speex parameters > */ > > public static Random random = new Random(); > public static boolean ogg = true; > public static boolean enhanced = true; > public static int mode = 0; > public static int quality = 8; > public static int complexity = 3; > public static int bitrate = -1; > public static int nframes = 1; > public static int sampleRate = -1; > public static float vbr_quality = -1; > public static boolean vbr = false; > public static int channels = 1; > public static int loss = 0; > > DataInputStream dis; > Reader(TestClient t, DataInputStream dis){ > this.t=t; > this.dis=dis; > } > > public void run(){ > try{ > > if(t.output==null){ > > System.out.println("Opening output line"); > AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false); > > DataLine.Info sourceInfo = new DataLine.Info(SourceDataLine.class, format, 44100); > > t.output = (SourceDataLine) AudioSystem.getLine(sourceInfo); > > t.output.open(format,44100); > System.out.println("Output line opened."); > > > t.output.start(); > > System.out.println("everything ok"); > } > > //byte[] buffer=new byte[t.bufferlength]; > double ratio=t.bufferlength/t.framelength; > byte[] compressed=new byte[t.framelength+1]; > > AudioOutput ao=new AudioOutput(t); > ao.start(); > > > > > while(true){ > > dis.read(compressed); > > //now we have an 8k 16 bit mono int array > > > byte[] buffer=new byte[t.bufferlength]; > > //decompress > > for(int i=0;i<t.bufferlength;i++){ > buffer[i]=compressed[(int)((double)i/ratio)]; > } > > > //plaback decompressed buffer > t.playbackBuffer.add(buffer); > > System.out.println("Buffer recieved."+compressed.length+" decompressed to "+buffer.length + " ... "+ao.isAlive() +" : "+t.playbackBuffer.size()); > >// } > > } > > } > catch(Exception e){ > e.printStackTrace(); > } > } > > /** > * from jspeexdec > * @param packet > * @param offset > * @param bytes > * @return > */ > private boolean readSpeexHeader(byte[] packet, int offset, int bytes) > { > if (bytes!=80) { > return false; > } > if (!"Speex ".equals(new String(packet, 0, 8))) { > return false; > } > mode = packet[40+offset] & 0xFF; > sampleRate = bytestoint(packet, offset+36); > channels = bytestoint(packet, offset+48); > nframes = bytestoint(packet, offset+64); > //return speexDecoder.init(mode, sampleRate, channels, enhanced); > return true; > } > > /** > * Converts the bytes from the given array to an integer > * @param a - the array > * @param i - the offset > */ > private static int bytestoint(byte[] a, int i) > { > return ((a[i+3] & 0xFF) << 24) | ((a[i+2] & 0xFF) << 16) | ((a[i+1] & 0xFF) << 8) | (a[i] & 0xFF); > } > >} > >class AudioInput extends Thread{ > TestClient t; > AudioInput(TestClient t){ > this.t=t; > > } > > public void run(){ > while(true){ > try{ > if(t.recordBuffer.size()>0){ > byte[] buffer=(byte[])t.recordBuffer.elementAt(0); > //t.output.write(buffer,0,buffer.length); > t.w.dos.write(buffer,0,buffer.length); > t.w.dos.flush(); > t.recordBuffer.removeElementAt(0); > System.out.println("Buffersize after write: "+t.recordBuffer.size()); > } > else{ > //System.out.println("Buffer zero! "); > sleep(5*t.frameduration); > } > > } > catch(Exception e){ > e.printStackTrace(); > } > } > > } >} > >class AudioOutput extends Thread{ > > TestClient t; > AudioOutput(TestClient t){ > this.t=t; > } > > public void run(){ > while(true){ > //System.out.println("Running ... "); > try{ > if(t.playbackBuffer.size()>0){ > byte[] buffer=(byte[])t.playbackBuffer.elementAt(0); > t.output.write(buffer,0,buffer.length); > > //t.output.flush(); > System.out.println("Buffersize after play: "+t.playbackBuffer.size()); > t.playbackBuffer.removeElementAt(0); > } > if(t.playbackBuffer.size()==0){ > //System.out.println("Buffer zero! "); > sleep(50); > } > //while(t.output.isActive()){ > //sleep(t.frameduration); > //sleep(10); > //} > } > catch(Exception e){ > e.printStackTrace(); > } > } > } > >} > >class Loop extends Thread{ > > Loop(){ > > } > public void run(){ > try{ > System.out.println("run"); > AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false); > DataLine.Info targetInfo = new DataLine.Info(TargetDataLine.class, format, 44100); > DataLine.Info sourceInfo = new DataLine.Info(SourceDataLine.class, format, 44100); > System.out.println("2"); > TargetDataLine input = (TargetDataLine) AudioSystem.getLine(targetInfo); > SourceDataLine output = (SourceDataLine) AudioSystem.getLine(sourceInfo); > System.out.println("3"); > input.open(format,44100); > System.out.println("4"); > output.open(format,44100); > System.out.println("5"); > > input.start(); > output.start(); > > int bufferlength=44100; > int framelength=2757; > System.out.println("everything ok"); > byte[] buffer=new byte[bufferlength]; > double ratio=(double)bufferlength/(double)framelength; > byte[] compressed=new byte[framelength]; > while(true){ > > int n=input.read(buffer, 0, buffer.length); > > System.out.println("compressing"); > > > for(int i=0;i<bufferlength;i++){ > compressed[(int)((double)i/ratio)]=(byte)(2*(buffer[i])); > } > System.out.println("now decompressing "); > for(int i=0;i<bufferlength;i++){ > buffer[i]=compressed[(int)((double)i/(ratio))]; > } > > output.write(buffer,0,buffer.length); > > } > > } > catch(Exception e){ > > } > > } >} > ><p> -- Ulrich B. Staudinger http://www.die-horde.de email: us@die-horde.de jid: uls@jabber.org current project: REDHORN http://redhorn.sourceforge.net Blog: uls@jabber.org">http://jabber.linux.it/jogger/user.php?jid=uls@jabber.org</a> <p>--- >8 ---- List archives: http://www.xiph.org/archives/ Ogg project homepage: http://www.xiph.org/ogg/ To unsubscribe from this list, send a message to 'speex-dev-request@xiph.org' containing only the word 'unsubscribe' in the body. No subject is needed. Unsubscribe messages sent to the list will be ignored/filtered.
Hi Marc, thanks for the quick reply. Marc Gimpel wrote:> It would appear the the 'pcm2speex.read(frame, 0, frame.length)' is > blocking which means that it is waiting for data from the underlying > inputstream (i.e.AudioInputStream(t.input)). If it could read > sufficient data it would transcode it. If it recieved an EOF, it > should do some zero padding and then transcode it. Are you sure that > you are receiving data from the underlying inputstream???Yes, it can recieve data from the underlying input stream. If i read directly from the audioinputstream with auin=new AudioInputStream(t.input); //int n=pcm2speex.read(frame, 0, frame.length); int n=auin.read(frame, 0, frame.length); i can read the specified frame length of bytes repetively. What else could be the cause for blocking? I am really glad about every hint!> One point to note though is that is you are receiving 44kHz audio, > it will try to encode this as UWB (i.e. pretending it's 32kHz sampling > rate), which means that to encode 1 speex packet you are going to need > 640 samples, or 1280 bytes (which should compress down to something > like 29 bytes because the quality setting should be 3 by default).what about piping the input streams? can't i manually read 640 samples from my AudioInputStream (which works) and hand them to a pipe (PipedInputStream connected with an PipedOutputStream) which ends in an InputStream in the Pcm2Speex constructor?> Having said this, jspeex does provide an SPI interface so you > should be able to ask JavaSound to give you directly a a Speex > AudioInputStream. It's coded although I admit that I never got round > to testing it so it might not work. It does work for the decoding, > that I'm sure of in any case.that's interesting ... i have to look into this, but am not really that familiar with SPI ... more with Swing and user interfaces ;-) I attached my TestClient.java, maybe it's of help ... Just press 'join' if you actually start it ... best regards, ulrich -------------- next part -------------- A non-text attachment was scrubbed... Name: TestClient.java Type: text/x-java Size: 14776 bytes Desc: TestClient.java Url : http://lists.xiph.org/pipermail/speex-dev/attachments/20031031/28efc5ae/TestClient-0001.java
Ulrich B. Staudinger
2004-Aug-06 15:01 UTC
[speex-dev] q about jspeex - repost of TestClient.java with PipedInputStream
There is actually a mail missing - the version with the pipedinputstream construction. attached the current source with pipedinputstream/pipedoutputstream tia, ulrich <p><p> -------------- next part -------------- A non-text attachment was scrubbed... Name: TestClient.java Type: text/x-java Size: 14939 bytes Desc: TestClient.java Url : http://lists.xiph.org/pipermail/speex-dev/attachments/20031031/b78cc240/TestClient-0001.java
Hi, i changed the read method after constructing a pipedinputstream/opipedoutputstream to int n=auin.read(frame, 0, frame.length); System.out.println(""+n+" bytes read."); pout.write(frame); int m=pcm2speex.read(); System.out.println("something recieved"); and still can't recieve a single value from the pipe .. thanks, ulrich Ulrich B. Staudinger wrote:> Hi Marc, > thanks for the quick reply. > > Marc Gimpel wrote: > >> It would appear the the 'pcm2speex.read(frame, 0, frame.length)' >> is blocking which means that it is waiting for data from the >> underlying inputstream (i.e.AudioInputStream(t.input)). If it could >> read sufficient data it would transcode it. If it recieved an EOF, it >> should do some zero padding and then transcode it. Are you sure that >> you are receiving data from the underlying inputstream??? > > > Yes, it can recieve data from the underlying input stream. > If i read directly from the audioinputstream with > > auin=new AudioInputStream(t.input); > //int n=pcm2speex.read(frame, 0, frame.length); > int n=auin.read(frame, 0, frame.length); > > i can read the specified frame length of bytes repetively. What else > could be the cause for blocking? I am really glad about every hint!<p><p>--- >8 ---- List archives: http://www.xiph.org/archives/ Ogg project homepage: http://www.xiph.org/ogg/ To unsubscribe from this list, send a message to 'speex-dev-request@xiph.org' containing only the word 'unsubscribe' in the body. No subject is needed. Unsubscribe messages sent to the list will be ignored/filtered.