Thread: Logical Problems

  1. #1
    Registered User carrotcake1029's Avatar
    Join Date
    Apr 2008
    Posts
    404

    Logical Problems

    I am trying to read a flac file, and the format specifies that the sample rate is stored as a 20 bit number.

    I have found the 3 bytes that this pertains to: 0x0A 0xC4 0x42
    Now from online calculators, I have tested my AND operation to strip off the last 4 bits, because these are 8 bit bytes.
    0x0AC442(hex) & 0xFFFFF0(hex) = 705600(dec), however, there are still 4 bits of 0 in there

    705600(dec) = 10101100010001000000(bin)
    I'm actually looking for it with those trimmed off
    1010110001000100(bin) = 44100(dec)

    So the sample rate I'm looking for is 44100 Hz or 44.1 kHz.

    I'm having a really hard time doing this in C. Endianness and other factors are confusing the hell out of me.

    Here is how I am trying it:

    Code:
    char num[9] = {0};
    unsigned long sample_rate = 0; //sizeof on my system = 4
    
    ...
    
    memcpy(&num, &data[pos], 3);//this copies the next 3 bytes of my buffer into a byte array
    sample_rate = num[0] << 16 | num[1] << 8 | num[2]; //num[0] = 0x0A, num[1] = 0xC4, num[2] = 0x42
    sample_rate = sample_rate & 0xFFFFF0
    
    printf("Sample Rate = %lu\n", sample_rate);
    This is giving me the result of "Sample Rate = 16761920", so I'm obviously doing something wrong.

    Thanks for any help you guys can provide!

  2. #2
    Registered User lattica's Avatar
    Join Date
    Aug 2008
    Location
    Spacelike Hyperplane
    Posts
    16
    Code:
    sample_rate = sample_rate & 0xFFFFF0
    Right shift by 4 is what you need to do here.

  3. #3
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    You're missing a shift right by four bits (705600 / 16.0 = 44100), and you also happen to be missing some required brackets to get the precedence right.
    An easier way to do it would be:
    Code:
    sample_rate = (num[0] << 12) | (num[1] << 4) | (num[2] >> 4);
    No masking required.
    Although you should make sure you declare num as unsigned char to ensure that always works.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  4. #4
    Registered User carrotcake1029's Avatar
    Join Date
    Apr 2008
    Posts
    404
    Thanks for both of your input. It was a stupid little error like I thought.

    iMalc: That is really clever, I'm going to have to revise some other parts of my program as well.

  5. #5
    Registered User carrotcake1029's Avatar
    Join Date
    Apr 2008
    Posts
    404
    Hey I've got another quick question. I got a little curious with bitshifting tricks and was trying to do it on the next part, but have failed. I could AND my calculations, but I want to get a firm grasp on bit shifting.

    The next bit of information is the bits/sample, which is a number that only has 5 bits that span through these two bytes:
    0x42 = 01000010
    0xF0 = 11110000

    The number consists of the last bit (furthest right) of 0x42 and the first 4 bits of 0xF0.
    So the bits/sample should be 0x0F = 00001111. (the bold will always be 0 due to specs, only 5 bit sized number)

    I seem to do well with shifting with 4-8-12 bit shifts, but for some reason I can't get this one. I feel like I need to shift 0x42 left 7, or with 0xF0 shifted left 6, and then shift all right 6.
    Code:
    bps = ((0x42 << 7) | (0xF0 >> 4)) >> 6
    But that seems to be wrong and I just need a little explanation.

  6. #6
    Registered User lattica's Avatar
    Join Date
    Aug 2008
    Location
    Spacelike Hyperplane
    Posts
    16
    So, what you want to do is put the lowest bit of 0x42 into the highest of an
    intermediary, unsigned byte. Put the top half of 0xF0 into the next four bits. And as the
    five right-most bits make up the bps, you'll need to shift right by three.

    Code:
    bps = ((0x42 << 7) | (0xF0 >> 1)) >> 3

  7. #7
    Registered User
    Join Date
    Apr 2008
    Posts
    90
    Also, you need to watch signed vs. unsigned when doing shifts. If you do a right shift on a signed value, and the MSB is 1, it will result in 1's being pushed on the left side instead of 0's. This is meant to preserve the number's sign.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Physical and Logical Memory.
    By TheUmer in forum General Discussions
    Replies: 3
    Last Post: 11-04-2010, 04:28 AM
  2. Logical! Logical! Why do you have to be so Logical?
    By g8ortech14 in forum C Programming
    Replies: 24
    Last Post: 09-20-2010, 02:40 PM
  3. Logical Error
    By gardenair in forum C Programming
    Replies: 2
    Last Post: 04-06-2003, 04:18 PM
  4. Size of 1 pixel
    By ooosawaddee3 in forum C++ Programming
    Replies: 4
    Last Post: 07-26-2002, 08:06 PM
  5. Coding Problems
    By RpiMatty in forum C++ Programming
    Replies: 12
    Last Post: 01-06-2002, 02:47 AM