Bitstuct and binary files

Discussion in 'Ruby' started by Rob Lee, Oct 24, 2006.

  1. Rob Lee

    Rob Lee Guest

    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, Oct 24, 2006
    #1
    1. Advertising

  2. 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
     
    Joel VanderWerf, Oct 24, 2006
    #2
    1. Advertising

  3. Rob Lee

    Ben Nagy Guest

    > -----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. :(

    ben
     
    Ben Nagy, Oct 24, 2006
    #3
  4. Rob Lee

    Rob Lee Guest

    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/.
     
    Rob Lee, Oct 24, 2006
    #4
  5. Rob Lee

    Rob Lee Guest


    >
    > 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. :(
    >
    > ben


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

    --
    Posted via http://www.ruby-forum.com/.
     
    Rob Lee, Oct 24, 2006
    #5
  6. 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
     
    Joel VanderWerf, Oct 24, 2006
    #6
  7. Rob Lee

    Rob Lee Guest

    >
    > 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 :)

    --
    Posted via http://www.ruby-forum.com/.
     
    Rob Lee, Oct 24, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Fangs
    Replies:
    3
    Views:
    9,804
    darshana
    Oct 26, 2008
  2. Marc Schellens
    Replies:
    8
    Views:
    3,024
    John Harrison
    Jul 15, 2003
  3. dermoon
    Replies:
    0
    Views:
    486
    dermoon
    Oct 8, 2003
  4. utab
    Replies:
    3
    Views:
    858
  5. Jim
    Replies:
    6
    Views:
    736
Loading...

Share This Page