
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])