1. 개요
빌드 방법
제공된 정적 라이브러리(`libopencore-amrnb.a`)는 x86_64 아키텍처에서 컴파일된 것이므로, 해당 아키텍처 기반 시스템에서만 직접 빌드 및 실행이 가능합니다.데모 프로그램 빌드:
make
다른 플랫폼(예: ARM)에서 사용하려면 소스 코드로부터 직접 라이브러리를 빌드해야 합니다. 아래 스크립트를 통해 OpenCORE-AMR 0.1.3 버전을 컴파일할 수 있습니다:
#!/bin/bash
tar xzf opencore-amr-0.1.3.tar.gz
cd opencore-amr-0.1.3/
./configure --prefix=$PWD/_install
make -j$(nproc)
make install
빌드 후 생성된 헤더 파일과 라이브러리를 기존 프로젝트의 include/ 및 libs/ 디렉터리에 복사하여 사용하면 됩니다.
실행 방법
본 예제는 샘플링 주파수 8kHz, 비트 깊이 16비트의 PCM 데이터와 AMR-NB 형식 간 양방향 변환을 수행합니다.- PCM → AMR-NB 인코딩:
./pcm2amrnb ./audio/test_8000_16_1.pcm out.amr
- AMR-NB → PCM 디코딩:
./amrnb2pcm ./audio/test.amr out_8000_16_1.pcm
모든 출력 PCM 데이터는 8kHz, 단일 채널(모노) 형식으로 고정됩니다.
인코딩 제약 조건
- 입력 PCM은 반드시 8000Hz 샘플링 레이트를 가져야 함
- 지원 비트 심도: 16비트
- 채널 수: 모노 또는 스테레오 입력 가능하지만, 출력 AMR은 항상 모노
- AMR-NB는 기본적으로 20ms 프레임 단위로 처리 (초당 50프레임)
디코딩 출력 사양
- 출력 샘플 레이트: 8000Hz
- 샘플 포맷: 16비트 리틀엔디안
- 채널: 단일 채널
참고 자료
디렉터리 구조
.
├── audio
│ ├── test_8000_16_1.pcm
│ ├── test_8000_16_2.pcm
│ └── test.amr
├── docs
│ ├── AMR 파일 형식 분석 문서
│ └── 관련 기술 블로그 아티클 저장소
├── include
│ ├── interf_dec.h
│ └── interf_enc.h
├── libs
│ └── libopencore-amrnb.a
├── main_amrnb2pcm.c
├── main_pcm2amrnb.c
├── Makefile
└── README.md
2. 핵심 코드 요약
main_pcm2amrnb.c
#include <stdio.h>
#include <stdlib.h>
#include "interf_enc.h"
/* PCM 포맷 설정 */
#define PCM_RATE 8000
#define PCM_BIT_DEPTH 16
#define PCM_CH 1
/* 20ms 프레임당 바이트 수 계산 (8000 * 0.02 * 16 / 8 * 1 = 320바이트) */
#define FRAME_SIZE_PCM (PCM_RATE / 50 * PCM_BIT_DEPTH / 8 * PCM_CH)
/* AMR-NB 인코딩 설정 */
#define AMR_MODE MR122
#define FRAME_SIZE_AMR 32 /* MR122 모드 기준 */
/* DTX(비음성 구간 압축) 활성화 여부 */
#define DTX_ON 1
#define DTX_OFF 0
int main(int argc, char *argv[])
{
int enable_dtx = DTX_ON;
void *encoder_state = NULL;
FILE *file_in = NULL, *file_out = NULL;
short pcm_buffer[FRAME_SIZE_PCM / sizeof(short)];
unsigned char amr_buffer[50]; // 충분한 크기 확보
if (argc != 3) {
fprintf(stderr, "Usage: %s <input.pcm> <output.amr>\n", argv[0]);
return -1;
}
file_in = fopen(argv[1], "rb");
if (!file_in) {
perror("Failed to open input PCM file");
return -1;
}
file_out = fopen(argv[2], "wb");
if (!file_out) {
perror("Failed to create output AMR file");
fclose(file_in);
return -1;
}
// AMR 인코더 초기화
encoder_state = Encoder_Interface_init(enable_dtx);
if (!encoder_state) {
fprintf(stderr, "Failed to initialize AMR encoder\n");
fclose(file_in);
fclose(file_out);
return -1;
}
// 헤더 쓰기 (옵션, 일부 포맷에서 필요)
fwrite("#!AMR\n", 1, 6, file_out);
// 인코딩 루프
while (fread(pcm_buffer, 1, FRAME_SIZE_PCM, file_in) == FRAME_SIZE_PCM) {
int encoded_bytes = Encoder_Interface_Encode(
encoder_state,
AMR_MODE,
pcm_buffer,
amr_buffer,
0 // 비트스트림 포맷 (IETF RFC 3267 기준)
);
if (encoded_bytes > 0) {
fwrite(amr_buffer, 1, encoded_bytes, file_out);
}
}
// 종료 처리
Encoder_Interface_exit(encoder_state);
fclose(file_in);
fclose(file_out);
printf("Encoding completed: %s → %s\n", argv[1], argv[2]);
return 0;
}