Python으로 24비트 PCM WAV를 16비트로 변환하기
24비트 PCM의 음수 샘플을 읽고, 16비트 변환 시 반올림과 범위 제한을 적용한다. Python 예제로 스테레오 순서와 잘린 프레임까지 검증한다.
녹음 파일이나 TTS 후처리 파이프라인에서 24비트 PCM WAV를 16비트 PCM WAV로 바꾸려면, 3바이트 샘플을 부호 있는 정수로 읽고 256으로 스케일링한 뒤 반올림과 범위 제한을 적용한다. 아래 Python 예제는 리틀엔디언 환경에서 비트 깊이만 변환한다. 스테레오 채널 순서와 샘플레이트를 유지하고, 잘린 입력 프레임을 검출하는 방법까지 다룬다.
청록색 오디오 파형이 주황색 변환 지점을 지나 더 굵은 층으로 표현된 일러스트
음수 샘플이 큰 양수로 바뀌는 이유
패킹된 24비트 PCM에서 샘플 하나는 3바이트를 차지한다. 리틀엔디언 2의 보수 값 ff ff ff는 부호를 적용하면 -1이고, 부호 없이 읽으면 16,777,215다. 부호 없는 값으로 해석하고 그대로 16비트 범위에 맞추면 조용한 음수 샘플이 최대 양수에 가까운 값으로 바뀔 수 있다. int.from_bytes(sample, "little", signed=True)는 바이트 순서와 부호를 함께 지정한다. Python int.from_bytes 문서
스테레오에서 프레임 하나에는 각 채널의 샘플이 하나씩 들어간다. 24비트 스테레오의 프레임 크기는 6바이트다. 코드는 프레임 단위로 읽고, 프레임 안의 샘플을 3바이트씩 순서대로 변환한다. 16비트 WAV에 쓸 때는 struct.pack에 리틀엔디언 부호 있는 16비트 형식을 지정한다. Python wave 문서 · Python struct 문서
반올림하고 16비트 범위에 맞추기
24비트 정수를 16비트로 줄이는 스케일은 256이다. 예제는 가장 가까운 정수로 반올림하며, 정확히 중간이면 0에서 먼 쪽을 선택한다. 따라서 -128과 128은 각각 -1과 1이 되고, -127과 127은 모두 0이 된다. 하위 바이트를 버리는 산술 우측 시프트는 음수에서 내림과 같아서, 예를 들어 -1을 -1로 보낸다. 예제의 반올림 규칙에서는 -1이 0이 된다.
양의 최대 입력값 8,388,607을 반올림하면 32,768이 된다. 부호 있는 16비트의 상한이 32,767이므로 마지막에 범위를 제한한다. 음의 최대 크기인 -8,388,608은 정확히 -32,768로 변환된다. 이 스케일은 고정된 비트 깊이 변환 비율이다. 파일의 피크나 음량을 측정해 이득을 조정하는 단계는 없다.
아래 코드를 pcm24_to_pcm16.py로 저장하고 python3 pcm24_to_pcm16.py를 실행한다. 표준 라이브러리만 사용한다.
경계값과 손상된 입력 확인하기
2026년 11월 10일 Linux x86-64에서 Python 3.12.14로 실행했다. 생성한 스테레오 WAV를 변환한 뒤 다시 열어 채널 수, 샘플 폭, 샘플레이트, 프레임 수와 8개 샘플의 순서 및 값을 검사했다. 마지막 바이트를 제거한 WAV도 입력해 잘린 프레임이 거부되는 것을 확인했다.
(2, 2, 24000, 4)는 2채널, 샘플당 2바이트, 24 kHz, 4프레임이다. 프레임 수와 샘플레이트가 유지되어 재생 시간도 같다. 값 목록의 첫 두 원소는 첫 프레임의 왼쪽과 오른쪽 채널이다.
실제 파일에 적용할 때
convert_wav에 서로 다른 입력·출력 경로 문자열을 넘길 수 있다. 오류가 발생하면 출력에 이미 일부 데이터가 쓰였을 수 있으므로, 배치 작업에서는 임시 파일에 쓴 뒤 변환 성공 시 최종 경로로 옮긴다. 예제는 메모리의 일반 PCM WAV로 검증했다. wave가 지원하는 PCM 확장 헤더의 유효 비트 수와 채널 마스크를 보존하거나, 추가 WAV 메타데이터 청크를 복사하는 기능은 포함하지 않는다. 컨테이너 비트 수와 유효 비트 수가 다른 파일은 포맷 필드를 해석할 수 있는 도구로 별도 처리한다. Python wave 문서 · Microsoft WAVEFORMATEXTENSIBLE 문서
예제는 디더를 적용하지 않는다. 수치 검사는 변환 규칙을 확인하는 데 사용했으며, 저레벨 신호의 양자화 왜곡이나 청감 품질은 평가하지 않았다. 마스터링처럼 저레벨 품질이 중요한 작업이라면 디더를 포함한 변환 정책을 별도로 비교한다.
English version ·
Convert 24-Bit PCM WAV to 16-Bit PCM in Python