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.

// https://github.com/s4l4x/audio-analysis/blob/master/src/com/badlogic/audio/io/WaveDecoder.java

/**
 * A simple class that can read in the PCM data from a
 * Wav file, converting the data to signed 32-bit floats
 * in the range [-1,1], merging stereo channels to a mono
 * channel for processing. This only supports 16-bit signed
 * stereo and mono Wav files with a sampling rate of 44100.
 * 
 * @author mzechner
 *
 */
sclass WAVDecoder /*implements com.badlogic.audio.io.Decoder*/ implements AutoCloseable {
  /** the input stream we read from **/
  EndianDataInputStream in;
  
  /** number of channels **/
  int channels;
  
  /** sample rate in Herz**/
  float sampleRate;
  
  bool ignoreSampleRate = true;
  bool twentyFourBit;
  
  // data length in bytes according to header
  int specifiedDataLength;
  
  int remainingDataBytes;
  
  static int defaultBufferSize = 128*1024; //1024*1024
  
  *(File wavFile) {
    this(fileInputStream(wavFile));
  }
  
  *(InputStream stream) ctex {
    in = new EndianDataInputStream( new BufferedInputStream( stream, defaultBufferSize) );
    if( !in.read4ByteString().equals( "RIFF" ) )
      throw new IllegalArgumentException( "not a wav" );
    
    in.readIntLittleEndian();
    
    if( !in.read4ByteString().equals( "WAVE" ) )
      throw new IllegalArgumentException( "expected WAVE tag" );
    
    S s = in.read4ByteString();
    if (eq(s, "bext")) { // skip extension block
      in.skip(in.readIntLittleEndian());
      s = in.read4ByteString();
    }
    
    if (!s.equals("fmt "))
      throw new IllegalArgumentException( "expected fmt tag, got: " + s);
    
    if( in.readIntLittleEndian() != 16 )
      throw new IllegalArgumentException( "expected wave chunk size to be 16" );
    
    int format;
    if ((format = in.readShortLittleEndian()) != 1)
      throw new IllegalArgumentException( "expected format to be 1, got: " + format);
    
    channels = in.readShortLittleEndian();
    //print("Channels: " + channels);
    sampleRate = in.readIntLittleEndian();
    if (sampleRate != 44100)
      if (ignoreSampleRate) {
        // print("Sample rate: " + sampleRate);
      } else
        fail("Not 44100 sampling rate: " + sampleRate);
    in.readIntLittleEndian();
    in.readShortLittleEndian();
    int fmt = in.readShortLittleEndian();

    if (fmt == 24) twentyFourBit = true;
    else if (fmt != 16)
      fail("Only 16/24-bit samples supported: " + fmt);
    
    S tag;
    while (!(tag = in.read4ByteString()).equals("data")) {
      //print("Skipping tag " + tag);
      //fail( "expected data tag, got: " + tag);
      int len = in.readIntLittleEndian();
      in.skip(len);
    }
        
    remainingDataBytes = specifiedDataLength = in.readIntLittleEndian();
  }
  
  /**
   * Tries to read in samples.length samples, merging stereo to a mono
   * channel by averaging and converting non float formats to float 32-bit.
   * Returns the number of samples actually read. Guarantees that samples.length
   * samples are read in if there was enough data in the stream.
   * 
   * @param samples The samples array to write the samples to
   * @return The number of samples actually read.
   */
  public int readMonoSamples(short[] samples, int n default samples.length) {
    int readSamples = 0;
    for (int i = 0; i < n && remainingDataBytes > 0; i++) {
      double sample = 0; 
      try {
        for j to channels:
          sample += readSample();
        sample /= channels;
        samples[i] = (short) iround(max(-32768, min(32767, sample)));
        readSamples++;
      }
      catch (Exception ex) { break; } // ouch
    }
    
    ret readSamples; 
  }
  
  public int readStereoSamples(short[] samples, int n default samples.length) {
    int readSamples = 0;
    for (int i = 0; i < n && remainingDataBytes > 0; i += 2) {
      double sample = 0; 
      try {
        short left = readSample();
        short right;
        if (channels > 1)
          right = readSample();
        else
          right = left;
        samples[i] = left;
        samples[i+1] = right;
        readSamples += 2;
      }
      catch (Exception ex) { break; } // ouch
    }
    
    ret readSamples; 
  }
  
  short readSample() ctex {
    if (twentyFourBit) { --remainingDataBytes; in.read(); }
    remainingDataBytes -= 2;
    ret in.readShortLittleEndian();
  }
  
  int bytesPerValue() { ret twentyFourBit ? 3 : 2; }
  
  int totalValues() { ret specifiedDataLength/bytesPerValue(); }
  
  // skips this number of samples (what is the terminology again
  // for 1 value vs <channels> values)
  public void skipSamples(long samples) ctex {
    long bytesToSkip = samples*channels*bytesPerValue();
    remainingDataBytes -= bytesToSkip;
    in.skip(bytesToSkip);
  }
  
  public void close() ctex { in.close(); }
}

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: 521 / 1165
Version history: 35 change(s)
Referenced in: [show references]