文章目錄
- 一、MIDI簡介
- 二、MIDI隱藏代碼
- 三、取出MIDI隱藏資訊
一、MIDI簡介
MIDI(Musical Instrument Digital Interface,樂器數字介面),電子樂器制造商們建立的通信標準,輔助音樂創作、確定電腦音樂程式,用音符的數字控制信號來記錄音樂,
一個標準MIDI檔案基本上由兩部分組成:頭塊和音軌塊,頭塊用來描述整個MIDI檔案基本資訊,音軌塊則包含一系列由MIDI訊息構成的MIDI資料流,原則上,可為某種聲音、某種樂譜或某種樂器等分配一個音軌塊,
MIDI檔案中前四個位元組是ASCI1字符"MThd" ,用來判斷該檔案是否為Midi檔案,而隨后的四個位元組指明檔案頭描述部分的位元組數,它總是6,所以一定是"00 00 00 06",隨后的ff ff nn nn dd dd中的nn nn表示指定軌道數,也就是實際音軌數加上一個全域音軌,頭塊之后剩下的檔案部分是一個或多個音軌塊,每一個音軌塊格式見下表,

每一個MIDI事件的構成:
MIDI事件= <delta time> <MIDI訊息>
< delta time>采用可變長編碼,它決定了其后的MIDI訊息被執行的時間,一個MIDI 訊息由一個狀態位元組及多個資料位元組構成,MIDI訊息根據性質可分為通道訊息 (Channel Message)和系統訊息(System Message)兩大類,
通道訊息對單一的MIDI Channel起作用,其Channel是利用狀態位元組的低4位來表示,可從0~15共有16個Channel,通道訊息又分為聲音訊息和模式訊息,聲音訊息用于控制合成器的聲音產生,模式訊息則為最多達16條通道分配聲音關系,包括設定單音模式或復音模式等,
MIDI檔案的聲音訊息有7種,見下表,

改變MIDI音樂檔案的部分聲音訊息并不影響MIDI檔案的聽覺效果,通過實驗,
改變 聲音開啟 的最低位位元、樂器編號 的最低位位元和 通道觸動壓力 的低4位元位,
都不會引起聽覺差異,因此可在這三種聲音訊息中嵌入水印資訊,
若(s[i]&0xf0) =0x90,十六進制90轉十進制為144,轉二進制為1001 0000
則在第i+2個位元組s[i+2]中嵌入1位元水印資訊,表示修改聲音開啟的最低位,
若(s[i]&0xf0) =0xc0,c0=192=1100 0000
則在第i+1個位元組s[i+1]中嵌入1位元水印資訊,表示修改樂器編號的最低位位元,
若(s[i]&0xf0) =0xd0,d0=208=1101 0000=16+64+128
則在第i+1個位元組s[i+1]中嵌入4位元水印資訊,表示修改通道觸動壓力的低4位元位,
二、MIDI隱藏代碼
目的:在a.txt中寫入“123456789”藏入love.mid后得到midihide.mid
clear;
clc;
hidefid=fopen('a.txt','r');
[msg,count]=fread(hidefid,inf,'ubit1');
fid=fopen('love.mid','r');
[wa,length]=fread(fid,inf,'uint8');
fclose(hidefid);
fclose(fid);
modcount=1;
p=1;
for i=1:length
if bitand(wa(i,1),240)==144&&p<=count % 240=1111 0000 144=1001 0000
wa(i+2,1)=bitset(wa(i+2,1),1,msg(p,1)); % msg(行,列)
p=p+1;
i=i+3;
modcount=modcount+1;
elseif bitand(wa(i,1),240)==192&&p<=count % 1100 0000
wa(i+1,1)=bitset(wa(i+1,1),1,msg(p,1));
p=p+1;
i=i+2;
modcount=modcount+1;
elseif bitand(wa(i,1),240)==208&&p<=count-3 % 必須足夠4位才可以隱藏
wa(i+1,1)=bitset(wa(i+1,1),1,msg(p,1));
wa(i+1,1)=bitset(wa(i+1,1),2,msg(p+1,1));
wa(i+1,1)=bitset(wa(i+1,1),3,msg(p+2,1));
wa(i+1,1)=bitset(wa(i+1,1),4,msg(p+3,1));
p=p+4;
i=i+2;
modcount=modcount+1;
else
i=i+1;
end
end
fid=fopen('midihide.mid','a');
fwrite(fid,wa);
fclose(fid);
三、取出MIDI隱藏資訊
clear;
clc;
fid=fopen('midihide.mid','r');
[wa,length]=fread(fid,inf,'uint8');
getfid=fopen('midget.txt','a');
fclose(fid);
count=72; % 這個值的選擇依據隱藏的資料,如果是9位數字或字母就是9×8=72,如果是2個漢字就是2×16=32
p=1;
for i=1:length
if(bitand(wa(i,1),240)==144)&&(p<=count)
fwrite(getfid,bitget(wa(i+2,1),1),'ubit1');
i=i+3;
if p==count
break;
end
p=p+1;
elseif(bitand(wa(i,1),240)==192)&&(p<=count)
fwrite(getfid,bitget(wa(i+1,1),1),'ubit1');
i=i+2;
if p==count
break;
end
p=p+1;
elseif(bitand(wa(i,1),240)==208)&&(p<=count-3)
fwrite(getfid,bitget(wa(i+1,1),1),'ubit1');
fwrite(getfid,bitget(wa(i+1,1),2),'ubit1');
fwrite(getfid,bitget(wa(i+1,1),3),'ubit1');
fwrite(getfid,bitget(wa(i+1,1),4),'ubit1');
i=i+2;
if p==count
break;
end
p=p+4;
end
end
fclose(getfid);

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/386742.html
標籤:其他
