Matlab實現簡單擴頻語音水印算法詳解

一、實驗背景

1.實驗目的

瞭解擴頻通信原理,掌握擴頻水印算法的基本原理,設計並實現一種基於音頻的擴頻水印算法,瞭解參數對擴頻水印算法性能的影響。

2.實驗環境

(1) Windows 11 操作系統;

(2) Matlab R2020b 科學計算軟件;

(3) WAV音頻文件。

3.原理簡介

①擴頻基本原理

擴頻是一種能在高噪聲環境下可靠傳輸數據的重要通信技術,其基本原理是:信號在大於所需的帶寬內進行傳輸,數據的帶寬擴展是通過一個與數據獨立的碼字完成的,並且在接收端需要該碼字的一個同步接收,以進行解擴和數據恢復。

②擴頻通信的特點

占據頻帶很寬,每個頻段上的能量很低;

即使幾個頻段的信號丟失,仍可恢復信號;

利用相互正交的擴頻碼,可以利用這個優點設計水印算法。

③實驗算法

本例中設計一種簡單的算法:利用正交的PN序列代表0、1信號,並將其疊加到信號DCT域。提取水印時,利用PN序列的正交性可以較為準確地恢復水印。

二、基礎知識

1.PN序列

PN序列(Pseudo-noise Sequence),又稱偽噪聲序列,這類序列具有類似隨機噪聲的一些統計特性,但和真正的隨機信號不同,它可以重復產生和處理,故稱作偽隨機噪聲序列。

PN序列一般用於擴展信號頻譜。PN序列的擴頻是指用一個 序列去乘以一個信息符號,序列碼片的時間遠小於信息符號的時間,由信號的時間與頻譜的關系,我們可以知道擴頻後的序列的頻譜是展寬的。

由於PN序列的相關性很低,隻有在發送的PN序列和接收的PN序列相同,並且其碼片同步時才能得到一個相關峰。當發射時,信號的功率是低於噪聲的功率的,如果不知道PN序列,則較難得知碼片的信息。因此,擴頻通信具有一定的加密性。

2.時域到頻域變換的原因

時域是信號在時間軸隨時間變化的總體概括,頻域是把時域波形的表達式做傅立葉變化,得到復頻域的表達式,所畫出的波形就是頻譜圖。是描述頻率變化和幅度變化的關系。將時域變換到頻域是為瞭做頻譜分析,即在時域中我們研究信號的時間特性,在頻域中我們研究信號的頻率特性,由於信號往往在頻域比在時域更加簡單、直觀,所以大部分信號分析的工作是在頻域進行的。

3.三種時域到頻域變換的區別

FTP: 離散傅裡葉變換,對於連續信號的靜態變換;

DWT:離散小波變換,對短時間(瞬間)信號的動態變換;

DCT:離散餘弦變換,對連續信號的動態變換。

三、算法源碼

1.PN產生函數

function out =pn_gen(g,init,shift)
format=1;
out_len = 0;
in_len= 0;
out=[];
%check parameter fomat, ether g2 =[100000101]or g1 = [820]
tp = max(g);
if tp==1
    format = 2;% format of parameter
    in_len = length(g) -1;
else
    fommat = 1;
    in_len= g(1);
end
out_len= 2^in_len-1; % length of output 
out = zeros(1, out_len);
for n = 1:out_len
    out(n) = init(in_len);
    if fommat==1
        tp=0;
        for m=2:length(g)
           tp = mod((tp+init(g(m) + 1)), 2);%caculate new init(1)
           tp = mod((tp + init(in_len- g(m))),2); %caculate new init(1)
        end
    else
        tp= init .* g(2 : (in_len+1));
        tp = mod(sun(tp), 2);
    end
    init=[tp init(1 : (in_len-1))];  
end
for n = (shift- 1):-1:0
    out = [out(2 : out_len),out(1)];
end

2.隱藏算法

function o = hide_ds(fragment, data, s, atten, pn0, pn1)
[row, col] = size(s);
if(row> col)
    s=s';
end
i =1;
n = min( floor(length(s) / fragment), length(data));
o = s;
len = length(pn0);
base = fragment -len + 1;
for i=1 : n
    st =(i- 1) *fragment+1;
    ed = i*fragment;
    tmp = dct(s(st:ed));
    attenl = atten *max(abs(tmp));
    if data(i) == 1
        tmp(base:fragment)=tmp( base:fragment)+ attenl*pn1;
    else
        tmp(base:fragment) = tmp(base:fragment) + attenl*pn0;
    end
    o(st : ed) = idct( tmp);
end

3.提取算法

function out = dh_ds(fragment, in, pn0, pnl)
[row, col] = size(in);
if(row> col)
    in = in';
end
i=1;
len = floor(length(in) / fragment);
out =[];
len_pn = length( pn0);% length of pn
base = fragment - len_pn+1;
for i = 1:len
    st = (i-1) *fragment +1;
    ed = i *fragment;
    p = dct(in(st: ed));
    t0 = sum( p(base:fragment).* pn0);
    t1 = sum( p(base:fragment).* pnl);
    if t1>t0
        out(i) = 1;
    else
        out(i) = 0;
    end
end

4.測試腳本

% 1 select cover audio
[fname, pname] = uigetfile(' *.wav','Select cover audio');
sourcename = strcat(pname, fname) ;
s = audioread( sourcename)';
s_len = length(s);
% 2 generate msg to be embedded
frag = 256;
msg_len = floor(s_len / frag);
msg = randsrc(1, msg_len, [0 1]);
% 3 generate PN
degree = 7;
pn0 = 2*pn_gen([degree 6 0], [zeros(1, degree - 1) 1],0) - 1;
pn1 = 2*pn_gen([degree 6 0],[zeros(1, degree - 1) 1],1) - 1;
%4 embed msg
atten = 0.005;
bld = hide_ds(frag, msg, s, atten, pn0, pn1);
% 5 save the stegoed-audio
audiowrite('hide.wav', bld, 8e+3);
% 6 select stegoed-audio
[fname, pname] = uigetfile('*.wav','Select stegoed-audio');
sourcename = strcat(pname, fname);
steg = audioread(sourcename)' ;
% 7 extract msg
out = dh_ds(frag, steg, pn0, pn1);
% 8 compute ebr
fid = 1;
ebr = sum( abs(msg -out)) / s_len;
fprintf(fid, 'ebr;%f\n', ebr);

四、運行測試

1.無攻擊(誤碼率0.000976):

① 運行test.m,選擇提前準備好的wav文件(載體音頻):

② 得到攜帶水印的音頻hide.wave, 可利用音頻處理軟件對音頻進行攻擊,觀察攻擊後水印的恢復情況。

③最後提取水印,並計算誤碼率

2.AU格式轉換(誤碼率0.001921):

(wav->mp3->wav)

3.壓縮與解壓縮(誤碼率0.002029):

到此這篇關於Matlab實現簡單擴頻語音水印算法詳解的文章就介紹到這瞭,更多相關Matlab 擴頻語音水印算法內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: