python - Trying to simulate constant byte rate. Confusion with time.sleep results -
context
i'm using windows 7 on computer(the player) , linux(debian) on college computer(the streamer), command using ssh. trying simulate constant byte rate of microphone reading wave file, if talking. problem byte rate below target.
choosing 32kb/s rate, , 0.020 seconds of capture time. implemented simulated microphone using time.sleep produce give each chunk of info each 0.020 seconds. rate obtained around 27kb/s, not 32kb/s
the problemi decided test how much precise time.sleep on linux machine, using ideas reading this question.
i did 2 kind of tests. 1) busy sleep 2) normal sleep
in average, samples got, shows linux machine sleep resolution 4ms. while on windows less/equal 1ms.
questions what can perchance limiting sleep resolution on linux machine? (on linux) why busy sleeping has same resolution time.sleep? how simulate microphone reading wave file? codeimport time def busy_sleep(t): s=time.time() while time.time() - s < t: pass e=time.time() homecoming e-s def normal_sleep(t): s=time.time() time.sleep(t) e=time.time() homecoming e-s def test(fun): f = lambda x: sum(fun(x) d in range(10))/10 print("0.100:{}".format(f(0.100))) print("0.050:{}".format(f(0.050))) print("0.025:{}".format(f(0.025))) print("0.010:{}".format(f(0.010))) print("0.009:{}".format(f(0.010))) print("0.008:{}".format(f(0.008))) print("0.007:{}".format(f(0.007))) print("0.006:{}".format(f(0.006))) print("0.005:{}".format(f(0.005))) print("0.004:{}".format(f(0.004))) print("0.003:{}".format(f(0.003))) print("0.002:{}".format(f(0.002))) print("0.001:{}".format(f(0.001))) if __name__=="__main__": print("testing busy_sleep:") test(busy_sleep) print("testing normal_sleep:") test(normal_sleep)
results """ debian testing busy_sleep: 0.100:0.10223722934722901 0.050:0.051996989250183104 0.025:0.027996940612792967 0.020:0.02207831859588623 0.010:0.011997451782226562 0.009:0.011997222900390625 0.008:0.009998440742492676 0.007:0.007997279167175292 0.006:0.0079974365234375 0.005:0.007997465133666993 0.004:0.005918483734130859 0.003:0.003997836112976074 0.002:0.0039977550506591795 0.001:0.003997611999511719 testing normal_sleep: 0.100:0.1020797061920166 0.050:0.051999988555908205 0.025:0.028000001907348634 0.020:0.02192000865936279 0.010:0.011999979019165039 0.009:0.012000055313110351 0.008:0.010639991760253906 0.007:0.008000001907348633 0.006:0.00799997329711914 0.005:0.008000059127807617 0.004:0.006159958839416504 0.003:0.004000000953674317 0.002:0.00399998664855957 0.001:0.004000091552734375 $ uname -a linux 3.2.0-4-amd64 #1 smp debian 3.2.57-3+deb7u2 x86_64 gnu/linux """ """ windows 7 testing busy_sleep: 0.100:0.10000572204589844 0.050:0.05000288486480713 0.025:0.0250014066696167 0.010:0.010500597953796388 0.009:0.010500597953796388 0.008:0.008000493049621582 0.007:0.00740041732788086 0.006:0.006400299072265625 0.005:0.005400300025939942 0.004:0.004700303077697754 0.003:0.003200197219848633 0.002:0.002700185775756836 0.001:0.0016000032424926759 testing normal_sleep: 0.100:0.10000579357147217 0.050:0.0500028133392334 0.025:0.02500150203704834 0.010:0.01000049114227295 0.009:0.0100006103515625 0.008:0.008000493049621582 0.007:0.007000398635864257 0.006:0.006000304222106934 0.005:0.00500030517578125 0.004:0.0040001869201660155 0.003:0.0030002117156982424 0.002:0.0020000934600830078 0.001:0.0010000944137573243 """
real code import os import wave import sys import io import time
format = 8 #get_format_from_width(2) nchannels = 1 framerate = 16000 # samples per sec sampwidth = 2 # bytes in sample byte_rate = framerate*sampwidth chunk_duration = 0.020 chunk_bytes = int(chunk_duration*byte_rate) class streamsimulator: def __init__(self): wf = wave.open("kalimba.wav","rb") buf = io.bytesio() buf.write(wf.readframes(wf.getnframes())) wf.close() buf.seek(0) self.buf = buf self.step = time.time() def delay(self): #delay delta = time.time() - self.step self.step=time.time() delay = chunk_duration - delta if delay > 0.001: time.sleep(delay) def read(self): buf = self.buf info = buf.read(chunk_bytes) if len(data) == 0: buf.seek(0) info = buf.read(chunk_bytes) self.delay() homecoming info def close(self): self.buf.close() class dynamicpainter: def __init__(self): self.l=0 def paint(self,obj): str1=str(obj) l1=len(str1) bs="\b"*self.l clean=" "*self.l total = bs+clean+bs+str1 sys.stdout.write(total) sys.stdout.flush() self.l=l1 if __name__=="__main__": painter = dynamicpainter() stream = streamsimulator() produced = 0 how_many = 0 painted = time.time() while true: while time.time()-painted < 1: d = stream.read() produced += len(d) how_many += 1 producing_speed = int(produced/(time.time()-painted)) painter.paint("producing speed: {} how many: {}".format(producing_speed,how_many)) produced=0 how_many=0 painted = time.time()
edit changed "real code" , added measure of time including sleeping time. have double byte rate: producing speed: 63996 how many: 100
got me much confused. have tried different byterates , ends beingness double everytime.
thanks @j.f.sebastian and code, came learned that:
its improve utilize use deadline time reference create new reference each loop using deadline "amortizes" imprecision of time.sleep, oscilating bit around desired bitrate resulting in correct(and much more constant) average. you need utilize time.time() once, means less calculations imprecisions.as result, constant 32000 b/s times oscilating 31999 , 31745 can hear music without lag or jitter!
final codedef read(self): buf = self.buf info = buf.read(chunk_bytes) if len(data) == 0: buf.seek(0) info = buf.read(chunk_bytes) self.deadline += chunk_duration delay = self.deadline - time.time() if delay > 0: time.sleep(delay) homecoming info
conclusion
thanks @j.f.sebastian and code, came learned that:
its improve utilize use deadline time reference create new reference each loop using deadline "amortizes" imprecision of time.sleep, oscilating bit around desired bitrate resulting in correct(and much more constant) average. you need utilize time.time() once, means less calculations imprecisions.as result, constant 32000 b/s times oscilating 31999 , 31745 can hear music without lag or jitter!
i tried using @j.f.sebastian implentation using %
operator sleep remainder, kb/s oscilate strangelly, decided maintain deadline implementation, suffers imprecision keeping adding float value. nevertheless, overall result plenty needs. give thanks everyone.
def read(self): self.deadline += 0.020 delay = self.deadline - time.perf_counter() if delay > 0: time.sleep(delay) homecoming self._read()
python linux windows sleep
No comments:
Post a Comment