Created
November 22, 2012 18:23
-
-
Save nddrylliog/4132467 to your computer and use it in GitHub Desktop.
An ogg player with libvorbis and cubeb in ooc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use cubeb | |
import cubeb | |
use vorbis | |
import vorbis | |
import structs/ArrayList, os/Time, io/FileWriter | |
main: func (args: ArrayList<String>) { | |
if (args size < 2) { | |
"Usage: %s FILE.ogg" printfln(args[0]) | |
exit(1) | |
} | |
context := CubeContext new("oggplayer") | |
if (!context) { | |
"Error initializing cubeb stream" println() | |
exit(-1) | |
} | |
stream := OggPlayer new(context, args[1]) | |
stream start() | |
while (stream playing) { | |
Time sleepMilli(200) | |
} | |
stream destroy() | |
context destroy() | |
} | |
DataSource: abstract class { | |
channels: Int | |
rate: Int | |
width: Int | |
init: func (=channels, =rate, =width) { | |
} | |
read: abstract func (ptr: Pointer, bytes: Int) -> Int | |
getFrameSize: func -> Int { | |
channels * width / 8 | |
} | |
} | |
OggSource: class extends DataSource { | |
path: String | |
file: OggFile | |
init: func (=path) { | |
"Opening ogg file %s" printfln(path) | |
file = OggFile new(path) | |
"Opened file, %s endian, %s words, %s" printfln( | |
file endianness == OggEndianness LITTLE ? "little" : "big", | |
file wordSize == OggWordsize WORD_8BIT ? "8bit" : "16bit", | |
file signedness == OggSignedness UNSIGNED ? "unsigned" : "signed" | |
) | |
"rate = %d, channels = %d" printfln(file info@ rate, file info@ channels) | |
super(file info@ channels, file info@ rate, file wordSize == OggWordsize WORD_8BIT ? 8 : 16) | |
} | |
read: func (ptr: Pointer, bytes: Int) -> Int { | |
file read(ptr, bytes) | |
} | |
} | |
OggPlayer: class extends CubeStream { | |
source: DataSource | |
pipe: FramePipe | |
playing := true | |
init: func (context: CubeContext, path: String) { | |
source = OggSource new(path) | |
pipe = FramePipe new(65_536, source) | |
params: CubeStreamParams | |
params format = CubeSampleFormat S16LE | |
params rate = source rate | |
params channels = source channels | |
super(context, "oggplayer: %s" format(path), params, 250) | |
} | |
stateChange: func (state: CubeState) { | |
match state { | |
case CubeState STARTED => | |
"stream started" println() | |
case CubeState STOPPED => | |
"stream stopped" println() | |
case CubeState DRAINED => | |
"stream drained" println() | |
playing = false | |
case => | |
"unknown stream state" println() | |
} | |
} | |
refill: func (dst: Int16*, nframes: Long) -> Long { | |
pipe write(dst, nframes) | |
} | |
} | |
FramePipe: class { | |
data: UInt8* | |
capacity: Long | |
size: Long = 0 | |
offset: Long = 0 | |
hasMore := true | |
channels: Int | |
framesize: Int | |
source: DataSource | |
init: func (=capacity, =source) { | |
framesize = source getFrameSize() | |
data = gc_malloc(capacity) | |
} | |
write: func (dst: UInt8*, requestedFrames: Long) { | |
written := 0 | |
requested := requestedFrames * framesize | |
while (written < requested && hasMore) { | |
available := size - offset | |
if (available <= 0) { | |
read() | |
continue | |
} | |
remaining := requested - written | |
copysize := remaining < available ? remaining : available | |
memcpy(dst + written, data + offset, copysize) | |
offset += copysize | |
written += copysize | |
} | |
written / framesize | |
} | |
read: func { | |
offset = 0 | |
size = source read(data, capacity) | |
if (size == 0) { | |
hasMore = false | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment