I've talked about my 100% .NET AVI player on this blog before and mentioned the issue with audio getting out of sync from the image frames. I believe I'm following the AVI specification to the letter but for the life of me, I cannot find a fix.*The all new Reef World!*
What I've tried
- crackle and pops between each audio frame; these are caused by not reading enough data ahead. The MSDN docs recommend 0.75 seconds of audio to be loaded at a time to help with streaming. If I do that then the crackles disappear but the audio gets way too far ahead.
- if I load the entire audio stream and play at the first audio frame, the stream gets out of sync - this method works reasonably for the ending video but not the other two (reef+astro). Also, it appears that playing a sound effect won't always happen on the same update, causing the audio to start out of sync
- if I stream portions into a DynamicSoundEffectInstance the result is the same as the point above
How do I fix it?
If Lode Runner was Windows only, the fix would be very simple; use either DirectX or the Windows libraries to play the video, but being cross-platform means I can't do this. I also don't want three lots of code for each of the three different platforms.
The FNA engine that powers Lode Runner Online: The Mad Monks' Rewrite cannot play AVI videos - even basic RIFF ones, but it can play Ogg Theora videos. This would mean converting the videos and using FNA's built-in video player. The problem with this is it goes against my main goal of preserving the original Presage artwork.
If you're following so far, there are three possible fixes;
- leave the pops in the audio which I'm not happy with
- use the native libraries for each platform and make three video players
- convert the videos to Ogg Theora
There is however a 4th option; if you focus on number three, converting to Ogg Theora... if we're going to convert the video, why not convert it to the propriety Presage format like the other 12 cut-scenes use? This in my opinion, allows me to "cheat" around my goal of preserving the original resources. I suspect Presage shipped AVI videos with The Mad Monks' Revenge because it was sold on CD-ROM and/or Windows 95/Mac had a video player handy.
Converting the videos
After quite a lot of thinking and some testing to make sure it was do-able, I forged ahead and started work on a little programme to convert the three videos. The programme needed to rapidly speed up editing to save me from having to manually edit each image but not too automated/over-board since there are only three videos to convert.
Below focuses just on the Jake Peril portion of the video.
Step 1 (automated): extract all image frames from the video. For this I used my RIFF AVI player.
Step 2 (manual): remove the background in MS Paint, position it to fit the different sized video player. The AVIs are 20 pixels smaller in height so I added a few extra rungs.
Step 3 (automated): using the above as a mask, remove the background from all frames extracted in step 1
Step 4 (automated): remove the monks by simply ignoring all pixels to the left of the liquid
Step 5 (automated): determine the coordinates of Jake within the images obtained in the previous step
Step 6 (automated): extract Jake from each frame
Step 7 (automated): build a list of what frames play when
We now have Jake's portion of the cut-scene without audio. This is made up of 172 images. We could build a cut-scene now but the original didn't do this. Since The Legend Returns shipped on floppy disks, space was a premium. Some frames are played more than once whilst others have portions played more than once. If we're going to convert the cut-scenes to the original format, we may as well go the whole hog and squeeze out some more bytes.
Step 8 (automated): find duplicate frames
Step 9 (manual): go through the frames visually and determine portions that repeat
Step 10 (manual): alter the frames in MS Paint
Step 12 (manual): repeat step 7
Step 13 (manual): extract audio snippets using GoldWave, convert to Presage format and add into the cut-scene
After duplicate frames are handled, that leaves us with 103 images for Jake - quite a saving. This process is by far the most time consuming. Steps 3 through 8 takes <30 seconds on my machine but steps 9 and 11 took about 5 days. There is a lot of testing from steps 8 onwards as quite a lot of manual tinkering is needed to make the videos match nicely.
Reef World cut-scene
In the image above, you can see all the sprites needed for the 31 second video. Not a lot in the end is there? To make it easier on myself, I made three separate cut-scenes; one for Jake and one for each of the monks. Once the videos worked nicely and matched the AVI, I merged them into the one.
You might notice in the new cut-scenes the sound effects for when Jake is climbing ladders. These aren't present in the original video but all other cut-scenes with ladders use them so I added them in. I think it gives it a little something extra.
The Reef World cut-scene is only 377kb in size compared to 1.09mb for the original AVI.
- 196kb; 14 sound effects
- the monk disrobing + the ladder effects are recycled from other cut-scenes
- 181kb; foreground, graphics and image/animation data
Overall, I'm quite pleased with how it turned out. The sound effects could be halved in size since the ones in the AVI are mono and not stereo and some of the frames could be made smaller but that is just nit-picking a little.
Only Astro and the ending cut-scenes to go!