11-13-2025, 11:39 AM
(11-13-2025, 08:42 AM)Rudy M Wrote: In the first listing, I med a small change: Second line CONST T! = 0.3 '100 ms chunks to '300ms chunks???
Reason: In the very low frequencies, I heard a "second click," which disappeared by increasing T! to 0.3.
(Remark: Possible its not the QB64 software but 'the limits' of the hardware board(s) in my PC.)
I might add a program line just before the line with the 'PlayPulsewave' statement:
if Frequency < 10 then T!=0.3 else T! = 0.1
Rudy
Yep. T will make PlayPulsewave() send T seconds worth of sample frames to the audio device in one go. You hear the clicks because I made some dumb assumptions. Here, I have updated the demo. This should work much better, and you should not hear the clicks anymore.
Code: (Select All)
OPTION _EXPLICIT
CONST HELP_TEXT = "VOL=" + CHR$(24) + CHR$(179) + CHR$(25) + ", BAL=" + CHR$(27) + CHR$(179) + CHR$(26) + ", DCY=HM" + CHR$(179) + "ED, FRQ=PU" + CHR$(179) + "PD, ESC"
CONST T! = 0.1! ' 100 ms chunks
DIM v AS SINGLE: v = 0.25! ' 25% volume
DIM d AS SINGLE: d = 0.5! ' 50% duty cycle ~ square wave
DIM b AS SINGLE ' center
DIM f AS SINGLE: f = 100 ' Hz
DIM k AS LONG
_CONTROLCHR OFF
DO
CLS
PRINT USING "Duty Cycle: ####%"; d * 100!
PRINT USING "Volume: ####%"; v * 100!
PRINT USING "Balance: ####"; b * 100!
PRINT USING "Frequency: ###### Hz"; f
PRINT
PRINT HELP_TEXT
_DISPLAY
k = _KEYHIT
SELECT CASE k
CASE _KEY_UP: v = _MIN(v + 0.01!, 1!)
CASE _KEY_DOWN: v = _MAX(v - 0.01!, 0!)
CASE _KEY_LEFT: b = _MAX(b - 0.01!, -1!)
CASE _KEY_RIGHT: b = _MIN(b + 0.01!, 1!)
CASE _KEY_HOME: d = _MIN(d + 0.01!, 1!)
CASE _KEY_END: d = _MAX(d - 0.01!, 0!)
CASE _KEY_PAGEUP: f = _MIN(f + 3!, 192000!)
CASE _KEY_PAGEDOWN: f = _MAX(f - 3!, 0!)
CASE _KEY_ESC: EXIT DO
END SELECT
IF _SNDRAWLEN < T THEN PlayPulseWave f, T, d, v, b
_LIMIT 60
LOOP
_AUTODISPLAY
END
''' @brief Plays a stereo pulse wave for a fixed duration. A STATIC phase accumulator is used so that
''' successive calls continue the wave without an audible click.
''' @param frequencyHz Frequency of the pulse wave in Hz.
''' @param timeSec Duration to play in seconds.
''' @param dutyCycle Duty cycle of the waveform [0..1].
''' @param volume Amplitude of the waveform [0..1].
''' @param pan Stereo pan value (-1 = left, 0 = center, +1 = right).
SUB PlayPulseWave (frequencyHz AS SINGLE, timeSec AS SINGLE, dutyCycle AS SINGLE, volume AS SINGLE, pan AS SINGLE)
STATIC phase AS SINGLE
DIM sampleRate AS SINGLE: sampleRate = _MAX(_SNDRATE, 1!)
DIM samples AS LONG: samples = _MAX(timeSec, 0!) * sampleRate
DIM duty AS SINGLE: duty = _CLAMP(dutyCycle, 0!, 1!)
DIM amp AS SINGLE: amp = _CLAMP(volume, 0!, 1!)
DIM freqStep AS SINGLE: freqStep = _MAX(frequencyHz, 0!) / sampleRate
DIM panMapped AS SINGLE: panMapped = (_CLAMP(pan, -1!, 1!) + 1!) * _PI(0.25!)
DIM gainLeft AS SINGLE: gainLeft = COS(panMapped)
DIM gainRight AS SINGLE: gainRight = SIN(panMapped)
DIM sample AS SINGLE, i AS LONG
WHILE i < samples
phase = phase + freqStep
IF phase >= 1! THEN phase = phase - INT(phase)
sample = _IIF(phase < duty, amp, -amp)
_SNDRAW sample * gainLeft, sample * gainRight
i = i + 1
WEND
END SUB

