| |
lft
Registered: Jul 2007 Posts: 369 |
Playroutine coding: A new way to represent pitch
Introducing the 9-bit pitch technique:
http://www.linusakesson.net/programming/9bitpitch/index.php |
|
| |
Mixer
Registered: Apr 2008 Posts: 460 |
Good Stuff!
Here is another riddle.
Consider a case where one plays samples using timer at 007d cycle intervals.(aka. 2 rasterlines) and one would like to represent notes between #$007d and full octave lower #$00fb with normal 12-tet intervals. The pitch represented with integer cycles between 00fb and 007d is not accurate enough, but can lead to significant and clearly hearable deviation from what the exact 12-tet value would be.
So, now the question is how to compensate for the error with the least rastertime loss. One way is to delay replay by a cycle every Nth sample depending on the note value.
Perhaps there is some other very clever way to add bits to that replay mechanism too. |
| |
soci
Registered: Sep 2003 Posts: 486 |
Sounds overly complicated. Why not just make a 192 entry log table for one octave only (that's 1/16 note precision).
Calculating the frequencies of higher/lower octaves is only a matter of left/right bit shifting as many times as the octave is different from the "reference" octave of the table.
Notes would be 11 bit numbers (from some other table), and there's plenty of precision for vibrato and other stuff. For frequency finding it's only a matter of adding/subtracting 192 until the number gets into the reference octaves number range, then this many shifts are applied in the proper direction to the value read from the log table. Done. Almost like a ~1500 entry table, just much shorter and a bit slower.
Or possibly I didn't understood something. Anyway I'm not a musician ;) |
| |
Jammer
Registered: Nov 2002 Posts: 1343 |
Isn't it something similar to SounDemon's one-channel chord? |
| |
Mixer
Registered: Apr 2008 Posts: 460 |
soci: That octave shifting you suggest works, but doing the shifts and lookups can be slow with extra "decimals". LFT:s idea is quite fast to implement. |
| |
algorithm
Registered: May 2002 Posts: 707 |
@mixer. Things get a bit more fiddly if you are mixing more data into a single channel. One of the fastest approaches this way is probably to have fixed sample rate and have 8 interval based adds from a pitch table to the sample pointer which should allow pitch changing in around 5hz increments. This is an approach I am using in my new sine based Amiga decoder which can mix 16 channels at 14khz on 68000. |
| |
lft
Registered: Jul 2007 Posts: 369 |
soci: With that approach, the conversion is certainly easier to grasp.
But it would be slow for three reasons:
1. The octave shifting itself. A 96-semitone range would involve a maximum shift of seven. That's 7 * 12 = 84 cycles with a straightforward implementation.
2. Decoding the 11-bit pitch value into an octave and a note index within that octave. This is basically division and modulo by 12 performed on the MSB. If you handcode it, you still need three compares with branches, for a total of 15 cycles. Then you need to combine the four-bit remainder with the three least significant bits to obtain the correct table index, which is 21 cycles with straightforward code.
So far that's 120 cycles per voice, compared to 46 using my approach (with the similarly-sized table).
But the real killer is probably this:
3. All the rest of your playroutine needs to work with 16-bit math. Granted, code that transposes by whole-semitone offsets only needs to deal with the MSB. But if you do arpeggios that way, you can't reuse the arpeggio engine to get vibrato for free, as in my approach.
The real strength with the 9-bit technique is that all computations in the playroutine work with 8-bit numbers, and then the two resulting 8-bit values are combined into a 9-bit sum right at the end.
So while the conversion routine itself is a bit cryptic, the rest of the code becomes cleaner and easier to follow. And everything gets faster. |
| |
Stone
Registered: Oct 2006 Posts: 176 |
I have thought about implementing microtone frequency tables myself, but I thought there would be too much overhead. Your ideas about table folding and base_pitch+offset_pitch have convinced me that I have to try this! Excellent work, lft! |
| |
ChristopherJam
Registered: Aug 2004 Posts: 1423 |
Working with log(frequency) until the last minute is indeed an excellent plan.
Just a thought though - most parts don't span more than an octave or two, three at most; why not have each instrument have an implied base-note, then use (eg) 240*log(frequency/base)/log(4), to have ten steps per semitone over two octaves, happily fitting within 8 bits? |
| |
Mixer
Registered: Apr 2008 Posts: 460 |
Regarding the 16 step semitone, 192 long table. http://6581.fi/sidwiki/doku.php?id=sid-knowledge has a section Expanded note table, that has an old example of the 192 long octave table discussed.
It uses 8.4 bits system per note, arpeggio and transpose only add to high byte. Vibrato and slides use low byte also.
Solution is split to two functions, first one figures out what the 8.4 bit note value is after all the pitch effects and second function translates that into a frequency value within some octave and then shifts the value depending on the octave value.
You can see how fast/slow that is. |
| |
Hein
Registered: Apr 2004 Posts: 964 |
Interesting. The base_pitch and offset_pitch need to be converted from regular 12-tet values to usable 48-tet values, if you'd want to provide musicians the conventional arpeggio tables/pattern notes, right?
I've also been thinking about microtonal music (esp. middle east stuff) but always thought this would either need a big frequency table or an additional quarter-note finetune command, if it's a 24-tet scale. Maybe I should fiddle with the 9-bit method. It's just that mastering microtonal music doesn't seem easy and requires alot of practice. I've found some nice info and examples at http://www.maqamworld.com. |
... 24 posts hidden. Click here to view all posts.... |
Previous - 1 | 2 | 3 | 4 - Next |