/Users/lyon/j4p/src/sound/UlawCodec.java

1    package sound; 
2     
3    import futils.FileList; 
4    import futils.Futil; 
5    import futils.WildFilter; 
6    import sun.audio.AudioData; 
7    import sun.audio.AudioDataStream; 
8    import sun.audio.AudioPlayer; 
9    import sun.audio.AudioStream; 
10    
11   import java.awt.Container; 
12   import java.awt.GridLayout; 
13   import java.io.DataOutputStream; 
14   import java.io.File; 
15   import java.io.FileInputStream; 
16   import java.io.FileOutputStream; 
17   import java.io.IOException; 
18   import java.io.InputStream; 
19   import java.net.MalformedURLException; 
20   import java.net.URL; 
21    
22   public class UlawCodec { 
23       private byte ulawData[]; 
24       private double doubleArray[]; 
25       private AudioDataStream audioDataStream = null; 
26    
27   //private  AudioStream audioStream = null; 
28    
29       private final int samplingRate = 8000; 
30    
31    
32    
33       // exp_lut - a lookup table for quick natural logarithm 
34       // transformation 
35    
36       private final static int 
37               exp_lut[] = {0, 0, 1, 1, 2, 2, 2, 2, 
38                            3, 3, 3, 3, 3, 3, 3, 3, 
39                            4, 4, 4, 4, 4, 4, 4, 4, 
40                            4, 4, 4, 4, 4, 4, 4, 4, 
41                            5, 5, 5, 5, 5, 5, 5, 5, 
42                            5, 5, 5, 5, 5, 5, 5, 5, 
43                            5, 5, 5, 5, 5, 5, 5, 5, 
44                            5, 5, 5, 5, 5, 5, 5, 5, 
45                            6, 6, 6, 6, 6, 6, 6, 6, 
46                            6, 6, 6, 6, 6, 6, 6, 6, 
47                            6, 6, 6, 6, 6, 6, 6, 6, 
48                            6, 6, 6, 6, 6, 6, 6, 6, 
49                            6, 6, 6, 6, 6, 6, 6, 6, 
50                            6, 6, 6, 6, 6, 6, 6, 6, 
51                            6, 6, 6, 6, 6, 6, 6, 6, 
52                            6, 6, 6, 6, 6, 6, 6, 6, 
53                            7, 7, 7, 7, 7, 7, 7, 7, 
54                            7, 7, 7, 7, 7, 7, 7, 7, 
55                            7, 7, 7, 7, 7, 7, 7, 7, 
56                            7, 7, 7, 7, 7, 7, 7, 7, 
57                            7, 7, 7, 7, 7, 7, 7, 7, 
58                            7, 7, 7, 7, 7, 7, 7, 7, 
59                            7, 7, 7, 7, 7, 7, 7, 7, 
60                            7, 7, 7, 7, 7, 7, 7, 7, 
61                            7, 7, 7, 7, 7, 7, 7, 7, 
62                            7, 7, 7, 7, 7, 7, 7, 7, 
63                            7, 7, 7, 7, 7, 7, 7, 7, 
64                            7, 7, 7, 7, 7, 7, 7, 7, 
65                            7, 7, 7, 7, 7, 7, 7, 7, 
66                            7, 7, 7, 7, 7, 7, 7, 7, 
67                            7, 7, 7, 7, 7, 7, 7, 7, 
68                            7, 7, 7, 7, 7, 7, 7, 7}; 
69    
70       public void echo() { 
71           double linearSamples[] = computeDoubleArray(); 
72           Utils.echo(linearSamples); 
73       } 
74       // this junk.... 
75       public void delay() { 
76           double s1, s2, s3; 
77           int delay = 100; 
78           int delay3 = 1000; 
79           double[] doubleData = getDoubleArray(); 
80           for (int i = 0; i < doubleData.length; i++) { 
81               s1 = doubleData[i]; 
82               s2 = 0; 
83               s3 = 0; 
84               if (i > delay) { 
85                   s2 = doubleData[i - delay]; 
86               } 
87               if (i > delay3) { 
88                   s3 = doubleData[i - delay3]; 
89               } 
90               doubleData[i] = (s3 + s2 + s1) / 3; 
91           } 
92           play(); 
93       } 
94    
95       public UlawCodec(byte ulawArrayOfByte[]) { 
96           ulawData = ulawArrayOfByte; 
97       } 
98    
99       /** 
100       * Open the <code>fileName</code> and read in the data 
101       * as if it were u-law encoded. Then turn it into linear 
102       * PCM data. 
103       * 
104       * @param fileName 
105       */ 
106      public void readAUFile(String fileName) { 
107          // force recomputation 
108          // of the doubleArray, as it is invalid 
109          doubleArray = null; 
110          try { 
111              readUlawDataFromAFile(fileName); 
112          } catch (Exception e) { 
113              e.printStackTrace(); 
114          } 
115      } 
116   
117      public static void main(String args[]) { 
118          //playFromFile(); 
119          //playAuFiles(getAuFiles()); 
120          //showSampleData(); 
121          UlawCodec ulc = new UlawCodec(); 
122          ulc.play(); 
123          ulc.echo(); 
124      } 
125   
126      private void readUlawDataFromAFile(String fileName) throws IOException { 
127          FileInputStream fis = new FileInputStream(fileName); 
128          ulawData = readData(fis); 
129          fis.close(); 
130      } 
131   
132      /** 
133       * Reads in all the data at once, from any inputstream. 
134       * Remember to close the InputStream when you are done. 
135       * 
136       * @param is 
137       * @return Array of data 
138       * @throws IOException 
139       */ 
140      public static byte[] readData(InputStream is) throws IOException { 
141          AudioStream as = new AudioStream(is); 
142          // AudioStream constructor 
143          // expects data stream from AU file as input 
144          int length = as.getLength(); 
145          if (length < 0) return null; 
146          byte b[] = new byte[length]; 
147          as.read(b, 0, length); 
148          return b; 
149      } 
150   
151      public static File[] getAuFiles() { 
152          FileList fl = new FileList(); 
153          File f = 
154                  Futil.getReadDirFile("select a start file"); 
155          WildFilter wf = new WildFilter(".au"); 
156          fl.list(f, wf); 
157          fl.print(); // todo will delete this later.... 
158          return fl.getFiles(); 
159      } 
160   
161      public static void playAuFiles(File f[]) { 
162          for (int i = 0; i < f.length; i++) { 
163              UlawCodec ulc = new UlawCodec(f[i].toString()); 
164              ulc.run(); 
165          } 
166      } 
167   
168      public UlawCodec() { 
169          readAUFile(Futil.getReadFileName("select an au file")); 
170      } 
171   
172      /** 
173       * Input a fully qualified file name 
174       * use the play method to hear it. 
175       * 
176       * @param _fn 
177       */ 
178      public UlawCodec(String _fn) { 
179          String fileName = _fn; 
180          readAUFile(fileName); 
181      } 
182   
183      public UlawCodec(URL _url) { 
184          try { 
185              readAU(_url); 
186          } catch (Exception e) { 
187          } 
188      } 
189   
190  // --------------------------------------------------------------- 
191  // 
192  // public UlawCodec(short linearData[]); 
193  // 
194  // This constructor can be used to produce u-law encoded ip.audio 
195  // samples from an linerly encoded array of 16 bit signed integers 
196  // 
197  // --------------------------------------------------------------- 
198   
199      public UlawCodec(short linearArrayOfShort[]) { 
200          ulawData = 
201                  new byte[linearArrayOfShort.length]; 
202          int max = 0; 
203          int sample, sign, exponent, mantissa; 
204   
205          // now we need to find the sample of maximal amplitude 
206          // then we can scale the data in such a way that the biggest 
207          // sample will be 0x7FFF (max signed short) 
208          for (int i = 0; i < 
209                  linearArrayOfShort.length; i++) 
210              if (Math.abs(linearArrayOfShort[i]) > 
211                      max) 
212                  max = Math.abs(linearArrayOfShort[i]); 
213          float factor = (float) 0x7FFF / max; 
214          for (int i = 0; i < 
215                  linearArrayOfShort.length; i++) { 
216              sample = (int) (linearArrayOfShort[i] * factor); 
217   
218              // lets calculate sign of the sample and its absolute value 
219   
220              sign = (sample >> 8) & 0x80; 
221              if (sign != 0) sample = -sample; 
222   
223              // adding bias 
224   
225              sample = sample + 0x84; 
226   
227              // now the tricky part: quick logarithmic transform, so that smaller samples 
228   
229              // will be larger and larger samples smaller 
230   
231              exponent = 
232                      exp_lut[(sample >> 7) & 0xFF]; 
233              mantissa = (sample >> (exponent + 3)) & 
234                      0x0F; 
235   
236              // lets pack it into one byte 
237   
238              ulawData[i] = 
239                      (byte) ~(sign | (exponent << 4) | 
240                      mantissa); 
241          } 
242      } 
243   
244   
245   
246  // --------------------------------------------------------------- 
247  // 
248  // public UlawCodec(double linearData[]); 
249  // 
250  // This constructor can be used to produce u-law encoded ip.audio 
251  // samples from an linerly encoded array of 64 bit signed signed 
252  // floating point numbers ranged from -1 to 1 
253  // 
254  // --------------------------------------------------------------- 
255   
256      public UlawCodec(double linearArrayOfDouble[]) { 
257          int sample, sign, exponent, mantissa; 
258          ulawData = 
259                  new byte[linearArrayOfDouble.length]; 
260   
261          // this metod is quite similar to UlawCodec(short linearData[]) 
262          //  with exception that no scaling is done, the input is assumed 
263          //  be in the appropriate range. What if it is not? ... crash and burn 
264   
265          for (int i = 0; i < 
266                  linearArrayOfDouble.length; i++) { 
267              sample = 
268                      (int) (linearArrayOfDouble[i] * 
269                      0x7FFF); 
270              sign = (sample >> 8) & 0x80; 
271              if (sign != 0) sample = -sample; 
272              sample = sample + 0x84; 
273              exponent = 
274                      exp_lut[(sample >> 7) & 0xFF]; 
275              mantissa = (sample >> (exponent + 3)) & 
276                      0x0F; 
277              ulawData[i] = 
278                      (byte) ~(sign | (exponent << 4) | 
279                      mantissa); 
280          } 
281      } 
282   
283      public void readAU(URL url) 
284              throws IOException { 
285          InputStream is = 
286                  getInputStream(url); 
287          readAU(is); 
288      } 
289   
290      public InputStream getInputStream(URL url) { 
291          InputStream is = null; 
292          try { 
293              url.openConnection(); 
294              is = url.openStream(); 
295          } catch (MalformedURLException e) { 
296              e.printStackTrace(); 
297          } catch (IOException e) { 
298              e.printStackTrace(); 
299          } 
300          return is; 
301      } 
302   
303      public void readAU(InputStream is) 
304              throws IOException { 
305          AudioStream audioStream = 
306                  new AudioStream(is); 
307          ulawData = 
308                  new byte[audioStream.getLength()]; 
309          audioStream.read(ulawData, 
310                  0, 
311                  audioStream.getLength()); 
312      } 
313   
314      public void readAUFile() { 
315          String fileName = 
316                  Futil.getReadFileName("Select an au file"); 
317          readAUFile(fileName); 
318      } 
319   
320      public void writeAUFile() { 
321          String fileName = 
322                  Futil.getWriteFile("select an au file").toString(); 
323          writeAUFile(fileName); 
324      } 
325   
326   
327   
328  // --------------------------------------------------------------- 
329   
330  // 
331   
332  // public void writeAUFile(String name); 
333   
334  // 
335   
336  // This method saves the ip.audio data stored in this object into 
337   
338  // an AU file. 
339   
340  // 
341   
342  // --------------------------------------------------------------- 
343   
344      public void writeAUFile(String fileName) { 
345          try { 
346              FileOutputStream fos = new FileOutputStream(fileName); 
347              DataOutputStream os = new 
348                      DataOutputStream(fos); 
349   
350              // not too much magic about it, just ".snd" ASCII string represented as 
351   
352              //integer 
353   
354              os.writeInt(0x2E736E64); // magic 
355              os.writeInt(0x00000020); // offset of the data 
356              os.writeInt(ulawData.length); // data size 
357   
358              // good old 8 bit per sample u-law encoded data format (code = 1) 
359   
360              os.writeInt(0x00000001); // format code 
361              os.writeInt(0x00001F40); // sampling rate 
362              os.writeInt(0x00000001); // channel count 
363              os.writeInt(0x00000000); // reserved 
364              os.writeInt(0x00000000); // reserved 
365              os.write(ulawData, 
366                      0, 
367                      ulawData.length); 
368              fos.close(); 
369          } catch (Exception e) { 
370              System.out.println(e); 
371          } 
372      } 
373   
374      public void run() { 
375          try { 
376              stop(); 
377              AudioData audioData = new AudioData(ulawData); 
378              audioDataStream = 
379                      new AudioDataStream(audioData); 
380              AudioPlayer.player.start(audioDataStream); 
381              Thread.sleep(ulawData.length / 8 + 100); 
382          } catch (Exception e) { 
383          } 
384      } 
385   
386      public void play() { 
387          stop(); 
388          if (ulawData == null) return; 
389          AudioData audioData = 
390                  new AudioData(ulawData); 
391          audioDataStream = new AudioDataStream(audioData); 
392          AudioPlayer.player.start(audioDataStream); 
393      } 
394   
395      private boolean isPlaying() { 
396          return audioDataStream != null; 
397      } 
398   
399      public void stop() { 
400          if (isPlaying()) { 
401              AudioPlayer.player.stop(audioDataStream); 
402              audioDataStream = null; 
403          } 
404      } 
405   
406      public static void playFromFile() { 
407          UlawCodec ulc = new UlawCodec(); 
408          ulc.play(); 
409          //ulc.writeAUFile(); 
410      } 
411   
412      public static void play(URL url) { 
413          UlawCodec ulc = new UlawCodec(url); 
414          ulc.play(); 
415      } 
416   
417      public double getFrequency() { 
418          return 8000 / (2 * getDistanceBetweenMaxAndMinValues()); 
419      } 
420   
421      public void printLocationOfMaxValue() { 
422          System.out.println("found max value at:" + getLocationOfMaxValue()); 
423      } 
424   
425      /** 
426       * Starting at the startPoint, scan the data array for 
427       * the value and return the location in the array. 
428       * If it can't find the value, return -1; 
429       * 
430       * @param value      to scan for 
431       * @param startPoint location for the start point 
432       * @return location or -1 
433       */ 
434      public int getLocation(double value, int startPoint) { 
435          double d[] = getDoubleArray(); 
436          for (int i = startPoint; i < d.length; i++) 
437              if (d[i] == value) 
438                  return i; 
439          return -1; 
440      } 
441   
442      public void printDistanceBetweenMaxAndMinValues() { 
443          System.out.println("getDistanceBetweenMaxAndMinValues=" + 
444                  getDistanceBetweenMaxAndMinValues()); 
445      } 
446   
447      public int getDistanceBetweenMaxAndMinValues() { 
448          return Math.abs(getLocationOfMinValue() - getLocationOfMaxValue()); 
449      } 
450   
451      public int getLocationOfMinValue() { 
452          return getLocation(getMinValue(), 0); 
453      } 
454   
455      public int getLocationOfMaxValue() { 
456          return getLocation(getMaxValue(), 0); 
457      } 
458   
459      public void printMaxData() { 
460          double maxValue = getMaxValue(); 
461          System.out.println("the max value is:" + maxValue); 
462      } 
463   
464      public double getMinValue() { 
465          double d[] = getDoubleArray(); 
466          double v = d[0]; 
467          for (int i = 0; i < d.length; i++) 
468              if (d[i] < v) 
469                  v = d[i]; 
470          return v; 
471      } 
472   
473      public double getMaxValue() { 
474          double d[] = getDoubleArray(); 
475          double maxValue = d[0]; 
476          for (int i = 0; i < d.length; i++) 
477              if (d[i] > maxValue) 
478                  maxValue = d[i]; 
479          return maxValue; 
480      } 
481   
482      public static void showSampleData() { 
483          UlawCodec ulc = new UlawCodec(); 
484          ulc.play(); 
485          OscopePanel osp = new OscopePanel(ulc.getDoubleArray()); 
486          gui.ClosableJFrame cf = new gui.ClosableJFrame(); 
487          Container c = cf.getContentPane(); 
488          c.add(osp); 
489          c.setLayout(new GridLayout(1, 0)); 
490          cf.setSize(400, 400); 
491          cf.show(); 
492      } 
493   
494      public void displayInternalData() { 
495          play(); 
496          OscopePanel osp = new OscopePanel(getDoubleArray()); 
497          gui.ClosableJFrame cf = new gui.ClosableJFrame(); 
498          Container c = cf.getContentPane(); 
499          c.add(osp); 
500          c.setLayout(new GridLayout(1, 0)); 
501          cf.setSize(400, 400); 
502          cf.show(); 
503      } 
504   
505      public static void printSampleData() { 
506          UlawCodec ulc = new UlawCodec(); 
507          ulc.play(); 
508          double d[] = ulc.getDoubleArray(); 
509          for (int i = 0; i < d.length; i++) { 
510              int q = (int) (100 * d[i]); 
511              System.out.print(q + " "); 
512              if (i % 10 == 0) 
513                  System.out.println(); 
514          } 
515      } 
516   
517      public byte[] getUlawData() { 
518          return ulawData; 
519      } 
520   
521      public void setUlawData(byte ulawArrayOfByte[]) { 
522          ulawData = ulawArrayOfByte; 
523          // force recomputation of the doubleArray 
524          doubleArray = null; 
525      } 
526   
527      public double[] getDoubleArray() { 
528          if (doubleArray == null) 
529              doubleArray = computeDoubleArray(); 
530          return doubleArray; 
531      } 
532   
533      // out = decodeUlaw(in) 
534   
535      private double[] computeDoubleArray() { 
536          double[] out = new double[ulawData.length]; 
537          for (int i = 0; i < ulawData.length; i++) { 
538              out[i] = 
539                      Ulaw.ulawToDouble(ulawData[i]); 
540          } 
541          return out; 
542      } 
543   
544      public int getLength() { 
545          return ulawData.length; 
546      } 
547   
548      public double getDuration() { 
549          // Assume 8,000 samples per second 
550          // then 
551          // number_samples / 8,000 = number of seconds. 
552          return ulawData.length / samplingRate; 
553      } 
554   
555      public void reverseUlaw() { 
556          int l = ulawData.length; 
557          int i; 
558          byte tmp; 
559          for (i = 0; i < l / 2; i++) { 
560              tmp = ulawData[i]; 
561              ulawData[i] = ulawData[l - i - 1]; 
562              ulawData[l - i - 1] = tmp; 
563          } 
564          doubleArray = null; 
565      } 
566  }