Skip to content

fix AY freq-to-tone calculation#443

Open
ahihi wants to merge 1 commit into
supercollider:mainfrom
ahihi:fix-ay-freqtotone
Open

fix AY freq-to-tone calculation#443
ahihi wants to merge 1 commit into
supercollider:mainfrom
ahihi:fix-ay-freqtotone

Conversation

@ahihi

@ahihi ahihi commented Jun 24, 2026

Copy link
Copy Markdown

fixes #348, and by extension https://codeberg.org/musikinformatik/SuperDirt/issues/281

AY.freqtotone is implemented with an "approximate empirical" formula:

*freqtotone { |freq|
// Approximate empirical...
//^(109300 / (freq - 3.70727))
^(110300 / (freq - 0.5))
}

it is reasonably accurate at a sample rate of 44100 Hz, but at other rates it is severely out of tune.

i noticed that the ayemu code calculates a value ChipTacts_per_outcount, which depends on the chip frequency of the emulator as well as the sample rate:

ay->ChipTacts_per_outcount = ay->ChipFreq / ay->sndfmt.freq / 8;

the AY_Ctor constructor does not set the chip frequency:

ayemu_set_chip_type(ay, chiptype, NULL);
//ayemu_set_chip_freq(ay, freq);
ayemu_set_sound_format(ay, freq, chans, bits);

therefore we fall back to the default frequency of 1773400, defined here:

AYEMU_DEFAULT_CHIP_FREQ = 1773400

so, some real-world values of ChipTacts_per_outcount are: (keeping in mind this is all integer division)

1773400/44100/8 = 5
1773400/48000/8 = 4
1773400/96000/8 = 2

now we can start to see where the magic number 110300 in freqtotone comes from; it is very close to 44100*5/2 = 110250. this hints at a general formula for the conversion constant:

sampleRate * chipTacts_per_outcount / 8

and indeed, this formula seems to work :) notes now sound in tune at both 44100 and 48000 Hz sample rates. (though due to the integer calculations, i guess there will always be some error.)

the PR just implements this calculation in AY.freqtotone.

Comment thread source/AYUGens/sc/AY.sc
// Approximate empirical...
//^(109300 / (freq - 3.70727))
^(110300 / (freq - 0.5))
*freqtotone { |freq, s=nil|

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! Thanks for looking into this ... Maybe it would be clearer to just pass the sample rate into the freqtotone method? Then we can also use the method in a synthDef (using the SampleRateugen). And if none is given, it can still be calculated as you do it.

Note that usually we call the argument server and there is no need to specify the default to nil, since the default is nil.

@capital-G capital-G added the bug label Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AY UGen freqtotone method is incorrect.

3 participants