PDA

View Full Version : How to Parse the Event Values



gmbartlett
02-07-2008, 06:49 PM
I'm sure this has been addressed before but I can not find it. I'm working on adding an mp3 player and file reader for my controller so it can be a stand alone system.

I've looked at the .vix file produced by Vixen and understand everything in it except the Event Values. It is obvious that the values are stored in channel order, i.e. all of channel 1 values then all of channel 2 values, etc. In order to make my stand alone system work I need to reorder the values in event order.

My plan was to create a Visual C# application to read in the values from the .vix file and then reorder them and create a new file that my controller would use. My problem is I don't understand how the values are encoded. To try and figure it out I created a sequence that only has one event. I set that event to off. I expected to find a 0 in the event value in the .vix file but instead it had "AA==". When I changed the event to be full on instead of a 255 the file has "/W==". Things got even stranger when I created a sequence with two events. Both events off produced "AAA=", both events on produced "//8=", the first event on and second off produced "/WA=" and off then on produced "AP8=". This has me very confused. I can't find a pattern to the encoding. Does anyone understand how these values are encoded? Even better do you have the C# code that reads these values in to an array of bytes that you would share with me?

Thank you,

fkostyun
02-07-2008, 06:54 PM
Now, one thing to note - once you under stand this, you could also make a converter for LOR.

P. Short
02-07-2008, 09:59 PM
It's encoded using the base64 encoding scheme, which you can find described on the web (including wikipedia). Each of the funny characters encodes 6 bits of data, so three characters of raw data (24 bits) ends up as four encoded characters. The rest of code (the stuff that calls the routine below) is very dependant on the environment of the program that it was written for, so I only included this lowest level subroutine.




/* decode one base64 char - assumes that input char is within proper range */
int inline base64decode(unsigned char x) {

if (isalpha(x))
return (isupper(x) ? x - 'A' : x - 'a' + 26);
if (isnumber(x))
return (x - '0' + 52);
if ('+' == x)
return(62);
if ('/' == x)
return(63);
return(-1);

};


--

Phil

gmbartlett
02-07-2008, 10:24 PM
Phil,

Thank you very much for your reply. After a lot more searching on the web I was about to post that I discovered that the encoding appears to be Base64. You have confirmed my conclusion.

I found a really good article on Base64 that allowed me to come to this conclusion. It can be found at: http://www.kbcafe.com/articles/HowTo.Base64.pdf

Again thank you very much!

teberle
02-10-2008, 08:32 PM
Greg,

Here is how I decode the base64 data.

// Create Byte Array hold the decrypted data.
byte[] data = Convert.FromBase64String(encryptedString);

Then you can convert the byte[] to string of data doing the following:
Return System.Text.Encoding.ASCII.GetString(data)

They are one liners in .Net.

gmbartlett
02-11-2008, 06:03 PM
Greg,

Here is how I decode the base64 data.

// Create Byte Array hold the decrypted data.
byte[] data = Convert.FromBase64String(encryptedString);

Then you can convert the byte[] to string of data doing the following:
Return System.Text.Encoding.ASCII.GetString(data)

They are one liners in .Net.


teberle,

Thank you for the input. I had some time this past weekend to work on this and was able to write a small app to get everything parsed correctly and stored to a binary file in the format that I need. Since Vixen uses an XML file I used an XmlTextReader to parse the file. Once I got to the EventValues node I used the XmlTextReader.ReadBase64(byte[], offset, count) method. This worked great. I agree .Net makes things very easy.

Greg.

Michael Sullivan
10-24-2008, 11:54 PM
Hi,

Could you please share what you have come up with as I am trying to get my head around base64 any code snippets would be great.

Cheers
Michael

gmbartlett
10-25-2008, 07:18 PM
Michael,

I've attached a couple of files that I hope will help you out. The file HowToBase64 is a good primer on Base 64 encoding. The other file is my VixenXMLParser class I created to read a Vixen file and extract the data out of it. It was written in Visual C# 2005 Express.

I hope this helps.

TimW
10-25-2008, 08:49 PM
Thanks for posting Greg. I had a look as well.. one day I'll get this c# thing.. but right now even the decoding info is useful. Thanks.

Tim

Michael Sullivan
10-26-2008, 01:11 AM
Thanks gmbartlett.

I have had some success since I posted and now with this info I am now miles ahead.

Cheers
Michael

oldcqr
04-24-2009, 12:21 PM
FYI...

For those of us still in the stone age (or who abhor that gremlin known as .net), it's also quite easy to convert to/from Base64 in VB6.

You just need to add a reference to Microsoft XML (for me, V6.0), and a couple of calls.

Check this article out for more:
http://www.nonhostile.com/howto-encode-decode-base64-vb6.asp

The only problem I had with it was the insistence that CHR(10)s (line feeds) be added. This is most likely to support sending the encoded blob thru eMail, however Vixen doesn't want/need those linefeeds.

I did take a quick look and didn't see a way to suppress them. So in the end I just stripped them:


Function RemoveLineBreaks(tstr As String) As String
Dim NoMoreMatches As Boolean
Dim ls As String
Dim rs As String
Dim loc As Integer
NoMoreMatches = True
Do
loc = InStr(tstr, Chr$(10))
If loc > 0 Then
If loc = Len(tstr) Then
tstr = Left$(tstr, loc - 1)
ElseIf loc = 1 Then
tstr = Mid$(tstr, loc + 1)
Else
ls = Left$(tstr, loc - 1)
rs = Mid$(tstr, loc + 1)
tstr = ls & rs
End If
NoMoreMatches = False
Else
NoMoreMatches = True
End If
Loop Until NoMoreMatches

RemoveLineBreaks = tstr
End Function

djulien
04-24-2009, 03:44 PM
The only problem I had with it was the insistence that CHR(10)s (line feeds) be added. This is most likely to support sending the encoded blob thru eMail, however Vixen doesn't want/need those linefeeds.

You should probably strip out other white space in there also, including spaces and tabs, if any. An easy way to do this would be to use the Replace function, which is available in VB and VB.NET. For example:

b64str = Replace(Replace(Replace(b64str, vbCrLf, ""), vbTab, ""), " ", "")

don

oldcqr
04-24-2009, 04:01 PM
You should probably strip out other white space in there also, including spaces and tabs, if any. An easy way to do this would be to use the Replace function, which is available in VB and VB.NET. For example:

b64str = Replace(Replace(Replace(b64str, vbCrLf, ""), vbTab, ""), " ", "")

don

You know.... I always forget about them thar new fangled string commands that VB6 had ('Replace' being one of them!).

I have to re-write my routine! :cool:

cbell
04-24-2009, 04:16 PM
For those of you who are PHP addicts like myself (if there are any here), here is a bit of PHP that I'm using to display the event values from a Vixen sequence.


<?php
/* load the XML file */
$xml = simplexml_load_file('testren.vix');

/* get the sequence length */
$seqLen = (int)$xml->Time;

/* get the interval */
$interval = (int)$xml->EventPeriodInMilliseconds;

/* calculate the number of periods */
$periods = $seqLen / $interval;

/* get the event values */
$data = (string)$xml->EventValues;

/* decode the base64 encoded values */
$values = base64_decode($data);

/* echo out the values */
for($i = 0; $i < strlen($values); $i++) {
echo str_pad(ord($values[$i]), 3, '0', STR_PAD_LEFT);
}
?>

djulien
04-25-2009, 12:29 PM
/* get the sequence length */
$seqLen = (int)$xml->Time;

/* get the interval */
$interval = (int)$xml->EventPeriodInMilliseconds;

/* calculate the number of periods */
$periods = $seqLen / $interval;


I've found that $seqLen is often not an even multiple of $interval (Vixen 2.0.x just sets EventPeriodInMilliseconds to the actual audio length), so you probably want to round up when doing the divide to get the #periods:



$periods = ($seqLen + $interval - 1) / $interval; //round up (no partial cells)


don

cbell
04-25-2009, 12:44 PM
I've found that $seqLen is often not an even multiple of $interval (Vixen 2.0.x just sets EventPeriodInMilliseconds to the actual audio length), so you probably want to round up when doing the divide to get the #periods:



$periods = ($seqLen + $interval - 1) / $interval; //round up (no partial cells)


don

Nice catch Don. I'll have to try and keep that in the back of my head, because sure enough some day I'll run into that and spend hours trying to figure out why the number of periods doesn't match (or isn't an integer).

djulien
04-25-2009, 01:10 PM
some day I'll run into that and spend hours trying to figure out why the number of periods doesn't match (or isn't an integer).

Yep, that's what I did. :P

don

oldcqr
04-25-2009, 01:53 PM
FYI: (and it's nice that it does this and doesn't just crash out...)

If you create a sequence that has a SHORTER time than the underlying audio file that goes with it, Vixen simply pops up a warning when you load that sequence and then extends the grid automagically to the correct time.

Sweet.