Single precision conversion errors?
Show older comments
I am creating an audio encoder using splines and the polyval function. I would like to be able to store all the polynomial coefficients as singles. The entire code works fine when the coefficients are stored as doubles. However, if I cast them as singles, their values change and the code breaks. I thought the break was coming from the polyval function, so I scratched it and evaluated the polynomials with my own code. The singles still have weird values though. I've attached the code I've been working with. Can anyone shed any light on how I could use single precision and not have the values change?
warning off all;
clc;
clf;
clear all;
[wave_data, Fs] = wavread('10 ms guitar.wav');
% Set display options for polyfit_constrained
options = optimset('lsqlin');
options = optimset(options, 'Display', 'off');
% Creates file to write to
writefile = 'outfile.dat';
fid = fopen(writefile, 'w');
% Low Pass Filter
fNorm = 16000 / (Fs/2);
[b, a] = butter(10, fNorm, 'low');
wave_data = filtfilt(b, a, wave_data);
differences = diff(wave_data);
flags = [];
xrange = [];
k = 1;
degree = 5;
minpoints = 6;
tic
% For loop plants flags at data index points when derivative changes sign
for i = 1:(length(differences) - 1)
if (differences(i) > 0 && differences (i + 1) < 0)...
|| (differences(i) < 0 && differences (i + 1) > 0)
flags(k) = i + 1;
if k ~= 1 && (flags(k) - flags(k - 1)) < minpoints
k = k;
else
k = k + 1;
end
%if size > 40
end
end
% For loop creates range of x-values and y-values for polynomial fitting
for j = 1:length(flags)
% If statement creates different x and y ranges for the first and last
% windows separately from all other windows
if j == 1
xrange = 1:flags(j);
yrange = wave_data(1:flags(j));
elseif j == length(flags)
xrange = (flags(j - 1) + 1):length(wave_data);
yrange = wave_data((flags(j - 1) + 1):length(wave_data));
else
xrange = (flags(j - 1) + 1):flags(j);
yrange = wave_data((flags(j - 1) + 1):flags(j));
end
polyval_coeffs = polyfit_constrained(xrange, yrange, degree, options)
s_polyval_coeffs = single(polyval_coeffs)
s_xrange = single(xrange);
ys = [];
yd = [];
for i=1:length(xrange)
x = xrange(i);
s_temp_y = s_polyval_coeffs(1)*x*x*x*x*x + s_polyval_coeffs(2)*x*x*x*x + s_polyval_coeffs(3)*x*x*x + s_polyval_coeffs(4)*x*x + s_polyval_coeffs(5)*x + s_polyval_coeffs(6);
ys = [ys; s_temp_y];
%x = xrange(i);
d_temp_y = polyval_coeffs(1)*x*x*x*x*x + polyval_coeffs(2)*x*x*x*x + polyval_coeffs(3)*x*x*x + polyval_coeffs(4)*x*x + polyval_coeffs(5)*x + polyval_coeffs(6);
yd = [yd; d_temp_y];
end
subplot(3,1,1);
plot(wave_data);
subplot(3,1,2);
plot(xrange, yd);
hold all;
subplot(3,1,3);
plot(xrange, ys);
hold all;
fwrite(fid, polyval_coeffs, 'double');
fwrite(fid, length(xrange), 'uint8');
end
fclose(fid);
toc
Answers (1)
Jan
on 27 Mar 2012
If problem appear in a program, this:
warning off all
is a bad idea. This suppresses warnings if the polynomial fitting is ill-conditioned and a normalization of the input data is recommended. If this happens in your code, using single values can lead to a loss of accuracy.
This:
polyval_coeffs(1)*x*x*x*x*x
is an instable method to evaluate a polynomial. Use the Horner-method instead.
Categories
Find more on Fourier Analysis and Filtering in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!