samer@0
|
1 /*
|
samer@0
|
2 * StreamSource.java
|
samer@0
|
3 *
|
samer@0
|
4 * Copyright (c) 2012, Samer Abdallah, King's College London.
|
samer@0
|
5 * All rights reserved.
|
samer@0
|
6 *
|
samer@0
|
7 * This software is provided AS iS and WITHOUT ANY WARRANTY;
|
samer@0
|
8 * without even the implied warranty of MERCHANTABILITY or
|
samer@0
|
9 * FITNESS FOR A PARTICULAR PURPOSE.
|
samer@0
|
10 */
|
samer@0
|
11
|
samer@46
|
12 package ishara.audio;
|
samer@0
|
13 import javax.sound.sampled.*;
|
samer@0
|
14 import java.io.*;
|
samer@0
|
15
|
samer@0
|
16 public class StreamSource extends AudioSource
|
samer@0
|
17 {
|
samer@0
|
18 InputStream in;
|
samer@0
|
19
|
samer@0
|
20 public StreamSource(AudioInputStream ain) throws Exception { super(ain.getFormat()); in=ain; }
|
samer@0
|
21 public StreamSource(AudioInputStream ain, AudioFormat target) throws Exception {
|
samer@0
|
22 this(prepareStream(ain,target));
|
samer@0
|
23 }
|
samer@0
|
24
|
samer@0
|
25 // AudioSource interface methods
|
samer@0
|
26 public void dispose() {
|
samer@0
|
27 print("Closing audio stream...");
|
samer@0
|
28 try { in.close(); } catch (IOException ex) {}
|
samer@0
|
29 }
|
samer@0
|
30
|
samer@0
|
31 public void start() {}
|
samer@0
|
32 public void stop() {}
|
samer@0
|
33 public int read(byte [] buf, int off, int len) throws Exception {
|
samer@0
|
34 return in.read(buf,off,len);
|
samer@0
|
35 }
|
samer@0
|
36
|
samer@0
|
37 public static AudioInputStream prepareStream(AudioInputStream ain, AudioFormat target) throws Exception {
|
samer@0
|
38 // convert to target format if required
|
samer@0
|
39 print("Preparing audio stream...");
|
samer@0
|
40 print(" / audio format: "+ain.getFormat().toString());
|
samer@0
|
41 if (target==null) {
|
samer@0
|
42 AudioFormat fin=ain.getFormat();
|
samer@0
|
43 ain=convertFormat(new AudioFormat( fin.getSampleRate(), 16, fin.getChannels(), true, false), ain);
|
samer@0
|
44 } else {
|
samer@0
|
45 ain=convertFormat(target, ain);
|
samer@0
|
46 }
|
samer@0
|
47 print(" \\ final format: "+ain.getFormat().toString());
|
samer@0
|
48 return ain;
|
samer@0
|
49 }
|
samer@0
|
50
|
samer@0
|
51 private static AudioInputStream convertVia(AudioFormat fout, AudioInputStream sin, AudioFormat fint) throws Exception
|
samer@0
|
52 {
|
samer@0
|
53 print(" | Trying recursive via "+fint.toString());
|
samer@0
|
54 AudioInputStream sint=AudioSystem.getAudioInputStream(fint,sin);
|
samer@0
|
55 AudioFormat fres=sint.getFormat();
|
samer@0
|
56 if (!fres.equals(fint)) {
|
samer@0
|
57 print(" | obtained "+fres.toString());
|
samer@0
|
58 }
|
samer@0
|
59 return convertFormat(fout, sint);
|
samer@0
|
60 }
|
samer@0
|
61
|
samer@0
|
62 public static AudioInputStream convertFormat(AudioFormat fout, AudioInputStream sin) throws Exception
|
samer@0
|
63 {
|
samer@0
|
64 AudioFormat fin=sin.getFormat();
|
samer@0
|
65
|
samer@0
|
66 if (fin.equals(fout)) return sin;
|
samer@0
|
67 if (fin.getEncoding()!=AudioFormat.Encoding.PCM_SIGNED) {
|
samer@0
|
68 if (fin.getEncoding().getClass().getName().startsWith("javazoom.spi.")) {
|
samer@0
|
69 // these are broken, must go via 16 bit decode with no channels change
|
samer@0
|
70 print(" ! Detected noncompliant Javazoom decoder, going via 16 bit.");
|
samer@0
|
71 return convertVia( fout, sin, new AudioFormat(
|
samer@0
|
72 fin.getSampleRate(), 16, fin.getChannels(), true, fout.isBigEndian()));
|
samer@0
|
73 }
|
samer@0
|
74
|
samer@0
|
75 // first get into PCM encoding, then try recursive
|
samer@0
|
76 try {
|
samer@0
|
77 return convertVia( fout, sin, new AudioFormat(
|
samer@0
|
78 fin.getSampleRate(), fout.getSampleSizeInBits(),
|
samer@0
|
79 fin.getChannels(), true, fout.isBigEndian()));
|
samer@0
|
80 } catch (IllegalArgumentException ex) {
|
samer@0
|
81 print(" * Direct conversion failed");
|
samer@0
|
82 }
|
samer@0
|
83 return convertVia( fout, sin, new AudioFormat(
|
samer@0
|
84 fin.getSampleRate(), fin.getSampleSizeInBits(),
|
samer@0
|
85 fin.getChannels(), true, fout.isBigEndian()));
|
samer@0
|
86 }
|
samer@0
|
87
|
samer@0
|
88 if ( !unify(fin.getChannels(),fout.getChannels())
|
samer@0
|
89 || !unify(fin.getSampleSizeInBits(),fout.getSampleSizeInBits())) {
|
samer@0
|
90 // convert these before doing any sample rate conversion
|
samer@0
|
91 return convertVia(fout, sin, new AudioFormat(
|
samer@0
|
92 fin.getSampleRate(), fout.getSampleSizeInBits(),
|
samer@0
|
93 fout.getChannels(), true, fout.isBigEndian()));
|
samer@0
|
94 }
|
samer@0
|
95
|
samer@0
|
96 // the only thing left is sample rate
|
samer@0
|
97 return AudioSystem.getAudioInputStream(fout,sin);
|
samer@0
|
98 }
|
samer@0
|
99
|
samer@0
|
100 private static boolean unify(int x, int y) { return x==-1 || y==-1 || x==y; }
|
samer@0
|
101 private static boolean unify(float x, float y) { return x==-1 || y==-1 || x==y; }
|
samer@0
|
102 }
|
samer@0
|
103
|