Skip to content

Instantly share code, notes, and snippets.

@fuji246
Created February 10, 2021 19:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fuji246/d9b6e8e8742e5ebdb1e6a6e0b6b3fbd0 to your computer and use it in GitHub Desktop.
Save fuji246/d9b6e8e8742e5ebdb1e6a6e0b6b3fbd0 to your computer and use it in GitHub Desktop.
Audio RED simulation
import argparse
import random
import matplotlib.pyplot as plt
from collections import defaultdict
class PktDrop(object):
def drop(self):
return False
class BernoulliDrop(PktDrop):
def __init__(self, p):
self.pktloss = p
def drop(self):
return random.random() < self.pktloss
class IntervalDrop(PktDrop):
def __init__(self, burst, interval):
# loss burst packet every interval
assert burst <= interval
self.burst = burst
self.interval = interval
self.idx = 0
def drop(self):
drop = False
remain = self.idx % self.interval
if remain < self.burst:
drop = True
self.idx += 1
return drop
class GilbertSimpleDrop(PktDrop):
GOOD_ST = 0
BAD_ST = 1
def __init__(self, loss, burstlen):
self.g2bP = loss / burstlen / ( 1 - loss)
self.b2gR = 1.0 / burstlen
self.state = GilbertSimpleDrop.GOOD_ST
def drop(self):
prob = random.random()
drop = False
if self.state == GilbertSimpleDrop.GOOD_ST:
if prob <= self.g2bP:
self.state = GilbertSimpleDrop.BAD_ST
else:
if prob <= self.b2gR:
self.state = GilbertSimpleDrop.GOOD_ST
drop = True
return drop
class REDSimulation(object):
def __init__(self, pktNum, lossModel, distance):
self.pktNum = pktNum
self.lossModel = lossModel
self.distance = distance
def run(self):
drop = 0
actualDrop = 0
gap = 0
for i in range(self.pktNum):
if self.lossModel.drop():
#print('drop %d' % i)
gap += 1
else:
#print('recv %d' % i)
actualDrop += gap
gap = max(gap - self.distance, 0)
drop += gap
gap = 0
residualLoss = drop * 1.0 / self.pktNum
loss = actualDrop * 1.0 / self.pktNum
print('total:%d , lost: %d, recovered: %d, rloss:%.2f, loss:%.2f' % (self.pktNum, actualDrop, actualDrop - drop, residualLoss, loss))
return residualLoss
def bernoulli_red_sim(p, pktNum, d):
rl = defaultdict(list)
for distance in d:
print('\ndistance = %d' % distance)
for lr in p:
lossModel = BernoulliDrop(lr)
redsim = REDSimulation(pktNum, lossModel, distance)
residualLoss = redsim.run()
rl[distance].append((lr,residualLoss))
# plot
plt.title('RED simulation')
plt.xlabel('loss ratio')
plt.ylabel('residual loss ratio')
for distance, results in rl.items():
loss = [l[0] for l in results]
residualLoss = [l[1] for l in results]
plt.plot(loss, residualLoss, label='distance: %d' % distance)
plt.legend()
plt.show()
def gilbertsimple_red_sim(p, pktNum, d, blens):
rl = defaultdict(list)
for burst in blens:
for distance in d:
print('\ndistance = %d, burst = %d' % (distance, burst))
for lr in p:
lossModel = GilbertSimpleDrop(lr, burst)
redsim = REDSimulation(pktNum, lossModel, distance)
residualLoss = redsim.run()
rl[(distance, burst)].append((lr,residualLoss))
# plot
plt.title('RED simulation')
plt.xlabel('loss ratio')
plt.ylabel('residual loss ratio')
for key, results in rl.items():
loss = [l[0] for l in results]
residualLoss = [l[1] for l in results]
distance, burst = key
plt.plot(loss, residualLoss, label='distance: %d, burst: %d' % (distance, burst))
plt.legend()
plt.show()
if __name__ == '__main__':
p = [lr/100.0 for lr in range(2, 82, 2)]
pktNum = 10000
d = [1, 2, 3, 4, 5]
blens = [2, 3]
argParser = argparse.ArgumentParser()
argParser.add_argument('--ber', action="store_true", default=False, help="Bernoulli loss model simulation")
argParser.add_argument('--gilbers', action="store_true", default=False, help="GilbertSimple loss model simulation")
args = argParser.parse_args()
if args.ber:
bernoulli_red_sim(p, pktNum, d)
if args.gilbers:
gilbertsimple_red_sim(p, pktNum, d, blens)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment