Araçlar

Creating an EASE Speaker Data File

Bu makale hoparlör yönlülük verilerinin ölçümü için oluşturulmuş aşağıdaki MATLAB script’lerini tanıtmaktadır.

The two MATLAB scripts below were written to create EASE Speaker Data files in a simple and efficient manner. Measurement data is either input by hand or imported from Arta “.cvs” files.

The first script is used to lead the measurement process, gather required input data and create Ease Attenuation Data files. This script is called “createAD”.

The second script takes the output data from the first script and converts the data into “.xhn” file format. This is the file format EASE Speaker Base 4.3 can import.

CREATEAD

This script gathers measurement data, interpolates into required format and writes Attenuation Data tables. Loudspeaker symmetry and calculation of sensitivity is handled in this script.


%% Create Attenuation and Speaker Data and Write it in a .MAT File
%v13 - www.mtises.com

% ___________Data input_____________
% If "inputDataByHand" variable is set to "1", the script will ask the user
% measurement value for each and every measurement (cumbersome)
% For quickly inputting data, select 1/3 octave band view in Arta and 
% export measurement data as .csv file into the "./ProjectName" folder. 
% File  names shall be in "[theta]-[psi].txt" format.

% ___________Introduction of theta and psi Values____________________

% Looking out of the Speaker:
% THETA is,
% Every line (meridian) goes from the front to the back
%    => 180° in 5° steps = 36 values
% 
% Keep in Mind:
% The values for 0° and 180° must be all the same
% 
% PSI is,
% Every column (parallel) goes from the left over the top
% to the right down to the bottom and finally back to the left.
%    => 360° in 5° steps = 72 values

% ____Theta and Psi in Turkish____
% Hoparlör directivity iki açıdan ibaret
% 
% İlki theta açısı
% uçakta olsaydık theta açısı artınca uçak aynı düzlemde ilerlerken sola dönerdi
% theta açısı ölçümün yapıldığı düzlem üzerinde 180°'lik bir yarım daire
% dilimi
% 0°'si hoparlörün karşısını, 180° de hoparlörün arka tarafını ifade ediyor
% 
% 
% İkinci açı psi açısı
% uçakta olsaydık psi açısı artınca uçak arkadan bakınca saat yönünde dönerdi
% psi açısı 360°'e kadar artıyor ve psi açısı 0° iken beta açısı hoparlörün sol yöndeki yatay yönlülüğünü veriri
% psi açısı 90° iken beta açısı hoparlörün üst taraf düşey yönlülüğünü veriri
% psi açısı 180° iken beta açısı hoparlörün sağ yöndeki yatay yönlülüğünü veriri
% psi açısı 270° iken beta açısı hoparlörün alt taraf düşey yönlülüğünü veriri

%% Cleaning


%% Options
resolutionFront=input('Front side theta resolution for measurements: ');  %measurement resolution in Theta 0-90
existRear=0; %if the rear side data exists
resolutionRear=2*resolutionFront; %measurement resolution in rear Theta direction
axissymmetry=input('Does axial symmetry exist? (0 or 1): '); % axial symmetry (for round speakers)
if axissymmetry == 0
resolutionPsi=input('Psi resolution for measurements: '); %measurement resolution in Theta 90-180
symmetryHorizontal=input('Horizontal Symmetry? (0 or 1): ');
symmetryVertical=input('Vertical Symmetry? (0 or 1): ');
else
resolutionPsi=90;symmetryHorizontal=1;symmetryVertical=1; 
end
disp(' ')
disp('Which frequencies will be measured?')
freqs=input('Enter vector data or press Enter for EASE defaults: ');
if isempty(freqs), freqs=[100 125 160 200 250 315 400 500 630 800 1000 1250 1600 2000 2500 3150 4000 5000 6300 8000 10000];end
exp.resolution=5; %exported data resolution (5° for EASE)
dataInputByHand=input('Input data by hand? (0 or 1): '); %input each measurement by hand
doAmpCalibration=input('Do amplifier calibration? (0 or 1): '); %use amplifier response data "ampcalib.mat" to correct measurement results
                    %ampcalib file : first column frequency, second column
                    %amplifier response in dB
                    %100 Hz is reference voltage

%% Constants
Nfreqs=length(freqs);

%% Generate Input and Output Matrices and Get Project Name
% Generate Matrices of Directivity Data to be Exported
if existRear==1,exp.theta = (0:exp.resolution:180)'; else exp.theta = (0:exp.resolution:90)'; end
exp.psi = 0:exp.resolution:360-exp.resolution;
% Define Measurement Matrix
if existRear==1,
    meas.theta = [0:resolutionFront:90 90+resolutionRear:resolutionRear:180]';
else
    meas.theta = [0:resolutionFront:90]';
end
meas.psi = 0:resolutionPsi:360-resolutionPsi;
meas.Ntheta=length(meas.theta); meas.Npsi=length(meas.psi);
% Other Data
if exist('ProjectName')==1; ProjectNameOld=ProjectName;else ProjectNameOld='none'; end
ProjectName=input('Enter speaker data file name: ','s');
if strcmpi(ProjectNameOld,ProjectName)==0
    disp(' ')
    disp('Project name change..');
    disp('This will delete previous measurement data input by hand!!');
    pause,end
    meas.AD=zeros(length(meas.theta),length(meas.psi),length(freqs))-1; 
if exist(ProjectName)~=7, mkdir(ProjectName);end

%% Gather Data and Automatically Write Identical Measurement Data (if there is symmetry)
for j=1:meas.Npsi; for i=1:meas.Ntheta
        measDefString=['theta=' num2str(meas.theta(i)) ', psi=' num2str(meas.psi(j))];
        if ~any(meas.AD(i,j,:))==-1, disp(['Values suitable for ' measDefString ' exists']);
        elseif j ~= 1 && axissymmetry==1, meas.AD(i,j,:)=meas.AD(i,1,:);
        elseif meas.theta(i) == 0   && j ~= 1 ; meas.AD(i,j,:)=meas.AD(i,1,:);
        elseif meas.theta(i) == 180 && j ~= 1 ; meas.AD(i,j,:)=meas.AD(i,1,:);
        elseif meas.psi(j) > 90 && meas.psi(j) <= 180 && symmetryHorizontal==1, meas.AD(i,j,:)=meas.AD(i,2*(90/resolutionPsi+1)-j,:);
        elseif meas.psi(j) > 180 && meas.psi(j) <= 270 && symmetryVertical==1, meas.AD(i,j,:)=meas.AD(i,2*(180/resolutionPsi+1)-j,:);
        elseif meas.psi(j) > 270 && meas.psi(j) < 360 && symmetryHorizontal==1, meas.AD(i,j,:)=meas.AD(i,2*(270/resolutionPsi+1)-j,:);
        elseif meas.psi(j) > 270 && meas.psi(j) < 360 && symmetryVertical==1, meas.AD(i,j,:)=meas.AD(i,2*(180/resolutionPsi+1)-j,:);
        else    % Get Values by Measurement or CVS
            if dataInputByHand==0;
                    measFile=['./' ProjectName '/' num2str(meas.theta(i)) '-' num2str(meas.psi(j)) '.txt'];
                    while exist(measFile,'file')~=2
                        disp(' ')
                        disp(['Measurement data file not found for ' measDefString])
                    measFile=input( 'CSV file name:','s');
                    if  isempty(measFile), measFile=[num2str(meas.theta(i)) '-' num2str(meas.psi(j)) '.txt'];end
                    measFile=['./' ProjectName '/' measFile];
                    end
                    % File OK
                    disp(['Reading ' measFile ' for ' measDefString]);
                    arta=csvread(measFile,4,0);
                    for f=1:Nfreqs
                        freq=freqs(f);
                        devfreq=arta(:,1)/freq-1;
                        rowfreq=find(abs(devfreq)==min(abs(devfreq)));
                        value=arta(rowfreq,2);
                        disp([num2str(freqs(f)) 'Hz için değer ' num2str(value) 'dB (@' num2str(arta(rowfreq,1)) 'Hz)'])
                        meas.AD(i,j,f)=value;
                    end
            else
                for f=1:Nfreqs
                    if f==1; disp(' '); disp([measDefString ' measurement data:']); end
                    meas.AD(i,j,f)=input([num2str(freqs(f)) ' Hz:']);   
                end
            end
        end
    end
end
disp(meas.AD);
disp('Measurement data complete. Congrats...');
disp(' ')

%% Calculate Sensitivity
meas.voltage=input('Enter measurement voltage: ');
spkdata.impedance = input('Enter speaker impedance: ');
spkdata.maxpower = input('Enter speaker maximum power: ');
if doAmpCalibration==1
load('ampcalib')
ampcalib(:,2) = ampcalib(:,2)-ampcalib(1,2);
end
meas.power = meas.voltage^2/spkdata.impedance;
for f=1:length(freqs)
    if doAmpCalibration==1,
    spkdata.sens(f) = meas.AD(1,1,f)-10*log10(meas.power)-interp1(ampcalib(:,1),ampcalib(:,2),freqs(f));
    else
    spkdata.sens(f) = meas.AD(1,1,f)-10*log10(meas.power);
    end
end

%% Cubic Interpolation Into Required Export Format
% Add 2 border extras
interp.psi=[meas.psi(1)-2*resolutionPsi, meas.psi(1)-resolutionPsi, meas.psi, meas.psi(end)+resolutionPsi, meas.psi(end)+2*resolutionPsi];
if existRear==1,
    interp.theta=[meas.theta(1)-2*resolutionFront; meas.theta(1)-resolutionFront; meas.theta; meas.theta(end)+resolutionRear; meas.theta(end)+2*resolutionRear];
else
    interp.theta=[meas.theta(1)-2*resolutionFront; meas.theta(1)-resolutionFront; meas.theta];
end
interp.Ntheta=length(interp.theta); interp.Npsi=length(interp.psi);
interp.AD=zeros(interp.Ntheta, interp.Npsi, length(freqs))-1;
for f=1:Nfreqs
for j=1:interp.Npsi, for i=1:interp.Ntheta,
for l=1:meas.Npsi, for k=1:meas.Ntheta,
                if mod(interp.psi(j),360)==meas.psi(l) && interp.theta(i)==meas.theta(k)
                    interp.AD(i,j,f)=meas.AD(k,l,f);                    
                end
        end,end,
end,end
for j=1:interp.Npsi, for i=1:interp.Ntheta,
for l=1:meas.Npsi, for k=1:meas.Ntheta,
                if mod(interp.psi(j)+180,360)==meas.psi(l) && interp.theta(i)>180 && 2*180-interp.theta(i)==meas.theta(k)
                    interp.AD(i,j,f)=meas.AD(k,l,f);
                elseif mod(interp.psi(j)+180,360)==meas.psi(l) && interp.theta(i)<0 && -interp.theta(i)==meas.theta(k)
                    interp.AD(i,j,f)=meas.AD(k,l,f);                
                end
        end,end,
end,end
%% Prepare for EASE
% Interpolate and Transpose
    exp.AD(:,:,f)=interp2(interp.psi,interp.theta,interp.AD(:,:,f),exp.psi,exp.theta,'spline')';
% Normalize
    exp.AD(:,:,f)=exp.AD(1,1,f)-exp.AD(:,:,f);
% Plot
if freqs(f)==1000;
%subplot(ceil(length(freqs))/2,2,1)
pcolor(exp.psi,exp.theta,exp.AD(:,:,f)')
title([num2str(freqs(f)) ' Hz'])
shading flat
end

end
save(['./' ProjectName '/' ProjectName],'exp','freqs','spkdata','meas')
disp(['All data saved to ' ProjectName '.mat'])

EASEEXPORT

This script writes “.xhn” format ASCII files ready for importing to EASE Speaker Base 4.3.


%% Ease XHN File Export
% Gather data from createAD and export into EASE Speaker Map ASCII import format (.xhn)
% Create Data
clear attdata
ProjectName=input('Input the name of the project folder:','s');%okunacak dosya
inputfile=['./' ProjectName '/' ProjectName '.mat'];
load(inputfile)
Nfreqs=length(freqs);%dosyanın içerdiği frekans bantlarının adedi
width=size(exp.AD,2)+1; %width of .xhn file cell array

% Speaker Common Data
commondata={'FileType','Speaker Types';'Format',4.0;'LengthUnit','m'};
commondatafill=cell(3,width-2); %fill ile biten variable'lar, cell genişliğini sabit width'de tutmak için kullnılan boş hücreler
commondata=[commondata, commondatafill];

% Speaker Model Data
spkmodeldata={'SpeakerName',ProjectName; 'Manufacturer', 'Someone'};
spkmodeldatafill=cell(2,width-2);
spkmodeldata=[spkmodeldata, spkmodeldatafill];
% Other Data
maxpower=spkdata.maxpower*ones(Nfreqs,1);%power regarded equal throughout frequency band
space=cell(1,width);
datagood=space;
datagood{1}='DataGood';datagood{2}=1;
endin=space;endin{1}='End';
technicaldatafill=cell(4,width-3);
for i=1:360/5
    psi=(i-1)*5;
    if psi<10
        atttable{i}=['  ' num2str(psi) '°'];
    elseif psi*5<100
        atttable{i}=[' ' num2str(psi) '°'];
    else
        atttable{i}=[num2str(psi) '°'];
    end
end
%% Write the cell table to be exported to XLS
xls=space;
for f=1:Nfreqs % write speaker data for each frequency
    attdata=num2cell(exp.AD(:,:,f));
    attdata=[atttable', attdata];
    % Technical Data (frequency specific)
    technicaldata={'Frequency', freqs(f), 'Hz';'Sensitivity', spkdata.sens(f), 'dB'; 'Impedance', spkdata.impedance, 'ohms'; 'MaxPower', maxpower(f), 'W'};
    technicaldata=[technicaldata, technicaldatafill];
    xls=[xls;commondata;spkmodeldata;technicaldata;datagood;space;attdata;endin;space];
end
%% Write Comma Separated File
% Add characters for empty lines and strings
for i=1:size(xls,1), for j=1:size(xls,2),
        if j==1 && isempty(xls{i,j})
            xls{i,j}=';';
        elseif isnumeric(xls{i,j})~=1
            xls{i,j}=['"', xls{i,j}, '"']; 
        end
end,end
file=['./' ProjectName '/' ProjectName '.xhn'];
%%Cell 2 CSV
% Writes cell array content into a *.csv file.
% 
% CELL2CSV(filename,xls,delimiter)
%
% filename      = Name of the file to save. [ i.e. 'text.csv' ]
% xls    = Name of the Cell Array where the data is in
% delimiter = seperating sign, normally:',' (it's default)
%
% by Sylvain Fiedler, KA, 2004
% modified by Rob Kohr, Rutgers, 2005 - changed to english and fixed delimiter
delimiter = ',';
datei = fopen(file,'w');
for z=1:size(xls,1)
    for s=1:size(xls,2)
        
        var = eval(['xls{z,s}']);
        
        if size(var,1) == 0
            var = '';
        end
        
        if isnumeric(var) == 1
            var = num2str(var);
        end
        
        fprintf(datei,var);
        
        if s ~= size(xls,2) && size(xls{z,s+1},1)~=0
            fprintf(datei,[delimiter]);
        end
    end
    fprintf(datei,'\n');
end
fclose(datei);
disp(['XHN file written to ' file])