TanjentOGG

TanjentOGG is a free and open source library to decode .OGG/Vorbis files for C#, Java and HaXe

Download .zip (473 kB) 2015-05-01 (Version 1.0)

Introduction

This is an OGG-file software decoder library written in C#, Java and the HaXe 3.0 language.

My ambition with this library has been to create a free and portable OGG/Vorbis decoder that can be deployed and used on various devices including desktop, mobile phones and tablet devices.

At its core the library is a port of the floating point libvorbis reference decoder by the Xiph.org Foundation.

I hope that this library will make the .OGG/Vorbis file format more accessible as an audio format for game engines, music software and similar applications.

Example Decoding code (C#)

Example 1

byte[] bytes = File.ReadAllBytes("awesome.ogg");
TanjentOGG.TanjentOGG t = new TanjentOGG.TanjentOGG();
t.DecodeToFloats(bytes);
Console.WriteLine(t.Channels + " " + t.SampleRate + " " + t.DecodedFloats.Length);

Example 2

byte[] bytes = File.ReadAllBytes("awesome.ogg");
float[] decodedFloats = new float[456];
TanjentOGG.TanjentOGG t = new TanjentOGG.TanjentOGG();
while (true)
{
    int nos = t.DecodeToFloatSamples(bytes, decodedFloats);
    if (nos <= 0) break;
    // ... do something with decodedFloats here!
    // decodedFloats[i] *= 0.5; 
}
Console.WriteLine(t.Channels + " " + t.SampleRate + " " + decodedFloats.Length);

Example Decoding code (HaXe)

Example 1

var b:ByteArray = Assets.getBytes("awesome.ogg");
var fb:Bytes = Bytes.alloc(b.length);           
for (i in 0 ... b.length) {
    fb.set(i, b.readByte());
}
var tanjentOGG:TanjentOGG = new TanjentOGG();
tanjentOGG.decodeToFloats(fb);
trace(tanjentOGG.channels + " " + tanjentOGG.sampleRate + " " + tanjentOGG.decodedFloats.length);

Example 2

var b:ByteArray = Assets.getBytes("awesome.ogg");
var fb:Bytes = Bytes.alloc(b.length);           
for (i in 0 ... b.length) {
    fb.set(i, b.readByte());
}
var tanjentOGG:TanjentOGG = new TanjentOGG();
var floatSamples:Array<Float> = new Array<Float>();
for (i in 0 ... 456) floatSamples[i] = 0;
while (true) {
    var nos:Int = tanjentOGG.decodeToFloatSamples(fb, floatSamples);                
    if (nos <= 0) break;        
    // ... do something with floatSamples here!
    // floatSamples[i] *= 0.5;      
}
trace(tanjentOGG.channels + " " + tanjentOGG.sampleRate + " " + floatSamples.length);   

Included in the TanjentOGG library HaXe version is also a more interactive demo example (featured below if you have Flash installed).

Click the LOAD button to start decoding 4 OGG files. Whan the files have loaded just click on one of the four columns below the LOAD button bar to play each decoded file (... and enjoy the falling stars!):

AS3/Flash TanjentOGG Player Example

Example Decoding code (Java)

Example 1

// libgdx only used for file reading here
FileHandle file = Gdx.files.internal("awesome.ogg"); 
byte[] bytes = file.readBytes();
TanjentOGG t = new TanjentOGG();
t.decodeToFloats(bytes);
String outPut = t.channels + " " + t.sampleRate + " " + t.decodedFloats.length;

Example 2

// libgdx only used for file reading here
FileHandle file = Gdx.files.internal("awesome.ogg");
byte[] bytes = file.readBytes();
float[] decodedFloats = new float[456];
TanjentOGG t = new TanjentOGG();
while (true)
{
    int nos = t.decodeToFloatSamples(bytes, decodedFloats);
    if (nos <= 0) break;
    // ... do something with decodedFloats here!
    // decodedFloats[i] *= 0.5;         
}
String outPut = t.channels + " " + t.sampleRate + " " + decodedFloats.length;

Design

The interaction with the TanjentOGG library is done through an instance of the TanjentOGG class. In this class there are two functions and three variables of interest:

The function F1 decodes the entire file in one pass to the array V3 and stores the number of channels in V2 and the sample rate in V1.

The functions F2 decodes the OGG/Vorbis file in several passes by filling the provided parameter "floatSamples" with "floatSamples.length" samples. The return value is the actual number of samples filled. Call F2 in a loop to "stream" the decoded PCM data - only to stop when the return value is 0 or negative. During the loop F2 updates V1 continuously if any changes in sample rate takes place (unlikely).

F1 takes more memory but is easier to use if you only want to decode a small sample (like a short sound FX) into a single buffer. When testing it has been found that the memory requirements for this function might be too much for decoding an entire 3+ minute song on mobile devices and similar platforms with limited memory.

For longer files such as wavetable banks or 3+ minute songs it is usually better to use F2 because it requires less memory and decodes the audio in smaller chunks. It is also possible to call this function in the background to prevent the app from stalling or becoming non-responsive for longer decodes.

About

TanjentOGG is written and maintained by Jonas Murman at Tanjent.

The initial development started in the spring of 2015 and the first version was released in May 2015.

Reporting Issues

If you find a module that does not play correctly please let me know.

If you manage to find a problem and correct it I would be very happy to incorporate your changes to the library, provided you are ready to license them under the BSD-license.

License

TanjentOGG is released under the 3-clause BSD license. This means that you can use it free of charge in commercial and non-commercial projects. Please read the included license.txt for the full license.

Since the library in its essence is a port of the OGG/Vorbis decoding parts of the two C-code libraries libogg and libvorbis the original BSD license by the Xiph.org Foundation as specified in the file COPYING must also be met. This file is located in the folder Xiph.

Please note that the Xiph.org Foundation has NOT endorsed this port.