2014-11-07 4 views
0

나는 콜백 모드에서 paFloat32 형식, 2 채널, 버퍼 당 1024 프레임으로 pyaudio를 사용하고 있으며보다 효율적인 입/출력 오디오 버퍼 데이터 교환에 관심이 있습니다. struct.pack()struct.unpack()를 사용PyAudio : 콜백 모드에서 사용할 가장 효율적인 형식 및 팩/언팩 방법은 무엇입니까?

fmt  = str(N_CHANNELS * BUFFER_SIZE) + 'f' 
in_floats = struct.unpack(fmt, in_data) 

은 매우 비효율적이며 오디오 신호 처리와 거의 같은 중요한 CPU 리소스를 취합니다

는 입력 오디오 버퍼를 풀고 플로트 샘플의 목록을 얻으려면, 내가 사용 그 자체. 대부분의 사운드 카드는 16 비트이기 때문에 paInt16 형식을 사용하려고했지만 결과는 거의 동일합니다.

콜백 모드에서 사용할 수있는 가장 효율적인 형식 및 팩/압축 풀기 방법은 무엇입니까 (물론 전체 해상도 유지)?

편집 : PyAudio는 Portaudio에서 사용되는 C 데이터 구조와 유사한 바이너리 스트림 또는 버퍼를 사용하여 데이터를 교환합니다. float 샘플을 가져 와서 분석하려면 in_data 입력 버퍼의 압축을 풀어야합니다. 포장을 풀 때 약간 느리다는 것을 제외하면 모든 것이 OK입니다.

+0

'struct '는 비교적 빠릅니다. 좀 더 빠른 것이 필요하다면 아마도 python을 사용하고 싶지 않을 것입니다. C로 콜백을 작성하거나 완전히 압축을 풀어 볼 수있다. – goncalopp

+0

'numpy'를 시도 할 수도 있지만, 상대적으로 작은 버퍼를 다루기 때문에 오버 헤드가 커질 수 있으므로 이점을 무효화 할 수있다. – goncalopp

+0

왜해야 하는가? 데이터를 압축하고 압축을 푸시겠습니까? 어쨌든 numpy의 'frombuffer'가 여기에 유용 할 수 있습니다 .. http://docs.scipy.org/doc/numpy/reference/generated/numpy.frombuffer.html#numpy.frombuffer 후속 작업을 원할 경우 게시하십시오. 몇 가지 최소한이지만 기능적인 코드이므로 우리는 당신이하려는 것을 볼 수 있습니다. – tom10

답변

1

사용 중 NumPy 또는 다음 stdlib의 array 모듈은 struct.unpack의 비용의 대부분이 포장을 해체하지 않기 때문에, 훨씬 더 빨리 될 것입니다, 그것은 파이썬 float 개체의 각 float 값의 복싱이야. 예를 들어

: 빠른 속도로 100 배의

In [1177]: f = [random.random() for _ 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 

. 그리고 당신은 어느 방향 으로든 부동 소수점을 반복 할 수 있습니다. 단지 tuple 대신에 array입니다.

그러나 실제로 이러한 값에 대해 산술 연산을 수행하려는 경우 해당 값을 반복해야하며 array은 그렇게 할 때 각각의 값을 unbox해야합니다. 저장 한 시간의 좋은 덩어리로 다시 추가하십시오.

여기가 NumPy입니다. np.frombuffer(b, dtype=np.float32)array.array('f', b)보다 훨씬 빠르지 만, 박스 화되지 않은 값을 벡터화 된 산술로 직접 처리 할 수 ​​있습니다. 예를 들어 당신이 볼 수 있듯이

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 

array.array을 사용하면이 두 배 느린 (실제 반복 및 연산은 C에서 수행되기 때문에 내가 sum을 사용) 만들지 만, np.array을 사용하는 대신 최대한 빨리 5 배합니다.