1+ package org .sela ;
2+
3+ import java .io .File ;
4+ import java .io .IOException ;
5+ import java .util .ArrayList ;
6+ import java .util .List ;
7+
8+ import javax .sound .sampled .AudioFormat ;
9+ import javax .sound .sampled .AudioSystem ;
10+ import javax .sound .sampled .DataLine ;
11+ import javax .sound .sampled .LineUnavailableException ;
12+ import javax .sound .sampled .SourceDataLine ;
13+
14+ import org .sela .data .Progress ;
15+ import org .sela .data .WavFile ;
16+ import org .sela .data .WavFrame ;
17+ import org .sela .exception .FileException ;
18+ import org .sela .utils .ProgressPrinter ;
19+
20+ public class WavPlayer {
21+ private final WavFile wavFile ;
22+ private List <WavFrame > wavFrames ;
23+ private int frameCount ;
24+ private final int samplePerSubFrame = 2048 ;
25+
26+ public WavPlayer (final File inputFile ) throws IOException , FileException {
27+ wavFile = new WavFile (inputFile );
28+ }
29+
30+ private void readSamples () {
31+ final long sampleCount = wavFile .getSampleCount ();
32+ frameCount = (int ) Math .ceil ((double ) sampleCount / (samplePerSubFrame * wavFile .getNumChannels ()));
33+ wavFrames = new ArrayList <>(frameCount );
34+
35+ for (int i = 0 ; i < frameCount ; i ++) {
36+ final int [][] samples = new int [wavFile .getNumChannels ()][samplePerSubFrame ];
37+ wavFile .readFrames (samples , samplePerSubFrame );
38+ wavFrames .add (new WavFrame (i , samples , (byte ) wavFile .getBitsPerSample ()));
39+ }
40+ }
41+
42+ public void play () throws LineUnavailableException , InterruptedException , FileException , IOException {
43+ readSamples ();
44+
45+ // Select audio format parameters
46+ final AudioFormat af = new AudioFormat (wavFile .getSampleRate (), wavFile .getBitsPerSample (),
47+ wavFile .getNumChannels (), true , false );
48+ final DataLine .Info info = new DataLine .Info (SourceDataLine .class , af );
49+ final SourceDataLine line = (SourceDataLine ) AudioSystem .getLine (info );
50+
51+ // Prepare audio output
52+ line .open (af , 2048 * wavFile .getNumChannels ());
53+ line .start ();
54+
55+ // Prepare print thread
56+ final Progress progress = new Progress (wavFrames .size ());
57+ final Thread printThread = new Thread (new ProgressPrinter (progress ));
58+ printThread .start ();
59+
60+ // Output wave form repeatedly
61+ byte bytesPerSample = (byte ) ((byte ) wavFile .getBitsPerSample () / 8 );
62+ for (int i = 0 ; i < wavFrames .size (); i ++) {
63+ final byte [] bytes = wavFrames .get (i ).getDemuxedSamplesInByteArray (bytesPerSample );
64+ line .write (bytes , 0 , bytes .length );
65+ progress .current ++;
66+ }
67+ printThread .join ();
68+ line .drain ();
69+ line .stop ();
70+ line .close ();
71+ }
72+ }
0 commit comments