%SimpleCodecOptions % This function is based off of Program 11.1 from the book % It is a simple audio codec. It compresses and uncompresses a sound signal. % % This function has 7 arguments, 6 of which are optional. % % The first argument is the sound signal input: % If one number is input, a pure tone of that frequency will be used % If a short array of numbers is used, then a chord is used % If an array of more than 100 numbers is input, the music signal is used. % % The second argument is whether a windowing function is used % If the number 1 is input then a windowing function is used % If any other input is used or only one argument is given then no windoing function is used % % The third argument is whether a plot of the sound signal is created % If the number 1 is input a plot of the orignial and compressed sound is made % If any other input is used or only two arguments are given then no plot is made % % The fourth argument is whether the sound will be output by the program % If the number 0 is input, no sound will be played % If any other input is used or only three arguments are given then the sound is played % % The fifth argument is whether the sound created in the program is recorded % If the number 1 is input then the sound will be recorded as a WAV file % If any other input is used or if only four arguments are given then nothing is recorded % % The sixth argument is the user created title of the input signal if it is music % A string must be given in this argmument if you used the vector from a piece of music % IT IS IMPORTANT THAT IF YOU INPUT A TITLE YOU USE A STRING OR ELSE ERRORS HAPPEN % If the title is left blank, the title is 'YouShouldHavePickedATitleSeeHelp' % A title is only necessary if the input was music % % The seventh argument is importance sampling. I HAVE NOT GOTTEN IT TO WORK WELL % If the number 1 is input, the amount of bits changes depending on the frequency % If any other input is used or only six arguments are given 2 bits are used % % The output of this function in addition to the ones described in the arguments % is the RMSE error of the compressed then uncompressed sound compared to the % orignial sound. % % SAMPLE INPUTS: % SimpleCodecOptions(256) % SimpleCodecOptions(256,1) % SimpleCodecOptions(256,1,1) % SimpleCodecOptions(256,1,1,0) % SimpleCodecOptions(256,1,1,1,1) % SimpleCodecOptions(256,1,1,1,1,'No title is Necessary for a tone') % SimpleCodecOptions(256,1,1,1,0,'No title is Necessary for a tone',1) function Error=SimpleCodecOptions(Input,Windowing,Plotting,SoundOutput,Recording,Title,Importance) %%% The switch loop section sets the default values for optional variables %%% switch nargin case 1 Windowing=0; Plotting=0; SoundOutput=1; Recording=0; Title='YouShouldHavePickedATitleSeeHelp'; Importance=0; case 2 Plotting=0; SoundOutput=1; Recording=0; Title='YouShouldHavePickedATitleSeeHelp'; Importance=0; case 3 SoundOutput=1; Recording=0; Title='YouShouldHavePickedATitleSeeHelp'; Importance=0; case 4 Recording=0; Title='YouShouldHavePickedATitleSeeHelp'; Importance=0; case 5 Title='YouShouldHavePickedATitleSeeHelp'; Importance=0; case 6 Importance=0; end %%% The following if section sets the sound vector depending on the input %%% if length(Input)==1 x=cos((1:2^(13))*2*pi*Input/2^(13)); %Pure tone TitleVersion=1; elseif length(Input)<100 x=cos((1:2^(13))*2*pi*Input(1)/2^(13)); %Chord for i=2:length(Input) x=x+cos((1:2^(13))*2*pi*Input(i)/2^(13)); end TitleVersion=2; else x=Input; %Input music vector len=length(x); x=x(1:floor(len/64)*64).'; TitleVersion=3; end %%% The following lines set up parameters for the compression %%% len=length(x); n=2^5; % length of window nw=floor(len/n); % number of length n windows in x x=x(1:n*nw); % cut x to integer number of n windows Fs=2^(13); % Fs=sampling rate b=2; L=0.3; % b = quantization bits, [-L,L] amplitude range q=2*L/(2^b-1); % q used for b bits on interval [-L, L] %%% The following for loop creates the MDCT matrix %%% for i=1:n % form the MDCT matrix for j=1:2*n M(i,j)= cos((i-1+1/2)*(j-1+1/2+n/2)*pi/n); end end M=sqrt(2/n)*M; N=M'; % inverse MDCT x=0.3*x/max(abs(x)); % normalize signal to max amplitude = 0.3 %%% The following if statement plays the sound depending on the choice in the arguments %%% if (SoundOutput == 0) == 0 sound(x,Fs) % Matlab's sound command end out=[]; % Initialize output vector %%% The following if block records the sound and names it depending on the arguments %%% if Recording == 1 switch TitleVersion case 1 audiowrite([num2str(Input),'Hz Original.wav'],x,Fs); case 2 audiowrite([num2str(Input),' Chord Original.wav'],x,Fs); case 3 audiowrite([Title,' Original.wav'],x,Fs); end end %%% The following if block creates a windowing vector or an array of ones depending on the choice %%% if Windowing == 1 h=1:1:2*n; h=sqrt(2).*sin((h+.5).*(pi/(2*n))); % Windowing function else h=ones(1,2*n); end h=h.'; %x=x.*h; for k=1:nw-1 % loop over l ength 2n windows x0=x(1+(k-1)*n:2*n+(k-1)*n)'; x0=x0.*h; % Apply windowing vector y0=M*x0; if Importance == 1 b=ceil(log(max(abs(y0)+1.5))/log(2))+1; L=0.3; q=2*L/(2^b-1); end y1=round(y0/q); % transform components quantized % Storage/transmission of file occurs here y2=y1*q; % transform components dequantized w(:,k)=(N*y2).*h; % invert the MDCT and undo windowing if(k>1) w2=w(n+1:2*n,k-1);w3=w(1:n,k); out=[out;(w2+w3)/2]; % collect the reconstructed signal end % (of length 2n less than length of x) end %%% The following if statement plays the sound depending on the choice in the arguments %%% if (SoundOutput == 0) == 0 PauseTime=ceil(length(x)/Fs)+1; pause(PauseTime) sound(out,Fs) % play the reconstructed tone end %%% THe output is shorter than the input by 64 entries %%% xE=x(n+1:end-32).'; % Takes the first and last 32 off the input %%% The following large if block sets up plotting if that was chosen %%% % Different inputs affect the title of the plot. if Plotting == 1 PlotDomain=1:length(out); PlotDomain=PlotDomain(1:100); TitleFirstLine='Original and Compressed then Uncompressed Sound Values'; switch TitleVersion case 1 TitleSubstance=['Sound Frequency is ' num2str(Input) 'Hz,']; case 2 TitleSubstance=['With a ' num2str(Input) ' chord,']; case 3 TitleSubstance=['For: ' Title ',']; end if Windowing == 1 TitleWindowing =' and a Windowing Function is Used'; else TitleWindowing =' and No Windowing Function is Used'; end FigureTitle={TitleFirstLine, [TitleSubstance TitleWindowing]}; figure(1) plot(PlotDomain,xE(1:100),'r',PlotDomain,out(1:100),'b','LineWidth',2); title(FigureTitle) legend('Original Sound','Uncompressed Sound') xlabel('Samples') ylabel('Amplitude') end %%% The following if block records the uncompressed sound and names it depending on the arguments %%% if Recording == 1 if Windowing == 1 switch TitleVersion case 1 audiowrite([num2str(Input),'Hz UncompressedWindowed.wav'],x,Fs); case 2 audiowrite([num2str(Input),' Chord UncompressedWindowed.wav'],x,Fs); case 3 audiowrite([Title,' UncompressedWindowed.wav'],x,Fs); end else switch TitleVersion case 1 audiowrite([num2str(Input),'Hz Uncompressed.wav'],x,Fs); case 2 audiowrite([num2str(Input),' Chord Uncompressed.wav'],x,Fs); case 3 audiowrite([Title,' Uncompressed.wav'],x,Fs); end end end Error=RMSE(out,xE); %The output of the function is the RMSE (See Below) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% The following is the Root Mean Square error calculating function %%%% function Result=RMSE(Data,Correct) Result=Data-Correct; Result=Result.^2; %Square Result=sum(Result); Result=Result/(length(Data)); %Mean Result=sqrt(Result); %Root