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

188
LINES

< > BotCompany Repo | #1032905 // OpusFromStream

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

Uses 521K of libraries. Click here for Pure Java version (6402L/38K).

// derived from org.gagravarr.opus.OpusFile
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
lib 1400511 // VorbisJava (to unpack ogg file)
lib 1400502 // Concentus 1.0 (to decode OPUS audio in ogg file)

import org.gagravarr.ogg.*;
import org.gagravarr.ogg.audio.*;
import org.gagravarr.opus.*;
import static org.gagravarr.ogg.OggStreamIdentifier.OggStreamType;
import org.concentus.*;

sclass OpusFromStream implements OggAudioStream, OggAudioHeaders, Closeable {
  InputStream in;
  OggStreamPacketReader r;
  int sid = -1;
  int channels;
  OpusDecoder decoder;
  bool printResets;

  OpusInfo info;
  OpusTags tags;

  // channels = 1 or 2 (mono/stereo)
  *(InputStream *in, int *channels) throws IOException, OpusException {
    decoder = new OpusDecoder(48000, channels);
    r = new OggStreamPacketReader(in);
  }
  
  bool initialized() { ret tags != null; }
  
  bool initStep() throws IOException {
    OggPacket p = null;
    
    // find first packet (info)
    
    if (sid < 0) {
      while ((p = getNextPacket()) != null) {
        if (p.isBeginningOfStream() && p.getData().length > 10) {
          if (OpusPacketFactory.isOpusStream(p)) {
            sid = p.getSid();
            info = (OpusInfo) OpusPacketFactory.create(p);
            ifdef OpusFromStream_debug
              printVars OpusFromStream(+sid, +info);
            endifdef
            break;
          }
        }
      }
    }
    
    // find second packet (tags)
    
    if (tags == null) {  
      if ((p = getNextPacketWithSid(sid)) != null) {
        tags = (OpusTags) OpusPacketFactory.create(p);
        ifdef OpusFromStream_debug
          printVars OpusFromStream(+tags);
        endifdef
      }
    }
    
    ret initialized();
  }

  public OpusAudioData getNextAudioPacket() throws IOException {
    if (!initStep()) null;
    
    OggPacket p = null;
    OpusPacket op = null;
    while ((p = getNextPacketWithSid(sid)) != null) {
      op = OpusPacketFactory.create(p);
      if (op cast OpusAudioData) ret op;
      else
        warn("Skipping non audio packet " + op + " mid audio stream");
    }
    null;
  }

  /**
   * Returns the Ogg Stream ID
   */
  public int getSid() {
    ret sid;
  }

  /**
   * This is an Opus file
   */
  public OggStreamType getType() {
    ret OggStreamIdentifier.OPUS_AUDIO;
  }

  public OpusInfo getInfo() {
    return info;
  }
  
  public OpusTags getTags() {
    return tags;
  }
  
  public void skipToGranule(long granulePosition) throws IOException {
    unimplemented();
  }
  
  /**
   * Opus doesn't have setup headers, so this is always null
   */
  public OggAudioSetupHeader getSetup() {
    null;
  }

  close {
    dispose r;
    dispose in;
  }

  // return some audio samples. null if none available
  short[] nextSamples aka moreSamples() throws OpusException, IOException {
    OpusAudioData data;
    while ((data = getNextAudioPacket()) != null) {
      byte[] bytes = data.getData();
      if (empty(bytes)) continue;

      // decode packet
      short[] pcm = new[5760*channels]; // max opus frame size
      int nSamples = decoder.decode(bytes, 0, l(bytes), pcm, 0, l(pcm), false);
      ret subShortArray(pcm, 0, nSamples);
    }
    null;
  }
  
  public OggPacket getNextPacket() throws IOException {
    in.mark(65536);
    OggPacket p;
    try {
      p = r.getNextPacket();
      //if (p != null && printResets) print("OpusFromStream: Got packet");
    } catch (EOFException e) {
      if (printResets) print("OpusFromStream: EOFException, resetting");
      ifdef OpusFromStream_debug
        print("OpusFromStream: EOFException, resetting");
      endifdef
      in.reset();
      null;
    }
    
    if (p == null) {
      if (printResets) print("OpusFromStream: packet null, resetting");
      ifdef OpusFromStream_debug
        print("OpusFromStream: packet null, resetting");
      endifdef
      in.reset();
    }
    ifdef OpusFromStream_debug
      printVars OpusFromStream(packet := p, +in);
    endifdef
    ret p;
  }
  
  /**
     * Returns the next packet with the given SID (Stream ID), or
     *  null if no more packets remain.
     * Any packets from other streams will be silently discarded.
     */
  public OggPacket getNextPacketWithSid(int sid) throws IOException {
    OggPacket p = null;
    while ((p = getNextPacket()) != null) {
      if (p.getSid() == sid) ret p;
    }
    null;
  }
  
  // e.g. for mark/reset
  static int bufferSizeNeeded() { ret 65536; }
}

download  show line numbers  debug dex  old transpilations   

Travelled to 3 computer(s): bhatertpkbcr, mowyntqkapby, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1032905
Snippet name: OpusFromStream
Eternal ID of this version: #1032905/38
Text MD5: 74adb41deb905b85f819d116b7ce5ebc
Transpilation MD5: ed50e99a5140632871d1d80861062fb2
Author: stefan
Category: javax / audio
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-10-11 11:13:07
Source code size: 5166 bytes / 188 lines
Pitched / IR pitched: No / No
Views / Downloads: 274 / 468
Version history: 37 change(s)
Referenced in: #1032917 - OpusFromStream_v2
#1034167 - Standard Classes + Interfaces (LIVE, continuation of #1003674)