text:
Adaptive Filtering in Java, Getting Started
Java Programming, Notes # 2350
- Preface
- Preview
- Discussion and Sample Code
- Run the Program
- Summary
- What's Next
- Complete Program Listings
DSP and adaptive filtering
First in a series
This is the first lesson in a series designed to teach you about adaptive filtering in Java. This lesson will introduce you to the topic by showing you how to write a Java program to solve a relatively simple time-adaptive filtering problem for which the correct solution is well known in advance. This will make it possible to check the adaptive solution against the known correct solution.
An adaptive whitening filter
The next lesson will show you how to write an adaptive whitening filter program in Java, which is conceptually more difficult than the filter that I will explain in this lesson. The next lesson will also show you how to use the whitening filter to extract wide band signal from a channel in which the signal is corrupted by one or more components of narrow band noise.
More general adaptive filtering considerations
Following that, the lessons in the series will become somewhat more general. I plan to publish lessons that explain and provide examples for the four common scenarios in which adaptive filtering is used:
- System Identification
- Inverse System Identification
- Noise Cancellation
- Prediction
Somewhere along the way I will probably also publish a lesson that explains and illustrates the difference between least mean square (LMS) and recursive least squares (RLS) adaptive algorithms.
Viewing tip
You may find it useful to open another copy of this lesson in a separate browser window. That will make it easier for you to scroll back and forth among the different figures and listings while you are reading about them.Supplementary material
I recommend that you also study the other lessons in my extensive collection of online Java tutorials. You will find those lessons published at Gamelan.com. However, as of the date of this writing, Gamelan doesn't maintain a consolidated index of my Java tutorial lessons, and sometimes they are difficult to locate there. You will find a consolidated index at www.DickBaldwin.com.
A time-delay filter with a flat amplitude response
The program that I will present and explain in this lesson illustrates an aspect of adaptive filtering for which the correct solution is already well known. The program adaptively designs a time-delay filter with a flat amplitude response and a linear phase response in the frequency domain.
A straightforward but useful scenario for learning
Although this is a relatively straightforward scenario, it is also a useful scenario for learning purposes. To begin with, the program illustrates the use of a least mean square (LMS) adaptive algorithm in a relatively simple setting, making it easy to understand what the algorithm is doing. In addition, the program teaches you about the use of digital delay lines, a topic with which you may not yet be familiar. Beyond that, it is easy to confirm that the adaptive solution matches the known correct solution.
User experimentation is encouraged
When running this program, the user provides several parameters that have an impact on the adaptive process. This allows the user to experiment with the adaptive process comparing results for different input parameters.
Two channels of input data
Two sampled time series, chanA and chanB, are presented to the adaptive processing system. Each time series consists of the same wide band signal plus white noise that is uncorrelated between the two channels.
A time shift between the two channels
On the basis of user input, the signal in chanB can be delayed or advanced by up to six samples relative to the signal in chanA. In other words, the time base for chanB can be shifted in either direction causing chanB to lead chanA in time, or causing chanB to lag chanA in time.
(Also, for a trivial case, the time shift between the two channels can be set to zero.)
Filtering chanA
A nine-point convolution operator is developed adaptively and applied to chanA. The purpose of the adaptive process is to cause the filtered output to be in time registration with chanB.
(Because the coefficient values in the convolution operator change with time, the convolution process also changes with time.)
How do you measure success?
When the adaptive process converges successfully, the time series produced by applying the convolution operator to chanA matches the signal on chanB.
It is already well known that the correct solution to this problem is a finite impulse response (FIR) convolution filter in which one coefficient has a value of 1 and all the other coefficients have a value of 0. The location of the coefficient having the value of 1 is such as to cause the result of filtering chanA to be either advanced or delayed in time by a number of samples that causes it to be in time registration with chanB.
It is also already well known that the Fourier transform of the filter described above will have a flat amplitude response and a linear phase response.
If the adaptive process converges to this result, it is successful.
User inputs
The user provides the following information as command line parameters:
- timeShift: A negative value for this parameter delays chanB relative to chanA and a positive value advances chanB relative to chanA. If no command line parameters are provided, a default timeShift value of -4 is used. This causes a four-sample delay on chanB relative to chanA. Because the convolution operator has only nine points, time shifts outside the range of plus or minus four samples cannot be resolved and an adaptive solution will not be found. Time shifts greater than six samples cause the program to terminate.
- feedbackGain: This parameter controls the convergence rate of the adaptive process. If the value is very low, the process will take a long time to converge. If the value is too high, the process will become unstable. If no command line parameters are provided, a feedbackGain value of 0.001 is used. Depending on the random noise level, the process appears to be stable for feedbackGain values as large as 0.004, but goes unstable for a feedbackGain value of 0.005.
- noiseLevel: This parameter controls the amount of uncorrelated white noise that is added to the signal on each of the two channels. If no command line parameters are provided, the default noise level is 0.0. The noise level is provided as a decimal fraction of the signal level. For example, a noise level of 0.1 causes the level of the noise that is added to each of the channels to be one tenth of the signal level on that channel.
- numberIterations: This parameter controls the number of adaptive iterations that are performed before the adaptive process terminates and all of the data that has been saved is plotted. If no command line parameters are provided, the default is 100 iterations.
The first example was run using default parameters. This produced the following output on the command line screen. (Note that a line break was manually entered into the first line to force it to fit into this narrow publication format.)
Usage: java Adapt01 timeShift feedbackGain noiseLevel numberIterations Negative timeShift is delay Using -4 sample shift by default Using 0.001 feedbackGain by default noiseLevel is a decimal fraction Using 0.0 by default numberIterations is an int Using 100 by default
Graphic output
Figure 1 shows the first of three graphic outputs that are produced by this program. (The other two graphic outputs are shown later in Figure 2.)
The following four time series are plotted in color in Figure 1 showing the convergence (or lack thereof) of the adaptive algorithm:
- Black: Input to the convolution filter
- Red: Output from the convolution filter
- Blue: Adaptive target (chanB)
- Green: Error (difference between filter output and the target)
Figure 1
Traces wrap around and down
When the top four traces reach the right end of the plotting area in Figure 1, they wrap around and down resulting in four new traces further down the page. Thus, the bottom four traces in Figure 1 are the continuation of the right end of the top four traces.
Was the adaptive process successful?
If the adaptive process is successful for this problem, the green (error) trace should go to zero, and the red (filter output) trace should match the blue (target) trace. As you can see, the adaptive process converges to this solution about half way across the top four traces in Figure 1. Thus, the adaptive process was successful. I will have more to say about Figure 1 later when I explain the code.
Impulse response plots
The second of the three graphic outputs produced by this program is shown in the left column of Figure 2.
The impulse response of the adaptive convolution filter at the beginning and at the end of every tenth iteration is shown in the left column of Figure 2. Thus, the changes in the shape of the impulse response can be viewed from the beginning to the end of the adaptive process.
The progressive stages of the impulse response are shown from top to bottom in the left column in Figure 2.
Figure 2
(Note that the actual impulse response consists of the values to the left of the flat raised portion of the plots in the left column of Figure 2. The minimum allowable width of an AWT Frame object in Java running under WinXP is 112 pixels, and the length of the impulse response was insufficient to fill that width. Therefore, I plotted the flat raised portion to the right of the impulse response to flag the portion of the plots that is not part of the impulse response.)
Initial impulse response at the top
The filter is initialized with a single coefficient value of 1 at the center and 0 for all of the other eight coefficient values. The correct solution is a single coefficient value of 1 at a location in the convolution filter that matches the time shift between chanA and the target, chanB. For the case shown in Figure 2, the target was delayed by four samples relative to chanA.
The peak shifts to the left
As you can see from Figure 2, the impulse response begins at the top with a value of 1 in the center and values of 0 elsewhere. As the adaptive process progresses down the page, the peak value in the impulse response progresses from the center of the impulse response to the correct location at the left end. In other words, the impulse response modifies itself such that after about 70 iterations (the eighth impulse response plot), it has a value of 1 at the left end and zeros elsewhere.
The frequency response
The third graphic output produced by this program is shown in the right column of Figure 2.
The frequency response of the convolution filter at the beginning and at the end of every tenth iteration is computed and displayed in the right column of Figure 2. Both the amplitude response and the phase response of the filter are displayed, with the amplitude response being plotted above the phase response in the right column of Figure 2. The frequency-domain plots in the right column extend from zero frequency on the left to the Nyquist folding frequency, (which is one-half the sampling frequency), on the right.
Frequency response on the right corresponds to impulse response on the left
Each pair of plots in the right column immediately to the right of a single impulse response in the left column consists of the amplitude and phase responses of the corresponding impulse response. The amplitude response is plotted in black and the phase response is plotted in red below the amplitude response.
Frequency response starts out flat
At the beginning (at the top), the impulse response consists of a single impulse in the center of the convolution filter.
(The center of the convolution filter is defined as the zero time origin for purposes of computing the phase response.)
At that point in the adaptive process, both the amplitude response and the phase response of the convolution filter are flat across the entire frequency spectrum.
Deviations appear by the twentieth iteration
By the third impulse response going down the page (twenty adaptive iterations), the impulse response is no longer represented by a single impulse, and some deviation from flatness is apparent in the corresponding amplitude response.
By the fourth impulse response (thirty adaptive iterations), the shape of the impulse response has changed considerably and quite a lot of activity is apparent in the corresponding amplitude response and phase response.
An adaptive solution in 90 iterations
By the eighth impulse response (70 iterations), the impulse response has become a single time-shifted impulse, the amplitude response has returned to being flat across the frequency spectrum, and the phase response has taken on a saw tooth character.
This is the correct solution as described above.
A flat amplitude response
The fact that the impulse response is once again a single impulse means that the amplitude response of the convolution filter is flat across the entire frequency spectrum.
The new location (relative to the zero time origin) of the single impulse in the convolution filter causes the output of the filter to be shifted in time relative to its input. As evidenced in Figure 1, this causes the convolution filter output (red) to be in time registration with the target (blue). At that point, the error (green) has converged to zero.
A linear phase response
A convolution operator that produces a simple time shift is represented in the frequency domain by a flat amplitude response and a linear relationship between phase and frequency. In other words, the phase is a straight line that goes through the zero frequency origin. The slope of the line indicates the direction of the time shift. The magnitude of the slope indicates the amount of the time shift.
Because the phase response is plotted in the range from -180 degrees to +180 degrees, and wraps around whenever it exceeds either of those limits, a linear phase shift has a saw tooth appearance when plotted as shown near the bottom of Figure 2.
This program was tested using J2SE 5.0 and WinXP. J2SE 5.0 or later is required.
Discussion and Sample Code
The program named Adapt01
I will discuss and explain this program in fragments. A complete listing of the program is provided in Listing 32 near the end of the lesson.
The beginning of the class and the beginning of the main method is shown in Listing 1.
class Adapt01{ public static void main(String[] args){ //Default values int timeShift = -4; double feedbackGain = 0.001; double noiseLevel = 0.0; int numberIterations = 100; if(args.length != 4){ System.out.println( "Usage: java Adapt01 " + "timeShift feedbackGain " + "noiseLevel numberIterations"); System.out.println( "Negative timeShift is delay"); System.out.println( "Using -4 sample shift by default"); System.out.println( "Using 0.001 feedbackGain by default"); System.out.println( "noiseLevel is a decimal fraction"); System.out.println("Using 0.0 by default"); System.out.println( "numberIterations is an int"); System.out.println("Using 100 by default"); }else{//Command line params were provided. //Convert String to int timeShift = Integer.parseInt(args[0]); System.out.println( "timeShift: " + timeShift); //Convert String to double feedbackGain = Double.parseDouble(args[1]); System.out.println( "feedbackGain: " + feedbackGain); //Convert String to double noiseLevel = Double.parseDouble(args[2]); System.out.println( "noiseLevel: " + noiseLevel); //Convert String to int numberIterations = Integer.parseInt(args[3]); System.out.println( "numberIterations: " + numberIterations); }//end else if(abs(timeShift) > 6){ System.out.println( "Time shift magnitude > 6 not allowed."); System.out.println("Terminating"); System.exit(0); }//end if
The code in the main method in Listing 1 deals with the command line parameters. If the user enters command line parameters, those parameters are used in the adaptive process. If the user doesn't enter command line parameters, a set of default parameters are used in the adaptive process.
The code in Listing 1 is completely straightforward and shouldn't require explanation.
Perform the adaptive process
The code in Listing 2 instantiates an object of the Adapt01 class and invokes the process method to cause the adaptive process to be performed. As described above, the parameters passed to the process method are either provided by the user as command line parameters, or provided by the program by default if the user doesn't enter command line parameters.
new Adapt01().process(timeShift, feedbackGain, noiseLevel, numberIterations); }//end main
Listing 2 also signals the end of the main method.
The parameters for Figure 1 and Figure 2
The case that produced the output shown in Figure 1 and Figure 2 was run without entering command line parameters. Hence, the adaptive process was executed using the following default parameters, which were displayed by the code in the main method:
Using -4 sample shift by default Using 0.001 feedbackGain by default noiseLevel is a decimal fraction Using 0.0 by default numberIterations is an int Using 100 by default
The process method of the Adapt01 class
The process method of the Adapt01 class begins in Listing 3. The code in Listing 3 begins by declaring and populating a nine-element array of type double containing the initial convolution filter. This is the filter that is shown by the impulse response at the top of the left column in Figure 2. The contents of this array will be adaptively modified as the program executes.
void process(int timeShift, double feedbackGain, double noiseLevel, int numberIterations){ //Create the initial convolution filter. double[] filter = {0,0,0,0,1,0,0,0,0}; //Create array objects that will be used as // delay lines. double[] rawData = new double[13]; double[] chanA = new double[9]; double[] chanB = new double[9];
Create three tapped delay line objects
Then the code in Listing 3 declares three array objects, which will be used as tapped delay lines for the rawData, chanA, and chanB.
A delay line is similar to a queue. For example, think of a short section of hose that is full of colored marbles. When you insert a new marble in one end, a marble gets pushed out and discarded from the other end. Now think of cutting a series of small holes along the hose through which you can see the color of the marble next to each hole. You can think of these holes as taps from which you can extract the color of the marbles as they progress past the holes.
Each of the delay lines in this program is implemented using an array object. Data enters the delay line at the topmost element and moves to the next lower element once during each iteration. The data value that is in element 0 during a particular iteration is discarded and replaced by the value from element 1 during the next iteration.
The ability for the code to access any individual element provides taps by which the contents at any stage in the delay line can be retrieved by the code.
Instantiate a plotting object for time series data
The code in listing 4 instantiates an object of the class named PlotALot05, which provides the ability to plot the time series data in the format shown in Figure 1.
PlotALot05 plotObj = new PlotALot05( "Time Series",398,250,25,5,4,4);
The class named PlotALot05 is a simple extension of the class named PlotALot04, which I explained in the lesson entitled Plotting Large Quantities of Data using Java. I will refer you to that lesson for a general explanation of the class.
(The source code for the class named PlotALot05 is provided in Listing 33 near the end of this lesson.)
Output on the command-line screen
The parameters passed to the constructor for the class caused the constructor to display the following information about the plotting object on the command line screen.
Title: Time Series Frame width: 398 Frame height: 250 Page width: 390 Page height: 223 Trace spacing: 25 Sample spacing: 5 Traces per page: 8 Samples per page: 156
Instantiate a plotting object for frequency response data
The code in Listing 5 instantiates a plotting object for two channels of frequency response data. One channel is used to plot the amplitude response in db and the other channel is used to plot the phase on a scale that extends from -180 degrees to +180 degrees.
PlotALot03 freqPlotObj = new PlotALot03("Freq",264,487,20,2,0,0);
The class named PlotALot03 is one of the classes that I explained in the earlier lesson entitled Plotting Large Quantities of Data using Java. (I will refer you back to that lesson for a copy of the source code for this class.) The parameters that describe this plotting object are given below.
Title: Freq Frame width: 264 Frame height: 487 Page width: 256 Page height: 460 Trace spacing: 20 Sample spacing: 2 Traces per page: 22 Samples per page: 1408
Instantiate a plotting object for the impulse response data
The code in Listing 6 instantiates a plotting object to display the impulse response of the convolution filter at intervals during the adaptive process. I explained the class named PlotALot01 in the earlier lesson entitled Plotting Large Quantities of Data using Java. (Once again, I will refer you back to that lesson for a copy of the source code for this class.)
PlotALot01 filterPlotObj = new PlotALot01( "Filter",(filter.length * 4) + 8, 487,40,4,0,0);
The actual plotting object parameters
The actual parameters that describe this plotting object are:
Title: Filter Frame width: 112 Frame height: 487 Page width: 104 Page height: 460 Trace spacing: 40 Sample spacing: 4 Traces per page: 11 Samples per page: 286
The Frame width is different
Note that the actual Frame width of 112 is different from the specified Frame width of 44 in Listing 6. This is because the minimum allowable width for an AWT Frame object is 112 pixels under WinXP regardless of the specified width.
(As described below, this code is very specific to the WinXP operating system for correct plotting of the impulse response data.)
Because the actual Frame width doesn't match the specified Frame width, the code in Listing 6 won't cause the plotting process to synchronize properly and to plot a single impulse response on each axis for filter lengths less than 25 coefficients. To compensate for this problem, the code that feeds the filter data to the plotting object later in the program extends the length of the filter to cause it to synchronize and to plot one impulse response on each axis.
(If the program is run on an operating system for which the sum of the left and right Frame inset values is other than eight pixels, even that compensating code won't provide proper synchronization. In that case, the individual impulse response functions will appear to walk across their axes with each one starting at a different location on the axis.)
Display frequency response of the filter
Listing 7 invokes the method named displayFreqResponse to compute and display the frequency response of the initial convolution filter at 128 points between zero frequency and the Nyquist folding frequency.
displayFreqResponse(filter, freqPlotObj, 128, filter.length - 5);
At this point, I am going to set the discussion of the process method aside momentarily while I explain the method named displayFreqResponse. I will return to the discussion of the process method shortly.
The displayFreqResponse method
The displayFreqResponse method, which begins in Listing 8, receives a reference to a double array containing a convolution filter along with a reference to a plotting object capable of plotting two channels of data. The method also receives a value specifying the number of frequencies at which a discrete Fourier transform (DFT) is to be performed on the filter, along with the sample number that represents the zero time location in the filter.
The method uses this information to perform a DFT on the filter from zero to the Nyquist folding frequency. It feeds the resulting amplitude spectrum and the phase spectrum to the plotting object for plotting later.
void displayFreqResponse(double[] filter, PlotALot03 plot, int len, int zeroTime){
Performing the discrete Fourier transform
The process method uses a static method named transform belonging to a class named ForwardRealToComplex01 to perform the Fourier transform. I explained that class and method in detail in the earlier lesson entitled Spectrum Analysis using Java, Sampling Frequency, Folding Frequency, and the FFT Algorithm.
Description of the transform method
(I will refer you to that lesson for a copy of the source code for the ForwardRealToComplex01 class.)
The static method named transform performs a real to complex Fourier transform. The method does not implement the FFT algorithm. Rather, it implements a straightforward sampled data version of the continuous Fourier transform defined using integral calculus.
The return values
The method returns the following:
- Real part of the spectral analysis result
- Imaginary part of the spectral analysis result
- Magnitude of the spectral analysis result
- Phase angle of the spectral analysis result in degrees
The transform method parameters
The method parameters for the transform method are:
- double[] data - incoming real data
- double[] realOut - outgoing real data
- double[] imagOut - outgoing imaginary data
- double[] angleOut - outgoing phase angle in degrees
- double[] magnitude - outgoing amplitude spectrum
- int zero - the index of the incoming data sample that represents zero time
- double lowF - low frequency limit for computation as a fraction of sampling frequency
- double highF - high frequency limit for computation as a fraction of sampling frequency
Frequency increment, magnitude spectrum, and number of returned values
The computational frequency increment is the difference between the high and low limits divided by the length of the magnitude array.
The magnitude (amplitude) is computed as the square root of the sum of the squares of the real and imaginary parts. This value is divided by the incoming data length, which is given by data.length.
The method returns a number of points in the frequency domain equal to the incoming data length regardless of the high and low frequency limits.
Prepare the required array objects
Listing 9 creates the five array objects required as input parameters by the transform method. Then Listing 9 uses the arraycopy method of the System class to copy the incoming filter data into the array object referred to by timeDataIn.
double[] timeDataIn = new double[len]; double[] realSpect = new double[len]; double[] imagSpect = new double[len]; double[] angle = new double[len]; double[] magnitude = new double[len]; //Copy the filter into the timeDataIn array. System.arraycopy(filter,0,timeDataIn,0, filter.length);
Note that the length of the timeDataIn array is about fourteen times greater than the length of the actual convolution filter. This results in a small frequency increment value producing smooth representations of the frequency response curves in Figure 2.
Compute the frequency response of the convolution filter
Listing 10 invokes the static transform method of the ForwardRealToComplex01 class to compute and return the frequency response of the convolution operator from zero to the Nyquist folding frequency.
ForwardRealToComplex01.transform(timeDataIn, realSpect, imagSpect, angle, magnitude, zeroTime, 0.0, 0.5);
You can compare the parameter values in Listing 10 with the description of the parameters given earlier. We will discard all of the transform results other than the amplitude response returned in the array referred to by magnitude, and the phase response returned in the array referred to by angle.
Prepare to convert amplitude response to log base 10
That's all there is to getting the amplitude and phase response of the convolution filter. The remaining code in the displayFreqResponse method is concerned with plotting the data in the format shown in the right column of Figure 2.
The amplitude response will be converted to decibels before plotting. This requires converting the amplitude data to log base 10. I will use the log10 method of the Math class to perform the conversion.
Some possible amplitude response values are not compatible with the log10 method. I invite you to examine Sun's documentation for that method to see what I mean. The code in Listing 11 converts those values to compatible values if they exist in the amplitude response.
//Eliminate or change all values that are // incompatible with log10 method. for(int cnt = 0;cnt < magnitude.length; cnt++){ if((magnitude[cnt] == Double.NaN) || (magnitude[cnt] <= 0)){ magnitude[cnt] = 0.0000001; }else if(magnitude[cnt] == Double.POSITIVE_INFINITY){ magnitude[cnt] = 9999999999.0; }//end else if }//end for loop
Convert amplitude response to log base 10
The code in Listing 12 invokes the log10 method in a for loop to convert each amplitude response value to log base 10.
for(int cnt = 0;cnt < magnitude.length; cnt++){ magnitude[cnt] = log10(magnitude[cnt]); }//end for loop
Because this is an in-place conversion, all future references to the array referred to by magnitude will be referring to data values that have been converted to log base 10. This data can be thought of scaled decibels.
Normalize the data for plotting
One of the difficulties that is always encountered in plotting large quantities of data is the problem of scaling the data so that it fits in the range allocated to the plotting space. The code in Listing 13 begins by finding the absolute peak value of the log base 10 amplitude response data. Then it scales that data by a factor of 50, divided by the peak value, and adds a constant value of 50 producing the results shown in Figure 2.
//Find the absolute peak value double peak = -9999999999.0; for(int cnt = 0;cnt < magnitude.length; cnt++){ if(peak < abs(magnitude[cnt])){ peak = abs(magnitude[cnt]); }//end if }//end for loop //Normalize to 50 times the peak value and // shift up the screen by 50 units to make // the values compatible with the plotting // program. Recall that adding a constant to // log values is equivalent to scaling the // original data. for(int cnt = 0;cnt < magnitude.length; cnt++){ magnitude[cnt] = 50*magnitude[cnt]/peak + 50; }//end for loop
Feed the data to the plotting object
The code in Listing 14 feeds the normalized decibel data and the phase response data to the plotting object where it will be plotted later.
The phase data ranges from -180 to +180 degrees. This data is divided by a factor of 20 to make it compatible with the plotting format being used.
for(int cnt = 0;cnt < magnitude.length; cnt++){ plot.feedData( magnitude[cnt],angle[cnt]/20); }//end for loop }//end displayFreqResponse
Listing 14 signals the end of the displayFreqResponse method. At this point, I will resume my discussion of the process method of the Adapt01 class.
Display impulse response of the initial convolution filter
Back in the process method, Listing 15 feeds the values of the initial convolution filter (see Listing 3) to one of the plotting objects (see Listing 6) for plotting as shown at the top of the left column in Figure 2.
for(int cnt = 0;cnt < filter.length;cnt++){ filterPlotObj.feedData(30*filter[cnt]); }//end for loop
Extend the convolution filter
Recall from the lesson entitled Plotting Large Quantities of Data using Java that this plotting object knows nothing about the end of one convolution filter and the beginning of the next. Rather, the plotting object is designed to simply accept large quantities of data values to be plotted and to cause the plot to automatically wrap from the current axis down to the next axis when the right side of the current axis is encountered.
Adjust width of the plotting surface to match length of impulse response
Normally, to cause each impulse response to appear on a separate axis, I would adjust the width of the plotting surface (Page width) to cause it to match the length of the impulse response. However, an AWT Frame object has a minimum allowable width of 112 pixels under WinXP, regardless of the width that you specify in the setSize method. Therefore, it was not possible to cause the width of the plotting surface to match the length of the impulse response in this case.
Extend the length of the impulse response
Therefore, the code in Listing 16 (working in conjunction with the code in Listing 6) extends the length of each impulse response to cause it to match the width of the plotting surface.
(As mentioned earlier, however, this will not cause the plot of the impulse response to synchronize properly when run under an operating system for which the sum of the left and right inset values for an AWT Frame object is something other than eight pixels. In that case, a single point (such as the peak) on the impulse response will appear to move across the successive axes.)
if(filter.length <= 26){ for(int cnt = 0;cnt < (26 - filter.length); cnt++){ filterPlotObj.feedData(2.5); }//end for loop }//end if
A constant value of 2.5
I extended the impulse response with a constant value of 2.5 to cause the extended portion to be visually separable from the actual impulse response values. The extended portion is shown by the broad flat areas to the right of the impulse response plots in the left column of Figure 2.
Declare and initialize adaptive variables
Listing 17 declares and initializes some variables that are used later in the adaptive process.
double output = 0; double err = 0; double target = 0; double input = 0; double dataScale = 25;//Default data scale
Execute the adaptive process
Listing 18 shows the beginning of a for loop that creates the data and performs the adaptive process on that data. The body of this loop executes once for each adaptive iteration specified by the user as numberIterations (see Listing 1).
//Do the iterative adaptive process for(int cnt = 0;cnt < numberIterations; cnt++){ //Add new input data to the delay line // containing the raw input data. flowLine(rawData,Math.random() - 0.5);
Create the wide bandwidth signal data
Listing 18 uses a random number generator to get a random value to serve as a wide bandwidth signal sample. The random number generator produces random values having a flat distribution from 0 to 1.0. Listing 18 subtracts 0.5 from the random value causing the resulting distribution to range from -0.5 to +0.5.
Insert data into the rawData delay line
Listing 18 passes the random value to the method named flowLine. Listing 18 also passes a reference to an array object named rawData to the flowLine method.
(The array object referred to by rawData was instantiated in Listing 3 to serve as a tapped delay line for raw data.)
At this point, I will put the discussion of the process method aside for momentarily and explain the method named flowLine. I will return to the explanation of the process method shortly.
The flowLine method
The flowLine method, which is shown in its entirety in Listing 19, is a simple utility method that causes an array object to behave as a tapped delay line.
void flowLine(double[] line,double val){ for(int cnt = 0;cnt < (line.length - 1); cnt++){ line[cnt] = line[cnt+1]; }//end for loop line[line.length - 1] = val; }//end flowLine
The flowLine method receives a reference to an array and a reference to a value of type double. It discards the value at index 0 of the array, moves all the other values down by one element toward index 0, and inserts the new value at the top of the array.
That's all that there is to the flowLine method, so I will resume my discussion of the process method at this point.
Getting raw data for chanA
The purpose of the rawData delay line is to make it possible to get wide band data representing chanA and chanB where chanB can be shifted in time by up to plus or minus six samples relative to chanA.
The array used for the rawData delay line has a length of thirteen elements (see Listing 3). In this case, the value at element index 6 is considered to represent the zero time origin. Therefore, the value at index 0 represents a time delay of six samples and the value at index 12 represents a time advance of six samples.
Feed signal plus noise into chanA
Listing 20 extracts the middle sample (at zero time) from the rawData delay line, adds some random noise to it, and inserts it into a nine-element delay line (see Listing 3) containing the data for chanA.
flowLine(chanA,dataScale*rawData[6] + noiseLevel*dataScale*(Math.random() - 0.5));
The amount of additive random noise is controlled by the value of noiseLevel, which is provided by the user as an input parameter.
Feed signal plus noise into chanB
Listing 21 extracts data with a timeShift from the rawData delay line, adds some random noise, and inserts it into a delay line (see Listing 3) containing the data for chanB.
flowLine(chanB, dataScale*rawData[6 + timeShift] + noiseLevel*dataScale*(Math.random() - 0.5));
Once again, the level of the additive noise is controlled by the value of noiseLevel described earlier.
The time shift is controlled by the value of timeShift, which is provided by the user as a command line parameter.
(The results shown in Figure 1 and Figure 2 were produced with a value of 0.0 for noiseLevel and a value of -4 for timeShift.)
Get the input (chanA) data for plotting
Listing 22 gets and saves the value at the middle of the chanA delay line for plotting later. These are the values that are plotted in black in Figure 1.
input = chanA[chanA.length/2];
Time is relative
When processing sampled data in a computer, (assuming that you are willing to suffer an overall time delay), time is relative. You can consider any sample in a time series to represent zero time.
At this point, we will shift our thinking and consider the center taps for the chanA and chanB delay lines to represent zero time. Thus, each of those delay lines contains the sample value at the current time, four samples of historical data, and four samples of future data.
Why should we think about it this way?
The primary motivation for thinking about it this way is to cause the output from a convolution filter with a single impulse at the center to represent a time series with no time shift in either direction.
Not possible for a real-time system
Obviously, in a real time system, the delay line could not possibly contain future data. Considering the center tap of the chanA delay line to represent zero time actually inserts an overall time delay of four samples into the entire process. This is evident in Figure 5 for which you see four samples with a value of zero at the beginning of the black trace. In this case, noise is inserted into the chanA delay line during the first iteration, but it doesn't emerge from the center tap on the delay line until the fifth iteration.
Figure 1, on the other hand, shows ten iterations before anything emerges from the center tap on the chanA delay line. This is because Figure 1 shows a noise free case where the only input to the chanA delay line is obtained from the center tap on the rawData delay line. Thus, the rawData delay line causes a six-sample delay in addition to the four-sample delay caused by the chanA delay line.
The bottom line
The bottom line is that the value that is extracted and saved for plotting in Listing 22 represents our concept of the value at zero time from the input chanA (but in actuality, an overall time delay has been incurred).
Apply the convolution filter to chanA
Normally, if I were going to apply a fixed convolution filter to a time series, I would write a method that receives the filter and the time series, performs the convolution, and returns the filtered time series. For example, that is what I did in Listing 13 in the earlier lesson entitled Convolution and Frequency Filtering in Java.
However, the situation here is different. The convolution filter is not fixed. Rather, I need to interrupt the convolution operation at the end of each iteration and modify the filter coefficients.
Listing 23 invokes the dotProduct method to apply the filter coefficients to the current data in the chanA delay line returning a single value of type double as a result.
(Click here to read a description of a vector dot product from Mathworld. While I may not have used this terminology in earlier lessons on convolution, the vector dot product is a central element in the computation process involved in convolution.)
output = dotProduct(filter,chanA);
I will explain the dotProduct method at this point and return to the explanation of the process method shortly.
The dotProduct method
This method receives two arrays and treats the first n elements in each array as a pair of vectors. It computes and returns the vector dot product of the two vectors. If the length of one array is greater than the length of the other array, it considers the number of dimensions of the vectors to be equal to the length of the smaller array.
double dotProduct(double[] v1,double[] v2){ double result = 0; if((v1.length) <= (v2.length)){ for(int cnt = 0;cnt < v1.length;cnt++){ result += v1[cnt]*v2[cnt]; }//end for loop return result; }else{ for(int cnt = 0;cnt < v2.length;cnt++){ result += v1[cnt]*v2[cnt]; }//end for loop return result; }//end else }//end dotProduct
As you can see, the vector dot product is simply the sum of the products of the values that describe each of the two vectors.
Get the adaptive target
Returning now to the explanation of the process method, the code in Listing 25 gets and saves the middle sample from the chanB delay line to be used as the adaptive target.
(This is a value from the blue time series plotted in Figure 1.)
In other words, the adaptive process will attempt to cause the filtered version of chanA to match the value in the middle of the chanB delay line.
target = chanB[chanB.length/2];
Compute the error value
As you will see shortly, the adaptive process makes an adjustment to each of the filter coefficients based on the value of an error.
(The error time series is plotted in green in Figure 1.)
As you can see in Listing 26, the error value is the difference between the output produced by applying the filter coefficients to the contents of the chanA delay line (see Listing 23) and the value of the target from Listing 25.
err = output - target;
Update the filter coefficients
We've now arrived at the heart of the matter for an LMS adaptive algorithm. The code in Listing 27 uses a for loop to modify each of the filter coefficient values by computing a correction value for each coefficient and subtracting that correction value from the coefficient.
for(int ctr = 0;ctr < filter.length;ctr++){ filter[ctr] -= err*chanA[ctr]*feedbackGain; }//end for loop
The correction value
The correction value for each coefficient value consists of the product of the following:
- The error value.
- The value of the input time series in chanA that was registered with the coefficient value to produce the dot product that was used to compute the error.
- A constant referred to as feedbackGain that controls the overall magnitude of the correction value.
As you can see from Figure 1 and Listing 27, as the value of the error approaches zero, the magnitude of the correction values also approaches zero and the coefficient values converge to fixed values.
A theoretical justification
I'm not going to attempt to justify this adaptive algorithm theoretically. There are hundreds of articles on the web that provide such justification. If you are interested in a justification, I recommend that you use Google to search them out and read them. For example, you might search for the keywords LMS Adaptive Algorithm or for the keywords Steepest Descent.
An important concept
This is an important concept because I will be using this adaptive algorithm in several future lessons. As mentioned earlier, I wanted to present the algorithm here in a relatively simple case so that when we get to the more difficult cases, you will already have an understanding of the adaptive algorithm and can concentrate on the bigger picture.
The end of the adaptive code
This is the end of the adaptive process. All of the remaining code in the process method is used to display information about the adaptive process.
Feed the time series plotting object
Recall that we are still in a for loop processing one input sample during each iteration of the loop.
The code in Listing 28 feeds the values from four time series to the plotting object that will eventually be used to plot the time series in Figure 1.
The order of the input parameters to the feedData in Listing 28 corresponds to the black, red, blue, and green traces in Figure 1.
Compute and display frequency response data
Listing 29 shows the beginning of an if statement that is used to plot the impulse response and the frequency response of the convolution operator at the end of every tenth iteration.
if(cnt%10 == 0){ displayFreqResponse(filter, freqPlotObj, 128, filter.length - 5);
The code in Listing 29 invokes the displayFreqResponse method discussed earlier to produce the amplitude and phase response plots shown in the right column of Figure 2.
Extend and display impulse response data
The code in Listing 30 deals with the need to extend the impulse response data in order to plot the impulse response at the end of every tenth iteration as shown in the left column of Figure 2.
//Plot the filter coefficient values. // Scale the coefficient values by 30 // to make them compatible with the // plotting software. for(int ctr = 0;ctr < filter.length; ctr++){ filterPlotObj.feedData(30*filter[ctr]); }//end for loop //Extend the filter with a value of 2.5 // for plotting to cause it to // synchronize with one filter on each // axis. See explanatory comment // earlier. if(filter.length <= 26){ for(int count = 0; count < (26 - filter.length); count++){ filterPlotObj.feedData(2.5); }//end for loop }//end if }//end if on cnt%10 }//end for loop
Extending the impulse response for plotting
I discussed the need for extending impulse response for plotting earlier and won't discuss it further here. Suffice it to say that the code in Listing 30 feeds the extended impulse response data to the plotting object so that it can be plotted later.
Listing 30 also signals the end of the if statement that is used to cause its body to be executed every tenth iteration.
Listing 30 also signals the end of the for loop whose body is executed once for every adaptive iteration.
Plot the results
Up to this point in time, a lot of data has been fed into the three plotting objects responsible for plotting the results shown in Figure 1 and Figure 2. However, nothing has actually been plotted yet.
By invoking the plotData method on each of the three plotting objects, the code in Listing 31 causes them to plot their data at the screen coordinates passed as parameters to the plotData method.
(Default screen coordinates are used by the plotting object referred to by plotObj. Once again, I refer you to the earlier lesson entitled Plotting Large Quantities of Data using Java for an explanation as to how this plotting system works.)
plotObj.plotData(); freqPlotObj.plotData(0,201); filterPlotObj.plotData(265,201); }//end process }//end class Adapt01
The end of the process method
Listing 31 also signals the end of the process method and the end of the Adapt01 class.
Some more sample results
Before ending this lesson, I want to show you the results for a few more cases. I will begin with a case having no uncorrelated noise on chanA and chanB but with chanB having a time shift of +3 samples relative to chanA.
I will run this case using the following command on the command line:
java Adapt01 3 0.001 0.0 100
This produces the following output on the command line:
timeShift: 3 feedbackGain: 0.0010 noiseLevel: 0.0 numberIterations: 100
Compare this output with the command line output for the first example, particularly with respect to the value of timeShift.
The graphic output
The time series output for this case is shown in Figure 3.
Figure 3
If you compare Figure 3 with Figure 1, you will see that the target (blue) data in Figure 3 leads the input (black) data in Figure 3, which is just the reverse of Figure 1 where the target data lags the input data.
In both cases, the error is decreased to near zero about midway across the top four traces, and the filter output (red) data converges to become a good match for the target (blue) data at that point.
The impulse and frequency response
The impulse response of the convolution filter is shown in the left column of Figure 4. The frequency response is shown in the right column of Figure 4.
Figure 4
Compare Figure 4 with Figure 2
If you compare Figure 4 with Figure 2, you will see that the adaptive process causes the peak in the impulse response to move three samples to the right in Figure 4, as compared to four samples to the left in Figure 2. This is the difference between a leading target for this example and a lagging target for the previous example.
In addition, the slope of the phase response in positive in Figure 4 and negative in Figure 2. A positive slope indicates a leading target for this example whereas a negative slope indicates a lagging target for the previous example.
Finally, the magnitude of the slope of the phase response in Figure 4 is less than the magnitude of the slope in Figure 2. This is an indication that the relative time shift of three samples in this example is less than the relative time shift of four samples in the previous example.
One final example
For this case, white random noise was added to both chanA and chanB at a level equal to twenty-five percent of the signal level on each channel. The noise was uncorrelated between chanA and chanB.
Some changes to the input parameters were required to achieve reasonably good results. The following command was entered on the command line for this case:
java Adapt01 3 0.0005 0.25 210
Compare with the previous example
Compare this with the command line input for the previous example and you will see that:
- The feedbackGain was reduced from 0.0010 to 0.0005.
- The noiseLevel was increased from 0.0 to 0.25.
- The numberIterations were increased from 100 to 210.
These parameters produced the following output on the command line:
timeShift: 3 feedbackGain: 5.0E-4 noiseLevel: 0.25 numberIterations: 210
Note that the time shift of the target relative to chanA is still +3 samples as in the previous example.
The time series output
The time series output for this case is shown in Figure 5.
Figure 5
Error never goes to zero
One thing worth noting is that the error (green) never goes to zero in Figure 5 regardless of the quality of the adaptive solution. The target contains white random noise. There is nothing that the convolution filter being applied to chanA can do to eliminate that noise and it passes straight through from the target to the error in the subtraction process shown in Listing 26.
There is also white random noise on chanA. If the convolution filter maintains a flat amplitude response as intended, this noise will be passed through to the output also and will contribute to the noise on the error signal in Figure 5.
(Theoretically, however, the average of the white random noise from chanA and the white random noise from the target will be reduced by about the square root of 2 relative to the level on either channel.)
Despite the uncorrelated noise on both channels, the filtered output (red) is a reasonably good replica of the target (blue) by the beginning of the traces in the bottom page of Figure 5.
The impulse response
The impulse response at the beginning and at the end of every tenth adaptive iteration is shown in the left column in the two pages in Figure 6. As you can see, this impulse response is converted from a single impulse in the center of the convolution filter to a single impulse (plus a few very small non-zero values) three samples to the right of center after about 140 iterations. As you know, this is the correct solution, and it was achieved despite the presence of random noise on the two channels.
Figure 6
What this means is that after about 140 iterations, the output from the convolution filter has been shifted so as to register with the target. Most of the error that we see in Figure 5 after this point in time is simply the result of the random white noise being passed through from chanA and the target to the error.
The frequency response
After about 140 iterations, the amplitude response shown in the right column of Figure 6 is very flat, and the phase response has a positive slope and a linear shape indicating that the convolution filter has converged to the simple time-shift filter that we know to be the correct solution to the problem.
Page 1 of 2
IT Solutions Builder TOP IT RESOURCES TO MOVE YOUR BUSINESS FORWARD
Which topic are you interested in?
Data Storage
IT Management
What is your company size?
What is your job title?
What is your job function?
Searching our resource database to find your matches...


text:
A Chevy II for Runnin' and Ridin'
Purchasing an already completed hot rod is both exciting and nerve-racking. Just ask Ed Vannoy of Jefferson, North Carolina.
When he stumbled upon this car, its look got him excited, but he was concerned whether it could be a fun and dependable driver. To add to the drama, even before taking a short drive in it, he had pretty much decided to buy it. On the short drive home, Vannoy found he wasn't thrilled with the car's road manners, so he called Kyle Tucker, owner of Detroit Speed & Engineering (DSE) in Brighton, Michigan, for help. Vannoy needed DSE to take the show-pretty Chevy II to the land of cross-country road warrior.
Not surprising to anyone who's had a car in the shop for upgrades, the list of Vannoy-requested changes grew once the car was torn apart. DSE is well-known for their skilled mini-tub work, custom dashboards, and some neat bolt-on components, and Vannoy couldn't avoid having these and a few more upgrades thrown at his Deuce.
The biggest structural and visual change was to the rear wheelwells. They were mini-tubbed and widened 2 inches to accept 285/40ZR17 BFGoodrich G-Force T/As on Budnik's new Fatlips 17×10 Famosa Dish wheels (to complement the front-running 245/45ZR17 BFG G-Forces on 17×8 Budnik Famosa Fatlips operating with rolled fender well lips for increased tire-turning clearance). All the fun is brought to a halt by Baer brakes all around, utilizing 12-inch rotors with the zinc wash to prevent rusting.
At the same time, DSE's Paul Morgan fabricated a custom dashboard and console from sheetmetal and loaded it with carbon fiber Auto Meter gauges, Phipps A/C ducts, a DSE headlight switch, and Sony CD stereo. Behind the dash sits a Vintage Air Gen II Compact unit, the motor for the DSE delay wiper system (which provides late-model intermittent wiper control), and an American Autowire electrical harness. An ididit steering column steers with the help of a DSE remote-reservoir pump, pushing fluid through a DSE rack to add power-assist and eliminate bump steer in the front suspension.
For added comfort, many rolls of Dynamat sound deadener were applied to the floor, and new Year One rubber was installed on all the window and door seal areas. The final upgrades to the interior were the additions of a custom carpet kit by All-American Auto and Juliano's seat belts.
DSE kept the ZZ3 GM Crate Engine and the clutch system on the Muncie four-speed manual transmission that came with the "II" when he'd bought it. But, they added a Street & Performance accessory drive to the engine and converted the clutch from mechanical to hydraulic by installing a Centerforce dual friction clutch and flywheel (with a Tilton hydraulic) throwout bearing and actuating it with an AP master cylinder tucked under the dashboard.
The front suspension had already been upgraded to a FatMan Fabrications 3rd-Gen Camaro MacPherson strut system, which was left alone except for the steering upgrades. The forward leaf spring mounts for the rear suspension were relocated 2 inches inward on each side to accommodate the mini-tubbing.
DSE offset shackles were used in the rear to get the Eaton multi-leaf springs sitting right. They hold a DTS-narrowed 12-bolt rearend with Ford housing ends, Moser axles, Eaton carbon clutch limited-slip unit, aluminum rear cover with support bolts, and a 3.08 gear for open-road cruising (and as a match to those relatively short tires).
The engine breathes through a DSE-crafted Borla 3-inch stainless exhaust with XR-1 mufflers, and cools through a polished Be Cool radiator blown through with Spal electric fans. All the fluids run through Goodridge braided steel and InLine Tube stainless hard lines, and juice is provided by an Optima battery safely held in "The Clamp" DSE battery mount, located in the trunk.
Vannoy reports the car is everything he wanted. "I always liked the way the car looked, now I love the way it drives. DSE obviously knows what needs to be done to get a hot rod to drive like a late-model. Now that he's proved to himself a great-looking car can be a great driver, Vannoy's plans are to put some serious miles on his pretty Chevy II.

subset: commoncrawl


text:
Here are some happy eaters:
The cupcake paparazzi were present, as usual! I think ICL entries must be amongst the most photographed cakes in the world….
….and looking at how gorgeous they are, I can see why!
We had a total of 35 entries from 25 bakers; as we only had 2 professional bakers this time we merged it back into one competition – it made more sense.
All the entries:
Winner – Shelley's Tea and biscuit cupcakes
As soon as I heard Shelley's combination I knew it had potential to be great…and boy did it deliver! The sponge was chai tea flavoured, as was the amazingly smooth frosting. One of my fellow eaters described it as "incredible". It was sprinkled with crisp biscuit crumbs and a little heart shaped butter biscuit sat atop. The creamy frosting and crumbly sponge was divine to eat –a taste and texture sensation. The pretty gingham wrapper also attracted many compliments. Well done Shelley on your most deserved win!
Runner up – Annabelle's Strawberry and vanilla cupcakes
Annabelle's cupcake proved that classic flavour combinations are always popular. A flavoursome vanilla cupcake was topped with strawberry and vanilla frosting which was creamy and soft in your mouth. The overall cupcake had a lovely lightness to it that made you think of summer and warm days. This cake was a big hit at my table of eaters and we wondered if the strawberry on top would count as one of our five a day, lessening the calorific damage we were doing by eating so many yummy cakes!
Those were the two winners on the night, here are all our other entries. Prepare yourself for a journey through flavour and awesomeness……
Gjinn's Lychee and vanilla cupcakes
Gjinn's pretty cupcake comprised of vanilla sponge with lychee buttercream and lychee jelly. The inclusion of the jelly (it's nestling in the buttercream) added an extra layer of texture. Beautiful scented lychee came through and lingered in your mouth after eating the cake. It was sweet and fruity and – being a lychee addict – I loved it!
Gem's "It was mint to be" cupcakes
Gem gave us a chocolate mint oreo cupcake with mint oreo frosting and an oreo truffle topping. She made the truffle by crushing oreos, mixing them with some cream cheese before covering it in thick chocolate. The balance of the mint and chocolate was perfect and the flavour was rich and deep. It was the sort of cupcake you could happily eat every day and never tire of it.
Ellie's Peanut butter and jelly cupcakes
Ellie provided us with the first of our peanut butter and jelly. Ellie really packed the cupcake with peanut – it was moist and nutty and incredibly flavoursome. The jelly (or jam if, like me, you always think of jelly as something Knitted Character should be riding) was in the sponge as well as on top of the buttercream and worked very well with the crumbly sponge.
Charlotte's Chocolate and vanilla cupcakes
Charlotte's vanilla sponge was topped with chocolate buttercream. The stunning twist to this entry was that Charlotte, instead of using a paper case, made her cases out of chocolate so the whole thing was edible! As if that weren't enough, she also coloured the chocolate and painted it in designs – one looked like zebra markings, others were pastel coloured. Quite amazing! The edible case added some texture and bite to the cupcake – eating sponge encased in thick chocolate is something I definitely need to do more often!
Kelly's Chocolate and peanut butter hi-hat cupcakes
Kelly, I am in awe at your complete mastery of the hi-hat, and I speak as someone who has wanted to make these for a long time but always bottled it! A hi-hat is a cupcake that, once frosted, is dipped in molten chocolate so that the frosting is coated in a thin layer of chocolate. When the chocolate sets you have a crisp veneer encasing the fluffy frosting. To achieve this you hold your cupcake upside down in a bowl of molten chocolate – I always have visions of my frosting dropping into the bowl! Kelly's frosting was whipped and light and teamed with the chocolate it was a knock out combination. Lovely flavours too – so clear and distinct. I know I'm not allowed to be partisan but you've probably guessed this was one of my favourites of the night.
Mitsu's Coffee and walnut cupcakes
Mitsu's vegan entry comprised of coffee and walnut sponge with coffee icing. The icing was whipped and light. Mitsu's flavours were great – you got the full richness of the coffee but then the slight nutty bitterness of the walnut.
Sasha's Chocolate and ginger zing cupcakes
Sasha's vegan-friendly cupcake was a chocolate sponge containing chunks of fiery ginger topped with chocolate frosting. They certainly lived up to the "zing" in their name – my mouth was filled with hot ginger and then cleansed with smooth chocolate. A lovely combination.
Sasha's Orange and apricot cupcakes
Sasha's second vegan entry was a sweet and juicy orange sponge containing dried apricot pieces with a buttercream frosting. The orange flavour dominated but then the tangy apricot cut through in a fruity, refreshing way.
Sasha's third entry technically breached the rules as it contained 4 flavours (including the vanilla frosting) but we allowed it. Sasha admitted she got confused and thought the challenge was a minimum of two flavours! All the flavours were identifiable – the banana and walnut being the strongest and the maple syrup lurking in the background.
Luke's Lavender and vanilla cupcakes
Poor Luke had an awful day at work and arrived at the venue just in time to pipe the vanilla icing on his cupcakes. We're all glad he did as these were yummy. I often find lavender overpowering in baked goods but Luke judged these perfectly, telling me that he infused lavender overnight in the milk he then used for the sponge. The creamy vanilla flavour gave way to the sweet scented lavender in a dreamy way – so tasty!
Victoria's Cheese and pickle cupcakes
Most bonkers entry of the night? Step forward Victoria! Cheddar cheese and proper pickles (i.e. pickles, not a jar of pickle like Branston for example) combined to make one of the strangest cupcakes I've seen. But believe me - it tasted good! The cheese and pickle flavour was exactly like eating a savoury roll but the sponge was so light and crumbly you had no doubt that it was a cake. I have to be honest – this was one I was nervous about but it was so tasty that we all went back for seconds!
Victoria's Apple and clove cupcakes
Victoria's second entry was an apple and clove sponge with decorative apple on top. The sweet apple and intense clove worked very well. Max, my fellow taster, said admiringly, "this cake smells like a lovely forest" and I sort of know what he meant! The clove flavour built in your mouth and got more intense – I loved it!
Annabelle's Mint chocolate cupcakes
This was Annabelle's second entry of the night (her first entry claimed the runner's up spot) and her favourite of the two. It just shows that you can't always trust your own judgement! Her chocolate sponge was topped with mint buttercream and an After Eight chocolate. The sponge was moist and gooey and rich, then the mint cut through and cleansed your palate. My fellow eater Jasmin (who frankly has been watching far too much "Gavin and Stacey" lately) described it as "lush".
Fiona's Vodka and cranberry cupcakes
Fiona's combination was a classic for anyone with a penchant for cocktails! The sponge and frosting both contained the two flavours; the cranberry was sharp and fruity then the vodka came through subtly. That sticky marshmallow frosting was a work of art – how something can be so light, yet so satisfyingly sticky beats me!
Alix's "Rebel rebel" cupcakes
Alix's vegan cupcake was a powerhouse of flavour – the flavours being chocolate and peanut. The chocolate and peanut sponge was rich and flavoursome and the peanut butter frosting was smooth and whipped. Extra texture came from the chocolate shavings and caramelised peanuts. The caramelised peanuts were the star component for me – they added crunch and bite but also intense nuttiness. I can say no more than three out of the five eaters at my table voted for this one!
Betty's Peanut butter and jelly cupcakes
Betty combined her peanut butter sponge housing a nice splodge (that's a technical term) of strawberry jam) with peanut butter frosting dotted with more jam. I think it's a very pretty, happy looking cake! I loved the stickiness of the jam in this cake – the peanut butter is smooth and the textures worked well together.
Rosalyn's Pecan and homemade marmalade cupcake
Rosalyn's light sponge contained both pecan and marmalade. The flavours really complimented each other and we all liked how the marmalade was packed with flavour but not overly sweet. The nuttiness of the pecans added more flavour and I like that Rosalyn kept the decoration simple – just some more of her yummy homemade marmalade (how talented are our bakers?) and a pecan.
Rosalyn's Chocolate and beetroot cupcakes
Rosalyn's second entry was this dark beauty! The intensely chocolate sponge had the extra depth of flavour, colour and moisture that beetroot adds. It was a great decision to top the sponge with whipped cream as it cleansed and freshened your palate leaving you desperate to go back for another forkful of decadence!
Florence's "Fluff and nutter" cupcakes
If you're not au fait with 'fluff and nutter' (and why would you be – Florence invented the term!) I can tell you that it's marshmallow and peanut butter. The first thing you tasted eating Florence's cupcake was the sweet and sticky marshmallow frosting – it was stick to your lips fluffy marshmallow and hugely satisfying! Once you'd licked your lips clean you noticed the peanut butter sponge. If I had to describe this cake in two words I'd pick "gooey" and "naughty". If I was allowed three, I'd add "divine"!
Jack's Saffron and orange cupcakes
Jack's elegant cupcakes were packed with flavour and intrigue. The juicy sweet orange was heavenly then the saffron came through – it added an exotic richness that was unique. This was an imaginative combination that worked well. I've never used saffron in baking before, saving it for my paella, but this cupcake opened my eyes!
Mara's Chocolate and strawberry cupcakes
Mara's chocolate sponge contained strawberry juice and was topped off with a light and flavoursome strawberry buttercream. I like that Mara managed to make the strawberry as dominant as the chocolate. It reminded me of a strawberry Quality Street – remember that gorgeous fruity pink filling? That was exactly like this beautiful cake.
Mara's Lime and coconut cupcakes
Mara used her flavours in both the sponge and the frosting and it was a tropical delight! The fruity aroma hit you as you moved the fork towards your mouth. It's a classic combination – the sweet citrus lime then the rich coconut. I always love anything with coconut – it's the way it adds texture as well as taste.
Tamara's Lemon and blueberry cupcakes
Our defending champion's cupcake comprised of a lemon and blueberry sponge topped with lemon and blueberry frosting. The sponge was delightful and contained blueberries that oozed their fruity goodness into the sponge. The frosting was smooth and not overly sweet. I think blueberries are one of the prettiest coloured fruits for baking – just look at the gorgeous colour of the frosting!
Shelley's Lemon and blueberry cupcakes
Our winner Shelley spoiled us and entered this cupcake too – it was our lucky night! Her lemon and blueberry sponge was topped with an intense lemon frosting – it had the richness to it that lemon curd has. My fellow taster Max rightly observed that the blueberries sitting on top of the frosting cut through the tartness of the lemon resulting in a gorgeous flavour.
Vanessa's Pink champagne and strawberry cupcakes
Vanessa's decadent champagne and strawberry sponge was topped with a strawberry frosting. There were two key aspects of this cupcake that delighted me: firstly, the incredibly soft sponge and secondly, the lovely fruitiness. I have to admit a fondness for the dinky little strawberry decoration too!
Natalie's Raspberry and white chocolate cupcakes
Natalie produced an intensely fruity frosting that worked so well sitting on top of a creamy, mellow white chocolate sponge. White chocolate is so nice in sponge cakes (well, in anything really!) as it seems to make the sponge even softer than normal. I have never teamed white chocolate with raspberry in a cupcake and it worked so well that I can see myself dabbling with these ingredients!
Gill's Blackberry and white chocolate cupcakes
Poor Gill was stuck in traffic and fearful that her cupcakes might not make it in time – luckily for us, they did! This combination proved, again, how well white chocolate works with fruit; the white chocolate and blackberry sponge created creamy, fruity flavours in your mouth and the blackberry in the frosting added fruity stickiness.
Nathalina's "Tropical Paradise" cupcakes
Nathalina's coconut sponge was teamed with passion fruit buttercream. Not only was this a great flavour combination but great texture too. I love the way passion fruit seeds crunch – it's inexplicably satisfying! I'm always a fan of shredded coconut too.
Nathalina's "Batman and Robin" cupcakes
Nathalina's lemon sponge was drizzled with liquorice before being topped with lemon and liquorice buttercream. Nathalina used popular liquorice sweets from Finland (her home country) for the liquorice. The liquorice hit first then the lemon swept through to clean your palate. My favourite description of these was from fellow taster Tina who likened them – because the flavours were so clean and distinct - to Willy Wonka's 3 course meal bubblegum!
Eloise's Cookies and cream cupcake
Eloise went for a classic – who doesn't love cookies and cream? You could have eaten this with your eyes closed and been able to identify the flavours. As with all of Eloise's cupcakes, the frosting was awesome – whipped so it was light as air and creamy smooth.
Eloise's Toffee apple cupcakes
Eloise's second entry of the night was one of my all time favourite combinations – a sticky toffee sponge cupcake containing apple and topped with two-tone apple and toffee buttercream. I have three things to say about the frosting: firstly, how pretty is it? Secondly, how clever is it? Thirdly, how delicious was it? Answer to all three questions: very! And I haven't even mentioned the adorable little caterpillar!
Amanda's Chocolate orange cupcakes
Amanda really provided us with a masterclass her in beautiful flower-making. It's a work of art! Amanda's chocolate orange sponge was filled with orange curd. The sponge was topped with chocolate Ganache and then chocolate orange buttercream. This truly was a luxury, indulgent cupcake! The chocolate and orange was perfectly balanced and I adored the Ganache – it was amazingly chocolaty and smooth and shiny.
So there you have it – I'm sure you'll agree that we were spoiled rotten with the selection of amazing cupcakes on offer.
As always I'd like to thank all the bakers for taking the time to enter, and all the eaters for coming along and helping us pick the winners:
Special thanks to my awesome team of helpers who make the event run so smoothly on the night: Paul, Dave, Tina, Jasmin and Max – thanks. I couldn't do it without you.
All photos are the property of Dave Shipman and are reproduced here with his kind permission. If you wish to use any of his photos please can you email me first for permission – thanks.


text:
Charleston Gazette
Defendants Are Charged With List Of Crimes
The Celebrated Atkins Bankruptcy Case Begun in Federal Court
Eleven Men Are Tried
Northcott Declares Government Will Prove Both Murder and Arson
December 6, 1907
Charleston Gazette
Defendants Are Charged With List Of Crimes
The Celebrated Atkins Bankruptcy Case Begun in Federal Court
Eleven Men Are Tried
Northcott Declares Government Will Prove Both Murder and Arson
The tale told by Elliott Northcott yesterday morning in his opening address to the jury in the celebrated Adkins' bankruptcy case, if proven by witnesses for the government, will equal any novel ever written by Victor Hugo.
Judge Keller was on the bench promptly at 9 o'clock in the federal court yesterday morning, and after some motions had been disposed of, Clerk Edwin M. Keatley called the case of the United States vs. Fred Adkins and others, who are charged with conspiracy to defraud the government and to impede the administration of justice after the government had taken possession of Adkins' store. Mr. Northcott, always a forcible speaker, was fierce in his denunciation of the eleven men who have been a terror to the country surrounding the village of Hart, in Lincoln county, for the past six months.
The indictment on which these eleven defendants are now being tried; charges Fred Adkins, Charles Brumfield, Albert Davis, Man Adkins, John Fleming, Willard Fleming, Bob Fleming, John Adkins, Albert Adkins, Floyd E. Adkins and William Brumfield with conspiring unlawfully, corruptly, fraudulently the feloniously impeding the administration of justice. The district attorney told the jury that this was one of the most important cases that had ever been heard in this or any other court of justice. He stated in words burning with bitterness that the government expected to prove beyond any reasonable doubt that crimes that would harrow the very souls of every juror had been committed in the vicinity of Hart, and had the story been told him three weeks ago he would have thought it a piece of fiction pure and simple, but that ht government had an abundance of testimony from responsible witnesses which it would introduce to prove all the statements be made.
He then went into the details of the case and showed what constituted conspiracy by referring the jury to section 5399 of the revised code of the United States. He also alluded to the factto the fact that the government would prove by witnesses who would tell of the horror that had been created in the neighborhood; houses burned, men shot down from ambush, houses with unprotected women had been shot up and the inmates terrorized until they were afraid to venture outdoors. It was a thrilling recital of the worst crimes that have taken place in this state in a decade.
Hon. Lace Marcum of Huntington, who with R. L. Blackwood, in defending the accused, replied to Mr. Northcott, and said that the distinguished district attorney had tried to prejudice the minds of the jury from the very beginning of the case and pleaded with the jury not to form an opinion until all the evidence for both sides had been offered. He ridiculed the idea that any crimes had ever been committed, as stated by Mr. Northcott, and said that the evidence which the defense would offer, would contradict any such statement. Mr. Marcum's address consumed only ten minutes, but he covered all the vital points that the district attorney had disclosed.
The witnesses, both for the government and defense, were then sent out of the room and the case was formally opened, by placing on the stand Mr. Edwin M. Keatley, clerk of the federal court, who swore that he received the bankruptcy petition of Adkins on July 3, 1907 at 3 o'clock in the afternoon. He was not cross examined by the defense, as that point was admitted by them. Mr. R. M. Barker was the second witness on behalf of the government, and he stated that he was the referee in the matter and received the papers on July 4, and on the 5th appointed J. P. Douglass receiver.
Mr. Douglas was then called and testified that the statements of Mr. Baker were true, and then told of the trip to the Adkins' store where he found that most of the goods were stolen. A. L. Smith was the next witness. He described the robbery and told how Fred Adkins had threatened his life if he stayed at the building. Mr. Smith was one of the guards appointed by the receiver. At this juncture Judge Keller adjourned court until 3 o' clock.
Upon reassembling the examination of the government witnesses continued. Nearly all the evidence was of a highly sensational nature. Hendrix Brumfield, a nephew of Henry Brumfield, one of the defendants swore positively that his uncle tried to drown him, and that Charles Brumfield and Fred Adkins had tried to get him to steal a sack of goods that was contained in the store, and when he refused to do as they bade him, his life was in danger. He was put through a rigid cross examination by Attorney Marcum, but he stuck to his statement. Another witness who was on the stand in the afternoon session was George Ward, a negro, who swore that he was employed to move the goods every day to a different place, and that they (the defendants) were continually changing the locations.
The court adjourned at 5:30, after spending the entire afternoon in the examination of three witnesses. Judge Keller is extremely anxious to conclude the case by Saturday, but judging from the large number of witnesses that are to come, it is thought hardly possible to close on that day. Mr. Northcott is assisted in this case by the assistant district, H. D. Rummell and his law partner in Huntington, Hon. J. P. Douglass.
Crime and Punishment


text:
Recently I purchased Lisa Louise Cooke's new book, The Genealogist's Google Toolbox. It is better than good ... it's excellent. Over the past few years Lisa Louise Cooke has become a popular name in genealogy circles, along with her web site presence of Genealogy Gems. She produces and hosts the Genealogy Gems Podcast which is available in iTunes, the monthly Family Tree Magazine Podcast and videocasts for Family History Expos. She also blogs at Genealogy Gems News Blog. Yes, she's a busy lady.
Her 209 page, 8.5x11 inch book is packed with information and illustrations. I love the illustrations. Why did I need to buy another genealogy book? I play Lisa Louise Cooke's great CDs on Google Earth over and over. Once involved in actual Google Earth use, I have to go back and review them. It will now be easier with the book.
Google is a very popular search engine, widely used by genealogists. The book brings up many ideas and tips about the effective use of Google for genealogy searching. You will learn about Google Alerts, iGoogle, Books, Translation, Gmail and more. There is great information about Google Earth and creating Family History Tour Maps, adding video and images to your Google Earth creations and a bundle more. The book can be purchased from a variety of vendors.
Thanks Lisa for writing such a marvelous book. Your expertise in Google and Google Earth is valuable and appreciated.


text:
There are a number of sources available in the United Kingdom which can be used in searching for births, baptisms, marriages, deaths and burials of British persons overseas. For some baptisms and marriages in the period before ca.1880 there is the worldwide International Genealogical Index (IGI), compiled by the Church of Jesus Christ of Latter-Day Saints (Mormon Church), which includes some British residents overseas. Guildhall Library does not hold the parts of this index which relate to countries outside the British Isles, but these are available at the Genealogical Library of the Church of Jesus Christ of Latter-Day Saints, 64-8 Exhibition Road, London SW7 2PA, at other Mormon libraries throughout the world and at the Society of Genealogists, 14 Charterhouse Buildings, Goswell Road, London EC1M 7BA. There are many other sources besides the IGI. Some of these are at Guildhall Library, but the majority are held elsewhere. Brief details of the more important sources can be found below. More information is given in The British Overseas: a guide to records of their births, baptisms, marriages, deaths and burials available in the United Kingdom (3rd edition, 1994) published by Guildhall Libraryand available in the Guildhall Library Bookshop The British Overseas gives full details of sources held by: Guildhall Library; the National Archives, Kew, Surrey TW9 4DU; the Society of Genealogists; and other record offices and libraries throughout the United Kingdom.
Those records of overseas chaplaincies available for consultation in the United Kingdom fall into three categories: original registers brought back to the United Kingdom; copies made for official purposes, such as bishop's transcripts; and published and unpublished transcripts or copies made by researchers. Guildhall Library holds many Anglican registers, both originals and official copies, as part of the archives of the Bishop of London, and of the Bishop of Gibraltar and his successors.
From 1633, the Bishop of London was held to have responsibility for Anglican chaplaincies overseas where no local bishop had been appointed. In Europe, Anglican chaplaincies and congregations were established after the Reformation, and proliferated from the 17th century. The Bishop's of London's jurisdiction over those in southern Europe ceased in 1842 on the creation of the Diocese of Gibraltar. However, he retained responsibility for those in northern and central Europe until 1980 (although from 1883 this was administered through a suffragan bishop, later given the title of Bishop of Fulham). Between 1970 and 1980 the jurisdictions of Gibraltar, and of North and Central Europe, remained separate, but were administered by one bishop, the Bishop of Fulham and Gibraltar. In 1980 the Bishop of London divested himself of all jurisdiction overseas and a single diocese of Gibraltar in Europe was formed, known subsequently and to this day as the Diocese in Europe.
Outside Europe, the allegiance of the American (Episcopal) church to the Bishop of London had ended after American independence in 1776. The first Anglican bishop in Canada was appointed in 1787, and other British colonies generally acquired bishops of their own in the 19th century. This explains why registers from colonial territories are not usually found in the Bishop of London's archives. In addition, records of baptisms, marriages and burials in India were returned to the civil authorities and are now part of the India Office Records at the British Library. Remember also that few chaplaincies in non-English-speaking countries outside Europe were established before the 19th century.
When English chaplaincies were established overseas, they naturally began to maintain their own registers. The earliest known survive for the 16th century for chaplaincies in Europe. However, for most Anglican chaplaincies in Europe, and indeed elsewhere, the surviving records do not begin until the 18th or (more commonly) the 19th century. Chaplaincies within the Diocese in Europe continue to deposit their registers, some including events in the 20th century, but it is important to realise that this is inevitably on a piecemeal basis. Others are keen to retain their registers, and in some cases Guildhall Library has lists of these: details are given in The British Overseas. Addresses of overseas chaplaincies within the Diocese can be found in its current yearbook or online at http://europe.anglican.org/.
It is not known what arrangements were made by Anglican and English non-conformist residents in countries where there was no English chaplaincy. Some baptisms, marriages and burials may have been entered in the registers of local protestant churches. These registers are of course kept in their country of origin, usually at the church in question or at a local repository. English Roman Catholics overseas should be sought in the registers of local Roman Catholic churches.
From 1816 to 1924 the Bishop of London's registry maintained a series of volumes, now known as the "International Memoranda", for the registration of miscellaneous foreign baptisms, marriages and burials (Ms 10926). Most of the entries are for baptisms and marriages by chaplains officiating at British embassies abroad, but the series includes a number of other registrations, for example, by clergymen travelling overseas or on board ship. It is important to note that registrations were sometimes accepted up to thirty years after a baptism, marriage or burial took place. The British Overseas gives full details of countries covered by the series. Indexes are available in the Manuscripts reading room.
Associated with the "International Memoranda" are the original certificates of baptisms, marriages and burials transmitted to the Bishop of London for registration in the "International Memoranda", 1816-1924 (Ms 11224). Note that not every certificate transcribed in the "International Memoranda" survives in the original. Further details are given in The British Overseas.
From 1921 to 1969, the Bishop of Gibraltar also maintained a memorandum book of miscellaneous baptisms, by clergymen travelling overseas or on board ship, or at British embassies or other diplomatic premises abroad (Ms 23607). An index is available in the Manuscripts reading room and The British Overseas gives details of countries covered.
Many registers held by Guildhall Library are official copies or transcripts deposited with the diocesan authorities for safekeeping. The official copies come in a variety of formats, not solely register transcripts. For example, in some cases certificates were returned, in others merely the certificate stubs.
Both the "International Memoranda" and the Bishop of Gibraltar's memorandum book are indexed as described above. There is also an index compiled by the London Diocesan Registry in the 1960s to the foreign registers and register transcripts which it held (Ms 15061). The index is not entirely straightforward to use as it is arranged alphabetically by the initial letter of each surname, and within each letter alphabetically by place. It also uses references formerly in use at the Diocesan Registry, but the Library's catalogue cross-refers to these. Other indexes are few and far between.
Few marriage allegations exist within the overseas records of the diocesan authorities because licences for marriages outside British colonial territory were not granted by them. However, some allegations survive for intended marriages in Gibraltar Cathedral and the King's (Military) Chapel on Gibraltar from 1859-1873 (Ms 20979). There also survive some marriage licence allegations and certificates for marriages at the British Embassy in Paris,1828-1829, 1835-1837, amongst the records of the Bishop of London (Ms 10891C). Neither of these sets of marriage allegations is indexed.
Australia: microfiche copies of the civil registration indexes of births, marriages and deaths in some Australian states and other sources are available at the Society of Genealogists (see above for address). Otherwise advice may be sought from the civil registration authorities in the state concerned. Addresses can be obtained from The British Overseas, on application to the Office for National Statistics (at the Family Records Centre, 1 Myddleton Street, London EC1R 1UW for personal enquiries and at the Overseas Section of the General Register Office, Smedley Hydro, Trafalgar Road, Birkdale, Southport, Merseyside PR8 2HH for postal enquiries) or from the Australian Overseas Information Service, Australian High Commission, Strand, London WC2B 4LA. Some state houses provide a service for certificates; details are given in The British Overseas. Assistance may also be obtained from the Society of Australian Genealogists, Richmond Villa, 120 Kent Street, Sydney, New South Wales 2000, Australia.
Canada: apart from the IGI and some other sources held at the Society of Genealogists (see above), there are no sources available in the United Kingdom. Advice may be sought from the local genealogical societies in the province concerned, whose addresses can be found in Meyer's Directory of Genealogical Societies in the USA and Canada (edited by Mary Keysor Meyer, Mount Airy, Maryland, 1990); a copy is held by Guildhall Library.
India, Burma, Pakistan, Bangladesh: records, virtually complete, 1698-1968, are in the India Office Records at the British Library, 96 Euston Road, London NW1 2DB.
New Zealand; apart from the IGI and some other sources held at the Society of Genealogists (see above), there are no sources held in the United Kingdom. Advice may be sought from the Registrar General of Births, Deaths and Marriages, PO Box 31-115, Lower Hutt, New Zealand. Assistance is also available from the New Zealand Society of Genealogists, PO Box 8795, Symonds Street, Auckland 1035, New Zealand.
West Indies: original records are held locally in the West Indies. However, some register transcripts for a number of West Indian islands are available in the United Kingdom: details are given in The British Overseas.
Other countries in the British Empire or Commonwealth: most original records are likely to be held locally in the country concerned. However, a few sources are available in the United Kingdom (for example, some 19th and 20th century sources are held by the National Archives); details are given in The British Overseas.
United States: for persons of English or Welsh origin, there are "consular" records 1849 to date at the Office for National Statistics (see above); and for persons of Scottish origin, there are "consular" records 1860 to date at the General Register Office for Scotland, New Register House, Edinburgh EH1 3YT. For the period before 1849, apart from the IGI and some other sources held by the Society of Genealogists, there are no sources in the United Kingdom. Advice may be sought from the Church of Jesus Christ of Latter-Day Saints Family History Centre, 35 North West Temple Street, Salt Lake City, Utah 84150, USA, or from local genealogical societies in the state concerned, whose addresses can be found in Meyer's Directory of Genealogical Societies in the USA and Canada (see above).
Other countries outside the British Empire or Commonwealth: for persons of English or Welsh origin, there are "consular" records 1849 to date at the Office for National Statistics (see above) and at the National Archives (full details of the latter are given in The British Overseas); for persons of Scottish origin, there are "consular" records 1860 to date at the General Register Office for Scotland (see above). Further records, 17th to 20th centuries, are available in the United Kingdom as follows: the National Archives has numerous registers for individual places overseas; other records are in Guildhall Library and various other libraries and record offices. Full details are given in The British Overseas.
Persons on board ship or in a military unit abroad: records of births, marriages and deaths in British Army regiments abroad after ca. 1790, and of English or Welsh births and deaths at sea after 1837, are mostly at the Office for National Statistics (see above). Records of Scottish births and deaths at sea after 1855 are mostly at the General Record Office for Scotland (see above). There are some entries for baptisms at sea after 1893 in the parish registers of St Dunstan Stepney (held at London Metropolitan Archives, 40 Northampton Road, London EC1R 0HB); however, the popular belief that all baptisms at sea were registered there is incorrect. Details of other sources are given in The British Overseas.
What if no record can be found?
· If no relevant entry can be found in the year when the birth, marriage or death is thought to have occurred, it may be useful to consult the records of subsequent years, as events abroad were often registered some time after they took place.
· If no registers exist for the town or locality concerned, it may be useful to examine the records of other towns in the same country, as births, marriages and deaths abroad were not always registered in the place where they occurred.
· If no relevant records can be traced in the United Kingdom, it will be necessary to search for records held overseas. Advice on where to begin such a search may be obtained from the Overseas Registration Section of the General Register Office or from the London embassy or high commission of the country concerned. Some further information is given in The British Overseas.
· Many births, marriages and deaths overseas, especially in the 18th century and earlier, were not registered at all. In other cases, the register may have failed to survive. Thus for a large number of births, marriages and deaths overseas no record exists anywhere.
Last updated October 2004
Leaflet Guides to Records
Guildhall Library Manuscripts Section


text:
Uncle Luke (Feat. Kid Capri & Jiggie) - Party Don't Start [Throwback Music Video]
Off Uncle Luke's "Something Nasty" Album. From around 2002-2003
Please click the "Report" button below if the video on this page is not working properly.
Comments will only be displayed by verified emails. No Spamming or Racism.