零、GitHub地址(含音频效果对比)
https://github.com/iwuqing/Intertwine
一、基本原理
按照一定规律打乱传输信号顺序,使信道传输过程中所突发产生集中的错误最大限度的分散化。由于音频信号具有较大的冗余性,可十分明显的减少失真。
二、特点
- 不增加带宽
- 仅对面向报文(即数据包)传输有效
- 交织深度(每个报文的长度)越大,散乱度越大,交织效果越明显
三、编码(交织深度为2)
四、译码
五、模拟差错
基本思想: 制造映射
具体步骤(设定:N个包运输,丢包率为1%。)
- 新建一个长度为 N 的数组
- 数组中存 [1,100] 的随机数
- 若随机数为 1 ,则认为对应的包发生丢失
简单图示
七、代码(Java实现)
import java.io.*;
import java.util.ArrayList;
import java.util.Random;
public class Intertwine {
private Intertwine(){
//构造器私有化
}
/**
* 写入文件
* @param fileName 写入文件名
* @param data 数据
* @param numLine 每一行数据个数
*/
public static void writeFile(String fileName, ArrayList<Integer> data, int numLine){
BufferedWriter bufferedWriter = null;
try {
bufferedWriter = new BufferedWriter(new FileWriter(fileName));
int num = 0;
for (Integer integer: data){
bufferedWriter.write(integer.toString());
num ++;
if (num == numLine){
bufferedWriter.write("\r\n");
num = 0;
}
}
} catch (IOException e){
System.out.println("文件写入错误");
} finally {
if (bufferedWriter != null){
try {
bufferedWriter.close();
} catch (IOException e){
System.out.println("文件流关闭错误");
}
}
}
}
/**
* 模拟丢包误差制造
* @param encodeData 已交织编码数据
* @param errorRate 丢包率 100(1/100)
* @param deepin 交织深度
* @return 丢包后的数据
*/
public static ArrayList<Integer> makeError(ArrayList<Integer> encodeData, int errorRate, int deepin){
int errorNum = 0; //实际丢包数
ArrayList<Integer> returnArray = new ArrayList<>(); //已丢包数据,作为返回值
ArrayList<ArrayList<Integer>> encodeDataMax = zenwei(encodeData, deepin); //构造矩阵,列数为 deepin,作为丢包中间矩阵
ArrayList<Integer> array = new ArrayList<>(); //随机数组
//使用[0,errorRate)中的随机数填充随机数组
Random r = new Random();
for (int i = 0; i < encodeDataMax.size(); i ++){
array.add(r.nextInt(errorRate)); // [0,errorRate)中的随机整数
}
//ArrayList<Integer> indexError = new ArrayList<>(); //丢失包序号
//遍历矩阵
for (int i = 0; i < encodeDataMax.size(); i ++){
// 随机数组数据为0
if (array.get(i) == 0){
//indexError.add(i);
ArrayList<Integer> temp = encodeDataMax.get(i);
// 对应包丢失
for (int j = 0; j < temp.size(); j ++){
if (temp.get(j) == 0){
temp.set(j, 1);
}else {
temp.set(j, 0);
}
}
errorNum ++;
}
}
//Intertwine.writeFile("./data/丢包序号.txt", indexError, 1);
System.out.println("总包数: " + encodeDataMax.size());
System.out.println("丢包数: " + errorNum);
System.out.println("丢包率: 1/" + errorRate);
//降维
for (ArrayList<Integer> arrayList: encodeDataMax){
for (Integer integer: arrayList){
returnArray.add(integer);
}
}
return returnArray;
}
/**
* 读取文件
* @param fileName 文件名
* @return 文件数据
*/
public static ArrayList<Integer> readFile(String fileName){
ArrayList<Integer> returnArray = new ArrayList<>(); //读取到的数据
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new FileReader(fileName));
String tempLine;
while ((tempLine=bufferedReader.readLine()) != null){
for (int i = 0; i < tempLine.length(); i ++){
char tempChar = tempLine.charAt(i);
if (tempChar == '1'){
returnArray.add(1);
}else{
returnArray.add(0);
}
}
}
}catch (IOException e){
returnArray.clear();
System.out.println("文件读取错误");
return null;
}finally {
if (bufferedReader != null){
try {
bufferedReader.close();
}catch (IOException e){
System.out.println("文件流关闭错误");
}
}
}
return returnArray;
}
/**
* 交织编码
* @param data 源数据
* @param deepin 交织深度
* @return 已交织编码数据
*/
public static ArrayList<Integer> encoding(ArrayList<Integer> data, int deepin){
ArrayList<Integer> temp1 = new ArrayList<>(); //储存截取的原始数据,其大小是交织深度的整数倍
ArrayList<ArrayList<Integer>> temp2 = new ArrayList<>(); //存储按照交织深度为间隔的N个ArrayList
ArrayList<ArrayList<ArrayList<Integer>>> temp3 = new ArrayList<>(); //每一个元素都是包含deepin个ArrayList
ArrayList<Integer> returnArray = new ArrayList<>(); //已编码数据
//截取原始数据,使得起大小为交织深度的整数倍
for (int i = 0; i < data.size()/deepin*deepin; i ++){
temp1.add(data.get(i));
}
temp2 = Intertwine.zenwei(temp1, deepin); //增加维数 1->2
temp3 = Intertwine.zenwei(temp2, deepin); //增加维数 2->3
for (int i = 0; i < temp3.size(); i ++){
ArrayList<ArrayList<Integer>> temp4 = temp3.get(i);
for (int k = 0; k < deepin; k ++){
for (int j = 0; j < temp4.size(); j ++){
returnArray.add(temp4.get(j).get(k));
}
}
}
return returnArray;
}
/**
* 增加维数
* @param data 源数据
* @param deepin 每行元素个数
* @return
*/
private static ArrayList zenwei(ArrayList data, int deepin){
ArrayList tempData = new ArrayList();
ArrayList temp = new ArrayList();
for (int i = 0; i < data.size(); i ++){
temp.add(data.get(i)); //从原始数据从读取数据送入单个临时ArryList
if (temp.size() == deepin){ //临时分组已满
tempData.add(temp); //将临时分组存入temp
temp = new ArrayList(); //新的ArrayList
}
}
return tempData;
}
/**
* 交织译码
* @param encodedData 已编码数据
* @param deepin 交织深度
* @return 译码数据
*/
public static ArrayList<Integer> decoding(ArrayList<Integer> encodedData, int deepin){
return Intertwine.encoding(encodedData, deepin);
}
}