function song = inference(song, bnet, param)


if param.dsp.separatenormalising % means that also bass and treble chroma are separate
    evidence = cell(bnet.nnodes_per_slice,song.nBeat);
    if param.dbn.nBass > 0
        basschromanode = bnet.names('basschroma');
        evidence(basschromanode,:) = ...
            num2cell(song.segchroma.bass(:,1:param.dbn.nBass)',1);
    end

    treblechromanode = bnet.names('treblechroma');
    evidence(treblechromanode,:) = ...
        num2cell(song.segchroma.treble',1);

    if param.dbn.inferencebypart
        fprintf(2,'    ');
        song = integratesmallparts(song);
        song.mpe = cell(size(evidence));
        nIntegratedParts = numel(song.integratedparts);
        if param.dbn.infermpe
            for iIP = 1:nIntegratedParts
                startind = song.integratedparts(iIP).indices; % only one index for integrated parts
                endind = song.integratedparts(iIP).indices + song.integratedparts(iIP).n - 1;
                leftoverlap = min(startind - 1, param.seg.inferenceoverlap);
                rightoverlap = min(song.nBeat - endind, param.seg.inferenceoverlap);
                currevidence = evidence(:,startind - leftoverlap:endind + rightoverlap);
                engine = smoother_engine(jtree_2TBN_inf_engine(bnet));
                fprintf(1,'\nFinding maximum probability path (part %1.0f of %1.0f, beats %1.0f to %1.0f)... \n', iIP, nIntegratedParts, startind, endind)
                fprintf(2,'\b\b\b\b%3.0f%%',iIP/nIntegratedParts*100);
                currmpe = find_mpeMM(engine, currevidence);
                song.mpe(:,startind:endind) = currmpe(:,leftoverlap + 1:size(currmpe,2)-rightoverlap);
            end
        else
            error('inference by part + mpe not yet supported');
        end
    else

        if param.dbn.infermpe
            engine = smoother_engine(jtree_2TBN_inf_engine(bnet));
            fprintf(1,'\n__ Finding maximum probability path... _________\n')
            song.mpe = find_mpeMM(engine, evidence);
        else
            engine = filter_engine(jtree_2TBN_inf_engine(bnet));
            fprintf(1,'\n__ Inference... _________\n')
            tic
            for t = 1:song.nBeat
                t
                param.engine = enter_evidence(engine,[evidence{:,t}],t);
            end
            toc
            song.inferred = cell(bnet.nnodes_per_slice, song.nBeat);
            for iBeat = 1:song.nBeat
                for iNode = 1:bnet.nnodes_per_slice-2
                    temp = marginal_nodes(engine,iNode,iBeat);
                    song.inferred{iNode, iBeat} = temp.T;
                end
            end
        end
    end
else
    chromanode = bnet.names('chroma');

    evidence = cell(bnet.nnodes_per_slice,song.nBeat);

    evidence(chromanode,:) = ...
        num2cell([song.segchroma.bass, song.segchroma.treble]',1);

    if param.dbn.inferencebypart
    else
        engine = smoother_engine(jtree_2TBN_inf_engine(bnet));
        if param.dbn.infermpe
            fprintf(1,'\n__ Finding maximum probability path... _________\n')
            song.mpe = find_mpe(engine, evidence);
        else
            fprintf(1,'\n__ Inference... _________\n')
            tic
            param.engine = enter_evidence(engine,evidence);
            toc
            song.inferred = cell(bnet.nnodes_per_slice, song.nBeat);
            for iBeat = 1:beat.n
                for iNode = 1:bnet.nnodes_per_slice-1
                    temp = marginal_nodes(engine,iNode,iBeat);
                    song.inferred{iNode, iBeat} = temp.T;
                end
            end
        end
    end
end
