function y = ol_celp( x ) % function y = ol_celp( x ) % % Simulation of CELP Codec with Open-Loop Pitch Predictor % % x: codec input signal (sampled with 8 kHz, 16-bit quantized, i.e range -32768 ... 32767) % y: codec output signal (sampled with 8 kHz, 16-bit quantized, i.e range -32768 ... 32767) % % Author: Markus Hauenstein % Date: 16.01.2002 % Contact: www.markus-hauenstein.de % % This program is copyrighted. test = 0; fprintf(1,'\nSimulation of CELP Codec with Open-Loop Pitch Predictor') fprintf(1,'\nInitializing') % % init parameters identical for both coder and decoder which influence the bitrate % % ltp (number of samples) numberOfSubblocks = 4; subblockLength = 40; minDelay = 20; maxDelay = 147; ltpGainsQuantBits = 6; % lpc: bits for quantization of predictor coefficients predQuantBits = 4*[1 1 1 1 1 1 1 1 1 1]; % size of stochastic gain codebook stochGainCBSize = 64; % size of stochastic Vec codebook stochVecCBSize = 1024; % % init parameters identical for both coder and decoder which do NOT influence the bitrate % blockLength = numberOfSubblocks * subblockLength; % ltp ltpMaxGainQ = 1; % lpc lpcOrder = length(predQuantBits); maxLarQ = 2.5; % create stochastic gain codebook minStochGain = -512; maxStochGain = 512; stochGainCBmu = 64; stochGainCB = crmucb(minStochGain, maxStochGain, stochGainCBmu, stochGainCBSize); % create normalized stochastic Vec codebook stochVecCBAmp = 16; randn('seed',0); stochVecCB = randn( blockLength, stochVecCBSize ); for i=1:stochVecCBSize, oneDivRms = 1/sqrt((stochVecCB(:,i)' * stochVecCB(:,i)) / blockLength); stochVecCB(:,i) = oneDivRms * stochVecCB(:,i); end stochVecCB = stochVecCBAmp * stochVecCB; % calculate and display required bitrate sampleFrequency = 8000; lpcBitRate = sum( predQuantBits ) * sampleFrequency / blockLength; ltpDelaysBitRate = ceil( log(maxDelay-minDelay)/log(2) ) * sampleFrequency / subblockLength; ltpGainsBitRate = ltpGainsQuantBits * sampleFrequency / subblockLength; stochVecBitRate = ceil( log(stochVecCBSize)/log(2) ) * sampleFrequency / blockLength; stochGainBitRate = ceil( log(stochGainCBSize)/log(2) ) * sampleFrequency / blockLength; bitRate = lpcBitRate + ltpDelaysBitRate + ltpGainsBitRate + stochVecBitRate + stochGainBitRate; fprintf(1, '\nBitrate: %d bps', bitRate) % format Input signal x=x(:); % make column Vector inputLength = length(x); rest = inputLength - blockLength * floor(inputLength/blockLength); if rest == 0, numberOfBlocks = inputLength / blockLength; else numberOfBlocks = ceil( inputLength / blockLength ); x = [x; zeros( blockLength-rest, 1 )]; end % initialize data storage for transmitted parameters aChannel = zeros(lpcOrder, numberOfBlocks); ltpGainsChannel = zeros(numberOfSubblocks, numberOfBlocks); ltpDelaysChannel = zeros(numberOfSubblocks, numberOfBlocks); stochVecChannel = zeros(1, numberOfBlocks); stochGainChannel = zeros(1, numberOfBlocks); % % THIS IS CODER % fprintf(1,'\nCoding ') % initialize coder variables % ltp zLpc = zeros(lpcOrder,1); ltpInputPast = zeros(maxDelay,1); ltpGains = zeros(numberOfSubblocks,1); ltpGainsQ = zeros(numberOfSubblocks,1); ltpDelays = zeros(numberOfSubblocks,1); % inverse ltp invLtpOutputPast = zeros(maxDelay,1); % inverse lpc zInvLpc = zeros(lpcOrder,1); % Vec quantization of LPC/LTP residual - helper variables for Vec quantization synFilterOutSignals = zeros( blockLength, stochVecCBSize ); zeroOutput = zeros(blockLength,1); zeroInput = zeros(blockLength,1); % coder main loop blockIndex = 1 : blockLength; for i=1:numberOfBlocks, fprintf(1,'.') %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % get current block xBlock = x( blockIndex ); blockIndex = blockIndex + blockLength; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % lpc (inverse vocal tract filter) lpcInputBlock = xBlock; % calculate linear prediction coefficients a = linpred( lpcInputBlock, lpcOrder ); % simulate log-area-ratio quantization of LPC parameters aQ = larpredq( a, maxLarQ, predQuantBits ); % lpc filter [lpcOutputBlock, zLpc] = filter([1;-aQ], 1, lpcInputBlock, zLpc); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % ltp (inverse pitch filter) ltpInputBlock = lpcOutputBlock; % determine LTP parameters [ltpDelays, ltpGains] = olltpdg( ltpInputBlock, subblockLength, minDelay, ltpInputPast ); % simulate quantization of LTP parameters ltpGainsQ = muquant( ltpGains, ltpMaxGainQ, ltpGainsQuantBits ); % calculate ltp filter states for next looping [dummy, ltpInputPast] = ... ltpfilt( ltpInputBlock, subblockLength, ltpDelays, ltpGainsQ, ltpInputPast); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Analysis-by-Synthesis: % take LPC filter states from last looping into account and calculate a target vector zeroOutput = filter(1, [1;-aQ], zeroInput, zInvLpc); target = xBlock - zeroOutput; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Analysis-by-Synthesis: % Synthesize all possible speech vectors by inverse ltp & lpc filtering % of all noise vectors in stochastic codebook for l=1:stochVecCBSize, % Inverse LTP invLtpInputBlock = stochVecCB(:,l); [invLtpOutputBlock, dummy] = ... iltpfilt( invLtpInputBlock, subblockLength, ltpDelays, ltpGainsQ, invLtpOutputPast ); % Inverse LPC invLpcInputBlock = invLtpOutputBlock; synFilterOutSignals(:,l) = filter( 1, [1;-aQ], invLpcInputBlock ); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Analysis-by-Synthesis: % Vector quantization of target vector [bestStochGainIndex, bestStochVecIndex] = gsvecq( target, stochGainCB, synFilterOutSignals ); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Prepare next block by calculating filter states % calculate inverse ltp filter (pitch filter) states for next looping - % this corresponds to a decoder! invLtpInputBlock = stochVecCB(:,bestStochVecIndex); [invLtpOutputBlock,invLtpOutputPast ] = ... iltpfilt( invLtpInputBlock, subblockLength, ltpDelays, ltpGainsQ, invLtpOutputPast ); % calculate inverse lpc filter (vocal tract filter) states invLpcInputBlock = stochGainCB(bestStochGainIndex) * invLtpOutputBlock; [dummy, zInvLpc] = filter(1, [1;-aQ], invLpcInputBlock, zInvLpc); if test == 1, clg plot(xBlock,'g') hold plot(dummy,'r') pause end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % simulate transmission of parameters via channel to decoder aChannel(:,i) = aQ; ltpGainsChannel(:,i) = ltpGainsQ; ltpDelaysChannel(:,i) = ltpDelays; stochGainChannel(i) = bestStochGainIndex; stochVecChannel(i) = bestStochVecIndex; end % coder main loop % % THIS IS DECODER % fprintf(1,'\nDecoding') % initialize decoder variables y = zeros(numberOfBlocks*blockLength,1); % inverse ltp invLtpOutputPast = zeros(maxDelay, 1); % inverse lpc zInvLpc = zeros(lpcOrder,1); % decoder main loop blockIndex = 1 : blockLength; for i=1:numberOfBlocks, fprintf(1,'.') %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % inverse ltp (pitch reconstruction) %invLtpInputBlock = ltpGainBlockChannel(i) * stochVecCB(:,stochVecChannel(i)); invLtpInputBlock = stochVecCB(:,stochVecChannel(i)); [invLtpOutputBlock, invLtpOutputPast] = ... iltpfilt( invLtpInputBlock, subblockLength, ltpDelaysChannel(:,i), ... ltpGainsChannel(:,i), invLtpOutputPast ); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % inverse lpc (vocal tract model) a = aChannel(:,i); invLpcInputBlock = invLtpOutputBlock; [invLpcOutputBlock, zInvLpc] = filter(1, [1;-a], invLpcInputBlock, zInvLpc); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % scaling yBlock = stochGainCB(stochGainChannel(i)) * invLpcOutputBlock; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % construct output signal y( blockIndex ) = yBlock; blockIndex = blockIndex + blockLength; end % decoder main loop % format Output signal y = y(1:inputLength); if test == 1, clg plot(x,'g') hold plot(y,'r') end fprintf(1,'\nReady\n')