Famitracker: DPCM Loop Problem

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Famitracker: DPCM Loop Problem
by on (#153996)
I have encountered an interesting problem in Famitracker, when using DPCM samples. I made a thread about it on the Famitracker forum, but nobody replied, so I'm hoping somebody here can help.

I would like to use some DPCM bass for some of my projects. I want the samples to be really small, so I can have more space for drum and maybe sound effect samples and fit it all in the 16KB space, dedicated to DPCM data. So I made a bunch of Saw Wave samples for different notes. Each one is short and small. The way I would play longer notes is by looping them. And here is where I ran into an issue. When they loop, the samples sound like arpeggios are being used or something. As if there is some silence either in the beginning or the end of the sample, which ruins the clear sounding of the loop. And when creating those samples, I made sure they sound clear, when looping.

When I looked at the waveform in Famitracker, I noticed this:
Image
The compression has changed the beginning and ending of the wave. Is there a way to prevent this from happening? If I try using a sample with one wave cycle, this problem doesn't appear, but the pitch gets changed and every sample sounds like the same note. Perhaps the current length of the samples I'm using isn't right. If so, can someone tell me how long is the selection I've made in the screenshot and will this solve the problem with the looping?

I've included an FTM with one of the samples and the original .wav file.
Re: Famitracker: DPCM Loop Problem
by on (#154003)
The DPCM sample length (in bytes) has to be of form 16*n+1 (where n=0, 1, 2, ..., 255). Most likely FamiTracker is padding the sample because of that. If you want clean looping samples, I think it's best if you familiarize yourself with how the APU DPCM channel actually works: http://wiki.nesdev.com/w/index.php/APU_DMC

It might be easier to construct the samples manually in a hex editor (or by writing a custom tool) rather than use the WAV import for it. That way you have full control over what APU is doing.

...

EDIT: For example, here's a saw(ish) DPCM wave that loops perfectly at amplitude 32:
Code:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000  73 73 73 77 73 73 73 77 73 73 73 77 73 00 00 00  ssswssswsssws...
00000010  00                                               .

The 73, 77 section ramps the waveform down, and the 00 section ramps it back up. Of course only a limited range of frequencies can be covered by a single sample, so you'd have to have variations for different frequencies, while keeping the sample length restriction in mind at the same time.

EDIT2: I guess I should've also mentioned this technique developed by blargg that plays saw, pulse and triangle waves in the DPCM channel by playing a 1-byte sample at varying frequencies: http://www.slack.net/~ant/misc/nes-saw/ It requires custom code and IRQs though, so you can't directly use it in FamiTracker.
Re: Famitracker: DPCM Loop Problem
by on (#154006)
I think a good strategy for DPCM samples is - first in Audacity trim all silence from before and after the sample. Then cut it to about 0.1-0.2 seconds. Then have Famitracker produce a sample that is LARGER than you want. Then save it. Open the sample in a hex editor, and trim it to exactly 16*n + 1 bytes long (where n = 1-255). Then reimport to Famitracker.
Re: Famitracker: DPCM Loop Problem
by on (#154009)
Well, Here's a low C saw wave, done exactly how I described. I didn't have to edit it in a hex editor, but I have had to do that with other samples.
Re: Famitracker: DPCM Loop Problem
by on (#154010)
Also, you won't be able to play looped Bass DPCM samples and Drum DPCM samples at the same time. You might want to consider Noise channel, or a combination of Noise and Sq/Tr, to simulate a drum sound.
Re: Famitracker: DPCM Loop Problem
by on (#154029)
Thanks! That explained a lot, though I still have a question. When I asked about the selection, I didn't ask about file size, but time. So, how long would 1 byte from a sample play at rate 15? According to the wiki, 8 bits, played at rate 15 are equal to 4 scanline lengths. What does it mean by that? 4 scanlines(in which case, I'd have to find out the time it takes for the TV to draw a scanline), 4 pixels, what exactly?

Also, creating the samples in a hex editor is a pretty cool idea, but figuring out how to make a sample play an exact frequency is a pain in the ass and it also wouldn't work for some other samples I want to use. So, what I need to do right now is edit the original wave file, so that the lenght and playback rate match the ones, that can be used by the DPCM(for instance, have the file size match the formula and have the playback rate roughly around 33144.94 Hz). And for that I would need the time it takes to play a given portion of the sample. If those things are impossible, then I need to know what kind of algorithm does Famitracker use to compress the files, so that I can make the proper adjustments.

dougeff wrote:
I think a good strategy for DPCM samples is - first in Audacity trim all silence from before and after the sample. Then cut it to about 0.1-0.2 seconds. Then have Famitracker produce a sample that is LARGER than you want. Then save it. Open the sample in a hex editor, and trim it to exactly 16*n + 1 bytes long (where n = 1-255). Then reimport to Famitracker.

This is a pretty interesting idea, but the example you've made doesn't really work. It still has that problem. It's not as noticeable, but it's there. So, sorry, but it doesn't do it for me. :(

dougeff wrote:
Also, you won't be able to play looped Bass DPCM samples and Drum DPCM samples at the same time.

I know. I never said I'll have them play at the same time, though I have an interesting idea, that could simulate that. Once this problem's taken care of and I finish the track, I will post it, so you can see for yourself.
Re: Famitracker: DPCM Loop Problem
by on (#154031)
AlienX wrote:
Thanks! That explained a lot, though I still have a question. When I asked about the selection, I didn't ask about file size, but time. So, how long would 1 byte from a sample play at rate 15? According to the wiki, 8 bits, played at rate 15 are equal to 4 scanline lengths. What does it mean by that? 4 scanlines(in which case, I'd have to find out the time it takes for the TV to draw a scanline), 4 pixels, what exactly?

The scanline lengths aren't really useful for you. They're just there for people who might want to use the DPCM IRQ as a makeshift scanline IRQ.

If you're playing at rate 15, the frequency of playback (of 1-bit samples) is 1789773/54 Hz ~= 33143.94 Hz (check the table in wiki). Every byte contains 8 1-bit samples, so divide by 8 to get the frequency of how often sample bytes are fetched.
Re: Famitracker: DPCM Loop Problem
by on (#154032)
AlienX wrote:
So, how long would 1 byte from a sample play at rate 15?
The sample rates are stated on the DMC page in two different ways:
1- The "Rate Index" in the functional description, which gives the period (in CPU clocks) from bit to bit; multiply these numbers by 8 to get the number of CPU clocks to emit a whole byte.
2- The "Pitch table", which is the raw sample rates for each. (It's the same information, just 1789773 Hz divided by the above table). Divide these numbers by 8 to get the bytes/second.

To directly answer the question, the highest sample rate consumes bytes at ≈4143 bytes/second. (546875 ÷ 132 by definition)

Quote:
how to make a sample play an exact frequency is a pain in the ass and it also wouldn't work for some other samples I want to use.
Unfortunately, you're really constrained by the DMC hardware for "chip" looping samples. You basically can only get pitches that are the existing pre-provided sample rates divided by some integer.

I made a simple perl script some years ago that made triangle waves (included dmc files) for all periods in this manner, for divisors of 2 up through 127, and a reference table (included html file) of which triangle at which rate produces which pitch:
Re: Famitracker: DPCM Loop Problem
by on (#154036)
lidnariq wrote:
I made a simple perl script some years ago that made triangle waves (included dmc files) for all periods in this manner, for divisors of 2 up through 127, and a reference table (included html file) of which triangle at which rate produces which pitch:

Cool, I was just about to do the same thing. :)
Re: Famitracker: DPCM Loop Problem
by on (#154041)
My sample sounds ok to me, except for a very small higher pitch click at the end of each loop.

Here's the output wav file.
Re: Famitracker: DPCM Loop Problem
by on (#154063)
I looked at your sample...

I think lower and longer and louder original samples sound better looped. The sample you have is too short and too quiet. Quiet, you get alot of artifact noise from the DMC sampling process. Short, you get more artifacts and misaligned peaks in the looping process, and you get a loop buzz (I don't know the technical term for this, but if you loop ANY sample short enough you get weird high pitch buzz, the shorter the loop the higher pitch the buzz).

Lower notes work better, because it's easier to match the peaks up in a loop without clipping (repeated clicks).

NES technology was just not designed to produce great looped samples. I was able to produce a less stuttered / noisy sample from your wav with a lot of modification (doubling it's length, boosting its volume, editing in hex editor), but it's still pretty noisy. Sounds a bit like a buzzing bee.
Re: Famitracker: DPCM Loop Problem
by on (#154066)
You can make a very limited scale with just a 17 byte looping sample, but unfortunately it is a bit detuned compared to the A440 scale usually used by programs like Famitracker.

Example: http://forums.nesdev.com/viewtopic.php?p=92494#p92494

The Immortal did this in a few tracks, it mostly just limited itself to a few droney bass notes that didn't sound too badly detuned.

If you want other pitches you need to use longer samples. To cover the pop/blip at the loop point, you can crossfade the waveform with its original phase just before the loop; this creates a phased/layered sound variation just before the loop, but it could be a lot less objectional than the pop/blip.
Re: Famitracker: DPCM Loop Problem
by on (#219744)
lidnariq wrote:
I made a simple perl script some years ago that made triangle waves (included dmc files) for all periods in this manner, for divisors of 2 up through 127, and a reference table (included html file) of which triangle at which rate produces which pitch:

Here's those samples stuck into a Famitracker file, in case someone wants to play with it. I had to split it into 2 instruments (4 octaves each) because there's a limit on sample entries per instrument. There's a lot of redundant notes, but I believe it always favours the one with the highest samplerate.

Here's also the very hastily written python program that parses the HTML file into entries for Famitracker's text import, in case someone wants to regenerate it in a different manner.
Code:
notes = { "C-":0, "C#":1, "D-":2, "D#":3, "E-":4, "F-":5, "F#":6, "G-":7, "G#":8, "A-":9, "A#":10, "B-":11 }
sample = 0
lines = open("makeall.html","rt").readlines()
for line in lines[1:]:
    pitches = 0
    p = 0
    p = line.find("<td",p+1)
    p = line.find("<td",p+1)
    p = line.find("<td",p+1)
    p = line.find("<td",p+1)
    for n in range(16):
        if line[p+3] == ">":
            note_name = line[p+4:p+6]
            octave = int(line[p+6])-1
            inst = 0
            if octave >= 4:
                inst = 1
            note_number = notes[note_name]
            print("KEYDPCM   %d   %d  %2d    %2d  %2d   1     0  -1" %
                  (inst,octave,note_number,sample,n))
            pitches += 1
        p = line.find("<td",p+1)
    if pitches > 0:
        sample += 1
Re: Famitracker: DPCM Loop Problem
by on (#219746)
That's cool. I was thinking about this exact thing recently.

My issues with it
-there are quite a lot of samples (53), some seem to be unused.
-some of the samples are large (1000+ bytes), and maybe not even used.

But sounds good. Thanks.
Re: Famitracker: DPCM Loop Problem
by on (#219748)
Well, lidnariq's goal was to provide every possible usable sample that evenly divides the available sample lengths.

My goal was to collate as many of those as possible into a Famitracker toy you could play with as a more tactile demonstration of what it can do.

Eliminating notes and redundancies to find a practical smaller set is yet another goal, which would require someone to first spend some time figuring out what they actually need for their specific musical case, and even more time figuring out how to build the Famitracker instrument definitions that implement this smaller set. ;)
Re: Famitracker: DPCM Loop Problem
by on (#219749)
Are these samples explicitly open-source / free to use?

I am working on a music related NES project, and I might be able to use these as a pseudo 2nd triangle channel.
Re: Famitracker: DPCM Loop Problem
by on (#219750)
dougeff wrote:
Are these samples explicitly open-source / free to use?

lidnariq provided the script that generated them, so yes they're open source: http://forums.nesdev.com/viewtopic.php?p=154032#p154032

I don't think any license was explicitly stated but I suspect that it's not really possible to copyright a triangle wave anyway?

One thing you might try to take into account if trying to build a more practical version is that the samples have a volume that is kind of determined by the divisor of its sample period, so the volumes are very mismatched between different samples. (The timbre varies too.)
Re: Famitracker: DPCM Loop Problem
by on (#219752)
1- I think they probably count as "math", so not copyrightable
2- If they are, I'm certain there's prior art to my instance
3- as far as I am concerned, they're public domain / CC-0 / WTFPL as you wish.


Different timbre? Oh, right, there's
A- weirdness with odd divisors (because ÷3 when quantized has to be 001101), but this gets more and more subtle the larger the divisor.
B- the stairstep harmonics because it's DPCM: The ÷2 case is necessarily just a square wave, and the larger the divisor the subtler the distortion and louder the triangle wave.
C- clipping with divisors larger than ÷62 124

edit:
rainwarrior wrote:
Well, lidnariq's goal was to provide every possible usable sample that evenly divides the available sample lengths.
Where I chose "usable" to mean "within 7 cents of A440 12-TET". Some of the other divisors (e.g. ÷7, ÷11) just don't fit into 12-TET, but might fit into 17-, 19-, or 24-TET...

.. has anyone written chiptune music that uses these microtonal temperaments? I guess I just found Sevish, who's done a bunch of random things, including 10-TET FM and 13-TET PSG...
Re: Famitracker: DPCM Loop Problem
by on (#220171)
Apropos of
But it'll eventually be an easy check up if the tuning sounds too raunchy or not once i get back home in august. But i'm pretty sure i need to either use another of lidnariqs' samples for my B-2 that doesn't use sample rate $C as a divisor, or if it still would sound too raunchy on PAL, come up with separate instrument lists for PAL and NTSC.
it's trivial for me to generate a new table for 2A07 tuning, so here's the perl, HTML table, dmc files, and the DPCM import script (h/t rainwarrior for pointing that that could be a thing) for same.

There's a few differences, primarily:
* Rate #4 (÷276) is usually only useful for a single pitch, but there are a few divisors where rate #12 (÷98) is also in A440 12TET. (Unfortunately, rates #4 and #12 are an octave plus a tritone apart, 1793 cents)
* Rates #7, #8, #9, #11, and #15 are all about 6-8 cents more sharp. Rates #7 and #15 are mostly unaffected (being a little flat on 2A03), rate #11 is improved (being too flat on 2A03, so 2A07 in A440 12TET) but rates #8 and #9 are moved out of A440 12TET.
* Rate #14 is 23 cents more sharp. This causes more notes to be in A440 12TET, but they're not the same ones as in 2A03 tuning.

.... of course, I tried to run my generated DPCM import script and famitracker crashed.
Re: Famitracker: DPCM Loop Problem
by on (#220174)
lidnariq wrote:
.... of course, I tried to run my generated DPCM import script and famitracker crashed.

I think there's a limit to how many notes you can stick in a single instrument, at least I ran into a crash when doing that earlier, which is why I split the instrument into 2 halves.
Re: Famitracker: DPCM Loop Problem
by on (#220176)
I was trying to divide the instruments into ranges that covered overlapping groups of 2 octaves of divisor, to try to minimize volume and tone color changes within an instrument... but without even a message to start debugging what went wrong I'm kinda inclined to stop trying.
Re: Famitracker: DPCM Loop Problem
by on (#220178)
Thanks, lindariq! That saves a lot of manual labor, again.

I wouldn't worry about the auto-import. It's not much of a job to hand pick some with those tables as a guide.


It looks like i may be able to make a fairly region-consistent version of the song without exploding the filesize too much. I estimate going from 132 to 626 bytes for all the divisor samples needed if the sound of it checks out fine, or if not, some more. As a bonus, the note range will be a bit more complete, perhaps for use in some other song.

I suppose keeping the size super small is a criteria that mostly applies to the scenario where music using .dmc:s is everywhere (since they'd then need to be accessed everywhere), but since i've isolated use of them to menus and perhaps story, i probably don't need to be that frugal.
Re: Famitracker: DPCM Loop Problem
by on (#220352)
I figured out why my own attempt at a WAV to DMC converter never sounded very good. I misunderstood the order of the bits being read. For some reason, I thought it would read the highest bit first. Duh. Lowest bit first.

Visually, if something goes from on to off, it might look like

FF FF F0 00 00
but that's
\\ \\ /\ // //
so it should be like
FF FF 0F 00 00 to get
\\ \\ \/ // //

the hex looks wrong to me, because I misunderstood.


Anyway, I made some progress making some DMC triangle samples, but I'm working slowly on it.
Re: Famitracker: DPCM Loop Problem
by on (#220358)
I had also written a program that used Bresenham's Line Algorithm / 1st order delta-sigma modulation to generate other (non-integer) divisors of the sample rate. It didn't sound good at all... basically any fractional part smaller than 1/2 produced a horrible spectral smear rather than something useful.
Re: Famitracker: DPCM Loop Problem
by on (#220418)
Here's my attempt. 6 samples at different rates, makes triangle waves from c3-c5 (and f5). Total 1254 bytes. Some are slightly off tune.

http://dl.dropboxusercontent.com/s/f07v ... _test2.ftm

I didn't use an c5 sample, because it was too long, but if you did, you could then tune that one sample like this...

rate / freq / note
15 523 same c5
14 392 g4
13 335 e4
12 266 c4 octave down
11 221 a3
10 199 g3
9 177 f3
8 148 d3
7 132 c3 2 octaves down
6 125 b3
5 111 a3
4 99 g2
3 88 f2
...didn't test 2-0

(I also wrote a bad python script to produce these dmc files)
Re: Famitracker: DPCM Loop Problem
by on (#220422)
Just for reference, the loops dougeff generated were:
"a5" - divisor of 226/3, 75⅓
"as5" - divisor of 1928/27, approximately 71.4
"b5" - divisor of 1544/23, approximately 67.1
"f5" - divisor of 900/19, approximately 47.4
"g4" - divisor of 84. Not clear why there's phase shift here; there's a very gradual accumulation of DC shift (two counts per loop)
"gs4" - divisor of 1672/21, approximately 79.6

Also, my tables indicate that a period 84 divisor should generate tones that about 25 cents sharp (relative to A440 12TET)...

If you listen to "a5.dmc", you can easily hear the kind of (unwanted-by-me) subharmonics that led me to discard this approach... of course, people with more musical experience might find those fun or useful.
Re: Famitracker: DPCM Loop Problem
by on (#220433)
Quote:
about 25 cents sharp


Yes, I chose some slightly off-tune frequencies for some of these, to produce a cleaner cut-off point, and reduce unwanted loop sounds.

These could be redone, but I suspect they will have longer DMC files.