HHD Software  FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 

 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
Enjoy Your Skills

HHD Software

Ogg Vorbis

 
Post new topic   Reply to topic    HHD Software Forum Index -> Structure Library
View previous topic :: View next topic  
Author Message
Leo Davidson



Joined: 19 Aug 2008
Posts: 9
Location: London, UK

PostPosted: Sun Apr 26, 2009 10:06 pm    Post subject: Ogg Vorbis Reply with quote

Hello,

I've created a Structure Viewer definition for Ogg Vorbis audio files and thought I'd share it here in case someone else finds it useful.

I'm writing code to extract Ogg Vorbis meta-data (album, artist, cover-art, etc.) and basic information (sample rate, bitrate, channels) so that's what I have focused on.

This is my first time creating a Structure Viewer definition and I'd welcome any advice.

EDIT: The question in the quote box below was part of my original post. Barfy's reply solved my problem and I've updated my definition. I've left the question, and the old defintion, here in case it helps someone else (and so the rest of the thread still makes sense):

Quote:
In particular, I wonder if there is a better way to handle the variable-length Segment array within each Page, rather than the 256 if-statements I have used. :-) The problem I had there is that each Segment needs to know its own length, but the length is stored in a separate array:

Code:
BYTE SegmentCount;
BYTE SegmentSizes[SegmentCount];
OggSegment Segments[SegmentCount];


Some kind of for-loop would be ideal for that sort of thing but maybe there's another good way to do it?

OLD version of the definition: ogg_vorbis.zip (4KB)


Anyway, here's the definition and a screenshot. Hope it's useful to someone else! I've found making it a useful way to confirm that I've understood the file format's spec, and then to experiment with different example files to test boundary conditions etc. without a lot of tedious, error-prone manual counting.

Leo

UPDATED definition: ogg.zip (2KB)

(This adds some of the improvements from Barfy's Apr 27th post. It still does the "bind" stuff like before, though... See discussion below.)



Last edited by Leo Davidson on Sat May 02, 2009 3:42 pm; edited 2 times in total
Back to top
View user's profile Send private message
Barfy
Site Admin


Joined: 09 Mar 2006
Posts: 192
Location: Support Department

PostPosted: Mon Apr 27, 2009 12:15 pm    Post subject: Reply with quote

Hello Leo,

First of all, we would like to thank you very much for contibuting the OGG file format!

Certainly it would be great to have a for operator (and we plan to add support for it in the future), but there currently is a way to simplify the definition using the intrinsic array_index variable. When used inside an array, it returns a current array index, thus allowing us to reference data from other arrays, for example:

Code:

BYTE ElementsCount;
BYTE Sizes[ElementsCount];
struct SomeData
{
   BYTE raw[Sizes[array_index]];
} data[ElementsCount];


I've slightly corrected your variant to use this feature. Note that I only breifly looked at the file format specification and did not go any further, so only the basic file structure is parsed and your variants of VorbisHeader and VorbisComments structures are connected at the proper positions.

In addition, while you can use the $bind directive to bind an arbitrary data type, its main usage is for totally dynamic structures, where it is almost impossible to determine the correct structure to bind at the initial bind pass. For almost all other cases, usual methods with if, switch and case_union may be used. This is also reflected in my version of the file. As a bonus we get a "straight" binding experience, that is, the whole file is parsed as one big single structure with substructures.

ogg.zip (1.4 KB)
Back to top
View user's profile Send private message Send e-mail
Leo Davidson



Joined: 19 Aug 2008
Posts: 9
Location: London, UK

PostPosted: Tue Apr 28, 2009 2:40 pm    Post subject: Reply with quote

Thanks for the tips!

array_index does exactly what I needed. I overlooked the Field Access page in the manual and I see there are some other useful things in there.

The stuff I did with $bind was for convenience, but not really needed anymore so I'll switch to using your version. Originally I had it parsing the entire Ogg container, which could have thousands of pages/segments, and it was a bit of a pain to see just the metadata stuff in the top few segments. So I moved those structures into separate top-level binds and collapsed all the other stuff. But now that it stops parsing the file after the end of the metadata, and also now that I've discovered that Hex Editor Neo will save which branches of the tree are expanded/collapsed, there's no need for that.

I'll update my copy of the file in a little while, once I've had a chance to check out the changes against a few examples. (Taking a short break from this project at the moment!)

I really appreciate your quick & helpful support, as always! Hex Editor Neo has made doing this kind of work soooo much better.

Sometime later this week I expect I'll have a FLAC (free lossless audio codec) structure viewer example to put up as well. Edit: Done. FLAC sample is up too.


Last edited by Leo Davidson on Sat May 02, 2009 3:43 pm; edited 1 time in total
Back to top
View user's profile Send private message
Leo Davidson



Joined: 19 Aug 2008
Posts: 9
Location: London, UK

PostPosted: Thu Apr 30, 2009 1:31 pm    Post subject: Reply with quote

I checked out your changes against some test files and incorporated most of them into my version, which I've updated in the root post. Thanks again! Using array_length makes things much more elegant. I also noticed the improvement that using an enum for the bitfields gives (where the structure viewer uses less space to say which bits are set).

I've kept my old bind logic though, and remembered the most important reason it's needed.

The Ogg container is split into pages and segments. Each page can contain up to 255 segments and each segment can contain up to 255 bytes.

Chunks of Vorbis data within the Ogg container can be longer than 255 bytes, and also longer than 255*255 bytes. So a Vorbis data structure can span multiple segments or even multiple pages.

If any structure spans segments (e.g. a VorbisComments block that is longer than 255 chars then I don't think you can parse the Ogg and Vorbis parts at once, because the Vorbis structures are not always contained within the Ogg ones. However, within a given page there is no data between each segment -- the length array comes first and there is no padding -- so you can treat contiguous segments as a Vorbis structure. Using bind does just that and solves that problem well.

Here's an animated gif I made to show what I mean:



(Essentially Ogg Vorbis is a format within a format.)

It gets more complex with page spanning:

If any structure spans pages (which could be due to a very long structure, or just a >255 byte structure that happens to appear at the end of a page after several other segments) then I don't think we can parse that structure at all, at least not in full. That's because there will be bits of Ogg page headers interwoven with the Vorbis data.

With Ogg Vorbis metadata parsing, you're most likely to encounter this problem when there's cover-art in the VorbisComments block. (It's base64 encoded and inserted like any other comment string. Since a cover image could be a couple of meg, in an extreme case, it's possible for several pages, and lots and logs of segments, to be spanned.)

Perhaps page-spanning Vorbis data could be parsed by a script which actually extracted and combined the data into a memory buffer and then parsed that, but that's overkill for my purposes. So long as the structure viewer shows me the start of the structure (and doesn't give up completely) I'm happy, and that's what I've got right now.
Back to top
View user's profile Send private message
Barfy
Site Admin


Joined: 09 Mar 2006
Posts: 192
Location: Support Department

PostPosted: Mon Oct 05, 2009 8:52 pm    Post subject: Reply with quote

Decided to post here again to mention that we have implemented a while, for and do... while loops (as discusses above), as well as improved the scripting support.

For a good starting example, you may consult the updated PE header file, which now uses a Javascript file to keep some state and to perform address translation. This allows it to parse almost as much information as contained in PE header, including export directory, import directory, resources table and so on. It even displays the type of individual resource.

In addition, javascript code may now be specified directly inside Structure Viewer's definition files, there is no need to use external files anymore (pe.h still uses one, though).
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic    HHD Software Forum Index -> Structure Library All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group