two signals with different frequencies to play at the same time without audio clipping

19 views (last 30 days)
Hi
I want to play two sounds at the same time (d1 and d01), and they have different frequencies. My issue is that when I run the code the audio clips and it is because of d01(when I remove it the code works fine). I considered combining them but im not sure how to do that.
C=220*2^(3/12);
Cc=220*2^(4/12);
G=220*2^(10/12);
T=1/8000;
num=[1:1:(2*8000)+1];
d1=sin(2*pi*C*T*num).*(heaviside(T*num)-heaviside(T.*num-0.5));
d01=sin(2*pi*Cc*T*num).*(heaviside(T*num)-heaviside(T.*num-0.5));
d2=sin(2*pi*C*T*num).*(heaviside(T*num-0.75)-heaviside(T.*num-1.25));
d3=sin(2*pi*G*T*num).*(heaviside(T*num-1.5)-heaviside(T.*num-2));
notes=d1+d01+d2+d3;
vector=zeros(1,2*8000+1);
for i=1:2*8000+1
vector(i)=notes(i);
end
audiowrite('test.wav',vector,8000);
Warning: Data clipped when writing file.
r=audioread('test.wav');
sound(r,8000,8);

Accepted Answer

William Rose
William Rose on 4 Nov 2022
I see that you are starting from A440, divividing by 2 to go down an octave, then using the circle of fifths with equal temperament to go up to middle C, C#, G.
audiowrite likes signals to be in the range -1 to +1. I added a line to your code to display the min and max of notes. As you will see, min=-2, max=+2. Therefore you could just divide the whole signal by 2 and it would be OK. I wrote a more general rescaling funciton that will re-map notes to the rage [-1,+1], for any min and max. I also added a line to display the min and max of rescaled notes.
C=220*2^(3/12);
Cc=220*2^(4/12);
G=220*2^(10/12);
T=1/8000;
num=[1:1:(2*8000)+1];
d1=sin(2*pi*C*T*num).*(heaviside(T*num)-heaviside(T.*num-0.5));
d01=sin(2*pi*Cc*T*num).*(heaviside(T*num)-heaviside(T.*num-0.5));
d2=sin(2*pi*C*T*num).*(heaviside(T*num-0.75)-heaviside(T.*num-1.25));
d3=sin(2*pi*G*T*num).*(heaviside(T*num-1.5)-heaviside(T.*num-2));
notes=d1+d01+d2+d3;
fprintf('notes: min=%.2f, max=%.2f\n',min(notes),max(notes))
notesRe=(notes-min(notes))*2/(max(notes)-min(notes))-1; %rescaled notes
fprintf('rescaled notes: min=%.2f, max=%.2f\n',min(notesRe),max(notesRe))
vector=zeros(1,2*8000+1);
for i=1:2*8000+1
vector(i)=notesRe(i);
end
audiowrite('test.wav',vector,8000);
r=audioread('test.wav');
sound(r,8000,8);
It seems to work. No more warning message.
  4 Comments
William Rose
William Rose on 4 Nov 2022
You have undoubtedly noticed that the sound of C and C# together, generated by the script, does not sound like C and C# when struck simultaneously on a real piano. Why not? I think because our Matlab sound is too "perfect". The C and C# waveforms in the script are perfect sinusoids with no frequency broadening and no overtones.
A similar example is that if you generate a C major triad in Matlab in the same way as your script, it does not sound like a C major triad played on a piano.
This is an interesting topic to investigate further in a term paper or project. This has been worked out exhaustively when analog and then digital synthesizers were developed in the 60s and 70s. But it would still be an interesting little project. Use a cell phone to record notes and chords from a real piano. Import the sound file to Matlab. Compare the real waveforms to the Matlab-generated waveforms, and determine how they differ. One might learn why music played on a real (analog or electronic) piano sounds different (better) than the pure sine wave music we have generated in Matlab.
William Rose
William Rose on 4 Nov 2022
Here is a script that generates a C major arpeggio and triad:
fC=220*2^(3/12); %middle C frequency (Hz)
fEe=fC*2^(4/12); %E frequency (Hz), equal temperament
fGe=fC*2^(7/12); %G frequency (Hz), equal temperament
fs=8000; %sampling rate (Hz)
dT=1/fs; %sampling interval (s)
t10=dT:dT:1; %1.0 second long time vector
si1=zeros(1,fs*0.1); %0.1 seconds of silence
t6=dT:dT:0.6; %0.6 second long time vector
%generate arpeggio + triad waveform
r1=[sin(2*pi*fC*t6),si1,sin(2*pi*fEe*t6),si1,sin(2*pi*fGe*t6),si1,...
(sin(2*pi*fC*t10)+sin(2*pi*fEe*t10)+sin(2*pi*fGe*t10))/3];
r1=rescale(r1,-1,1); %probably not necessary in this case
sound(r1,fs) %play arpeggio + triad
The individual notes sound reasonable, but when combined in a chord, they sound different than doing it on the piano.
I also tried it using the just temperament frequencies for E and G, not shown above. The resulting sounds were the same, to my ear. I wondered if the computer-generated just and equal temperament chords would sound different, because the just temperament frequencies are exact fractional multiples of the base frequency, and the equal temperament values are not. Therefore the C, E, G waveforms stay in phase for just temperament, but they get out of phase for equal temperament. The computer-generated just and equal temperament triads sound the same to me: they both sound different from a real piano.

Sign in to comment.

More Answers (0)

Categories

Find more on Measurements and Spatial Audio in Help Center and File Exchange

Products


Release

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!