Created
December 26, 2013 16:02
-
-
Save nicolamontecchio/8135423 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.nicolamontecchio.chroma; | |
import java.io.*; | |
import javax.sound.sampled.*; | |
/** | |
* Read an audio file. Provided that the appropriate packages are in the classpath, mp3 and ogg should be readable too. The safest route is to read from a MONO, WAV file. | |
*/ | |
public class AudioReader { | |
private AudioInputStream signedBigEndianInputStream = null; | |
private AudioInputStream originalAudioInputStream = null; | |
public AudioReader(File inputfile) throws UnsupportedAudioFileException, IOException { | |
originalAudioInputStream = AudioSystem.getAudioInputStream(inputfile); | |
AudioFormat destaf = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, | |
originalAudioInputStream.getFormat().getSampleRate(), | |
16, originalAudioInputStream.getFormat().getChannels(), | |
16 / 8 * originalAudioInputStream.getFormat().getChannels(), | |
originalAudioInputStream.getFormat().getSampleRate(), true); | |
signedBigEndianInputStream = AudioSystem.getAudioInputStream(destaf, originalAudioInputStream); | |
} | |
/** | |
* Read next n samples (at most) from file (convert automatically to MONO). Return as double[]. | |
*/ | |
public double[] readDoubleSamples(int n) throws IOException { | |
int channels = signedBigEndianInputStream.getFormat().getChannels(); | |
int ss = signedBigEndianInputStream.getFormat().getSampleSizeInBits(); | |
int ssB = ss / 8; // in bytes | |
// System.out.println(String.format("fl: %d, ss: %d, ssB: %d, samplerate: %f", | |
// fl, ss, ssB, signedBigEndianInputStream.getFormat().getSampleRate())); | |
byte[] b = new byte[n * channels * ssB]; | |
int read = signedBigEndianInputStream.read(b); | |
double[] res = new double[read / ssB / channels]; | |
for (int i = 0; i < res.length; i++) | |
res[i] = 0; | |
for (int i = 0; i < res.length * channels; i++) { | |
double val = 0; | |
switch (ss) { | |
case 8: | |
val = ((b[i * ssB] & 0xFF) - 128) / 128.0; | |
break; | |
case 16: | |
val = ((b[i * ssB + 0] << 8) | (b[i * ssB + 1] & 0xFF)) / 32768.0; | |
break; | |
case 24: | |
val = ((b[i * ssB + 0] << 16) | ((b[i * ssB + 1] & 0xFF) << 8) | |
| (b[i * ssB + 2] & 0xFF)) / 8388606.0; | |
break; | |
case 32: | |
val = ((b[i * ssB + 0] << 24) | ((b[i * ssB + 1] & 0xFF) << 16) | |
| ((b[i * ssB + 2] & 0xFF) << 8) | (b[i * ssB + 3] & 0xFF)) / 2147483648.0; | |
break; | |
} | |
res[i/channels] += val / channels; | |
} | |
return res; | |
} | |
public float getSampleRate() { | |
return signedBigEndianInputStream.getFormat().getSampleRate(); | |
} | |
public void close() throws IOException { | |
signedBigEndianInputStream.close(); | |
originalAudioInputStream.close(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello,
if its not too much too ask, can u please give a working demo(through driver class)?
Like i am confused what to pass (samples per second or total samples in whole audio) as 'n' in readDoubleSamples.
PS. I am a noob.