Why is the error between the desired signal and estimated signal in the case of LMS filter remaining constant even after n number of iterations
As mentioned in the comment, I modified the code given here and was able to adapt the LMS filter with error tapering to zero. The only assumption I made is that (since I am not an audio expert and do not know how the channel from speaker to the microphone would look like), I assumed a 10 tap channel with only first 3 non-zero values (multi-path reflection from walls). OP is free to use a channel of his/her choice. Using this I generated 'actual_fb_path' by convolving white-noise with assumed channel. If I get access to 'actual_fb_path' it would be great. I would request OP to modify this as per the system model to see if it adapts to the delay.

clc
clear all
close all
training_input = rand(1,100);
h_actual = [0.8 0.3 0.05 zeros(1,7)]; %channel assumption
actual_fb_path = conv(training_input, h_actual);
d = actual_fb_path;
mu = 0.1;
%ha = lms(40,mu);
%[y,e] = filter(ha, training_input, d);
lms = dsp.LMSFilter;
lms.StepSize = mu;
lms.Length = 10;
[y,e]=lms([training_input zeros(1,9)]', d');
%subplot(2,1,1)
N=length(training_input) + length(h_actual)-1;
figure()
plot(1:N,d,'r',1:N,y,'b',1:N,e,'g')
title('System')
legend('Desired','Output','Error')