OpenCORE-AMR을 이용한 PCM과 AMR-NB 오디오 간 상호 변환 실습

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;
}

태그: OpenCORE-AMR AMR-NB PCM 오디오 코덱 인코딩

7월 8일 23:42에 게시됨