Mod Archive Forums Mod Archive Forums
Advanced search  


Please note: Your main account will not work here, you must create a forum account to post on the forums.

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - DZ-Jay

Pages: [1]
Players / Arpeggio processing ...
« on: March 10, 2024, 14:12:12 »
I have a question about the Arpeggio (0xy) effect.

All the documentation I read on common implementations of XM (FT2, OpenMPT, MilkyTracker, etc.) state that the effect alternates between 3 semi-tones:
  • Base note
  • Base note + x param
  • Base note + y param

This makes perfect sense to me and it is how I originally implemented it.

However, I am looking at the ported FT2 code and that logic appears to be incorrect.  Unless I am completely misunderstanding something, the code works like this:
  • The effect is processed only on non-zero ticks.
  • It uses the song timer (i.e., the tick counter -- which counts down on every tick from the song speed until zero) to determine the semi-tone offset to use:  a value that cycles through 0, 1, and 2.
  • Those values are used like this:
    • 0: Base note
    • 1: Base note + x param
    • 2: Base note + y param

Essentially, the three offsets are read from a table of 16 entries, using the count-down timer as an index, so the values are read in reverse:

Arpeggio Table:
Code: [Select]
0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0

What all this means in practice is that the first tick of every row is skipped, and the countdown causes it to process the parameters in reverse.

Therefore, the ultimate product is the something like in the following table.  Consider a song speed of 8 ticks per row. 

Tick #TimerTbl ValueResult
0 (start of row)8 (timer recycled at zero of last row)SkippedBase
17arpTab[7] = 1Base + x param
26arpTab[6] = 0Base
35arpTab[5] = 2Base + y param
44arpTab[4] = 1Base + x param
53arpTab[3] = 0Base
62arpTab[2] = 2Base + y param
71arpTab[1] = 1Base + x param
08 (timer recycled at zero)SkippedBase
17arpTab[7] = 1Base + x param
26arpTab[6] = 0Base

Moreover, because the first tick on every row is skipped, when you use a speed number which is a multiple of 3, it will cause the base note to be played twice.

This is sort of weird to me, so perhaps someone with more experience can shed some light on how it should work in practice, or whether this is the expected behaviour.


Players / Question about Volume Slide (Axy)
« on: February 27, 2024, 20:00:05 »

Yes, I am still working on my project.  I had some major set-backs (more than before), and have to come up with a brand now way to encode the data.  That lead to a re-writing of the music player, instrument synthesizer, and the effect handlers.

The good news is that I've been looking at a C port of the FT2 source code to guide my understanding of the effects in the original XM implementation.  This has been very helpful indeed, and I have managed to implement (correctly) Portamento Up/Down, Note Portamento, Arpeggio, Vibrato, and I'm in the process of completing Volume Slide.

I do have one question on the Volume Slide (Axy) effect.  Suppose I have an instrument volume envelope enabled, does the Volume Slide effect respect it, or does it actually adjust the absolute volume of the note?

Let me give you an example.  If someone sets a volume slide to go up, and lets it go up all the way to maximum volume, does the note continue playing at maximum volume even if the envelope is in decay?

If I am reading the source code of FT2 correctly, it seems that the Volume Slide effect ignores any modulation on the volume of the note, and produces an output based on the "real" volume of the note (the one in the pattern data) modified by the slide.

I hope this question makes sense.


Players / Tempo, Speed, Rows, etc.
« on: January 08, 2024, 16:11:08 »
I have what is probably a very silly question, but I will ask it anyway:  What is the actual relation of the BPM to the Speed of the song?

Here's what I know:
  • Speed is the number of "ticks" representing the duration of a row.  So, a speed of 5 means that each row lasts for 5 "ticks."
  • "Ticks" are the lowest unit of time in the tracker:  the state of effects, envelope, and other instrument synthesis is updated on each tick.
  • BPM is another way of measuring the speed of a song, in beats-per-minute.

On my tracker (and I thought this was standard, but I'm not sure now), a "tick" is 1/60th of a second, tied to the vertical refresh rate of the video signal (or 1/50th of a second, on PAL/SECAM video).

So, my question is, where does the BPM fit in there if the tracker sequencing is controlled by the speed of the song, which is counted in 60Hz "ticks"?  It is not clear to me where in a pattern is a "beat," since it could be arbitrary depending on how you arrange it.

I suppose I could change the speed of "ticks" by scaling them down.  However, I wouldn't be able to make them go faster on my tracker, since the only source of timing I have is the vertical refresh signal at 60Hz.

Any insight in clearing my confusion will be greatly appreciated.


Players / Understanding effects processing
« on: December 27, 2023, 16:49:02 »

I'm a retro-game developer for the old Mattel Intellivision, and I maintain a music player software library that plays tracks in a bastardized version of XM format.

I'm currently working on adding support for some (most?) FT2 effects and I need some help understanding how they should work.

Most docs suggest that when a new note is read, the note is played on the first tick, and the effect start playing on the subsequent ticks.  This sounds reasonable.  However, I would like to know how does this affect the behaviour of effects such as "note delay," "pattern delay," "jump to order," and other such effects that affect the music player's behaviour and not just the note waveform/amplitude.

For "pattern delay," do we really wait until the second tick to start counting down?  And what happens during the delay -- do we play the new note, or do we continue stretching what is already playing on the channel (i.e., the previous note)?

For "note delay," what plays while we are delaying the note?  Do we continue playing the previous note, or do we start playing the first one and just stretch it during the delay period without advancing the player state?  (I can't imagine it would just be silence ...)

For "jump to order," do we jump immediately upon reading the note/effect, or do we play the note and jump when it finishes?  (Same for "pattern loop" and "pattern break": do we break/loop immediately when signaled, on second tick, or when the note plays out?)

I apologize if these questions seem silly, but my target platform is severely constrained in resources (it's a games console from 1980!), and I wish to understand how to implement the effects in the most efficient and optimized way.

Thanks in advance!

Pages: [1]