|
6 | 6 | import java.util.HashMap; |
7 | 7 | import java.util.Map; |
8 | 8 |
|
| 9 | +import javax.sound.sampled.AudioFormat; |
| 10 | +import javax.sound.sampled.AudioInputStream; |
| 11 | +import javax.sound.sampled.AudioSystem; |
| 12 | +import javax.sound.sampled.UnsupportedAudioFileException; |
| 13 | + |
9 | 14 | import com.jsyn.data.FloatSample; |
10 | 15 | import com.jsyn.util.SampleLoader; |
11 | 16 |
|
12 | | -import fr.delthas.javamp3.Sound; |
13 | 17 | import processing.core.PApplet; |
14 | 18 |
|
15 | 19 | // calls to amp(), pan() etc affect both the LAST initiated and still running sample, AND all subsequently started ones |
@@ -63,40 +67,41 @@ public SoundFile(PApplet parent, String path, boolean cache) { |
63 | 67 | try { |
64 | 68 | // load WAV or AIF using JSyn |
65 | 69 | this.sample = SampleLoader.loadFloatSample(fin); |
66 | | - |
67 | | - // switching to JavaSound decoders is supposed to support 8bit |
68 | | - // unsigned WAV files as well, but doesn't actually seem to be |
69 | | - // the case |
70 | | - //SampleLoader.setJavaSoundPreferred(true); |
71 | | - |
72 | 70 | } catch (IOException e) { |
73 | | - // try parsing as mp3 |
| 71 | + // not wav/aiff -- try converting via JavaSound... |
74 | 72 | try { |
75 | | - // stream as to be re-created, since it was modified in SampleLoader.loadFloatSample() |
76 | | - fin = parent.createInput(path); |
77 | | - Sound mp3 = new Sound(fin); |
78 | | - try { |
79 | | - ByteArrayOutputStream os = new ByteArrayOutputStream(); |
80 | | - // TODO make decoding asynchronous with a FutureTask<FloatSample> |
81 | | - // this call is expensive |
82 | | - mp3.decodeFullyInto(os); |
83 | | - float data[] = new float[os.size() / 2]; |
84 | | - SampleLoader.decodeLittleI16ToF32(os.toByteArray(), 0, os.size(), data, 0); |
85 | | - this.sample = new FloatSample(data, mp3.isStereo() ? 2 : 1); |
86 | | - this.sample.setFrameRate(mp3.getSamplingFrequency()); |
87 | | - } catch (IOException ee) { |
88 | | - throw ee; |
89 | | - } catch (NullPointerException ee) { |
90 | | - throw new IOException(); |
91 | | - } catch (ArrayIndexOutOfBoundsException ee) { |
92 | | - throw new IOException(); |
93 | | - } finally { |
94 | | - mp3.close(); |
| 73 | + // stream was modified by first read attempt, so re-create it |
| 74 | + AudioInputStream in = AudioSystem.getAudioInputStream(parent.createInput(path)); |
| 75 | + // https://docs.oracle.com/javase%2Ftutorial%2F/sound/converters.html |
| 76 | + // https://stackoverflow.com/questions/41784397/convert-mp3-to-wav-in-java |
| 77 | + AudioFormat targetFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, |
| 78 | + in.getFormat().getSampleRate(), 16, // in.getFormat().getSampleSizeInBits(), |
| 79 | + in.getFormat().getChannels(), in.getFormat().getChannels() * 2, |
| 80 | + in.getFormat().getSampleRate(), false); |
| 81 | + // if AudioSystem.isConversionSupported(targetFormat, in.getFormat()) |
| 82 | + // returns false, then this will raise an Exception: |
| 83 | + AudioInputStream converted = AudioSystem.getAudioInputStream(targetFormat, in); |
| 84 | + // decoded mpeg streams don't know their exact output framelength, so |
| 85 | + // no other way than to just decode the whole thing, then allocate the |
| 86 | + // array for it... |
| 87 | + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); |
| 88 | + int nRead; |
| 89 | + byte[] buf = new byte[65536]; |
| 90 | + while ((nRead = converted.read(buf, 0, buf.length)) != -1) { |
| 91 | + buffer.write(buf, 0, nRead); |
95 | 92 | } |
| 93 | + buffer.flush(); |
| 94 | + float data[] = new float[buffer.size() / 2]; |
| 95 | + SampleLoader.decodeLittleI16ToF32(buffer.toByteArray(), 0, buffer.size(), data, 0); |
| 96 | + this.sample = new FloatSample(data, converted.getFormat().getChannels()); |
| 97 | + this.sample.setFrameRate(converted.getFormat().getSampleRate()); |
| 98 | + fin.close(); |
96 | 99 | } catch (IOException ee) { |
97 | 100 | Engine.printError("unable to decode sound file " + path); |
98 | 101 | // return dysfunctional SoundFile object |
99 | 102 | return; |
| 103 | + } catch (UnsupportedAudioFileException ee) { |
| 104 | + throw new RuntimeException(ee); |
100 | 105 | } |
101 | 106 | } |
102 | 107 | if (cache) { |
|
0 commit comments