Jump to content
IGNORED

Sound synthesis with Square Waves


DZ-Jay
 Share

Recommended Posts

Can someone provide some general information or resources on practical sound synthesis with only square waves? All my experience is centered around 1980s synth technology using additive synthesis with sine waves, subtractive with filters, or FM synthesis.

 

Can someone guide me in affecting the harmonic content of square waves using, well, other square waves (and perhaps a noise generator)?

 

(Note, extra bonus points if you avoid using maths.)

Link to comment
Share on other sites

Using the envelope generator at a pretty high frequency and using with a basic channel you can trigger a kind of electronic instrument.

 

Like this (14:20)

 

https://www.youtube.com/watch?v=QhsaziIz4Mg

 

Edit: BTW, liking the noise drums, maybe IntyBASIC should have something of this.

  • Like 2
Link to comment
Share on other sites

Using the envelope generator at a pretty high frequency and using with a basic channel you can trigger a kind of electronic instrument.

 

Like this (14:20)

 

https://www.youtube.com/watch?v=QhsaziIz4Mg

 

Edit: BTW, liking the noise drums, maybe IntyBASIC should have something of this.

Thanks, but I'm looking more into reproducing sound effects and musical instruments by altering the timbre of a tone.

Link to comment
Share on other sites

Thanks, but I'm looking more into reproducing sound effects and musical instruments by altering the timbre of a tone.

I've done experiments with attack/sustain/decay volume, IntyBASIC contains piano, flute and clarinet instruments.

 

The most difficult instruments to even approximate are trumpet, violin and other related ones.

Link to comment
Share on other sites

I've done experiments with attack/sustain/decay volume, IntyBASIC contains piano, flute and clarinet instruments.

 

The most difficult instruments to even approximate are trumpet, violin and other related ones.

Yeah, but that doesn't change the colour of the sound. Thanks, but my question is about sound synthesis, not about tracking chiptunes.

Link to comment
Share on other sites

DZ, you might find this useful :-

 

http://cmc.music.columbia.edu/musicandcomputers/

 

ADSR also comes in handy for creating instruments :-

 

http://en.wikiaudio.org/ADSR_envelope

Hi, GroovyBee,

 

Thanks for the resources. The problem is that the PSG has only square waves and no filters, so to change the timbre of a sound, you'll probably have to combine multiple channels in some way. Furthermore, my understanding is that square waves only have odd harmonics and I don't know how to shape the waves with that. My experience in additive synthesis is with fundamental sine waves. :(

 

I'm sure there's some mathematical formula for the sum of two square waves, and I figured that, being "square" (i.e., duty cycle is stable throughout all frequencies), the specific harmonics altered (if any) must be known for a given combination of pitches. That is, this is what my intuition tells me. I have no idea what is the physical result of combining square waves.

 

I took a quick look at that site you sent and on the surface, it seems to go in the same direction I have always seen: square waves are rich in harmonics, so you use filters to alter them. I don't ever find how to use other square waves to shape a tone -- or if that is done at all. Unfortunately, on the PSG, using filters is out of the question.

 

That said, I'll read further since it seems to be comprehensive.

 

As for ADSR envelopes, I'm all familiar with those for shaping the amplitude of the tones. At the moment I'm interested in altering the timbre or colour of the stock tones.

 

dZ.

Link to comment
Share on other sites

The only synth effect I've heard in PSG, TI SN, and clones is using 2 channels with similar(same?) frequency. Also, playing same note in different octaves (Wizball song does both). Other than that, I've only heard digital samples.

 

Atari ST, Wizball title screen: (skip to 0m 23s)

https://www.youtube.com/watch?v=nOnLKqD2NSE&feature=youtu.be&t=24s

 

Sega Master, Rastan ending (skip to 2m 47s)

https://www.youtube.com/watch?v=ljUI9AZLL5Q&feature=youtu.be&t=2m47s

 

I also found a yt video of a zx spectrum song called "Megaherc", I'm guessing it's alternating between digital samples and square waves.

Link to comment
Share on other sites

I think the 3 oscillators in the Intellivision sound chip are completely independent of one another, so you can't mix the signals and expect them to mesh together in any consistent way.

 

(The reason I I think this is my experience on the infamous Match 5 soundtrack. I created this soundtrack for the tracker program. The tracker program requires you to set up sound data for all 3 channels of the sound chip. Unfortunately, as a newbie sound composer, I only had 2 channels worth of musical ideas. What could I do about the third, unneeded channel? In this case my two options were:

 

1. Hack the tracker to only use 2 channels (I think Joe did this for Space Patrol so he would have one channel free for sound effects.)

2. Create zero volume sound data for the unused channel that is the exact same length (timewise) as the other 2 channel's sound data.

 

Instead of one of these two sensible workable options, I created option 3...

 

3. Setup the unneeded third channel to play the exact same sound data as one of the other two channels.

 

 

I thought 2 channels playing he same data would be better than one. But apparently, because the channels are entirely independent - sometimes the waves are in sync and add together, but other times the waves are completely out of phase and cancel each other out... So, my music had random fluctuations in volume.

 

(On the other hand - the music was never played the same way twice.....))

 

 

Catsfolly

  • Like 1
Link to comment
Share on other sites

I think the 3 oscillators in the Intellivision sound chip are completely independent of one another, so you can't mix the signals and expect them to mesh together in any consistent way.

 

(The reason I I think this is my experience on the infamous Match 5 soundtrack. I created this soundtrack for the tracker program. The tracker program requires you to set up sound data for all 3 channels of the sound chip. Unfortunately, as a newbie sound composer, I only had 2 channels worth of musical ideas. What could I do about the third, unneeded channel? In this case my two options were:

 

1. Hack the tracker to only use 2 channels (I think Joe did this for Space Patrol so he would have one channel free for sound effects.)

2. Create zero volume sound data for the unused channel that is the exact same length (timewise) as the other 2 channel's sound data.

 

Instead of one of these two sensible workable options, I created option 3...

 

3. Setup the unneeded third channel to play the exact same sound data as one of the other two channels.

 

 

I thought 2 channels playing he same data would be better than one. But apparently, because the channels are entirely independent - sometimes the waves are in sync and add together, but other times the waves are completely out of phase and cancel each other out... So, my music had random fluctuations in volume.

 

(On the other hand - the music was never played the same way twice.....))

 

 

Catsfolly

 

Interesting. That was going to be one of my questions to the group at some point: if the oscillators were synchronized in some way. I personally thought they were, since duplicating one track of my Christmas Carol theme resulted in a "phasing" effect of that track. I always thought I could take advantage of this by slightly de-tuning one channel against another.

 

It is interesting that you found the opposite to be the case. I wonder if this could be controlled with the "Sound Enable" flag of each channel. That is, if enabling all channels simultaneously cause them to be in synchronicity.

 

All that said, the IntelliWiki does specify that each channel has a dedicated tone generator and D/A converter, so perhaps it's not possible.

 

-dZ.

Link to comment
Share on other sites

Detuning a doubled-up voice with a small frequency variance will result in the phasing effect that mmarrero was referencing. The frequency difference between the oscillators will represent the frequency of the phase sweep. To get a nice long sweep on the VCS I run the same frequency for most of the time, and change the frequency for a few scanlines.

 

If you run doubled up square waves with no frequency difference between them, it's a pretty good approximation of PCM, with most of the wave being cancelled or reinforced, depending on the phase difference. In practice, the phase will probably drift during a song, because you can't change both oscillators at the same instant. You'd probably want to periodically resync them, assuming thats possible.

 

Back to the original question - there's a handful of techniques to use with square wave. Additive synthesis isn't particularly useful, since square waves aready hit a bunch of harmonics. You can do a so-so approximation of sawtooth with 2 squarewaves - one at your main frequency, another at half the volume and twice the frequency. It fills in every other even harmonic of the main frequency. But sawtooth without filters... meh.

 

That leaves you with phasing (discussed) and changing volume/envelope or frequency at audio-frequency speeds. (Edit: and sample/soft-synth playback)

 

Changing envelope at audio-frequency rates can be used to create a sound that's more or less the same as a base frequency run through one or more band pass filters (the frequency that the voices you're volume-switching are actually set to). I've used this before to create vowel phonemes for a speech synth I was writing on a microcontroller. For anyone trying this, it's better if the volume envelope is less square, and more sine. (glottal pulse shaped is ideal)

 

Changing voice frequency at audio-frequency speeds is the basis behind FM, but the resolution on these old chips is too coarse to pull that off. But something similar to the polycounter type sounds on TIA/POKEY is doubtlessly possible. If the switching frequency is related to the frequency played it would be more musical.

  • Like 1
Link to comment
Share on other sites

Detuning a doubled-up voice with a small frequency variance will result in the phasing effect that mmarrero was referencing. The frequency difference between the oscillators will represent the frequency of the phase sweep. To get a nice long sweep on the VCS I run the same frequency for most of the time, and change the frequency for a few scanlines.

 

If you run doubled up square waves with no frequency difference between them, it's a pretty good approximation of PCM, with most of the wave being cancelled or reinforced, depending on the phase difference. In practice, the phase will probably drift during a song, because you can't change both oscillators at the same instant. You'd probably want to periodically resync them, assuming thats possible.

 

Back to the original question - there's a handful of techniques to use with square wave. Additive synthesis isn't particularly useful, since square waves aready hit a bunch of harmonics. You can do a so-so approximation of sawtooth with 2 squarewaves - one at your main frequency, another at half the volume and twice the frequency. It fills in every other even harmonic of the main frequency. But sawtooth without filters... meh.

 

That leaves you with phasing (discussed) and changing volume/envelope or frequency at audio-frequency speeds. (Edit: and sample/soft-synth playback)

 

Changing envelope at audio-frequency rates can be used to create a sound that's more or less the same as a base frequency run through one or more band pass filters (the frequency that the voices you're volume-switching are actually set to). I've used this before to create vowel phonemes for a speech synth I was writing on a microcontroller. For anyone trying this, it's better if the volume envelope is less square, and more sine. (glottal pulse shaped is ideal)

 

Changing voice frequency at audio-frequency speeds is the basis behind FM, but the resolution on these old chips is too coarse to pull that off. But something similar to the polycounter type sounds on TIA/POKEY is doubtlessly possible. If the switching frequency is related to the frequency played it would be more musical.

 

Thank you, that was very useful.

 

-dZ.

  • Like 1
Link to comment
Share on other sites

DZ if you want a mathematical solution to the problem of developing a signal using square waves, this is what you need. I used a pdf, because the forum does not allow math notation.

The method is general and lends itself to an encoder close to the voice encoder I've released. Anyway, for the voice encoder, I ended to use the FFT, as it was a fast algorithm ready to use, even if not optimal.


[edited in order to debug the pdf]

[edited again in order to add a matlab example and remove other errors]


square waves.pdf

Edited by artrag
  • Like 1
Link to comment
Share on other sites

 

DZ if you want a mathematical solution to the problem of developing a signal using square waves, this is what you need. I used a pdf, because the forum does not allow math notation.
The method is general and lends itself to an encoder close to the voice encoder I've released. Anyway, for the voice encoder, I ended to use the FFT, as it was a fast algorithm ready to use, even if not optimal.
[edited in order to debug the pdf]

 

 

Well, I was trying to avoid a mathematical solution, since I suck at maths, but I really appreciate it nonetheless. Thanks, artrag; I'll take a look at it. :)

 

-dZ.

Link to comment
Share on other sites

I added a matlab example in the pdf as the forum does not allow to attach m files. Being few lines, I attached here same script.

%% Fourier representation of a signal on a set of square waves 
% The code represents a signal s(t) in [0,T) using an approximated basis 
% of square waves spaced at frequency n/T

%% Section 1 digital framework

FF = 22000; % sampling frequancy 22KHz
Ts = 1/50;  % PAL

Ns = FF * Ts;       % number of samples in [0,T)

t = (0:(Ns-1))/FF;  % time line in [0,T)

Fs = 1/Ts;
%% Section 2 Title
% Generation of the basis B as matrix 

B = zeros(Ns);
for n=0:(Ns-1)
    B(:,1+n) = (sign(cos(2*pi*(n/2)*Fs*t))/sqrt(Ts))';
end

%% Section 3 Title
% Analisys of the pseudo orthogonality of the base B

figure(1);
plot(t,B)

figure(2);
O =  B'*B/Ns*Ts;
imagesc(abs(O))
colormap(gray);

%% Section 4 Title
% generate a test function

s = sin(2*pi*t/Ts).^6; % put here what you like to see

%% Section 5 Title
% decompose the test function on B

c = s*B;

% reconstruction using ALL the base function
so = B*c'/Fs/Ns;

% reconstruction using the 3 strongest base function (as the PSG would do)
[~,i] = sort(abs(c),'descend');
cc = zeros(size(c));
cc(i(1:3)) = c(i(1:3));

ss = B*cc'/Fs/Ns;

figure(3)
plot(t,s,t,so,t,ss)
% in blue the original
% in red the PSG version
% in green the "complete" reconstruction 

  • Like 1
Link to comment
Share on other sites

Wow, Arturo, that's fantastic. I can't say I understand it (maths elude me), but this seems like exactly what I was looking for. I will brush up on my calculus and try to make sense of it. I'll play around with MatLab as well.

 

Thanks a lot! :)

 

-dZ.

 

P.S. I do understand the synthesis part and its implications. By your test it seems that the results are at least acceptable. My aim was not necessarily to simulate any specific sound (like you were trying to do with speech synthesis), but to at least be able to change the character of a tone by altering its harmonic content. I'll have to implement something on the PSG and see how it actually sounds. Great job! :thumbsup:

Edited by DZ-Jay
Link to comment
Share on other sites

As you have matlab, you should play also this other script, where I take into account the non orthogonality of the square waves in computing the coefficients used in reconstructing the test signal.

Comments on the results are in the source.

%% Fourier representation of a signal on a set of square waves
% The code represents a signal s(t) in [0,T) using an approximated basis
% of square waves spaced at frequency n/T

%% Section 1 digital framework
FF = 22000; % sampling frequancy 22KHz
Ts = 1/50; % PAL
Ns = FF * Ts; % number of samples in [0,T)
t = (0:(Ns-1))/FF; % time line in [0,T)
Fs = 1/Ts;

%% Section 2 
% Generation of the basis B as matrix
B = zeros(Ns);
for n=0:(Ns-1)
 B(:,1+n) = (sign(cos(2*pi*(n/2)*Fs*t))/sqrt(Ts))';
end

%% Section 3 
% Analysis of the pseudo orthogonality of the base B
figure(1);
plot(t,B)
figure(2);
M = B'*B/FF;
imagesc(abs(M)); % as before, the basis is not completely orthonormal (look at the off diagonal gray stripes )
colormap(gray);

%% Section 4 
% Generate a test function
s = sin(2*pi*t'/Ts).^6;     % put here any s(t) you like to see
Nc = 3;                     % number of psg channels
%
% try to vary Nc from 3 up to Ns to see how the reconstructed signal 
% approximates the test function with the different methods 

%% Section 5 
% decompose the test function on B
c = B'*s/FF;
% reconstruction of s(t) using ALL the base function as they were
% orthonormal
s0 = B*c;             % noise in the reconstruction is due to the non orthogonality of the base functions

% reconstruction of s(t) using the 3 strongest base function (as the PSG would do)
[~,i] = sort(abs(c),'descend');
s1 = B(:,i(1:Nc))*c(i(1:Nc));    % approximate reconstruction

figure(3)
plot(t,s,t,s0,t,s1)         % compare the original, the full reconstruction affected by the correlation noise, the approximation using the 3 strongest functions 

%% Section 5 
% remove the approximation of orthogonality

M = B'*B/FF;    % cross products among the base functions
x = M\c;        % as we have M*x = c we can get x as M^-1*c

s2 = B*x;       % exact reconstruction on a complete non orthonormal basis, it is exactly equal to s (!!)

% reconstruction of s(t) using the 3 strongest base function (as the PSG would do)
% recomputing the coefficients taking into account the correlation among the 3
% base functions
BB = B(:,i(1:Nc));
MM = BB'*BB/FF;
xx = MM\c(i(1:Nc));
s3 = BB*xx;       % reconstruction on a non orthonormal set of sole 3 tones

figure(4)
plot(t,s,t,s2,'.',t,s3) % compare the original, the complete reconstruction (dotted), and the approximation using the 3 strongest coefficients

Edited by artrag
  • Like 1
Link to comment
Share on other sites

Willing to express the algorithm in words, one should

1) compute the decomposition of s(t) on the complete non orthogonal base B

c = B'*s/FF;

 

2) find the indexes of the highest coefficients

[~,i] = sort(abs©,'descend');

 

3) compute a new set of base functions with the Nc=3 frequencies that give the strongest coefficients

BB = B(:,i(1:Nc));

 

4) compute the cross correlation matrix of the new set of functions (it will be 3x3)

MM = BB'*BB/FF;

 

5) compute the weights to be used in the reconstruction by inverting the cross correlation matrix and producing it by the strongest coefficients

xx = MM\c(i(1:Nc));

 

6) reconstruct the approximated signal using the weights in xx and the functions B(:,i(1)), B(:,i(2)) and B(:,i(3))

s3 = BB*xx;

The values in xx(1),xx(2) and xx(3) are the amplitudes to be used with the functions B(:,i(1)), B(:,i(2)) and B(:,i(3)).

B(:,n), with n in [1,Ns], in turns corresponds to a square wave of period 2Ts/n

 

In the end, you need to find the values of i(1),i(2)and i(3) that give the frequencies and xx(1),xx(2) and xx(3) that give the volumes of the 3 PSG channels

Edited by artrag
  • Like 1
Link to comment
Share on other sites

Thank you again for that, Arturo. You've been very kind with all this information. It'll come in handy as one of my personal passion projects is to build an Intellivision synthesizer to create sounds the way we used to do it back with old analog synths. :)

Link to comment
Share on other sites

About the methods depicted above, the improvement over the quick and dirty solution i used in the voice encoder appears only when the number of square waves increases.

As the intellivision has (can have) two PSGs, it could be worth a try if you use 6 channels.

 

The problem is the phase control. Phase offsets among the channels impair the actual result and the resilience of the human hear is limited, because in this case the error affects square waves and not sines.

 

If one could control, the phase error among channels the result would be exactly what you get from matlab.

 

I was thinking about setting the period to 1 before setting the actual value to reset the counter of the AY8910 divider. If this is works, one could limit the phase offset to the time the CPU needs to load the values in the PSG registers.

 

Do you have any insight of how to reset the phase of a AY8910 ?

 

[edit: period should be 1 to reset immediately the internal counter, not 0xFFF, me bad]

Edited by artrag
  • Like 1
Link to comment
Share on other sites

 

Do you have any insight of how to reset the phase of a AY8910 ?

 

No, I don't, but I also considered like you that you could somewhat synchronize the phases by resetting the counters. My understanding is that they all divide the same master clock, so it should be possible. Also, it should be possible to exploit the execution length of CPU instructions in order to correct for delays between loading registers.

 

All this is theoretical, though, and I am much too slow a coder to be able to make trial-and-error tests to experiment. Perhaps intvnut can chime in, for he has a much greater insight into the PSG's machinery.

 

-dZ.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...