Bitstuct and binary files

Hi,

I've been working with modifying a binary file to replace some meta-data
included within. I've had some discussions previously
(http://www.ruby-forum.com/topic/85591) about this but couldn't get to a
satisfactory conclusion. Basically I need to encode an integer value
into 3 bytes as part of a binary file - Bitstruct was suggested as one
of the solutions, however I haven't been able to get it to work for
values larger than 1024 :

require 'bit-struct'

class Audio < BitStruct
   signed :aheader, 8, :endian => :little
   unsigned :alength, 3*8, :endian => :little
   signed :afooter, 8, :endian => :little
end

audio = Audio.new
audio.aheader = 1
audio.alength = 3027
audio.afooter = 1
f = open("testfile","wb")
f.write(audio)
f.close
f = open("testfile","rb")
f.pos=0
puts f.read(1).unpack("c").first.to_s
puts f.read(3).unpack('H6').first.to_i(16)
puts f.read(1).unpack("c").first.to_s
f.close

In the application above, if the value of audio.alength is set to equal
or below 1024 then the output for f.read(3).unpack('H6').first.to_i(16)
matches, however if set above this then the value printed doesn't match.

Can anybody tell me why setting an audio.alength>=1024 breaks the output
and provide a way to fix it ...

Thanks

···

--
Posted via http://www.ruby-forum.com/.

Rob Lee wrote:

puts f.read(3).unpack('H6').first.to_i(16)

I think you want 'h' instead of 'H', and you need to reverse the nibbles:

puts f.read(3).unpack('h6').first.reverse.to_i(16)

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

[...]

Can anybody tell me why setting an audio.alength>=1024 breaks
the output
and provide a way to fix it ...

---borked---
num=359447
f.write(num.to_s(16)[0..2].instance_eval {(self.reverse + '0' * (6 -
self.length)).reverse}.scan(/../).inject('') {|s,byte| s <<
byte.to_i(16)})

···

-----Original Message-----

---

My code is broken. Where I said [0..2] I meant [0..5], I added it in at the
last minute as an overflow check without testing - I was thinking 3 raw hex
bytes but the string after the conversion is a 6 byte 'friendly' hex string.

Sorry. :frowning:

ben

Joel VanderWerf wrote:

Rob Lee wrote:

puts f.read(3).unpack('H6').first.to_i(16)

I think you want 'h' instead of 'H', and you need to reverse the
nibbles:

puts f.read(3).unpack('h6').first.reverse.to_i(16)

Ah, OK that works with my example script - thanks. However, that means
the Bitstruct definition I gave is incorrect. The binary file I'm
trying to modify correctly unpacks the integer using :

f.read(3).unpack('H6').first.to_i(16)

However, I'm really confused over what the Bitstruct definition should
be to support this - do you have any suggestions ?

Thanks

···

--
Posted via http://www.ruby-forum.com/\.

My code is broken. Where I said [0..2] I meant [0..5], I added it in at
the
last minute as an overflow check without testing - I was thinking 3 raw
hex
bytes but the string after the conversion is a 6 byte 'friendly' hex
string.

Sorry. :frowning:

ben

No problem ! I've just modified the code and it works great - thanks :slight_smile:
I'm investigating bitstruct as well but it's always nice to have
alternatives ...

···

--
Posted via http://www.ruby-forum.com/\.

Rob Lee wrote:

Joel VanderWerf wrote:

Rob Lee wrote:

puts f.read(3).unpack('H6').first.to_i(16)

I think you want 'h' instead of 'H', and you need to reverse the nibbles:

puts f.read(3).unpack('h6').first.reverse.to_i(16)

Ah, OK that works with my example script - thanks. However, that means the Bitstruct definition I gave is incorrect. The binary file I'm trying to modify correctly unpacks the integer using :

f.read(3).unpack('H6').first.to_i(16)

However, I'm really confused over what the Bitstruct definition should be to support this - do you have any suggestions ?

Thanks

Then probably your data is in big endian order--I should have grokked that from your code. Try this:

class Audio < BitStruct
    signed :aheader, 8
    unsigned :alength, 3*8
    signed :afooter, 8
end

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Then probably your data is in big endian order--I should have grokked
that from your code. Try this:

class Audio < BitStruct
    signed :aheader, 8
    unsigned :alength, 3*8
    signed :afooter, 8
end

Excellent - thank you. It all works - if you're interested I'm working
on a Ruby proxy for the Nabaztag (wifi bunny rabbit) and I'm trying to
extend some of it's audio capabilities :slight_smile:

···

--
Posted via http://www.ruby-forum.com/\.