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

Rob L. 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)

-----Original Message-----
[…]
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)})

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 L. 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

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 …

Rob L. wrote:

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

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:

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs