Archive for July, 2010

New mapper…

Posted in Uncategorized on July 31, 2010 by pcedev

Street Fighter 2 Plus, or SF2+, extended mapper (or give it you’re own name!). The original SF2 mapper is mapped to four 512k rom segments (mapped into the upper 512k of the lower 1megabyte range). The first 512k of the 2.5megabyte image is fixed mapped to the lower 512k of the 1megabyte range. Writing any value to the $0000-$000f range, changes which upper 512k mapped into the lower 1megabyte address ranger. Of course this is mapped to $fff0-ffff since bank $00 is left at MPR7. The SF2 game only writes to $fff0-$fff3.

So the new mapper. It’s just an extension of the original SF2 mapper. But you have $fff0-ffff range. That’s up to 8.7megs or 69Mbits. And guess what? A private release of Mednafen WIP supports it. Yup, yup-yup-yup. I did some tests today on SF2 with the new mapper support today. Yay! Gonna do some SF2 stuff now. (I lost my though for a moment… oh yeah) Original bank of $00 for SF2 has some free space to add some hooks. Perfect!

Visual stuff

Posted in Uncategorized on July 26, 2010 by pcedev

I was tinkering around with viewing ROM’s as raw 8bit palette indexed data. I used a greyscale palette, but set the color 0 to bright green and the color 255 to brink purple-pink. I then set all colors from 01 to 31 to greyscale+blue hue. This way, I could see the free areas of the rom (be it 00 or 255) and also have 5bit short and long sample data show out among the rest of the data (as long as it isn’t compressed). This worked out very-very well.

So I improved upon it for looking over just sample data, to make sure there weren’t any errors. Or rather, values over 31 ($1f). I also increased the blue hue range (and removed the green for color 0). Works great. But I noticed something very cool. Visually looking at voice data. Have a look.. The pink dots are the ending markers for the long samples (all these in this pic are long samples from Parodius), so it separates the samples. Pretty cool looking, ehh? (Make sure you zoom to 100% in your web-browser) Near the very end/bottom of the pic, is some soft looking waves/rings. This is the sample of “I’m strong” that sounds very slowed down, in the game. Never thought human voice could look like that.

Some PCE sample rips

Posted in Audio on July 26, 2010 by pcedev

Yo, yo, yo, yooo! Yo…

Ok. I ripped these directly from the ROMs (or HES). A couple of them are only partial, because the instrument pak is nothing special (and it takes for ever load in each one into Milkytracker). None of the samples have volume envelopes, I leave that to you. But I did set the relative not for the long samples. Just use C-4 to play them. Some are 7khz and some are 3.5khz (depends on the game), but it’s setup so C-4 always plays the right frequency for the sample, regardless.

R-Type was an interesting one. I only took the interesting short waveforms. I included some demo notes to show the effect of the waveforms. There’s another game in there too, that does it as well – but only by a small amount IIRC.

Waveform modeling simulation tests..

Posted in Audio on July 19, 2010 by pcedev

Haha, not so good. Not so good.

I ran some simulation tests today using cool edit 2000 and milkytracker. Made a generic 32byte waveform, played it at a specific note, and recorded the output. I then isolated the particular repeating waveform shape. Cropped it and repeated it for a two cycle wave I could mess with.

Now, they sounded very clean. I was at G4 I believe. So I did my test by removing 6 samples from one of the waveforms (which is close to 6.3 of the TIMER step). I got my pitch change like expected, but I also got something else 😛

Repeating on the pair of waveforms gave a distinct tonal change to the sound. More than just a pitch drop. At this point, I was pretty pissed. I hadn’t even reached G5 range yet, and here I am already having problems. Having different tonal sounds at different pitch levels isn’t exactly unusable, but it’s not exactly desirable either. Muddy isn’t exactly the right word, but compared to pair of exactly even waveform cycles, it’s a good enough word to describe the different. Where one sounds very clean, and the other more sounds harsh/gritty/dirty.

So.. after a while of messing around, I came to the idea that maybe I should ‘muddy’ the clean pair. You know, so the pitch drop has somewhat of the same sounding tonal/muddy range. I ditched the smooth almost looking sine wave for a SAW pair instead. Both the SAW waveforms have a flat tail at the end. On one of them, I made 6 samples at a different peak amplitude. And on the other one, I left it alone. Both SAW waveforms are of the same length still. Sure enough, out goes the clean sound and in comes the muddiness. Perfect.

Now to test cutting out those six sample of the first SAW making it that much shorter than the second one. Sure enough, the pitch dropped and the tonal range was very similar. Then it dawned on me… I’m introducing additional frequencies on the first waveform not exactly matching the second waveform. And removing the 6 samples is actually doing the exact same thing.

Was does this all mean? It means I have a way of controlling the tonal changes and the pitch changes. I don’t have any math behind it, so I had to tweak the amplitude level on the clean pair by ear. I even tried it on the sine-ish waveform pair (although with a different amplitude range). The good thing is that it works, the bad side is that it requires a bit more code to do this (and possibly little bit bigger LUT). The other negative side is, the type of waveform will have to be tweaked a certain way and with some rules applied. But that aside, brand new timbre control for the PCE is still on track.

Here’s an ascii example:

          __/|          __/|
       __/   |       __/   |
    __/      | |  __/      |
   /         |_|_/         |___
              ###            ###

          __/|         __/|
       __/   |      __/   |
    __/      |   __/      |
   /         |__/         |___
              ##            ###

The top waveform is the even/clean one. Notice the spike in the tail end. The clean waveform represents the TIMER clock divided by a whole number. The second waveform is missing that spike and it one TIMER tick shorter on *one* of the pair of SAW types. This represents TIMER divided by a whole number + 1/2.

Waveform modeling numbers…

Posted in Audio on July 18, 2010 by pcedev

Here is a quick table I made for the frequency values. Guess there’s no room for in between frequencies. Frequency sliding would have to be on a semitone basis. The method I use to do in between frequencies of whole numbers, is to have a pair or group of three P1+P2. Where only one of the P1 or P2, in only one of the groups, is one 1/6991 longer.  Hopefully this won’t result in a warble-y sound in the higher notes (as it being really fast, should blend in sound). So far so good. Still need to test it out and see how it sound. Heck, still need to calculate some stuff for some of the method frequencies and timbre stages, and build out the tables.

Waveform modeling

Posted in Audio on July 18, 2010 by pcedev

This is a bit new. Having discovered some interesting things about the two top bits of $804, there are some exploits you can do.

First and foremost, the most important thing is that you can now sync the channel waveform to any cpu cycle. That is, you can both re-initialized the period counter and the waveform pointer. This opens up a whole new system of channel waveform manipulation.

If we take the 7khz TIRQ interrupt, we can ‘sync’ the channel to whatever cycle in that interrupt frequency. Using the 7khz interrupt for audio generation isn’t new. I’ve used it before to create soft channels (square/triangle/etc). But the problem original was that you need to output the waveform data manually with DDA writes. You do this by tying the interrupt routine to a phase accumulator, and use the overflow bits to clock a pointer into a waveform in ram/rom. You could even add multipliers on the top bits, but this causes frequency aliasing due to sample skipping (how bad it sounds depends on the multiplier value and the desired waveform). There’s a varying amount of techniques to get around this, but they include using a waveform table with multiple re- sampled variations of the same waveform. You cut down on nyquist aliasing, but your waveform output resolution is still a bit low. That’s not to say that isn’t useful and usable, because it is. It’s just that there is now another method of doing instrument synthesis.

This new method requires the latest discoveries (to me, at least).  Looking at this example I made here, you can see some methods of providing waveform distortion over time.

The setup requires a two phase system to run off the TIMER interrupt. The first phase starts before and ends at the pink bar. The second phase starts at the pink bar and ends where phase one would start again. We can label these as P1 and P2. The frequency of the note would be 7000/P1+P2.

Looking at the different methods:

Sync+cut‘. P1 = reset waveform pointer, reset period counter, set counter length. P2 = reset waveform pointer and reset period counter, leave the channel in DDA mode, write the sample offset to DDA port, set counter length. Repeat.  By varying ratio between P1 and P2, you get a timbre control over the sound. This is the easiest of the methods. But has the side effect that the waveform gets louder as it gets sharper on some waveform types (like the one shown).

Sync+cut+frequency stepping‘. This is very similar to the above, but with the distinction of having a full waveform inside of P1. As you increase the length of P1 (and shorten P2), you decrease the period counter value of the channel. This gives a less of a sharp increase in amplitude across the timbre control. It also has the benefit of having a higher resolution sample on P1, than the above, because the whole sample is playing in P1.

Sync+reset+frequency stepping‘. A more complex version of the above. Instead of writing a single sample value for P2 length; the channel waveform and period counter is reset and a new frequency value is set to the channel. A sample is still written at the end of P1 to bring the DAC back into place. For timbre control, as the ratio of P1 and P2 lengths change so does the corresponding frequency settings of P1 and P2. In the example given, the total waveform length is actually higher resolution than what the PCE normally gives. Because you have 1/2*32+32. This form of waveform distortion is very-very close to Phase Distortion Synthesis.

Sync+frequency stepping‘. Even though this is the last example, it’s not the most complex method. Sync happens at the start of P1, but *not* on P2 – which makes it different from the rest of the methods. Instead, the only thing that happens on P2 is a frequency channel to the channel. This basically is Phase Distortion Synthesis.

And there you have it. The nice thing about these methods, is that you don’t need a large 24bit phase accumulator function on each TIRQ call. Just one 8bit counter per call(which is actually overkill), irregardless of the phase it’s in. Some of the frequency settings of 6991/P1+P2 don’t exactly line up with actual note frequencies in the upper end. Most are damn close. To solve that problem, you vary between two P1+P2 accumulations. Say, if you want P1+P2=21.5 or such. There’s no harsh stepping.

The benefit of these methods, is that you can control the sharpness/brightness/timbre of a sound over time. On a normal PCE audio channel, you really can’t (at least not without using multiple channels for doing Additive Synthesis, or less effective single channel techniques). The downside is that frequency sliding between notes, won’t have as high of resolution steps as native channels. But frequency sliding isn’t used a whole lot and the trade off is worth it. The other downside is that these methods will require lookup tables for precalculated note frequencies. I can’t say for sure how big, but nothing more than 1-2k per ‘instrument’ if you include all the timbre changes.

Audio info continued

Posted in Audio on July 18, 2010 by pcedev

Just a quick run down of the top two bits of $804. A small part of a large audio doc.

              A)  Allows audio output to the DAC.
              B)  Writes to data port and waveform buffer playback 
                  output to the DAC.
              C)  Allow underflow from period counter to clock the waveform
              D)  Data port writes output to the DAC *and* transfer/replace
                  the waveform memory at the current pointer position.
              E)  Waveform memory pointer is not clocked by data port
              A)  Stops all audio from outputting to the DAC.
              B)  Writes to the data port store in the waveform memory and
                  clock the waveform memory pointer.
              C)  Period counter is paused and does not clock the waveform
                  memory pointer. The counter is *not* reset/re-initialized.
              A)  Waveform memory pointer is reset to $00.
              B)  Period counter is reset and halted/turned off.
              C)  Waveform memory pointer is locked and not clockable.
              D)  Writes to the data port do not transfer to the waveform
              A)  Waveform memory pointer is clockable.
              B)  Data port writes trasnfer to the waveform memory.
              C)  Period counter is not halted/off.
        00b:  Audio output is disabled. Period counter is paused. Data port
              writes transfer to waveform memory. Waveform memory pointer
              is clocked only by data port writes.

        01b:  Audio output is disabled. Period counter is halted and reset.
              Data port writes do not transfer to waveform memory. 
              Waveform memory is not clocked by either data port writes or
              period counter.
        10b:  Audio output is enabled. Period counter underflow clocks 
              waveform memory pointer. Data port writes output to the DAC
              and trasnfer into waveform memory. Data port writes do not 
              clock the waveform memory pointer.
        11b:  Audio output is enabled. Period counter is halted and reset.
              Data port writes do not transfer to waveform memory. Waveform
              memory pointer is not clocked by data port writes or period
     Note: Transition from 10b to 00b clocks the waveform memory pointer.