<converting bytes to ctypes.c_short array가 필요한 경우>

NAVER CAMPUS HACK DAY에서 진행한 프로젝트 중에

pcm 파일을 read하여 c 함수에 short array 파라미터로 전달해야했다

그 때 이 converting 과정이 필요했다


<example>

struct 라이브러리에 있는 struct.unpack(fmt, buf)를 사용하면 된다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import struct
 
# CONSTANT
FILE_PATH = 'sample.pcm'
BUF_SIZE = 3200
SHORT_PER_BYTE = 16/8 # 2
 
def callback(buf): # buf is POINTER(c_short)
    # read to bin_data
    f.open(FILE_PATH, 'rb')
    bin_data = f.read(BUF_SIZE)
 
    # unpack to short_arr
    count = len(bin_data)/SHORT_PER_BYTE
    short_arr = struct.unpack('<'+('h'*count), bin_data)
 
    #copy to buf
    for i in range(count):
        buf[i] = short_arr[i]
 
cs


struct.unpack('<hh', bin_data)

length=4의 bin_data 변수를 unpack하여 length=2의 tuple을 return한다

unpack format에 대해서 설명하자면,

'<'는 byte order 중 little-endian을 의미 (반대는 '>')

'h'는 short 1개를 의미, 즉 'hh'는 short 2개를 의미

즉 h 갯수를 len(bin_data)에 맞춰주면 된다


필자가 사용한 pcm 파일이 pcm_s16le 타입이었기 때문에 (ffmpeg audio Types 참고)

위와 같은 format을 사용했다


---


여담으로, 'h'와 'H'의 차이는 signed/unsigned인데

memory-level에서 보면 동일하지만 그것을 어떻게 decode하느냐가 다르다.

예를들어 'h' 또는 'H'에 따라 b'\xff\xff'는 -1 또는 65535로 decode된다



WRITTEN BY
hojongs
블로그 옮겼습니다 https://hojongs.github.io/