package uk.co.mmscomputing.dsp.phone; import java.io.*; // 1200baud FSK => 1200bit/sec => 1200/8000 = 6.666 samples per bit => 3 bits = 7+6+7 samples public class FSKOutputStream extends FilterOutputStream{ static private final int[] mark2space={ 0, 1,66,59,52,45,38,31,24,17,10,37,76,69,62,55,48,41,34,27, 20,13, 6,22,72,65,58,51,44,37,30,23,24, 9, 2,45,68,61,54,47, 40,41,26,19,12, 5,78,71,64,57,50,77,36,29,22,15, 8, 1,74,67, 60,53,46,62,32,25,18,11, 4,77,70,63,64,49,42, 5,28,21,14, 7, }; static private final int[] space2mark={ 0,57,34,11,68,45,22,79,56,33,10,67,44,21,78,55,32, 9,66,43, 20,77,54,31, 8,65,42,19,76,53,30, 7,64,41,18,45,52,29, 6,63, 40,17,74,51,28, 5,62,39,16,73,50,27, 4,61,38,15,72,49,26, 3, 60,37,14,71,48,25, 2,59,36,13,70,47,24, 1,58, 5,12,69,46,23, }; static private int[][] amps=new int[2][80]; private int counter=1,phase,lastsymbol=1; private byte[] pcm=new byte[2]; public FSKOutputStream(OutputStream out){ super(out); phase=0; } protected void writeSample(int sample)throws IOException{ pcm[0]=(byte) sample; pcm[1]=(byte)(sample>>8); out.write(pcm); // write sample to pcm stream } public void writeDelay(int milliseconds)throws IOException{ int samples=milliseconds<<3; // samples to send = 8000Hz * 0.001s for(int i=0;i<samples;i++){ writeSample(0); } } public void writeBit(int symbol)throws IOException{ // symbol: SPACE = 0; MARK = 1 int samples; int[] amps = this.amps[symbol&0x01]; if(symbol!=lastsymbol){ phase=(lastsymbol==0)?space2mark[phase]:mark2space[phase]; } counter++; if(counter==3){ // 7,6,7,7,6,7,... samples = 6;counter = 0; }else{ samples = 7; } for(int i=0;i<samples;i++){ writeSample(amps[phase]); phase=(phase+1)%amps.length; } lastsymbol=symbol; } public void writeBits(int b,int bits)throws IOException{ for(int i=0;i<bits;i++){ // send first bit 0 then bit 1 .. and last bit 7 writeBit(b&0x01); b>>=1; // ROR } } public void write(int b)throws IOException{ writeBit(0); // start bit writeBits(b,8); writeBit(1); // stop bit } public void write(byte[] b)throws IOException{ write(b,0,b.length); } public void write(byte[] b,int off,int len)throws IOException{ for(int i=0;i<len;i++){write(b[off+i]);} } public void writeMarkSignal(int len)throws IOException{ writeBits(-1,len); // mark signal; begin of message signal } static{ for(int i=0;i<80;i++){ amps[0][i]=(int)(8192.0*Math.sin(2.0*Math.PI*((double)i)*2100.0/8000.0-0.001)); amps[1][i]=(int)(8192.0*Math.sin(2.0*Math.PI*((double)i)*1300.0/8000.0-0.001)); } } public static void main(String[] argv){ try{ String file="uk/co/mmscomputing/dsp/phone/fsk.raw"; FSKOutputStream out=new FSKOutputStream(new FileOutputStream(file)); out.writeMarkSignal(80); // mark signal; begin of message signal out.write("Hello world!\n".getBytes()); out.write("ABCDEFGHIJKLMNOPQRSTUVWXYZ.".getBytes()); out.writeBits(-1,10); // end of message signal out.flush(); out.close(); }catch(Exception e){ e.printStackTrace(); } } } // [1] ETS 300 659-1/2 (1997-02)