pcmplay - new dragon sound routine

A place to discuss everything Dragon related that doesn't fall into the other categories.
User avatar
utz
Posts: 18
Joined: Mon Aug 31, 2015 8:49 pm
Location: Absurdistan
Contact:

Re: pcmplay - new dragon sound routine

Post by utz »

Hehe, welcome to github ;) And thanks for the great suggestions, I've incorporated them now.
sorchard wrote: What I was suggesting would still give you 16 bit counter resolution and less than 5 cents of pitch error in the region of A0.
The difference between 2 neighbouring halftones is about 6 cents, so a 5 cent error margin would be too large. Sorry :(
sorchard
Posts: 530
Joined: Sat Jun 07, 2014 9:43 pm
Location: Norwich UK

Re: pcmplay - new dragon sound routine

Post by sorchard »

utz wrote:The difference between 2 neighbouring halftones is about 6 cents
I get a different exchange rate where I live ;) I was referring to the size of cent where there are 100 per semi-tone: https://en.wikipedia.org/wiki/Cent_(music)

A 5 cent error at the frequency of A0 (27.5) is about 0.1Hz. Very hard to hear.

This was also a rough estimate. I've since thrown some numbers at a spreadsheet and found that the worst pitch error using 16 bit counters at an update rate of 8KHz is only 2.4 cents. It gets worse as the update rate goes up and reaches 5 cents at around 12KHz. (Because the pitch lookup values get smaller, making the rounding errors larger). So a higher update rate doesn't improve everything about the sound.

I'm amazed at how good your kick sample sounds in only 256 bytes. I've learned a lot from your player. Thankyou for sharing!
Stew
User avatar
utz
Posts: 18
Joined: Mon Aug 31, 2015 8:49 pm
Location: Absurdistan
Contact:

Re: pcmplay - new dragon sound routine

Post by utz »

Ah, I see what you mean. My bad ;)
So you basically want to still do ldd #counter, addd #baseval, std counter, but only use B as the frequency counter, and A as the sample offset? I still think that would give you a rather large frequency error.
User avatar
tormod
Posts: 416
Joined: Sat Apr 27, 2013 12:06 pm
Location: Switzerland
Contact:

Re: pcmplay - new dragon sound routine

Post by tormod »

Wow, this one called for powering up the real thing! Amazing. But I need to hook up something more bass gifted than my monitor's built-in speaker to fully appreciate it :)

utz, thanks also for the very nice, complete and documented software package!

This reminds me, and runs circles around for that sake, my own project, the last before my ~30 years Dragon hiatus, and one I haven't been able to find back to on my tapes. I remember I used the joystick port to record samples and then loop them, maybe four at a time with some sequencer/mod-like arrangement. I remember the work to get a fixed-cycle sampling routine, unlike the one in BASIC. I think I had something barely working, and hope to be able to recover it.
sorchard
Posts: 530
Joined: Sat Jun 07, 2014 9:43 pm
Location: Norwich UK

Re: pcmplay - new dragon sound routine

Post by sorchard »

utz wrote:So you basically want to still do ldd #counter, addd #baseval, std counter, but only use B as the frequency counter, and A as the sample offset?
Almost exactly as you describe, but use both A and B for the frequency counter, and yes, the tuning won't be as precise, but not a lot worse and possibly not as bad as you expect.

The main thing that affects the precision is the rounding error of the number in the lookup table. The smaller the number the bigger the possible error. I'm guessing it starts to become noticeable as the divider drops below 300 and becomes terrible below 100, which is why an 8 bit counter doesn't work well. The potential error in cents is given by 1200*log2((N+0.5)/N).

The biggest change caused by throwing away the top 8 bits of the counter is that the samples will play 256 times faster, so something has to change to compensate. Most of that change will come from making each sample a single wave. A non-repeating sample like the kick can be left as it is but played back using a lower divider. The overall result will be to give a pitch error approx 2x that of the SID chip.

Thinking about your 24 bit counter has given me an idea. The top 16 bits could be used as a sample pointer allowing longer and more complex samples that don't require any special alignment. That's got to be worth a look :)
Stew
User avatar
tormod
Posts: 416
Joined: Sat Apr 27, 2013 12:06 pm
Location: Switzerland
Contact:

Re: pcmplay - new dragon sound routine

Post by tormod »

BTW utz, if you add "end $0F00" to the end of your assembly program, lwtools will insert it as entry point in the (DECB) .bin file. My Dragon got a bit confused after executing $0000 :)
User avatar
utz
Posts: 18
Joined: Mon Aug 31, 2015 8:49 pm
Location: Absurdistan
Contact:

Re: pcmplay - new dragon sound routine

Post by utz »

@tormod: Good idea, I'll do that.

@sorchard: So you basically want to skip sample bytes?

Consider you have a triangle wave (I'm just going to demonstrate with a 16-byte sample instead of 256 bytes).

0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15

If you play this with a counter value of, say 1, it's all dandy, you get the proper saw wave. But now what happens when you step through this with a counter value of, say 5? You will output the following values:

0,5,10,15,4,9,14,3,8,13,2... - which is not an accurate saw wave, and will introduce a tuning error because the first wave cycle will take 4 steps, but the following ones will take only 3.
sorchard
Posts: 530
Joined: Sat Jun 07, 2014 9:43 pm
Location: Norwich UK

Re: pcmplay - new dragon sound routine

Post by sorchard »

utz wrote:So you basically want to skip sample bytes?
Yes, absolutely! If you want to play the same set of samples at different pitches then samples are going to be skipped, no matter how it's done. The player outputs a fixed number of samples per second, so the higher frequency waves necessarily have fewer samples in them than the lower frequency waves.

The concept behind your player is that you start by defining the highest possible frequencies and then stretch them by repeating samples to synthesise the lower frequencies. The concept I'm describing is starting with the lowest possible frequency and then skipping samples to synthesise the high frequencies. One process is the inverse of the other and there is conceptually no difference.

You rightly point out that there is a timing issue, with each wave cycle consisting of a different number of samples. This affects every player and is a result of the finite sample rate. The frequency being synthesised will generally not fit neatly into the player sample rate. The action of the counters ensures that the average wave cycle is the correct frequency and turns the timing errors into noise. It's closely related to drawing lines pixel by pixel. If you look closely at the line segments they alternate between two different lengths. The counter is trying to keep the line as close as possible to the true line.

If you are worried about producing accurate waves consider that the sawtooth waves in your demo only have 8 samples, not 256. They get stretched out into chunky staircases yet nothing bad happens :)
Stew
User avatar
utz
Posts: 18
Joined: Mon Aug 31, 2015 8:49 pm
Location: Absurdistan
Contact:

Re: pcmplay - new dragon sound routine

Post by utz »

Trust me, it doesn't matter if you apply the principle to a 256 byte waveform or a 16 byte waveform. You will still get a tuning error if the hi-byte of the frequency counter is not a power of 2. It's not like I haven't tried this before ;)

In the current player, the number of bytes played per cycle is consistent btw ;)

Edit: On second thought, no, you're right, pcmplay is not cycle consistent either. Still, I don't think your method would perform particularly well. But let's give it a try ;)
sorchard
Posts: 530
Joined: Sat Jun 07, 2014 9:43 pm
Location: Norwich UK

Re: pcmplay - new dragon sound routine

Post by sorchard »

To be honest, I don't understand it that well, most of my 'knowledge' comes from Wikipedia :-D

It's not my method by the way, it's how several existing players work. I'm just trying to analyse it and understand the errors: We already know the pitch precision will not be as good as your player, the question is how much?. Out of interest, what note is the first value in your lookup table, the one that is defined by $800? I'd like to try and compare.
Stew
Post Reply