Foreword
Very often I come across the fact that many people do not perceive PHP as anything other than a means for developing websites, but I want to dissuade them with this topic.
Today they called me and asked for help with the synthesizer of the company YAMAHA (in particular with the analogue of the model 403), which has one interesting feature - it allows you to save 5 written songs in your memory, but you can get them on your computer in any form other than the backup file no copy is allowed, as stated in all forums and in the technical documentation for this synthesizer.
The .bup format is used by the synthesizer to save all settings and 5 recorded songs.')
All the tips for recording these melodies boil down to recording music from a synthesizer in a velan time, but this is not an option.
so, let's begin
In my hands was a file named
08PK61.BUP . The first glance did not cause any positive emotions:
06PK61 BackFile
Glasil ascii-header file. Google also did not give any positive results.
But then I remembered that synthesizers use the midi format for music, and why don't developers keep a standard midi stream in a backup file?
“But how will I find him ?!” flashed through my mind. And everything turned out
to be
easy.As it turned out, the standard header of the midi-file looks like this:
4D 54 68 64 00 00 00 06 00 00 00 01 00 60
For a simplified understanding, I divided the title into 5 parts:
- Mthd - header, midi-file begins with it
- 00 00 00 06 - the length of the data behind this block (in bytes)
- 00 00 - file type (3 types)
- 00 01 - the number of MTrk blocks
- 00 60 - pace
Well, I read this in Wikipedia, and immediately decided to drive MThd into the search for this file. Here I was disappointed - this sequence of bytes was not in the file. My hands dropped.
Having nothing to do, I decided to finish reading the article to the end (and I realized that this should always be done) and I saw about MTrk recordings (briefly about them):
Starts with a sequence
4D 54 72 6B
The data goes farther and the block ends with a sequence
FF 2F 00
I start the search in the sequence 4D 54 72 6B, and about a miracle, I found as many as three such records.
Then it remained for the small:
It is necessary to copy the MTrk block ending with the sequence FF 2F 00 and after adding the standard MThd header to write all this to a file.
No sooner said than done.
Saving the result in the mid file and opening it in the player I heard the recorded music
And now about programming
Well, if you need to tear out one song from such a file, then okay, you could finish it, but if there is a need to process several files in a similar way, what then? But then automation comes to the rescue.
All the actions that we need to perform on the subject, we found out, now we will put them together and realize it, i.e. in code:
- Open file
- Read file
- Override the result in HEX
- Find matches with MTrk header, if any, continue, otherwise exit
- Match FF 2F 00
- The resulting indices copy the substring into a variable
- Create output file
- Write the MThd header and the variable with the MTrk block processed by the HEX2BIN function
- Save, close file
- Back to p.4
Ready php code:
- <? php
- function hex2bin ($ h) // function, which for some unknown reason is not in php
- {
- if (! is_string ($ h)) return null ;
- $ r = " ;
- for ($ a = 0; $ a <strlen ($ h); $ a + = 2) {$ r. = chr (hexdec ($ h {$ a}. $ h {($ a + 1)})); }
- return $ r;
- }
- $ lp = 0;
- $ i = 0;
- $ fh = fopen ( 'test.bup' , "r" ) or die ( "Can't open file!" ); // open the file
- $ file = fread ($ fh, filesize ( 'test.bup' )); // read
- $ bin = bin2hex ($ file); // translate to hex
- while (strpos ($ bin, '4d54726b' , $ lp)! == false ) // workflow
- {
- $ fp = strpos ($ bin, '4d54726b' , $ lp);
- $ lp = strpos ($ bin, 'ff2f' , $ fp);
- $ getss = substr ($ bin, $ fp, $ lp- $ fp + 6);
- $ fm = fopen ( "mid $ i.mid" , "w" );
- fwrite ($ fm, hex2bin ( '4d54686400000006000000010060' . $ getss)); // write to the MThd and MTrk header file
- fclose ($ fm);
- $ i ++;
- }
- fclose ($ fh);
- ?>
This is how everything is easy;)
UPD. On the advice of an unknown to me (except for nick eDogs) I will add a user about the function of converting to a binary form. Instead, it can use the standard PHP function:
string
pack (string
$ format [, mixed
$ args [, mixed
$ ... ]]))