[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Ogg Vorbis

asenchi

1/15/2005 6:14:00 PM

Hello All,

I am looking for Ogg Vorbis support in Ruby. Mostly encode, file
information and decode.

There is already one lib out there, ruby-vorbisfile, that does decoding.
However I want more! :)

I've worked for a little bit on extending this initial work into a more
thorough lib that supports a wide range of Ogg Vorbis features. However,
I am not a very good programmer, especially when it comes to extending
Ruby with C. I get some of the ideas, but is a bit over my head. I've
been using the ldap library as a reference, simply b/c it is quite
extensive in its support.

Mostly what I've been trying to do is create Ruby libs out of
vorbis/vorbisfile.h (already done, now integrating that with)
vorbis/vorbisenc.h and any other features.

Is there anyone willing to work with me on this? Granted, I can offer
some help, but I would need some tutoring in moving forward. I really
would like to learn more, but need help in grasping some of the ideas.

I understand this wouldn't be a top priority for most, but it might be a
good project.

If you would like to help me out, and are patient with a n00b, please
let me know. Thank you.

--
<<< Asenchi >>>


5 Answers

Florian Gross

1/15/2005 7:15:00 PM

0

asenchi@asenchi.com wrote:

> Hello All,

Moin.

> I am looking for Ogg Vorbis support in Ruby. Mostly encode, file
> information and decode.
>
> There is already one lib out there, ruby-vorbisfile, that does decoding.
> However I want more! :)
>
> [...]
>
> Mostly what I've been trying to do is create Ruby libs out of
> vorbis/vorbisfile.h (already done, now integrating that with)
> vorbis/vorbisenc.h and any other features.

Did you have a look at Ruby/DL already? IMHO using it is very frequently
easier than writing a C extension.

Maybe it would also be an option to just drive external applications
that already do those jobs well via the command line.

asenchi

1/15/2005 8:26:00 PM

0

Florian Gross spewed:
> Moin.
>
> Did you have a look at Ruby/DL already? IMHO using it is very frequently
> easier than writing a C extension.

From my limited understanding, the DL library is for Windows? I am in a linux
environment.

> Maybe it would also be an option to just drive external applications
> that already do those jobs well via the command line.

I've consider using external apps, but I would really like the comment
manipluation to happen in Ruby. I figure if I start there, why not move
forward and get encoding ability...

--
<<< Asenchi >>>


Florian Gross

1/15/2005 8:44:00 PM

0

asenchi@asenchi.com wrote:

> From my limited understanding, the DL library is for Windows? I am in a linux
> environment.

Works generally everywhere. It can be used for WinAPI or for writing
bindings to C libraries etc. It even comes bundled with Ruby.

I think manipulating the OGG tags ought to be possible fairly easily in
pure Ruby. (If I'm not totally wrong about the format it should just be
simple .pack and .unpack and maybe computing checksums.)

Encoding and decoding OTOH sounds like something that would need C
bindings to work nicely...

Florian Gross

1/15/2005 10:39:00 PM

0

asenchi@asenchi.com wrote:

> I've consider using external apps, but I would really like the comment
> manipluation to happen in Ruby.

See below. (I could not attach this because my news server complained
about it being an attachment, sorry.) It should be a good starting point...

It would probably be a good idea to refactor the repetitive parts into
private methods and being able to actually manipulate the data would
also be nifty.

----

> class OggFile
> class OggError < IOError; end
> class MagicError < OggError; end
> class VersionError < OggError; end
> class PageTypeError < OggError; end
> class PageOrderError < OggError; end
> class PacketTypeError < OggError; end
> class BlocksizeError < OggError; end
> class ValueError < OggError; end
>
> class << self
> alias :open :new
> end
>
> module HeaderFlags
> Continued, First, Last = *(0 .. 2).map { |i| 1 << i }
> end
>
> module PacketTypes
> Identification, Comment, Setup = *1 .. 2
> end
>
> AllowedBlocksizes = [64, 128, 256, 512, 1024, 2048, 4096, 8192]
>
> attr_accessor :vorbis_version, :audio_channels, :audio_sample_rate,
> :bitrate_maximum, :bitrate_nominal, :bitrate_minimum, :blocksize_0,
> :blocksize_1, :comments
>
> def initialize(filename)
> data = File.open(filename, "rb") { |file| file.read }
>
> magic, version, header_type, granule_position, serial_number,
> page_number, checksum, segment_size, rest = *data.unpack("a4CCQLLLCa*")
>
> raise(MagicError, "File magic bytes are not 'OggS'") if magic != "OggS"
> raise(VersionError, "Unknown structure version") if version != 0
> raise(PageOrderError, "Out of order page") if page_number != 0
> # Checksum is ignored for now
>
> if (header_type & HeaderFlags::First).zero? then
> raise(PageTypeError, "Unexpected non-first page at file beginning")
> end
>
> # Rest of initial page, identification header
> segment, id_packet_type, id_magic, @vorbis_version, @audio_channels,
> @audio_sample_rate, @bitrate_maximum, @bitrate_nominal, @bitrate_minimum,
> blocksize, framing_bit, rest = *rest.unpack(
> "a#{segment_size}Ca6LCLlllCCa*")
>
> @blocksize_0 = 2 ** (blocksize & 0b1111) # first 4 bits are 2 exponent
> @blocksize_1 = 2 ** (blocksize >> 4) # last 4 bits are 2 exponent
>
> #if id_packet_type != PacketTypes::Identification then
> # raise(PacketTypeError, "Out of order packet. Expected Identification, " +
> # "but got #{id_packet_type}")
> #end
>
> if id_magic != "vorbis" then
> raise(MagicError, "Header magic needs to be 'vorbis'")
> end
>
> raise(VersionError, "Unknown vorbis version") if @vorbis_version != 0
> raise(ValueError, "Audio channels need to be > 0") if @audio_channels == 0
>
> if @audio_sample_rate == 0 then
> raise(ValueError, "Audio sample rate needs to be > 0")
> end
>
> [@blocksize_0, @blocksize_1].each do |bs|
> unless AllowedBlocksizes.include?(bs)
> raise(ValueError, "Unallowed blocksize #{bs}")
> end
> end
>
> if @blocksize_0 > @blocksize_1 then
> raise(ValueError, "Blocksize 0 has to be > blocksize 1")
> end
>
> raise(ValueError, "Framing bit has to be non-zero") if framing_bit.zero?
>
> # Second page
> magic, version, header_type, granule_position, serial_number,
> page_number, checksum, segment_size, rest = *rest.unpack("a4CCQLLLCa*")
>
> raise(MagicError, "File magic bytes are not 'OggS'") if magic != "OggS"
> raise(VersionError, "Unknown structure version") if version != 0
> raise(PageOrderError, "Out of order page") if page_number != 1
> # Checksum is ignored for now
>
> # Rest of second page, comment header
> segment, cmt_packet_type, cmt_magic, vendor_length, rest = *rest.unpack(
> "a#{segment_size}Ca6LA*")
>
> #if cmt_packet_type != PacketTypes::Comment then
> # raise(PacketTypeError, "Out of order packet. Expected Comment, " +
> # "but got #{id_packet_type}")
> #end
>
> if cmt_magic != "vorbis" then
> raise(MagicError, "Header magic needs to be 'vorbis'")
> end
>
> vendor, comment_count, rest = *rest.unpack("a#{vendor_length}LA*")
>
> @comments = Hash.new { |hash, key| hash[key] = Array.new }
> comment_count.times do
> length, rest = *rest.unpack("La*")
> string, rest = *rest.unpack("a#{length}a*")
> key, value = string.split("=", 2)
> @comments[key.upcase] << value
> end
>
> framing_bit, rest = *rest.unpack("Ca*")
>
> raise(ValueError, "Framing bit has to be non-zero") if framing_bit.zero?
> end
> end

Martin DeMello

1/17/2005 8:09:00 AM

0

Florian Gross <flgr@ccan.de> wrote:
> >
> > module PacketTypes
> > Identification, Comment, Setup = *1 .. 2

0..2, surely

martin