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).

1  
// derived from org.gagravarr.opus.OpusFile
2  
/*
3  
 * Licensed under the Apache License, Version 2.0 (the "License");
4  
 * you may not use this file except in compliance with the License.
5  
 * You may obtain a copy of the License at
6  
 *
7  
 *     http://www.apache.org/licenses/LICENSE-2.0
8  
 *
9  
 * Unless required by applicable law or agreed to in writing, software
10  
 * distributed under the License is distributed on an "AS IS" BASIS,
11  
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  
 * See the License for the specific language governing permissions and
13  
 * limitations under the License.
14  
 */
15  
 
16  
lib 1400511 // VorbisJava (to unpack ogg file)
17  
lib 1400502 // Concentus 1.0 (to decode OPUS audio in ogg file)
18  
19  
import org.gagravarr.ogg.*;
20  
import org.gagravarr.ogg.audio.*;
21  
import org.gagravarr.opus.*;
22  
import static org.gagravarr.ogg.OggStreamIdentifier.OggStreamType;
23  
import org.concentus.*;
24  
25  
sclass OpusFromStream implements OggAudioStream, OggAudioHeaders, Closeable {
26  
  InputStream in;
27  
  OggStreamPacketReader r;
28  
  int sid = -1;
29  
  int channels;
30  
  OpusDecoder decoder;
31  
  bool printResets;
32  
33  
  OpusInfo info;
34  
  OpusTags tags;
35  
36  
  // channels = 1 or 2 (mono/stereo)
37  
  *(InputStream *in, int *channels) throws IOException, OpusException {
38  
    decoder = new OpusDecoder(48000, channels);
39  
    r = new OggStreamPacketReader(in);
40  
  }
41  
  
42  
  bool initialized() { ret tags != null; }
43  
  
44  
  bool initStep() throws IOException {
45  
    OggPacket p = null;
46  
    
47  
    // find first packet (info)
48  
    
49  
    if (sid < 0) {
50  
      while ((p = getNextPacket()) != null) {
51  
        if (p.isBeginningOfStream() && p.getData().length > 10) {
52  
          if (OpusPacketFactory.isOpusStream(p)) {
53  
            sid = p.getSid();
54  
            info = (OpusInfo) OpusPacketFactory.create(p);
55  
            ifdef OpusFromStream_debug
56  
              printVars OpusFromStream(+sid, +info);
57  
            endifdef
58  
            break;
59  
          }
60  
        }
61  
      }
62  
    }
63  
    
64  
    // find second packet (tags)
65  
    
66  
    if (tags == null) {  
67  
      if ((p = getNextPacketWithSid(sid)) != null) {
68  
        tags = (OpusTags) OpusPacketFactory.create(p);
69  
        ifdef OpusFromStream_debug
70  
          printVars OpusFromStream(+tags);
71  
        endifdef
72  
      }
73  
    }
74  
    
75  
    ret initialized();
76  
  }
77  
78  
  public OpusAudioData getNextAudioPacket() throws IOException {
79  
    if (!initStep()) null;
80  
    
81  
    OggPacket p = null;
82  
    OpusPacket op = null;
83  
    while ((p = getNextPacketWithSid(sid)) != null) {
84  
      op = OpusPacketFactory.create(p);
85  
      if (op cast OpusAudioData) ret op;
86  
      else
87  
        warn("Skipping non audio packet " + op + " mid audio stream");
88  
    }
89  
    null;
90  
  }
91  
92  
  /**
93  
   * Returns the Ogg Stream ID
94  
   */
95  
  public int getSid() {
96  
    ret sid;
97  
  }
98  
99  
  /**
100  
   * This is an Opus file
101  
   */
102  
  public OggStreamType getType() {
103  
    ret OggStreamIdentifier.OPUS_AUDIO;
104  
  }
105  
106  
  public OpusInfo getInfo() {
107  
    return info;
108  
  }
109  
  
110  
  public OpusTags getTags() {
111  
    return tags;
112  
  }
113  
  
114  
  public void skipToGranule(long granulePosition) throws IOException {
115  
    unimplemented();
116  
  }
117  
  
118  
  /**
119  
   * Opus doesn't have setup headers, so this is always null
120  
   */
121  
  public OggAudioSetupHeader getSetup() {
122  
    null;
123  
  }
124  
125  
  close {
126  
    dispose r;
127  
    dispose in;
128  
  }
129  
130  
  // return some audio samples. null if none available
131  
  short[] nextSamples aka moreSamples() throws OpusException, IOException {
132  
    OpusAudioData data;
133  
    while ((data = getNextAudioPacket()) != null) {
134  
      byte[] bytes = data.getData();
135  
      if (empty(bytes)) continue;
136  
137  
      // decode packet
138  
      short[] pcm = new[5760*channels]; // max opus frame size
139  
      int nSamples = decoder.decode(bytes, 0, l(bytes), pcm, 0, l(pcm), false);
140  
      ret subShortArray(pcm, 0, nSamples);
141  
    }
142  
    null;
143  
  }
144  
  
145  
  public OggPacket getNextPacket() throws IOException {
146  
    in.mark(65536);
147  
    OggPacket p;
148  
    try {
149  
      p = r.getNextPacket();
150  
      //if (p != null && printResets) print("OpusFromStream: Got packet");
151  
    } catch (EOFException e) {
152  
      if (printResets) print("OpusFromStream: EOFException, resetting");
153  
      ifdef OpusFromStream_debug
154  
        print("OpusFromStream: EOFException, resetting");
155  
      endifdef
156  
      in.reset();
157  
      null;
158  
    }
159  
    
160  
    if (p == null) {
161  
      if (printResets) print("OpusFromStream: packet null, resetting");
162  
      ifdef OpusFromStream_debug
163  
        print("OpusFromStream: packet null, resetting");
164  
      endifdef
165  
      in.reset();
166  
    }
167  
    ifdef OpusFromStream_debug
168  
      printVars OpusFromStream(packet := p, +in);
169  
    endifdef
170  
    ret p;
171  
  }
172  
  
173  
  /**
174  
     * Returns the next packet with the given SID (Stream ID), or
175  
     *  null if no more packets remain.
176  
     * Any packets from other streams will be silently discarded.
177  
     */
178  
  public OggPacket getNextPacketWithSid(int sid) throws IOException {
179  
    OggPacket p = null;
180  
    while ((p = getNextPacket()) != null) {
181  
      if (p.getSid() == sid) ret p;
182  
    }
183  
    null;
184  
  }
185  
  
186  
  // e.g. for mark/reset
187  
  static int bufferSizeNeeded() { ret 65536; }
188  
}

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: 187 / 374
Version history: 37 change(s)
Referenced in: [show references]