MIDI Files in Hex Value - c++

I am a beginner in programming
Is there a way to read a midi file in its hex numbers?
I searched the internet that midi files are composed of headers and their contents are in hex numbers like
4D 54 68 64 0A ....
So, what is the best way to extract those hex numbers from a midi file? If there is a C++ library to do this? (I want to write the program in C++ language)
For context, I want to put these hex numbers into an array and replace some of those hex numbers (of course according to the midi file format, so the midi file isn't corrupted) and save it back into a midi file. Like doing some kind of steganography

Let me tell you a secret: There are no hex numbers inside your computer. There are also no decimal numbers. All numbers in your computer are stored as binary. Whenever you write a decimal number like 95 in your code, what C++ does is convert it into binary internally and write it to disk as 1011111.
As such, the problem you're trying to solve needs to be re-phrased. You do not want to read hex numbers, but rather, you want to specify a number as hex in your code (instead of as decimal like usually).
There are various ways to specify a hex number. You could use a calculator to convert the number from hex to decimal, then specify that decimal number in your code (e.g. hex number 4D is 4 * 16 + 13 == 77. So when you've read a number, you can then do if (theNumber == 77) ...).
However, since writing numbers in decimal and hexadecimal is a common thing in programming, C++ actually has a way built in to write hexadecimal numbers. You write your hexadecimal number with a 0x at the start. So to write 77 in hex, you would write 0x4D. So once you've read the number from the file, you would do something like if (theNumber == 0x4D) ....
There are other bases in which you can specify a number in C++. There is 0b for binary numbers (so to specify the number exactly how it will be on disk), and if a number starts with just a 0, C++ thinks it is in octal. So be careful and don't prefix your decimal numbers with zeroes! Because 010 == 8, it's not 10 !
As to actually reading the data from the file, you do that using the fread() function.

Related

Binary to Octal

How to write code that converters a input file of binary numbers into octal. I had to write a code that converts it to decimal which I did, but now I'm supposed to write a code that converts it to octal by grouping the binary numbers in groups of 3 and then calling the binary to decimal function.
For example 10100 would be grouped 10 | 100. So I'd call binary to decimal on 10 and 100 and get 2 for 10 and 4 for 100, then place the numbers together to get 24, which is 10100 decimal in octal.
However, I cannot figure out how to group the numbers. (The number is type string by the way). Any tips would help thanks.
Simply add leading zeroes to your string if its length is not divisble by three then group them and convert to octal.

Outputting Huffman codes to file

I have a program that reads a file and saves the frequency of each character. It then constructs a huffman tree based on each character's frequency and then outputs to a file the huffman codes for the tree.
So an input like "Hello World" would output this sequence to a file:
01010101 0010 010 010 01010 0101010 000 01010 00101 010 0001
This makes sense because the most frequent characters have the shortest codes. The issue is, this increases the file size ten-fold. I realized the reason why is because each 1 and 0 is being represented in memory as its own character, so they get each get expanded out to a byte of data.
I was thinking what I could do is convert each code (E.G. "010") to a character and save that to file - but that still would pad the code to be a byte long (Or mess it up if the code is longer than a byte).
How do I go about this? I can give code snippets if needed - I'm basically saving each code into a string so that's why the file's coming out so big (It's outputting each "bit" as a byte). If I were to convert the code to a long for example, then a code like 00010 would be represented as 2 and a code like 010 would also be represented as 2.
You basically have to do it a byte (or a word) at a time. Maintain a byte which you fill with bits, and a record of how many bits have been filled in so far. When you get to 8, write the byte and start over with an empty one.

Byte to ASCII turns into square characters

I have an USB Device. It's a pedometer/activity tracker.
I'm able to send bytes to the device and I'm also able to retrieve bytes back.
But for some reason numbers are turned into those square characters and not into numbers... The characters that are actually letters come through just fine.
Any idea's on how to retrieve the bytes as numbers?
The expected format something like this:
The square characters are actually binary data, likely hex before 0x20 or above 0x7f.
The first 15 bytes are binary, you would need to interpret them using something approximately like the following pseudocode:
if (isascii(byte)) {
textToAppendToEditBox(byte);
} else {
textToAppendToEditBox( someKindOfSprintF( "{%02x}");
}
There are plenty of googleable examples of hex dumping code snippets that can make it look pretty
The expected format that you showed sends binary data. You first have to convert the received data to internal information, then you can pass that information to an std::ostringstream to display it in a gui.
When reading in the binary data, make sure to respect the used endianess.

Is it possible to losslessy compress 32 hexadecimal numbers into 30?

For example is it possible to compress
002e3483bbdc11ddaae0754822a559f6 into something that just takes at most 30 characters.
Yes, you can convert it to a base-32 number so the greatest 32 characters hex number i.e. ffffffffffffffffffffffffffffffff is equivalent to 80000000000000000000000000 in base-32 that only has 26 characters, also note that in base-32 you will end with a string containing only this characters: 123456789ABCDEFGHIJKLMNOPQRSTUV
For example: 002e3483bbdc11ddaae0754822a559f6 is 5OQ87EUS27F0000000000000 in base-32
If your question is to compress 32 hex numbers into 30 hex numbers.
This is impossible to occur for all test cases, since, if it were possible, multiple 32-length hex strings would have to compress to the same 30-length hex string, thus you wouldn't know which one it was (the pigeonhole principle).
A less proof-y proof - you'd be able to repeatedly invoke the process on any size file to get down to a single 30-length hex string, which doesn't make a whole lot of sense.
Here is a article I just found. Wikipedia says something similar.
Convert hex to binary then use something like base64 or any other encoding scheme, see Binary-to-text encoding (Wikipedia). This has the advantage of not requiring 128bit arithmetic like the suggested base32 solution.
Conversion to base64 and back:
$ echo 002e3483bbdc11ddaae0754822a559f6 |xxd -r -ps |openssl base64 -e |tee >(openssl base64 -d |xxd -ps)
AC40g7vcEd2q4HVIIqVZ9g==
002e3483bbdc11ddaae0754822a559f6
Cut the line starting from |tee to get only the encoded output. In most programing languages you will have core or external libraries to do hex to binary conversion and base64 encoding.
NB: Conversion to base32 would also be possible but the base32 binary to text encoding requires 8-bytes padding, so you would have to trim it then re-add the pads (=) on decode.

How to modify a value in textual data file using C

while(!feof(fp))
{
fscanf(fp,"%d %s %d %d",&res[i].id,res[i].title,&res[i].price,&res[i].qty);
i++;
}
while(j<i)
{
printf("\nID:|%d|\tNAME:|%s|\tPRICE:|%d|\tQTY:|%d|",res[j].id,res[j].title,res[j].price,res[j].qty);
j++;
}
I have this piece of code which is collecting data from the file. Now I want to know if get an input from a user like res[id] and I want to decrease the quantity of that particular id how to do that?
If the file is in binary format it is easier to do what you want.
What is the difference between the text and the binary format? If the file is written in binary format, then a 32-bit integer will be represented as 32 consecutive bits in the file. While in text format the number will be represented as sequence of digits for instance 32.
So what's the big deal in that difference? Well if you replace 32 with 1243, in binary format the number will still take the same 32 bits so nothing else needs to be moved, all you change is these 4 bytes. While in the second case you add 2 more digits which will cause all the subsequent contents of the file to shift with two bytes.
In order to shift everything as needed, you will need to read the current contents of the file change the value and then write the contents back. I mean all the contents following the change you are doing.