Matlab file doesn't produce audio
Show older comments
Hi, I am trying to produce an audio file out of the following matlab code. When I go to play these Matlab Files Matlab just hangs and I am unable to get any output out of them. Is there a specific way that these files have to be played to get a successful output? Any help is appreciated Matlab code below
I am trying to play the bach_fugue.mat file with the 2 matlab files below.
First File
clear;
load bach_fugue.mat;
fs = 11025; % set sampling frequency
bpm = 120; % set tempo in beats per minute
bps = bpm/60; % tempo in beats per second
spb = 1/bps; % seconds per beat (inverse of bps)
spp = spb/4; % seconds per pulse
sampp = fs*spp; % samples per pulse
voices = length(theVoices);
xx = zeros(1,560000);
for i = 1:voices % for loop that runs through different voices in theVoices
notenum = length(theVoices(i).noteNumbers);
n1 = 1;
% establish value for rest
rest = key2note(0,theVoices(i).startPulses(1)*spp,i);
n2 = n1 + length(rest) - 1;
xx(n1:n2) = xx(n1:n2) + rest;
n1 = n2 + 1;
% for loop that runs through each note in current voice
for k = 1:notenum
dur = theVoices(i).durations(k)*spp;
keynum = theVoices(i).noteNumbers(k);
firstPulse = theVoices(i).startPulses(k);
tone = key2note(keynum, dur, i);
n2 = n1 + length(tone) - 1;
xx(n1:n2) = xx(n1:n2) + tone;
n1 = n2 + 1;
% conditional statement to create inter-note pauses
if k < notenum
if (theVoices(i).startPulses(k+1)-firstPulse) > dur
pause = key2note(0,theVoices(i).startPulses(k+1)-(firstPulse)*spp,i);
n2 = n1 + length(pause) - 1;
xx(n1:n2) = xx(n1:n2) + pause;
n1 = n2 + 1;
end
end
end
end
soundsc(xx, fs);
specgram(xx,512,fs);
Second File
function xx = key2note(keynum, dur, voicenum)
fs = 11025;
tt = 0:(1/fs):dur;
if (keynum == 0)
xx = zeros(1, length(tt)); % pause if no note
else
freq = 440*2^((keynum-49)/12);
if (voicenum == 1)
f = freq*[1 2 3 4]';
A = [1 1/2 1/4 1/8];
elseif (voicenum == 2)
f = freq*[1 3 5]';
A = 0.8*[1 1/2 1/4];
elseif (voicenum == 3)
f = 1.5*freq*[1 2 3 4]';
A = [1 1/2 1/4 1/8];
end
xx = A*cos(2*pi*f*tt);
% ADSR Envelope
if( dur>0.15 )
E = interp1([0,0.05,0.1,dur-0.05,dur],[0,1,0.9,0.8,0],tt);
elseif( dur>0.10 )
E = interp1([0,0.05,dur-0.05,dur],[0,1,0.8,0],tt);
else
E = interp1([0,0.05,dur],[0,1,0],tt);
end
% multiply xx by ADSR envelope
xx = xx.*E;
end
end
10 Comments
Walter Roberson
on 7 Mar 2024
We need bach_fugue.mat to test with.
Jacob
on 7 Mar 2024
Jacob
on 7 Mar 2024
Voss
on 7 Mar 2024
xx = zeros(1,560000);
This makes xx length 560000. No subsequent part of the code increases the length of xx, only adds new notes onto existing consecutive elements of xx. So whatever length xx is initialized to has to be enough to store all the notes, and apparently 560000 is not enough samples to store all the notes.
Your song exceeds 1e8 in size.
load bach_fugue.mat;
fs = 11025; % set sampling frequency
bpm = 120; % set tempo in beats per minute
bps = bpm/60; % tempo in beats per second
spb = 1/bps; % seconds per beat (inverse of bps)
spp = spb/4; % seconds per pulse
sampp = fs*spp; % samples per pulse
voices = length(theVoices);
xx = zeros(1,1e8);
for i = 1:voices % for loop that runs through different voices in theVoices
notenum = length(theVoices(i).noteNumbers);
n1 = 1;
% establish value for rest
rest = key2note(0,theVoices(i).startPulses(1)*spp,i);
n2 = n1 + length(rest) - 1;
xx(n1:n2) = xx(n1:n2) + rest;
n1 = n2 + 1;
% for loop that runs through each note in current voice
for k = 1:notenum
dur = theVoices(i).durations(k)*spp;
keynum = theVoices(i).noteNumbers(k);
firstPulse = theVoices(i).startPulses(k);
tone = key2note(keynum, dur, i);
n2 = n1 + length(tone) - 1;
disp(-[n1, n2]), whos xx
xx(n1:n2) = xx(n1:n2) + tone;
n1 = n2 + 1;
% conditional statement to create inter-note pauses
if k < notenum
if (theVoices(i).startPulses(k+1)-firstPulse) > dur
pause = key2note(0,theVoices(i).startPulses(k+1)-(firstPulse)*spp,i);
n2 = n1 + length(pause) - 1;
disp([n1, n2]), whos xx
xx(n1:n2) = xx(n1:n2) + pause;
n1 = n2 + 1;
end
end
end
end
whos xx
soundsc(xx, fs);
specgram(xx,512,fs);
function xx = key2note(keynum, dur, voicenum)
fs = 11025;
tt = 0:(1/fs):dur;
if (keynum == 0)
xx = zeros(1, length(tt)); % pause if no note
else
freq = 440*2^((keynum-49)/12);
if (voicenum == 1)
f = freq*[1 2 3 4]';
A = [1 1/2 1/4 1/8];
elseif (voicenum == 2)
f = freq*[1 3 5]';
A = 0.8*[1 1/2 1/4];
elseif (voicenum == 3)
f = 1.5*freq*[1 2 3 4]';
A = [1 1/2 1/4 1/8];
end
xx = A*cos(2*pi*f*tt);
% ADSR Envelope
if( dur>0.15 )
E = interp1([0,0.05,0.1,dur-0.05,dur],[0,1,0.9,0.8,0],tt);
elseif( dur>0.10 )
E = interp1([0,0.05,dur-0.05,dur],[0,1,0.8,0],tt);
else
E = interp1([0,0.05,dur],[0,1,0],tt);
end
% multiply xx by ADSR envelope
xx = xx.*E;
end
end
Jacob
on 7 Mar 2024
Walter Roberson
on 7 Mar 2024
This is why it does not play anything: it reaches the end of array xx
Jacob
on 7 Mar 2024
You can set a buffer size and quit filling it when you get to the end of the buffer.
load bach_fugue.mat;
fs = 11025; % set sampling frequency
bpm = 120; % set tempo in beats per minute
bps = bpm/60; % tempo in beats per second
spb = 1/bps; % seconds per beat (inverse of bps)
spp = spb/4; % seconds per pulse
sampp = fs*spp; % samples per pulse
voices = length(theVoices);
maxXX = 560000;
xx = zeros(1,maxXX);
for i = 1:voices % for loop that runs through different voices in theVoices
notenum = length(theVoices(i).noteNumbers);
n1 = 1;
% establish value for rest
rest = key2note(0,theVoices(i).startPulses(1)*spp,i);
n2 = n1 + length(rest) - 1;
xx(n1:n2) = xx(n1:n2) + rest;
n1 = n2 + 1;
% for loop that runs through each note in current voice
for k = 1:notenum
dur = theVoices(i).durations(k)*spp;
keynum = theVoices(i).noteNumbers(k);
firstPulse = theVoices(i).startPulses(k);
tone = key2note(keynum, dur, i);
n2 = n1 + length(tone) - 1;
if n2 > maxXX
margin = maxXX - n1 + 1;
tone = tone(1:margin);
n2 = maxXX;
end
disp(-[n1, n2])
xx(n1:n2) = xx(n1:n2) + tone;
n1 = n2 + 1;
if n1 > maxXX; break; end
% conditional statement to create inter-note pauses
if k < notenum
if (theVoices(i).startPulses(k+1)-firstPulse) > dur
pause = key2note(0,theVoices(i).startPulses(k+1)-(firstPulse)*spp,i);
n2 = n1 + length(pause) - 1;
if n2 > maxXX
margin = maxXX - n1 + 1;
pause = pause(1:margin);
n2 = maxXX;
end
disp([n1, n2])
xx(n1:n2) = xx(n1:n2) + pause;
n1 = n2 + 1;
if n1 > maxXX; break; end
end
end
end
end
soundsc(xx, fs);
specgram(xx,512,fs);
function xx = key2note(keynum, dur, voicenum)
fs = 11025;
tt = 0:(1/fs):dur;
if (keynum == 0)
xx = zeros(1, length(tt)); % pause if no note
else
freq = 440*2^((keynum-49)/12);
if (voicenum == 1)
f = freq*[1 2 3 4]';
A = [1 1/2 1/4 1/8];
elseif (voicenum == 2)
f = freq*[1 3 5]';
A = 0.8*[1 1/2 1/4];
elseif (voicenum == 3)
f = 1.5*freq*[1 2 3 4]';
A = [1 1/2 1/4 1/8];
end
xx = A*cos(2*pi*f*tt);
% ADSR Envelope
if( dur>0.15 )
E = interp1([0,0.05,0.1,dur-0.05,dur],[0,1,0.9,0.8,0],tt);
elseif( dur>0.10 )
E = interp1([0,0.05,dur-0.05,dur],[0,1,0.8,0],tt);
else
E = interp1([0,0.05,dur],[0,1,0],tt);
end
% multiply xx by ADSR envelope
xx = xx.*E;
end
end
Answers (0)
Categories
Find more on Graphics Object Properties in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!