from Mean Opinion Score (MOS) test script by Evan Ruzanski
Script to automate ITU 5-grade Mean Opinion Score (MOS) test.

mos.m
% Conducts and records results for randomly-generated ITU 5 grade ACR scheme to get MOS scores 
% for 8 audio files (4 music, 4 speech) from MPEG SQAM database at chosen total bitrate.
% Follow on-screen instructions.  Saves .csv file to working directory
%
% AUTHOR: Evan Ruzanski, UCSB, 7/17/2003

clear all
clc
format short g

% Build track selection matrix (3 X 8)  
%-------------------------------------------------------------------------------------------------------------------------------------------------------
% System                     
%-------------------------------------------------------------------------------------------------------------------------------------------------------
% VM-LR                     bass47_1VMLR    gspi35_2VMLR    harp40_1VMLR    trpt21_2VMLR    spfe49_1VMLR    spff51_1VMLR    spme50_1VMLR    spmf52-1VMLR
% VM-SD                     bass47_1VMSD    gspi35_2VMSD    harp40_1VMSD    trpt21_2VMSD    spfe49_1VMSD    spff51_1VMSD    spme50_1VMSD    spmf52_1VMSD
% TB-SD                     bass47_1TBSD    gspi35_2TBSD    harp40_1TBSD    trpt21_2TBSD    spfe49-1TBSD    spff51-1TBSD    spme50_1TBSD    spmf52_1TBSD
%-------------------------------------------------------------------------------------------------------------------------------------------------------

% Choose storage array for string lengths = file name lengths
S = 16;

M(1,S) = 'bass47_1VMLR'; % For verification model - left/right channel coding (4 music, 4 speech)
M(1,1*length(S)+S) = 'gspi35_2VMLR';    % <- CHANGE THESE FILE NAMES TO THE NAMES OF THE DESIRED FILES TO TEST
M(1,2*length(S)+S) = 'harp40_1VMLR';    % KEEP FILENAME LENGTHS THE SAME AS THESE
M(1,3*length(S)+S) = 'trpt21_2VMLR';
M(1,4*length(S)+S) = 'spfe49_1VMLR';
M(1,5*length(S)+S) = 'spff51_1VMLR';
M(1,6*length(S)+S) = 'spme50_1VMLR';
M(1,7*length(S)+S) = 'spmf52-1VMLR';

M(2,S) = 'bass47_1VMSD'; % For verification model - sum/difference coding (4 music, 4 speech)
M(2,1*length(S)+S) = 'gspi35_2VMSD';
M(2,2*length(S)+S) = 'harp40_1VMSD';
M(2,3*length(S)+S) = 'trpt21_2VMSD';
M(2,4*length(S)+S) = 'spfe49_1VMSD';
M(2,5*length(S)+S) = 'spff51_1VMSD';
M(2,6*length(S)+S) = 'spme50_1VMSD';
M(2,7*length(S)+S) = 'spmf52_1VMSD';

M(3,S) = 'bass47_1TBSD'; % For Trellis - sum/difference coding (4 music, 4 speech)
M(3,1*length(S)+S) = 'gspi35_2TBSD';
M(3,2*length(S)+S) = 'harp40_1TBSD';
M(3,3*length(S)+S) = 'trpt21_2TBSD';
M(3,4*length(S)+S) = 'spfe49-1TBSD';
M(3,5*length(S)+S) = 'spff51-1TBSD';
M(3,6*length(S)+S) = 'spme50_1TBSD';
M(3,7*length(S)+S) = 'spmf52_1TBSD';

% Create actual play matrix
sz = size(M);
P(sz(1),sz(2)) = 0; 

%Display instructions to user
disp('Listen carefully to the following audio tracks.  After each segment is complete, you will be asked to rate    ');
disp('the quality of the track using the following guidelines:                                                      ');
disp('  5 = EXCELLENT                                                                                               ');
disp('  4 = GOOD                                                                                                    ');
disp('  3 = FAIR                                                                                                    ');
disp('  2 = POOR                                                                                                    ');
disp('  1 = BAD                                                                                                     ');
disp('                                                                                                              ');
disp('Press ENTER to begin');

pause

% Begin experiment
for k = 1:sz(1) * sz(2)
    
    g = 1; % Create matrix test variable
    while g == 1, 
        c = ceil(3*rand(1)); % Generate random number between 1 and 3 for row (system) selection
        d = ceil(8*rand(1)); % Generate random number between 1 and 8 for column (track) selection
        
        if P(c,d) == 0 % Avoid repetition
            [x,fs] = wavread(char(M(c,(d-1)*length(S)+S))))); % Read in track
            wavplay(x,fs);
                         
            while (P(c,d) ~= 1) | (P(c,d) ~= 2) | (P(c,d) ~= 3) | (P(c,d) ~= 4) | (P(c,d) ~= 5)% Ensure valid user input
                P(c,d) = input('Please score the track (1 (worst) - 5 (best))');
            end % END WHILE
            
            g = 0;
        end % END IF
    end % END WHILE
    
    disp('                                                                                                              ');
    disp('Press ENTER to continue')
    pause
    disp('                                                                                                              ');
   
end

disp('This concludes the test.  Thank you.')
pause

% LOAD saved array of previous results (NB: ensure file is not currently in use, init to zero for first run)
R = csvread('mosresults.csv');

R(10,1) = R(10,1) + 1; % Update experiment iteration number
for u = 1:3 % Append column array via recursion
    R(u,1) = (R(u,1) + sum(P(u,:))/8)/2; % Update previous mean (all files)
    R(u + 3,1) = (R(u + 3,1) + sum(P(u,1:4))/4)/2; % Update previous mean (music files)
    R(u + 6,1) = (R(u + 6,1) + sum(P(u,5:8))/4)/2; % Update previous mean (speech files)
end

% SAVE array of updated results (column array), keeps R variable active in current workspace
save('results.csv','R','-ASCII')

% OPTIONAL: Plot updated results
map = [0 0 0;.75 .75 .75;1 1 1];
colormap(map)
matr = [R(1:3,1)';R(4:6,1)';R(7:9,1)'];
bar(matr,1,'grouped')
set(gca,'XTick',1:3);
set(gca,'XTickLabel',{'All-Files','Music','Speech'});
axis([0 4 0 5])
title('Subjective 5-pt. MOS test results for VM-LR, VM-SD, and TB-ANMR for a test set of 4 music and 4 speech files quantized at 16kbps.');
legend('VM-LR','VM-SD','TB-SD')
grid on

% EOF "mos.m"

    

Contact us at files@mathworks.com