THE AUDITORY MODELING TOOLBOX

This documentation page applies to an outdated major AMT version. We show it for archival purposes only.
Click here for the documentation menu and here to download the latest AMT (1.6.0).

View the help

Go to function

KELVASA2015_CIPROCESSING - CI ACE processing strategy used in Kelvasa and Dietz 2015 binaural model

Program code:

function [electrodogram, vTime] = ...
            kelvasa2015_ciprocessing(insig,fs,varargin)
%KELVASA2015_CIPROCESSING CI ACE processing strategy used in Kelvasa and Dietz 2015 binaural model
%   Usage: [electrodogram, vTime] = kelvasa2015aceprocessing(insig,fs);
%
%   Input parameters:
%       insig       : single channel column vector signal
%       fs          : sampling rate (Hz) 
%
%   Output parameters:
%       electrodogram : N x M matrix of electrode current values in 
%                       (microAmpere) with N being the number of CI 
%                       electrodes and M being a time vector with 
%                       1/pulse rate/maxima sampling period 
%
%       vTime         : time vector in seconds with M samples 
%
%   KELVASA2015_ciprocessing(insig,fs,varargin) simuluates the ACE
%   CI signal processing strategy for an input signal using user defined 
%   parameters. 
%
%   References:
%     S. Fredelake and V. Hohmann. Factors affecting predicted speech
%     intelligibility with cochlear implants in an auditory model for
%     electrical stimulation. Hearing Research, 287(1):76 - 90, 2012.
%     [1]http ]
%     
%     B. A. Swanson. Pitch perception with cochlear implants. PhD thesis, The
%     University of Melbourne, 2008.
%     
%     References
%     
%     1. http://www.sciencedirect.com/science/article/pii/S0378595512000639
%     
%
%   Url: http://amtoolbox.sourceforge.net/amt-0.9.9/doc/modelstages/kelvasa2015_ciprocessing.php

% Copyright (C) 2009-2015 Piotr Majdak and the AMT team.
% This file is part of Auditory Modeling Toolbox (AMT) version 0.9.9
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.

%     
%     Laneau, J. (2005). When the deaf listen to music�pitch perception
%     with cochlear implants (Doctoral dissertation, Ph D dissertation).
%     Katholieke Universiteit Leuven, Faculteit Toegepaste Wetenschappen, 
%     Leuven, Belgium.
%
%   Authors: 
%            Daryl Kelvasa (daryl.kelvasa@uni-oldenburg.de) 2016
%            Mathias Dietz (mdietz@uwo.ca) 2016
%            Stefan Fredelake
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Check input paramters 
if nargin<3
  error('%s: Too few input parameters.',upper(mfilename));
end;

if ~isnumeric(insig) || size(insig,2) > size(insig,1)
  error('%s: insig has to be a numeric column vector signal!',upper(mfilename));
end

if ~isnumeric(fs) || ~isscalar(fs) || fs<=0
    error('%s: fs has to be a positive scalar!',upper(mfilename));
end

definput.import={'kelvasa2015'};
[~,kv]  = ltfatarghelper({},definput,varargin);

%% Main CI processing

%Initialize parameters
insig = process_preemphasis_CI(insig, kv.FS_ACE); % Hochpass
lenSignal = length(insig);
W = hann(kv.NFFT);

%%Compare pulse rate with signal sampling rate
switch kv.pps
    % muss zyklisch abgetastet werden
    case 900
        vorschub = [18 18 17 18 18 18 17 18 18];  % wegen rundungsfehler (16000/900 = 17.7778; mean(vorschub) = 17.7778)
    otherwise
        vorschub = round(kv.FS_ACE/kv.pps); 
        disp('Warnung: Rundungsfehler m�glich, da Abtastrate des Signales kein ganzzahliges Vielfaches der PPS ist!');
end

%%Calculate windowed indices of signal
numVorschub = (lenSignal - kv.NFFT)/(sum(vorschub));
numFFTwin = (floor(numVorschub)*numel(vorschub)) + ...
                    ceil(rem(numVorschub,1)*numel(vorschub));
vorschub = [1, repmat(vorschub,1,ceil(numVorschub))];
winInd = zeros(kv.NFFT,numFFTwin); winInd(:,1) = (1:kv.NFFT);
for ind =  2 : numFFTwin;
    winInd(:,ind) = (0:kv.NFFT-1)+sum(vorschub(1:ind)); end
insig(max(winInd)) = 0;    

%%Process signal
    %Window signal
    x = insig(winInd); %clear winInd insig
    x = repmat(W,1,size(x,2)).*x;

    % spectra
    S = abs(fft(x,kv.NFFT));

%%Main loop over signal
electrodogram = zeros(kv.NumOfChannels,numFFTwin*kv.maxima);
pulseInd = 1 : kv.maxima;
vTime   = (0:size(electrodogram,2)-1).*(1/kv.pps/kv.maxima);
for ind = 1 : numFFTwin
    
    % "envelope" per time unit
    F = process_ACE_filterbank_demo(S(:,ind)', kv);
    
    % choose n of m
    [A,iElectrode] = process_nOfm(F,kv.maxima);
    iElectrode = sort(iElectrode,1,'descend');

    % compression between Tlevels and Clevels
    C = process_compression_ci(A,kv.B,kv.M,kv.alpha_c);
    cl = zeros(length(kv.vActiveElectrodes),1);
    logicalNoPulse = C(iElectrode) == 0;
    
    cl(iElectrode) = round(kv.TCL(iElectrode,:) + ...
                             (kv.MCL(iElectrode,:)- ...
                             kv.TCL(iElectrode,:)).*C(iElectrode,:));
    
    % current amplitude in micro-Ampere
    I = zeros(length(kv.vActiveElectrodes),1);
    I(iElectrode) = conversion_CL2Iamp(cl(iElectrode),kv.devicename);
    I(iElectrode(logicalNoPulse)) = 0;  
%     stimulationsequence = 1:length(kv.vActiveElectrodes);
%     iElectrode = stimulationsequence(iElectrode);
    
    electrodogram(sub2ind(size(electrodogram),...
                    iElectrode',pulseInd)) = I(iElectrode);
    pulseInd = pulseInd + kv.maxima;
end

end

%% Model helperfunctions
%% Pre-emphasis function
function y = process_preemphasis_CI(x, FS)
% Author: Stefan Fredelake
% Date: 23-10-2008

fc = 1200; 
w = 2*fc/FS;

[b,a] = butter(1,w,'high');

y = filter(b,a,x);

end

%% ACE filterbank
function F = process_ACE_filterbank_demo(S, CIParams)
%Code from the dissertation of Brett Swanson (2008)
% Author: Stefan Fredelake
% Date: 23-10-2008
%
% usage:  F = process_ACE_filterbank(S)
% input:  S = complex spectrum
%         CIParams = Struct containing the CI Params. In this function only
%         NumofChannels, Q_Sum, G, indexOrg and vActiceElectrodes are
%         needed. See set_global_constant.m for a description of the
%         mentioned parameters
% output: F = f�ltered output spectrum
% 
% This filterbank is only applicable for a complex spectrum S with a length
% of 128 bins, and a sampling frequency of 16 kHz. 

S2 = abs(S).^2; % square the amplitude spectrum


F  = zeros(CIParams.NumOfChannels,1);
for n = 1:CIParams.NumOfChannels
    if n == 1
        index2 = CIParams.indexOrg;  % only for the first loop
    end
    index1 = index2 + 1;
    index2 = index1 + CIParams.Q_SUM(n)-1;
    index  = index1:index2;
    if CIParams.Q_SUM(n) == 1
        weight = CIParams.G(1);
    elseif CIParams.Q_SUM(n) == 2
        weight = CIParams.G(2);
    else
        weight = CIParams.G(3);
    end
    F(n,:) = weight*sqrt(sum(S2(index)));   % eq. 5.4
end

end

%% NofM
function [A,iElectrode] = process_nOfm(F,nChns)
% Reference: Laneau, 2005 PhD-thesis
%
% Author: Stefan Fredelake
% Date: 23-10-2008
%
% usage:  A     = process_nOfm(F,nChns)
% input:  F          = filterbank output (22 filters)
% output: nChns      = number of channels to simulate
%         iElectrode = index of the stimulating electrodes
% 
% This function chooses the channels to stimulate. The channels with the
% nChns maximal values are stimulated

A               = zeros(size(F));
[~,iElectrode] = sort(F,1,'descend');
iElectrode      = iElectrode(1:nChns);
A(iElectrode)   = F(iElectrode);      % eq 5.16

end

%% Process Compression
function C = process_compression_ci(A,B,M,alpha_c)

% usage:  C = process_compression_ci(A)
% input:  A = the amplitude values in each channel to simulate
%         B = Base level
%         M = saturation level
%         alpha = controls the steepness of the function
% output: C = clinical current unit
% 
% This function compresses the envelopes into the electrical dynamic range
% of CI users. 

%Code from the dissertation of Brett Swanson (2008)
% Author: Stefan Fredelake
% Date: 23-10-2008

C = zeros(size(A));
C(A<B) = 0;
index = find(A>=B & A<M); 
C(index) = log( 1 + alpha_c * ((A(index)-B)/(M-B) ))/log(1+alpha_c);
C(A>=M) = 1; 

end

function I = conversion_CL2Iamp(cl,szWhichDevice)
% Reference: Laneau, 2005 PhD-thesis
%
% Author: Stefan Fredelake
% Date: 23-10-2008

switch szWhichDevice
    case 'nucleus'
        I = 10.175.^(cl/255); % aus laneau
        % I = I/24.838;
    case 'CI22'
        I = 100e-6 * 1.0205.^(cl-100); % aus hearcom website
    case 'CI24M'
        I = 100e-6 * 1.0205.^(cl-100); % aus hearcom website
    case 'CI24R'
        I = 100e-6 * 1.0205.^(cl-100); % aus hearcom website
    case 'freedom' % also CI24RE
        I = 100e-6 * 1.0182.^(cl-100); % aus hearcom website
    otherwise
        error('this device is not known')
end
end