Saturday, 15 March 2014

python - Trying to simulate constant byte rate. Confusion with time.sleep results -



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 problem

i 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? code import 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.

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!

final code def 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.

final code 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