Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

156
LINES

< > BotCompany Repo | #1016681 // WAVDecoder

JavaX fragment (include) [tags: use-pretranspiled]

Transpiled version (4118L) is out of date.

1  
// https://github.com/s4l4x/audio-analysis/blob/master/src/com/badlogic/audio/io/WaveDecoder.java
2  
3  
/**
4  
 * A simple class that can read in the PCM data from a
5  
 * Wav file, converting the data to signed 32-bit floats
6  
 * in the range [-1,1], merging stereo channels to a mono
7  
 * channel for processing. This only supports 16-bit signed
8  
 * stereo and mono Wav files with a sampling rate of 44100.
9  
 * 
10  
 * @author mzechner
11  
 *
12  
 */
13  
sclass WAVDecoder /*implements com.badlogic.audio.io.Decoder*/ implements AutoCloseable {
14  
  /** the input stream we read from **/
15  
  EndianDataInputStream in;
16  
  
17  
  /** number of channels **/
18  
  int channels;
19  
  
20  
  /** sample rate in Herz**/
21  
  float sampleRate;
22  
  
23  
  bool ignoreSampleRate = true;
24  
  bool twentyFourBit;
25  
  
26  
  // data length in bytes according to header
27  
  int specifiedDataLength;
28  
  
29  
  int remainingDataBytes;
30  
  
31  
  static int defaultBufferSize = 128*1024; //1024*1024
32  
  
33  
  *(File wavFile) {
34  
    this(fileInputStream(wavFile));
35  
  }
36  
  
37  
  *(InputStream stream) ctex {
38  
    in = new EndianDataInputStream( new BufferedInputStream( stream, defaultBufferSize) );
39  
    if( !in.read4ByteString().equals( "RIFF" ) )
40  
      throw new IllegalArgumentException( "not a wav" );
41  
    
42  
    in.readIntLittleEndian();
43  
    
44  
    if( !in.read4ByteString().equals( "WAVE" ) )
45  
      throw new IllegalArgumentException( "expected WAVE tag" );
46  
    
47  
    S s = in.read4ByteString();
48  
    if (eq(s, "bext")) { // skip extension block
49  
      in.skip(in.readIntLittleEndian());
50  
      s = in.read4ByteString();
51  
    }
52  
    
53  
    if (!s.equals("fmt "))
54  
      throw new IllegalArgumentException( "expected fmt tag, got: " + s);
55  
    
56  
    if( in.readIntLittleEndian() != 16 )
57  
      throw new IllegalArgumentException( "expected wave chunk size to be 16" );
58  
    
59  
    int format;
60  
    if ((format = in.readShortLittleEndian()) != 1)
61  
      throw new IllegalArgumentException( "expected format to be 1, got: " + format);
62  
    
63  
    channels = in.readShortLittleEndian();
64  
    //print("Channels: " + channels);
65  
    sampleRate = in.readIntLittleEndian();
66  
    if (sampleRate != 44100)
67  
      if (ignoreSampleRate) {
68  
        // print("Sample rate: " + sampleRate);
69  
      } else
70  
        fail("Not 44100 sampling rate: " + sampleRate);
71  
    in.readIntLittleEndian();
72  
    in.readShortLittleEndian();
73  
    int fmt = in.readShortLittleEndian();
74  
75  
    if (fmt == 24) twentyFourBit = true;
76  
    else if (fmt != 16)
77  
      fail("Only 16/24-bit samples supported: " + fmt);
78  
    
79  
    S tag;
80  
    while (!(tag = in.read4ByteString()).equals("data")) {
81  
      //print("Skipping tag " + tag);
82  
      //fail( "expected data tag, got: " + tag);
83  
      int len = in.readIntLittleEndian();
84  
      in.skip(len);
85  
    }
86  
        
87  
    remainingDataBytes = specifiedDataLength = in.readIntLittleEndian();
88  
  }
89  
  
90  
  /**
91  
   * Tries to read in samples.length samples, merging stereo to a mono
92  
   * channel by averaging and converting non float formats to float 32-bit.
93  
   * Returns the number of samples actually read. Guarantees that samples.length
94  
   * samples are read in if there was enough data in the stream.
95  
   * 
96  
   * @param samples The samples array to write the samples to
97  
   * @return The number of samples actually read.
98  
   */
99  
  public int readMonoSamples(short[] samples, int n default samples.length) {
100  
    int readSamples = 0;
101  
    for (int i = 0; i < n && remainingDataBytes > 0; i++) {
102  
      double sample = 0; 
103  
      try {
104  
        for j to channels:
105  
          sample += readSample();
106  
        sample /= channels;
107  
        samples[i] = (short) iround(max(-32768, min(32767, sample)));
108  
        readSamples++;
109  
      }
110  
      catch (Exception ex) { break; } // ouch
111  
    }
112  
    
113  
    ret readSamples; 
114  
  }
115  
  
116  
  public int readStereoSamples(short[] samples, int n default samples.length) {
117  
    int readSamples = 0;
118  
    for (int i = 0; i < n && remainingDataBytes > 0; i += 2) {
119  
      double sample = 0; 
120  
      try {
121  
        short left = readSample();
122  
        short right;
123  
        if (channels > 1)
124  
          right = readSample();
125  
        else
126  
          right = left;
127  
        samples[i] = left;
128  
        samples[i+1] = right;
129  
        readSamples += 2;
130  
      }
131  
      catch (Exception ex) { break; } // ouch
132  
    }
133  
    
134  
    ret readSamples; 
135  
  }
136  
  
137  
  short readSample() ctex {
138  
    if (twentyFourBit) { --remainingDataBytes; in.read(); }
139  
    remainingDataBytes -= 2;
140  
    ret in.readShortLittleEndian();
141  
  }
142  
  
143  
  int bytesPerValue() { ret twentyFourBit ? 3 : 2; }
144  
  
145  
  int totalValues() { ret specifiedDataLength/bytesPerValue(); }
146  
  
147  
  // skips this number of samples (what is the terminology again
148  
  // for 1 value vs <channels> values)
149  
  public void skipSamples(long samples) ctex {
150  
    long bytesToSkip = samples*channels*bytesPerValue();
151  
    remainingDataBytes -= bytesToSkip;
152  
    in.skip(bytesToSkip);
153  
  }
154  
  
155  
  public void close() ctex { in.close(); }
156  
}

download  show line numbers  debug dex  old transpilations   

Travelled to 16 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, ekrmjmnbrukm, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv

No comments. add comment

Snippet ID: #1016681
Snippet name: WAVDecoder
Eternal ID of this version: #1016681/36
Text MD5: 9995b9fd715a983c92ae1388a30c1600
Author: stefan
Category: javax / sound
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-10-17 19:15:36
Source code size: 4956 bytes / 156 lines
Pitched / IR pitched: No / No
Views / Downloads: 522 / 1167
Version history: 35 change(s)
Referenced in: [show references]