Sie sind auf Seite 1von 14

Jacobs University

Communications Laboratory

DELAY

Kiran Adhikari, Mail-Box: 47

Submitted to
Fangning Hu

November 28, 2016


Objective
The objective of this experiment is to learn about the operation of a simple
delay block using MATLAB.

Background
Real-Time DSP Applications
The two characteristics of a typical MATLAB implementation of a signal
processing algorithm are:
1. All of the input samples are available at once.
2. The exact time for the algorithm to run is not critical.
But, real time application differ from a standard MATLAB program because
a continuous stream of signals is received in real time which must be pro-
cessed continuously. Timing is also critical, and the algorithm should not
introduce much latency. Real-time applications differ from a standard MAT-
LAB program. An example real-time signal processing application is echo
cancellation in a telephone network. Real-time processing in DSPs is usually
implemented using a buffer-based strategy as depicted below:

Figure 1: Real time processing

The input sample stream is divided into buffers of N samples. The DSP
algorithm then operates on one buffer at a time and processes the N input
samples to generate N samples in the output stream. The problem with
buffer-based arrangement is that the buffer boundaries are artificial, and we
may need some information from previous buffers in order to process the
current buffer. In order to do this, we must often store some state when we
have completed processing the samples for the current buffer, allowing later
buffers to be processed correctly. The size N of the buffers is generally a
tradeoff between the latency and the throughput. A small buffer size means

1
that the latency will be small, since we do not have to wait for a large buffer
to fill up. But, processing many small chunks means that we will waste
time storing and restoring state, which means overall lower throughput. The
application constraints will typically dictate the optimal value for N.

Real-Time DSP Simulation in MATLAB


Since many simple errors and problems can be flushed out using MATLAB
environment in much less time before coding it for DSP, MATLAB can serve
as an invaluable first step for prototyping and testing an algortithm before
coding it for DSP. DSP algorithms can usually be described using a block
diagram as in the Simulink labs. This object-oriented approach not only
allows the operations to be coded in an independent fashion, but also the
processing blocks to be reused and connected in arbitrary ways. In this lab,
we will take the approach of describing the various DSP operations with
logical blocks that then can be connected to perform more complex tasks.
In order to simulate a real-time block in MATLAB, we will learn in this lab
how to define MATLAB functions that can operate on a stream of samples
in a buffer-oriented fashion and pass state from one call to the next.

Circular Buffers
One way to simulate a continuous stream of samples with finite-sized buffers
is to use circular buffers. The following figure depicts a conceptual represen-
tation of a circular buffer:

Figure 2: Circular Buffer

Memory elements are arranged in a circle, where new incoming data items

2
(samples) are placed at the tail of the buffer, and the tail pointer is then
incremented. During processing, the oldest item not yet processed is taken
from the head of the buffer, after which the head pointer is also incremented.
The reason this arrangement is good for DSP is because we can avoid having
to copy or move data. Instead, we only need to update pointers, which is
usually much more efficient. In a processor, we dont actually store data in a
circle, but rather data is arranged logically in a linear fashion, so the circular
buffer is flattened as shown below.

Figure 3: Linear fashion

The only difficulty of this arrangement is that the pointers we use to ac-
cess the buffer need to somehow wrap from the end back to the beginning of
the buffer to simulate the operation of the circular buffer. This is illustrated
by showing two possible cases, one where the currently used samples actu-
ally wrap across the buffer boundary. Many DSPs have built-in support for
circular (wrap-around) addressing, but this usually requires some assembly
language programming, which is beyond the scope of this lab. In this lab,
we will simulate a circular buffer in MATLAB and C by making our buffer
size an integer power of 2. A simple bit masking operation can then be used
to make array indices circular.
To illustrate how circular buffering can be accomplished with simple bit
masking, consider the following conceptual code:
i n t samples [ 1 6 ] ;
u n s i g n e d i n t head =0;
u n s i g n e d i n t t a i l =0;

v o i d pu t s a m p l e ( i n t samp1 )
{
/∗ Put a sample a t th e head o f t he b u f f e r ∗/
samples [ t a i l ] = samp1 ;

3
/∗ Increment . By masking b i t s , make modulo 16 ∗/
t a i l = ( t a i l + 1) & 15;
}

int get sample ()


{
i n t samp1 ;

/∗ Get a sample from head o f b u f f e r . ∗/


samp1 = samples [ head ] ;

/∗ Increment t o next v a l u e ∗/
head = ( head + 1 ) & 1 5 ;
}
We have defined a FIFO or circular buffer with 16 samples, and head and tail
indices. The put sample() function places a single new sample at the tail of
the buffer and the get sample() function reads a sample from the head of the
buffer. The important thing to note is the incrementing operations. Instead
of just adding one, we AND with N-1, where N is the size of the buffer. This
has the effect of making the additions modulo-N, which is what we need to
ensure that we wrap from the end to the beginning of the buffer.

0.1 Execution
Each DSP block that we implement in MATLAB will consist of two functions:
[name]i nit() A function used to store parameters and initialize the block.
[name]() A function that processes a buffer of input items to generate a
buffer of outputs
For the delay block, the initialization function was written as follows:
f u n c t i o n [ s t a t e ] = d e l a y i n i t (Nmax, N ) ;

% [ s t a t e ] = d e l a y i n i t (Nmax, N ) ;
%
% I n i t i a l i z e s a delay block .
%
% Inputs :
% Nmax Maximum d e l a y s u p p o r t e d by t h i s b l o c k .
% N I n i t i a l delay

4
% Outputs :
% state State of block
% Notes :
% For t h i s b l o c k t o o p e r a t e c o r r e c t l y ,
% you s h o u l d not p a s s i n more than Nmax
% samples a t a time .

%% 1 . Save p a r a m e t e r s
s t a t e . Nmax = Nmax ;

% Store i n i t i a l desired delay .


s t a t e .N = N;

%% 2 . Create s t a t e v a r i a b l e s

% Make th e s i z e o f t he b u f f e r a t l e a s t t w i c e o f th e maximum d e l a y .
% Allows us t o copy i n and then re ad out i n j u s t two s t e p s .
s t a t e .M = 2 ˆ( c e i l ( l o g 2 (Nmax) ) + 1 ) ;

% Get mask a l l o w i n g us t o wrap i n d e x e a s i l y


s t a t e . Mmask = s t a t e .M−1;

% Temporary s t o r a g e f o r c i r c u l a r b u f f e r
s t a t e . b u f f = z e r o s ( s t a t e .M, 1 ) ;

% S e t i n i t i a l head and t a i l o f b u f f e r
state . n h = 0
state . n t = N
The function takes parameters Nmax, which is the maximum delay that
the block should support and N which is the initial delay that should be
used. The function creates a structure called state that will be used to store
parameters as well as the state of the block.
Next, the function creates a circular buffer for storing samples. The buffer
is made an integer power of 2 in size, and a mask is computed that allows us
to do the simple AND operation to ensure modulo Nmax indexing. The head
and the tail indices are then set. For this block to work, we must properly
set the initial state of these indices. The inital head was set to be zero and
the inital tail was set to be N which is equal to the initial desired delay N.
For processing function delay() used to process a single buffer of samples,
we define function as below:

5
function [ state out , y ] = delay ( state in , x ) ;

% [ state out , y ] = delay ( state in , x ) ;


%
% Delays a s i g n a l by t he s p e c i f i e d number o f samples .
%
% Inputs :
% state in Input s t a t e
% x Input b u f f e r o f samples
% Outputs :
% state out Output s t a t e
% y Output b u f f e r o f samples

% Get i n p u t s t a t e
s = state in ;

% Copy i n samples a t t a i l
f o r i i =0: l e n g t h ( x) −1 ,
% S t o r e a sample
s . b u f f ( s . n t +1) = x ( i i +1);
% Increment head i n d e x ( c i r c u l a r )
s . n t = b i t a n d ( s . n t +1, s . Mmask ) ;
end

% Get samples out from head


y = zeros ( size (x ) ) ;
f o r i i =0: l e n g t h ( y) −1 ,
% Get a sample
y ( i i +1) = s . b u f f ( s . n h +1);
% Increment t a i l i n d e x
s . n h = b i t a n d ( s . n h +1, s . Mmask ) ;
end

% Output t he updated s t a t e
state out = s ;
. In this function,the input state is stored in variable s. N input samples
are all copied to the tail of the circular buffer, where N is the length of the
buffer. For each sample, the tail pointer is incremented. N output samples
are then read from the head of the buffer. For each sample the head pointer
is incremented. The updated state and output buffer y are then returned.

6
The delay block was tested with the script below:
% t e s t d e l a y 1 .m
%
% S c r i p t t o t e s t t he d e l a y b l o c k . S et up t o model th e way
% samples would be p r o c e s s e d i n a DSP program .

% Global p a r a m e t e r s
Nb = 1 0 ; % Number o f b u f f e r s
Ns = 1 2 8 ; % Samples i n each b u f f e r
Nmax = 2 0 0 ; % Maximum d e l a y

Nd = 1 0 ; % Delay o f b l o c k

% I n i t i a l i z e the delay block


s t a t e d e l a y 1 = d e l a y i n i t (Nmax, Nd ) ;

% Generate some random samples .


x = randn ( Ns∗Nb , 1 ) ;
% Reshape i n t o b u f f e r s
xb = r e s h a p e ( x , Ns , Nb ) ;

% Output samples
yb = z e r o s ( Ns , Nb ) ;

% P r o c e s s each b u f f e r
f o r b i =1:Nb ,
[ s t a t e d e l a y 1 yb ( : , b i ) ] = d e l a y ( s t a t e d e l a y 1 , xb ( : , b i ) ) ;
end

% Convert i n d i v i d u a l b u f f e r s back i n t o a c o n t i g u o u s s i g n a l .
y = r e s h a p e ( yb , Ns∗Nb , 1 ) ;

% Check i f i t worked r i g h t
n = [ 0 : length ( x ) −1];

figure (1);
plot (n , x , n , y ) ;

figure (2);
p l o t ( n+Nd , x , n , y , ’ x ’ ) ;

7
% Do a check and g i v e a warning i f i t i s not r i g h t . Skip f i r s t b u f f e r
% to avoid i n i t i a l c o n d i t i o n s .
n chk = 1+[Ns : ( Nb−1)∗Ns − 1 ] ;
i f any ( x ( n chk − Nd) ˜= y ( n chk ) ) ,
warning ( ’A mismatch was e n c o u n t e r e d . ’ ) ;
end
We simulated this buffer-oriented processing by partitioning the vector x
into multiple buffers, each having 128 samples. After these buffers have
been processed separately, they are then concatenated again to make the
continuous buffer y.We set the delay of the block with 10. At the end of the
function, I generated two plots, one showing the input and output vectors,
and another where the signals are plotted with the shift undone, meaning
that the samples should line up. The figures are shown below:

Figure 4: Figure showing input and output vectors

In the figure, the red signal shows the original input signal while blue
signal shows the output delayed signal.

8
Figure 5: Signals with shift

For the next section, we cascaded two delay blocks by calling the de-
lay init() function and using two different state variables. The script is af
follows:
% t e s t d e l a y 1 .m
%
% S c r i p t t o t e s t t he d e l a y b l o c k . S et up t o model th e way
% samples would be p r o c e s s e d i n a DSP program .

% Global p a r a m e t e r s
Nb = 1 0 ; % Number o f b u f f e r s
Ns = 1 2 8 ; % Samples i n each b u f f e r
Nmax = 2 0 0 ; % Maximum d e l a y

Nd = 1 0 ; % Delay o f f i r s t b l o c k
Nd2 = 1 0 0 ; % Delay o f second b l o c k

% I n i t i a l i z e the delay block


s t a t e d e l a y 2 = d e l a y i n i t (Nmax, Nd2 ) ;
s t a t e d e l a y 1 = d e l a y i n i t (Nmax, Nd ) ;

9
% Generate some random samples .
x = randn ( Ns∗Nb , 1 ) ;
% Reshape i n t o b u f f e r s
xb = r e s h a p e ( x , Ns , Nb ) ;

% Output samples
yb = z e r o s ( Ns , Nb ) ;
yb2= z e r o s ( Ns , Nb ) ;
% P r o c e s s each b u f f e r
f o r b i =1:Nb ,
[ s t a t e d e l a y 2 yb1 ( : , b i ) ] = d e l a y ( s t a t e d e l a y 2 , xb ( : , b i ) ) ;
[ s t a t e d e l a y 1 yb ( : , b i ) ] = d e l a y ( s t a t e d e l a y 1 , yb1 ( : , b i ) ) ;
end
% Convert i n d i v i d u a l b u f f e r s back i n t o a c o n t i g u o u s s i g n a l .
y = r e s h a p e ( yb , Ns∗Nb , 1 ) ;

% Check i f i t worked r i g h t
n = [ 0 : length ( x ) −1];

figure (1);
plot (n , x , n , y ) ;

figure (3);
p l o t ( n+Nd+Nd2 , x , n , y , ’ x ’ ) ;

% Do a check and g i v e a warning i f i t i s not r i g h t . Skip f i r s t b u f f e r


% to avoid i n i t i a l c o n d i t i o n s .
n chk = 1+[Ns : ( Nb−1)∗Ns − 1 ] ;
i f any ( x ( n chk − Nd2−Nd) ˜= y ( n chk ) ) ,
warning ( ’A mismatch was e n c o u n t e r e d . ’ ) ;
end
As before, we got two figures one showing the input and output, and the
other showing shifted signals.

10
Figure 6: Figure showing input and output signal

Here, in the figure we can see that there is a delay of 110 between the
input and output signal.

11
Figure 7: Shifted version

Since, the input and shifted output signal match properly in the graph,
this proves that our cascaded script is working.

Evaluation
A short explanation of the difference between a usual
MATLAB simulation and real-time DSP code. Also,
briefly explain why buffer-oriented processing is needed
and what affects the latency and throughput of an al-
gorithm.
There are two properties of a typical MATLAB implementation of a signal
processing algorithm: all of the input samples are available at once, and the
exact time for the algorithm to run is not critical.However in real real-time
DSP code, a continuous stream of signals or data is received, which must also
be processed continuously.Timing is very critical, and the algorithm must not
introduce too much latency, defined loosely as the input to output delay of
the system.

12
We need to use buffer-oriented processing because it is not efficient to wait
for samples to be ready before we start processing. Thus, the input sample
stream should be divided into buffers of N samples. The DSP algorithm
then operates on one buffer at a time and processes the N input samples to
generate N samples in the output stream.
The proper choice for the size N of the buffers generally affects the latency
and the throughput of an algorithm. A small buffer size means that the
latency will be small, since we do not have to wait for a large buffer to fill
up. But, processing many small chunks means that we will waste time storing
and restoring state, which means overall lower throughput.

Conclusion
From this lab, we learnt about buffer-oriented signal processing using MAT-
LAB to prototype and debug real-time delay block. The problems that we
faced during the lab included trying to understand the code and debugging
it. We were able to fix those problems after more thought, and discussing
with the Teaching Assistant and the Instructor.

References
Fangning Hu, 2016, DSP and Communication, Retrieved from http : //dsp −
f hu.user.jacobs − university.de/?pagei d = 119

13

Das könnte Ihnen auch gefallen