function [finalOutput] = Shapee(file1, file2, outputFile, frameSize, overlap, omega) %Shapee(file1, file2, outputFile, frameSize, overlap, omega) %takes file1 and file2 %and combines them according to Christopher Penrose' Shapee %algorithm. The combination is output as a wav file (outputFile). %omega is the width (in bins) of the shaping region. %Generally this should be kept close to the main lobe width %of the window for best results %MATLAB version Jez Wells Nov 2004 NumShapingRegions = floor((frameSize-1)/omega)-1; frameCount = 1; %find length of first file file and number of channels params = wavread(file1,'size'); samples1 = params(1,1); channels1 = params(1,2); %do the same for the second file params = wavread(file2,'size'); samples2 = params(1,1); channels2 = params(1,2); if channels1 ~= channels2 error('Input files do not have the same number of channels'); end if samples1 ~= samples2 fprintf('Input files are not the same length.\nOutput file will be the same length as shortest input file.\n'); samples = min([samples1,samples2]); end samples = min([samples1,samples2]); %ensure our output matrix will be big enough to accomodate a whole number of %frames by rounding up outSamples = (ceil(samples/frameSize) + 1) * frameSize; finalOutput = zeros(outSamples, channels1); %generate window Hann = sqrt(hann(frameSize)); % set ranges for shaping regions lower = (omega*[0:NumShapingRegions])+1; upper = lower+omega; % read file [input1, Fs1, bits1] = wavread(file1); [input2, Fs2, bits2] = wavread(file2); if Fs1~=Fs2 error('Sample rates of input files are not the same'); end if bits1~=bits2 && frameCount==1 bits1 bits2 fprintf('Bit depth of files is not the same. Output bit depth will be the highest out of the two.\n'); bits = max([bits1, bits2]); end bits = max([bits1, bits2]); % get inputs to same length while frameCount < samples outPointer = frameCount + (frameSize-1); if outPointer > samples outPointer = samples; siz = outPointer - frameCount + 1; end ip1 = input1(frameCount:outPointer,:); ip2 = input2(frameCount:outPointer,:); if length(ip1) < frameSize %calculate difference between input and frame length diff = frameSize - length(ip1); %append zeros oo = zeros(diff,2); ip1 = [rot90(ip1), rot90(oo)]; %rotate back after appending zeros ip1 = rot90(ip1,-1); end if length(ip2) < frameSize %calculate difference between input and frame length diff = frameSize - length(ip2); %append zeros oo = zeros(diff,2); ip2 = [rot90(ip2), rot90(oo)]; %rotate back after appending zeros ip2 = rot90(ip2,-1); end %place individual channels in separate vectors and apply window left1 = ip1(:,1).*Hann; right1 = ip1(:,2).*Hann; left2 = ip2(:,1).*Hann; right2 = ip2(:,2).*Hann; %perform fft leftFFT1 = fft(left1, frameSize); rightFFT1 = fft(right1, frameSize); leftFFT2 = fft(left2, frameSize); rightFFT2 = fft(right2, frameSize); %extract magnitudes and phases for each bin leftMag1 = abs(leftFFT1); rightMag1 = abs(rightFFT1); %leftPhase1 = angle(leftFFT1); %rightPhase1 = angle(rightFFT1); leftMag2 = abs(leftFFT2); rightMag2 = abs(rightFFT2); leftPhase2 = angle(leftFFT2); rightPhase2 = angle(rightFFT2); %do something below here %to create your own cross synthesizer cumAmpLeft = [0;cumsum(leftMag1)]; cumAmpRight = [0;cumsum(rightMag1)]; cumFreqLeft = [0;cumsum(leftMag2)]; cumFreqRight = [0;cumsum(rightMag2)]; sigmaAmpMagLeft = cumAmpLeft(upper)-cumAmpLeft(lower); sigmaAmpMagRight = cumAmpRight(upper)-cumAmpRight(lower); sigmaAmpFreqLeft = cumFreqLeft(upper)-cumFreqLeft(lower); sigmaAmpFreqRight = cumFreqRight(upper)-cumFreqRight(lower); sigmaAmpFreqLeft(find(sigmaAmpFreqLeft==0)) = realmin; sigmaAmpFreqRight(find(sigmaAmpFreqRight==0)) = realmin; MagMultiplierLeft = sigmaAmpMagLeft./sigmaAmpFreqLeft; MagMultiplierRight = sigmaAmpMagRight./sigmaAmpFreqRight; for n = 1:NumShapingRegions+1 leftMag1(lower(n):upper(n)-1) = leftMag2(lower(n):upper(n)-1)* MagMultiplierLeft(n); rightMag1(lower(n):upper(n)-1) = rightMag2(lower(n):upper(n)-1) * MagMultiplierRight(n); end %phase for frequency reference is phase of second input file %when you're done modifying %resynthesise %convert mag and phase back to complex numbers %we'll re-use some of the input arrays to save on memory leftReal1 = leftMag1 .* cos(leftPhase2); leftImag1 = leftMag1 .* sin(leftPhase2); rightReal1 = rightMag1 .* cos(rightPhase2); rightImag1 = rightMag1 .* sin(rightPhase2); leftFFT1 = complex(leftReal1,leftImag1); rightFFT1 = complex(rightReal1, rightImag1); leftOutput = ifft(leftFFT1, 'symmetric'); %inverse FFT of data with complex conjugate symmetry is faster rightOutput = ifft(rightFFT1, 'symmetric'); %window finalOutput to remove any clicks from discontinuities at frame boundaries output(:,1) = leftOutput.*Hann; output(:,2) = rightOutput.*Hann; %place finalOutput in single matrix to be written to stereo .wav file finalOutput(frameCount:(frameCount + (frameSize-1)),:) = finalOutput(frameCount:(frameCount + (frameSize-1)),:) + output(1:(frameSize),:); frameCount = frameCount + (frameSize/overlap); end m1 = max(abs(finalOutput(:,1))); m2 = max(abs(finalOutput(:,2))); m = max([m1,m2]); m = 0.99/m; % avoids "output is clipped" error message in wavwrite finalOutput(:,1) = finalOutput(:,1)* m; finalOutput(:,2) = finalOutput(:,2)* m; %write entire finalOutput to wav file wavwrite(finalOutput,Fs1,bits,outputFile); %play the finalOutput wavplay(finalOutput, Fs1);