• Please review our updated Terms and Rules here

OPL clicking sound when triggering notes quickly

PgrAm

Experienced Member
Joined
Sep 28, 2011
Messages
276
Location
Toronto, Canada
Hey all,

While Ive been working on polishing up Adlib-Host V1.2, I've been noticing an annoying issue with my Adlib(OPL) music player, it seems that whenever I trigger a note immediately after releasing a previous note I get an audible clicking noise. Doing more testing I was able to determine that this happened any time two writes were done the the 0xB0 register on any given channel within a short period of time, such as when doing a pitch bend.

I know that OPL chips require delays between any register writes, which I have included, but I haven't read anything about requiring extra delay for writes to the same register. Stranger still is that this seems to affect both geniune chips (OPL3 tested) and DOSBox, which normally isn't affected by delays. I was even able to find this "bug" in commercial software from the 90s such as Voyetra sequencer.

Has anyone noticed this issue before, know why it happens? Maybe writing to the register resets the phase of the wave? I wasn't able to reproduce it in "tracker" style software (Adlib Tracker 2) however so maybe there is a way around it?

At this point I haven't yet determined how long the gap between writes needs to be but I'm hoping there is a way around this that doesn't involve delays. I also haven't tested this on an OPL2 (I don't have one) but I suspect the issue will still exist.
 
Ok I did some more work on this and I have found a sort of solution. Always playing a new note on the least recently used OPL channel, that way two notes never get triggered back to back on the same channel. This however seems unsatisfying to me, since it doesn't actually solve the problem it just hides it
 
Really curious to hear an example of this. IIRC the simpler Yamaha chips do reset the phase of the operator waveform on key-on (the DX7s and I think the higher-tier 4-op synths make this a per-operator parameter,) but it shouldn't happen just on writing the register. Otherwise, it sounds like maybe some kind of weird EG reset behavior.
 
Yeah its strange, I'll try to get you a recording of it just as soon as I can figure out how to attach audio into this forum
 
Ok I'm just gonna attach a link to the file here

You can hear it on the last note during the vibrato (just a fast pitch bend), its a clicking or popping noise.
 
Are you writing the register with the key-on bit set each time or are you toggling it? Based on what I've seen in the OPLL datasheet (not the same chip but similar) doing a quick on-off-on will cause a pop because it brings the previous note down to zero (in 10ms or less) before it starts the next one.

Aside from that, if you are changing the pitch maybe it would make a difference whether the low or high byte is written first. Also check that unused bits in the $B0 register aren't affecting anything.
 
So the pitch bend always sets the key on bit, and is only applied when the note is already on. I always write the least significant byte first, so 0xA0 followed by 0xB0.
 
Either you're not performing the correct delays (3.3 microseconds after a register select write, and 23 microseconds after a data write), or something you're doing is resetting the phase of the wave. Not sure which, but posting your adlib register write code might help.
 
Pretty sure the delay code is correct, but here it is if you wanna take a look, the first function is for OPL2 and the second is for OPL3

Code:
.8086
.model compact
.code
PUBLIC OPL_write_register_
PUBLIC OPL_enable_low_delay_write_

align 2
OPL_write_register_ Proc near
out dx, al
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
mov al, bl
inc dx		; switch to the data register 
out dx, al	; write to the data register
dec dx		; switch back to the index register
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
in al, dx
ret
OPL_write_register_  Endp 

align 2
OPL3_write_register_ Proc near
out dx, al
in al, dx
in al, dx
in al, dx
in al, dx
mov al, bl
inc dx
out dx, al
dec dx
in al, dx
in al, dx
in al, dx
in al, dx
ret
OPL3_Proc_end:
OPL3_write_register_  Endp 

; WARNING: self modifying code
; patches the OPL_write_register_ by copying
; OPL3_write_register_ in its place
OPL_enable_low_delay_write_  Proc near
push ds
mov cx, cs
mov es, cx
mov ds, cx
mov si, OPL3_write_register_
mov di, OPL_write_register_
mov cx, OPL3_Proc_end - OPL3_write_register_
rep movsb
pop ds
ret
OPL_enable_low_delay_write_ Endp

end
 
Your code is good, so what's going on is that you're switching to a frequency that, in combination with the phase of the output, is producing too high a zero-crossing. If you're hearing this on real hardware, an emulator, and in commercial software, there's nothing wrong with your code.

Whether it's a bug or design flaw in the chip, or incorrect handling of the data being sent to the chip, is up for debate -- but I will mention that the existence of vibrato bits in 0x20 to 0x35, and 0xBD, suggests that vibrato was intended to be handled by the chip.
 
I don't think there should be any problem in general doing either portamento or vibrato. Check the track "Gyges, Will You Please Help Me?" from Tyrian as an example. I made a test program and ran it on an SB16 which played a note and then ran through the range of frequency values. No pops. Although I didn't try crossing octaves.
 
Back
Top