5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

LDACエンコーダを使ってみた

Last updated at Posted at 2017-02-23

AOSPにあるオープンソースなソニー製のLDACエンコーダ libldac を使ってみました。

ソースコードはgithubに置いときました。 https://github.com/eggman/ldacenc

libldac の コンパイル

  • 普通のMakefileが無いので、普通にコンパイルして静的ライブラリを作ります。
$ git clone https://android.googlesource.com/platform/external/libldac
$ cd libldac/src
$ gcc -O2 -Werror -I../inc -c ldaclib.c 
$ gcc -O2 -Werror -I../inc -c ldacBT.c 
$ ar rcs libldacBT_enc.a ldaclib.o ldacBT.o
  • macbookでコンパイルした場合のサイズ
$ size libldacBT_enc.a 
__TEXT  __DATA  __OBJC  others  dec     hex
36292   192     0       1120    37604   92e4    libldacBT_enc.a(ldaclib.o)
7134    0       0       480     7614    1dbe    libldacBT_enc.a(ldacBT.o)

libldac の API

  • APIは ldacBT.h に定義してあります。
  • このヘッダファイルには親切な感じで使い方の記載があります。
LDACBT_API HANDLE_LDAC_BT ldacBT_get_handle( void );
LDACBT_API void ldacBT_free_handle( HANDLE_LDAC_BT hLdacBt );
LDACBT_API void ldacBT_close_handle( HANDLE_LDAC_BT hLdacBt );
LDACBT_API int  ldacBT_get_version( void );
LDACBT_API int  ldacBT_get_sampling_freq( HANDLE_LDAC_BT hLdacBt );
LDACBT_API int  ldacBT_get_bitrate( HANDLE_LDAC_BT hLdacBt );
LDACBT_API int  ldacBT_init_handle_encode( HANDLE_LDAC_BT hLdacBt, int mtu, int eqmid, int cm,
                                           LDACBT_SMPL_FMT_T fmt, int sf );
LDACBT_API int  ldacBT_set_eqmid( HANDLE_LDAC_BT hLdacBt, int eqmid );
LDACBT_API int  ldacBT_get_eqmid( HANDLE_LDAC_BT hLdacBt );
LDACBT_API int  ldacBT_alter_eqmid_priority( HANDLE_LDAC_BT hLdacBt, int priority );
LDACBT_API int  ldacBT_encode( HANDLE_LDAC_BT hLdacBt, void *p_pcm, int *pcm_used,
                               unsigned char *p_stream, int *stream_sz, int *frame_num );
LDACBT_API int  ldacBT_get_error_code( HANDLE_LDAC_BT hLdacBt );

  • ストリームのエンコード開始後に、ldacBT_set_eqmid()のemqidを設定することでeqmidに対応したビットレートを動的に変更できます。

Initialize

  • 初期化のサンプルコード
#include <stdio.h>
#include "ldacBT.h"

int main(void)
{
    HANDLE_LDAC_BT h;
    int ret, err;

    h = ldacBT_get_handle();
    printf("version       %08x\n",ldacBT_get_version());

    ret = ldacBT_init_handle_encode(h, 679, LDACBT_EQMID_HQ, LDACBT_CHANNEL_MODE_STEREO, LDACBT_SMPL_FMT_S24, 96000);
    err=ldacBT_get_error_code(h); 

    printf("ret=%d api_error=%d\n", ret, LDACBT_API_ERR(err));
    printf("sampling_freq %08x\n",ldacBT_get_sampling_freq(h));
    printf("bit_rate      %08x\n",ldacBT_get_bitrate(h));
    return 0;
}
  • 実行例
version       00020002
ret=0 api_error=0
sampling_freq 00017700
bit_rate      000003de

Encode

  • 256サンプルをencodeする。
  • 128サンプルだと何も出力されませんでした。
  • 256サンプルを入力すると、660バイトのエンコードデータが得られました。
#include <stdio.h>
#include "ldacBT.h"

int main(void)
{
    HANDLE_LDAC_BT h;
    int ret, err, pcm_used, ldac_stream_size, ldac_frame_num;
    unsigned char pcm[256*2*2]; /* 256 samples * 2ch * 16bit */
    unsigned char ldac[1024];
    h = ldacBT_get_handle();

    ret = ldacBT_init_handle_encode(h, 679, LDACBT_EQMID_HQ, LDACBT_CHANNEL_MODE_STEREO, LDACBT_SMPL_FMT_S16, 48000);
    err=ldacBT_get_error_code(h); 
    printf("ret=%d api_error=%d handle_error=%d block_error=%d\n", ret, LDACBT_API_ERR(err), LDACBT_HANDLE_ERR(err), LDACBT_BLOCK_ERR(err));

    ret = ldacBT_encode(h, pcm, &pcm_used, ldac, &ldac_stream_size, &ldac_frame_num);
    err=ldacBT_get_error_code(h); 
    printf("ret=%d api_error=%d handle_error=%d block_error=%d\n", ret, LDACBT_API_ERR(err), LDACBT_HANDLE_ERR(err), LDACBT_BLOCK_ERR(err));
    printf("  pcm_used=%d ldac_stream_size=%d ldac_frame_num=%d\n", pcm_used, ldac_stream_size, ldac_frame_num);
    
    ret = ldacBT_encode(h, &pcm[128*2*2], &pcm_used, ldac, &ldac_stream_size, &ldac_frame_num);
    err=ldacBT_get_error_code(h); 
    printf("ret=%d api_error=%d handle_error=%d block_error=%d\n", ret, LDACBT_API_ERR(err), LDACBT_HANDLE_ERR(err), LDACBT_BLOCK_ERR(err));
    printf("  pcm_used=%d ldac_stream_size=%d ldac_frame_num=%d\n", pcm_used, ldac_stream_size, ldac_frame_num);

    return 0;
}
  • 実行例
ret=0 api_error=0 handle_error=0 block_error=0
ret=0 api_error=0 handle_error=0 block_error=0
  pcm_used=512 ldac_stream_size=0 ldac_frame_num=0
ret=0 api_error=0 handle_error=0 block_error=0
  pcm_used=512 ldac_stream_size=660 ldac_frame_num=2

Encode wav file

  • 16bit stereo な wavファイルを読み込んでエンコードして出力します。
  • ファイルの最後の端数の部分はエンコードされません。
#include <stdio.h>
#include "ldacBT.h"

int main(int argc, char *argv[])
{
    HANDLE_LDAC_BT h;
    int ret, err, pcm_used, ldac_stream_size, ldac_frame_num;
    unsigned char pcm[128*2*2];
    unsigned char ldac[1024];
    FILE *infp, *outfp;
    unsigned char header[44];

    if ((infp = fopen(argv[1], "r"))==NULL) {
        printf("can't open input file\n");
        return -1;
    }

    if ((outfp = fopen(argv[2], "w"))==NULL) {
        printf("can't open output file\n");
        return -1;
    }

    //skip wave header
    fread(header, 44, 1, infp);
    
    h = ldacBT_get_handle();
    ret = ldacBT_init_handle_encode(h, 679, LDACBT_EQMID_HQ, LDACBT_CHANNEL_MODE_STEREO, LDACBT_SMPL_FMT_S16, 48000);

    while(fread(pcm, 512, 1, infp))
    {
        ret = ldacBT_encode(h, &pcm[0], &pcm_used, ldac, &ldac_stream_size, &ldac_frame_num);
        printf("  pcm_used=%d ldac_stream_size=%d ldac_frame_num=%d\n", pcm_used, ldac_stream_size, ldac_frame_num);
        fwrite(ldac, 1, ldac_stream_size, outfp);
    }

    ldacBT_close_handle(h);

    return 0;
}
  • 実行例
$./ldacenc 1kHz-0-dither.wav 1khz.ldac_hq
  pcm_used=512 ldac_stream_size=0 ldac_frame_num=0
  pcm_used=512 ldac_stream_size=660 ldac_frame_num=2
  pcm_used=512 ldac_stream_size=0 ldac_frame_num=0
  pcm_used=512 ldac_stream_size=660 ldac_frame_num=2
  pcm_used=512 ldac_stream_size=0 ldac_frame_num=0
  pcm_used=512 ldac_stream_size=660 ldac_frame_num=2
  • サイズ
  • HQ、SQ、MQでエンコードした場合のサイズです。 それぞれ990kbps, 660kbps, 330kbpsになっています。
  2880044  1kHz-0-dither.wav
  1855920  1khz.ldac_hq
  1237500  1khz.ldac_sq
   618420  1khz.ldac_mq
5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?