Some features of the music coprocessor

ZXNet echo conference «music.zx»

From Ivan Roshin To All 7 December 2000

Hello, All! ═══════════════════ mus_sopr.1 ══════════════════ (c) Ivan Roshchin, Moscow Fido: 2:5020/689.53 ZXNet: 500:95/462.53 E-mail: asder_ffc@softhome.net WWW: http://www.zx.ru/echo/roschin Some features of the music coprocessor ─────────────────────── ──────────────────────── ("Radio Amateur. Your Computer" 11/2000) (under the pseudonym BV_Creator) 1. Necessary explanations This article is written based on materials previously posted me to the ZX.SPECTRUM conference, and based on the subsequent these discussions, in which Vadik Akimoff, Roman took part Panteleyev and Ilya Vinogradov. I thank them for their help! Also thanks to Alexey Letaev, who helped me purchase AY music coprocessor and provided access to Fido and the Internet. The information given in the article was checked by me on two copies of coprocessors YM2149F (Yamaha, Japan) 1990 and 1992 years of manufacture and on the AY38910A/P coprocessor (Microchip, Taiwan). 2. Change in volume when adding sounds of the same frequency Exploring the capabilities of the music editor 'Pro Tracker 3'

From Ivan Roshin To All 7 December 2000

Hello, All! ═══════════════════ mus_sopr.2 ══════════════════ Apparently, in "on interrupt" melodies, i.e. when the music coprocessor is programmed 50 times per second, with nothing can be done about the occurrence of a phase difference. overcome the problem is only possible with the help of “digital sound”, when the program directly sets the output signal level coprocessor at any time, without using tone generators (i.e. the coprocessor operates in DAC mode). Maybe maybe someone can write one based on this principle "on interrupt" music player? I don’t know how this problem is dealt with in different Spectrum emulators/AY emulators. It is quite possible that there no phase difference occurs (which means the music sounds better than on the real Spectrum!). As the famous Spectrum writer wrote: musician EA/Antares, "you can't emulate a chip in software along with its glitches." At the same time, for sounds using only the envelope or just noise, it is quite possible to manipulate the volume, including sound in one, two or three channels at once. The point is that tone generators in the coprocessor are unique for each channel, and envelope and noise generators exist in a single instance, so when using them, the phase differences are simply nowhere to come from. A┼ A┼ A┼│ │ │ ┌─┐ ┌─┐ ┌─ │ + │ = │ │ │ │ │ │ │ ┌─┐ ┌─┐ ┌─ │ ┌─┐ ┌─┐ ┌─ │ ┌┘ └┐ ┌┘ └┐ ┌┘ │ ┌┘ └┐ ┌┘ └┐ ┌┘ │ ┌┘ └┐ ┌┘ └┐ ┌┘ │ │ │ │ │ │ └─┴───┴─┴───┴─┴──> └─┴───┴─┴───┴─┴──> └─┴───┴─┴───┴─┴──> t t t This opportunity is even more valuable if take into account that the volume of sounds obtained using envelope cannot be controlled any other way. 3. Extraneous sounds when changing the sound frequency This unpleasant effect was again discovered when studying features of the 'Pro Tracker' editor. Let's install it in this editor frequency table "SOUNDTRACKER" and create the following sample: ┌──────────────────── ────────────────────┐ │ EDIT SAMPLE 01 │ │ ▒00 000 -0004 00 T-E ███████████████ F │ │ ▒01 000 -0003 00 T-E ███████████████ F │ Now let's try what the note B-4 ('M' key) will sound like. Compare its sound with the sound of other notes. Well, did you hear? As I managed to find out, when playing this note the coprocessor alternately outputs sound at a frequency corresponding to division factor #0100 (hereinafter referred to as sound #0100) and sound #00FF. There is 1/50 of a second between two changes in sound frequency.For definiteness, let's assume that the sound is output in channel B. The frequency division ratio for this channel is set in registers R2 (low byte) and R3 (high byte). Since access to the coprocessor registers occurs in turn, and Pro Tracker first changes register R2, and then R3, when changing value #00FF to #0100, this is what happens: R3 R2 00 FF ;initial value #00FF 00 00 ;changed R2 - got #0000 01 00 ;changed R3 - got #0100 When changing back: R3 R2 01 00 ;initial value #0100 01 FF ;changed R2 - got #01FF 00 FF ;changed R3 - got #00FF It can be seen that at certain times the value of the divisor frequency turns out to be #0000 and #01FF, and somehow this leads to the appearance of extraneous sounds. I tried changing the register values in a different order, by writing a small program in assembly language. Let it when necessary go from sound #00FF to #0100, register R3 changes first, and when you need to go from #0100 to #00FF, the register is changed first R2: Method 1 ──────── R3 R2 00 FF ;initial value #00FF01 FF ;changed R3 - got #01FF 01 00 ;changed R2 - got #0100 01 00 ;initial value #0100 01 FF ;changed R2 - got #01FF 00 FF ;changed R3 - got #00FF In this case, the extraneous value of the frequency divider is only #01FF, but the situation did not improve. Let it now on the contrary, when you need to go from sound #00FF to #0100, the first register R2 changes, and when you need to go from #0100 to #00FF, Register R3 is changed first: Method 2 ──────── R3 R2 00 FF ;initial value #00FF 00 00 ;changed R2 - got #0000 01 00 ;changed R3 - got #0100 01 00 ;initial value #0100 00 00 ;changed R3 - got #0000 00 FF ;changed R2 - got #00FF The extraneous value of the frequency divider in this case is equal to #0000, but the sound did not improve. Then I tried to ban output the tone frequency for the duration of the change in R2 and R3, and then - allow. For this, register R7 (mixer) is used. Three The least significant bits of this register control the output of the tone frequency in channels A, B and C (0 - output enabled, 1 - disabled), and three The most significant bits similarly control the noise output. ════════════════════════ ════════════════════════Best regards, Ivan Roshchin. [ZX] [BestView 3.0 - 26%]

From Ivan Roshin To All 7 December 2000

Hello, All! ═══════════════════ mus_sopr.3 ══════════════════ Method 3 ──────── R7 R3 R2 %00111000 00 FF ;initial value #00FF %00111010 00 FF ;tone frequency output disabled %00111010 00 00 ;changed R2 - got #0000 %00111010 01 00 ;changed R3 - got #0100 %00111000 01 00 ;allowed tone frequency output But at the same time some crackling appeared, which also unpleasant, although better than in the previous case. Then I I tried this: set the divisor value in channel A frequencies #0100, in channel B - #00FF, and then switch these channels by controlling the mixer. Since at the same time tone frequency output is allowed in one channel and disabled in friend, the sound should have been better... Method 4 ──────── R7 R3 R2 R1 R0 %00111001 00 FF 01 00 ;A - disabled, B - enabled %00111010 00 FF 01 00 ;A - enabled, B - disabled The sound, however, only got worse. So, none of the four The considered methods failed to solve the problem. Let's try to figure it out in more detail. What do we have? When alternating sounds #00FF and #0100, outsiders become audible overtones (instead of a smooth transition). Obviously, a significant rolethis is played by the fact that #00FF and #0100 are different, and and the most significant byte, which means the frequency divider when moving from one sound to another acquires extraneous meanings (#0000 and #01FF). After all, if you alternate sounds that differ only in one byte (for example, #00FE and #00FF), no overtones arises. Let's make a generalization: when alternating any sounds that have frequency dividers differ in both the low and high bytes, they must extraneous sounds arise. As a result of the experiment this the assumption is confirmed. You can check it yourself sound pairs #01FF and #0200, #02FF and #0300 ... #0EFF and #0F00 (the frequency divider value is limited to #0FFF). As the values increase, the overtones become less noticeable, but don't disappear at all. Difference between two alternating values does not have to be single - overtones will appear when alternating sounds #00FE and #0101. It is clear that this reduces the usability music coprocessor. Musicians know about this unpleasant phenomenon - after all, they don’t use similar alternations of sounds in your works! When alternating sounds with frequency dividers differ in both the low and high bytes, the frequency divider will be acquire extraneous meanings. It's clear that this is happening because it is impossible to instantly change the values of two at oncecoprocessor registers. And if it were possible, then no there would be no extraneous sounds... Of course, one could completely refuse to use tone generator, with all the problems associated with the installation the frequency divider values for this generator would disappear on their own yourself. We use digital sound - that's all! The quality is perfect! Yes, but this will require absolutely all the resources of the Z80, which we not satisfied at all. Well, let's look into it further. Firstly, can general appearance of extraneous dividers for a very short time Do frequencies have any effect on the sound? You and I know what can it do, and how! But let's see what he says about this theory... The tone generator in the music coprocessor works quite well simple: there is a counter whose value is sequential decreases, and as soon as it decreases to zero, the level the output signal changes, and the value from frequency divider registers. Thus, they are formed rectangular pulses: A ┼ │ ├────┐ ┌────┐ ┌────┐ ┌────┐ ┌─── │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────┴────┴────┴────┴── ──┴────┴────┴────┴────> tIt follows from this that while the counter is not 0, the change Frequency divider registers should not affect the sound. But if the counter is reset at the moment when in the registers the frequency divider contains an extraneous value, this is undoubtedly will affect the sound. Let's try to calculate the probability of this events. Let the frequency divider value change from #0100 to #00FF, the interval between changing the frequency divider registers is 50 Z80 cycles (it is during this period that the divider frequency will take on an extraneous value #01FF), clock Z80 frequency is 3.5 MHz, and coprocessor clock speed is 1.75 MHz. When the frequency divider is #0100, the tone generator generates sound with the following frequency: (1750000/16)/256 = 427.2 Hz The tone generator counter is reset accordingly twice as often, with a frequency of 854.4 Hz. Let's count how many cycles Z80 goes between two counter reboots: 3500000/854.4 = 4096 Then the probability that the counter will be rebooted is at the moment when the frequency divider is equal to #01FF, it is equal to: 50/4096 = 0.012 As we can see, the probability that the tone generator will do although at least one half-cycle with an extraneous frequency, very small - barely more than 1%. But we hear extraneous sounds with 100% probability!Something is wrong here. Maybe the frequency counter is rebooting immediately when writing a new value to the frequency divider registers? ════════════════════════ ════════════════════════ Best regards, Ivan Roshchin. [ZX] [BestView 3.0 - 26%]

From Ivan Roshin To All 7 December 2000

Hello, All! ═══════════════════ mus_sopr.4 ══════════════════ If this is so, the appearance of extraneous sounds becomes understandable. Consider the waveform as the divider changes frequencies from #0100 to #00FF: A ┼ │ ├────┐ ┌──┐┌────┐ ┌────┐ ┌────┐ │ │ │ ││ │ │ │ │ │ │ │ │ ││ │ │ │ │ │ │ │ │ ││ │ │ │ │ │ └────┴────┴──┴┴────┴── ──┴────┴────┴────┴───> xy t At first, the frequency divider was equal to #0100 - that is, R3=#01, R2=#00. Let at the moment of register change R2 the output be high signal level, as shown in the graph. At point x #FF is written to R2 - the frequency divider receives extraneous value #01FF, frequency counter reboots, signal level changes from high to low. At point y #00 is written in R3 - frequency divider became equal to #00FF, frequency counter reboots, the signal level changes from low to high. Due to these two differences in signal level with very small Apparently, the interval between them is where the overtones appear. I had no way to check whether The output of the coprocessor produces a signal of exactly the same shape as on the chart. Then I did it differently: using "digitalsound", tried to reproduce the signal shown on the graph and appreciate its sound. As you would expect, the sound turned out to be the same as when using a tone generator, with the same extraneous sounds. From this we can conclude, that for the values ​​considered in the example, the frequency counter reloads immediately when writing a new value to the registers frequency divider. By the way, it’s easy to check by ear that the frequency counter the envelope also reboots immediately when installing a new one envelope frequency divider (it is set in registers R11 and R12). Here's a way to check: if you enter the envelope shape into the register (R13) value %1000 (gradual decrease in signal level from 15 to 0 in each period of the envelope), and in registers R11, R12 enter #FFFF (so that the envelope period is maximum), to The output of the coprocessor will be this: A ┼ │ │ │\n │ │ │ \n │ │ │ \n │ │ │ \n │ │ │ \n └──────────────────> <──T──> t Envelope frequency: F = (1750000/256)/#FFFF = 0.1043 Hz. Envelope period: T = 1/F = 9.59 s. That is The envelope frequency counter is reset every 9.59/16 = 0.6 seconds (this is for the AY coprocessor, and on the YM the counterwill reboot twice as often - 32 steps are formed there envelope instead of 16). If we assume that the counter is rebooting, only when it decreases to zero will we have to admit that no matter how the value of registers R11, R12 changes, the sound will change only after 0.6 seconds - and when holding experiment, the sound changed instantly! The maximum frequency divider value was chosen because that with this value the counter reset time is also maximum, and one can confidently distinguish the two by ear possible cases - when the sound changes instantly, and when it changes after the counter is reset. For smaller values frequency divider experiments were not carried out. In various Spectrum emulators/AY emulators, how I know that the counter is rebooted only when it is zeroed, so the sound produced is different from the sound real coprocessor (for example, when changing the frequency divider from #0100 to #00FF no extraneous sounds will be heard). You can it would be fair to say that the coprocessor sounds better under the emulator real - but there is no benefit from it, no one will write music exclusively for listening to emulator. But the bad side of inaccurate emulation is obvious - anyone who writes music under an emulator can allow such changes in the frequency of sounds that on a real coprocessorwill be played with extraneous sounds. 4. Determining the type of music coprocessor In the eighth issue of the electronic newspaper 'KrNews' I read that you can programmatically distinguish the type of used coprocessor - AY or YM, and that such a check was in the demo 'ACTION'. True, the method of definition in this newspaper is not described. In the process of studying the specified demo, I discovered the following code snippet: #8021: LD BC,#FFFD LD A,0 OUT (C),A ;set R0 LD B,#BF LD A,#40 ;wrote #40 to R0 OUT(C),A LD B,#FF IN A,(C) ;read from R0 CP #40 ;read what you wrote down? JR Z,#803B ;yes -> there is a coprocessor. LD HL,#84FA ;message address "NO" JR #804E ;go to proc. print messages #803B: LD BC,#FFFD LD A,#10 OUT (C),A ;set to "undocumented" ;register R16 IN A,(C) ;read from it CP #FF ;compare with #FF LD HL,#84E6 ;message address "AY-8910/12" JR NZ,#804E ;not #FF -> display this message. LD HL,#84F0 ;message address "YM2149F"#804E: ............ ;proc. print message Thus, if you try to read the content "undocumented register", then YM will always read #FF. And on AY, as I found out during experiments, the number will be read register (in this example - number #10). If the coprocessor is connected in such a way that its registers are not accessible for reading, the test will show the absence of a coprocessor. ════════════════════════ ════════════════════════ Best regards, Ivan Roshchin. [ZX] [BestView 3.0 - 26%]