Tuesday, 15 July 2014

python - PyAudio : What is the most efficient format and pack/unpack method to use in callback mode? -



python - PyAudio : What is the most efficient format and pack/unpack method to use in callback mode? -

i using pyaudio in callback mode pafloat32 format, 2 channels, 1024 frames per buffer, , interested in more efficient input/output sound buffer info exchange.

to unpack input sound buffer , list of float samples, use:

fmt = str( n_channels * buffer_size ) + 'f' in_floats = struct.unpack( fmt, in_data )

using struct.pack() , struct.unpack() quite inefficient , takes important cpu resources, same sound signal processing itself. since sound cards 16 bit, tried utilize paint16 format, results identical.

what efficient format , pack/unpack method utilize in callback mode (of course of study maintaining total resolution)?

edit: pyaudio exchanges info using binary streams or buffers similar c info structures used portaudio. need unpack in_data input buffer float samples , analyze them. everyting ok, except unpack bit slow.

using either numpy or stdlib's array module going much faster, because of cost of struct.unpack isn't unpacking, it's boxing of each float value in python float object.

for example:

in [1177]: f = [random.random() _ in range(65536)] in [1178]: b = struct.pack('65536f', *f) in [1179]: %timeit struct.unpack('65536f', b) 1000 loops, best of 3: 1.61 ms per loop in [1180]: %timeit array.array('f', b) 100000 loops, best of 3: 17.7 µs per loop

that's 100x fast. , you've got iterable of floats either way, it's it's array instead of tuple.

however, if you're planning arithmetic on these values, you're still going have iterate values—and array have unbox each of them so, going add together in chunk of time you've saved.

that's numpy comes in; uncertainty np.frombuffer(b, dtype=np.float32) going hugely faster array.array('f', b) create, allow vectorized arithmetic straight on unboxed values. example:

in [1186]: a1 = array.array('f', b) in [1187]: a2 = np.frombuffer(b, dtype=np.float32) in [1189]: %timeit sum(f) 1000 loops, best of 3: 586 µs per loop in [1189]: %timeit sum(a1) 1000 loops, best of 3: 907 µs per loop in [1190]: %timeit a2.sum() 10000 loops, best of 3: 80.3 µs per loop

as can see, using array.array makes twice slow (i used sum because actual iteration , arithmetic done in c), using np.array instead makes 5x fast.

python audio portaudio pyaudio

No comments:

Post a Comment