bits - みる会図書館


検索対象: Introduction to Lossless Audio Codec ロスレス音声コーデック -基本理論と実装-
10件見つかりました。

1. Introduction to Lossless Audio Codec ロスレス音声コーデック -基本理論と実装-

2.4 bit_stream. c 71 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 } / * 読み込みモードでは実行不可能 * / stream—>bit—buffer ー = (uint8—t)BITSTREAM—GETLOWERBITS (stream¯> n_bits = n_bits stream—>bit_count ; whi1e (n—bits > = stream—>bit—count) { * 2 回目以降は 8 し概単位で出力 */ * 初回ループでは端数 ( 出力に必要なビット数 ) 分を埋め出力 / * 乙の上位ビットから順次出力 return B 工 TSTREAM_APIRESULT—OK ; if (n—bits / * 0 ビット出力では何もしない * / return BITSTREAM_APIRESULT—工 NVALID—ARGUMENT ; if (n-bits > sizeof (uint64—t) * 8 ) { / * 出力可能な最大ビット数を越えている * / return B 工 TSTREAM_APIRESULT_ 工 NVALID—MODE ; if (stream->flags & B 工 TSTREAM-FLAGS-FILEOPENMODE—READ) { = EOF) { return BITSTREAM-AP 工 RESULT—IOERROR ; if (fputc (stream—>bit—buffer, stream—>fp) bit—count , va1 > > n—bits) ; / * 端数ビットの処理 : stream—>bit_count stream—>bit—buffer = 0 ; 8 ; * 残った分をバッフアの上位ビットにセット */ assert(n—bits く = 8 ) ; stream—>bit_count n_bits ; stream—>bit—buffer ー = (uint8—t) (BITSTREAM—GETLOWERB 工 TS (n—bits , stream—>bit—count) ; return BITSTREAM_AP 工 RESULT-OK ; val) くく コメントにもあるようにアプリケーション側で出力対象の値を lbit 単位に分けて出力 を行えばリスト 2.14 に相当する処理を実現できるが、その処理の簡略化のために本関数 リスト 2.15 上位 bit からの出力処理 (bit- ト 2.15 の while ループに表れている。 力する。即ち、出力対象の引数値 val の最上位 bit から順に出力を行う。この処理はリス 1 バイト (8bit) を超える数値出力の際には、本モジュールはビッグエンディアンで出 を用意している。 stream . C

2. Introduction to Lossless Audio Codec ロスレス音声コーデック -基本理論と実装-

実装編 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 = 8 ; tmp ト BITSTREAM_GETLOWERBITS (stream—>bit_count , stream—>bit—count ; n_bits while (n—bits > stream—>bit—count) { * 2 回目以降は 8 t 単位で入力し t にセット */ * 初回ループでは t の上位ビットにセット / * 最上位ビットからデータを埋めていく return BITSTREAM_APIRESULT_ 工 NVALID_ARGUMENT ; if (n—bits > sizeof (uint64_t) * 8 ) { / * 入力可能な最大ビット数を越えている * / return BITSTREAM_AP 工 RESULT_INVAL 工 D_MODE ; 第 2 章 n—bits , uint64—t *val) int32_t ch; uint64—t tmp = 0 ; / * 引数チェック * / if (stream = = NULL Ⅱ val = = NULL) { return BITSTREAM_APIRESULT_INVAL 工 D_ARGUMENT ; / * 読み込みモードでない場合は即時リターン */ if ( ! (stream—>flags & BITSTREAM_FLAGS-F 工 LEOPENMODE READ) ) { stream—>bit—buffer) くく n_bits; / * プバイト読み込みとエラー処理 */ if ( ()h = fgetc (stream->fp) ) = EOF) { if (feof (stream->fp) ) { / * 途中でファイル終端に達していたら、ループを抜ける * / goto END-OF_STREAM; } else { / * それ以外のエラー * / return BITSTREAM_APIRESULT_ 工 OERROR ; END_OF_STREAM : / * 端数ビットの処理 stream—>bit—buffer stream—>bit_count (uint8—t) ch ; * 残ったビット分を t の最下位ビットにセット * / stream—>bit—count n_bits; tmp ト (uint64-t) BITSTREAM_GETLOWERB 工 TS (n_bits , bit—buffer > > stream—>bit_count) ) ; / * 正常終了 */ *val tmp ; return B 工 TSTREAM_APIRESULT_OK ; (uint32—t) (stream—>

3. Introduction to Lossless Audio Codec ロスレス音声コーデック -基本理論と実装-

2.7 main . c 85 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 struct WAVFi1e* wavfile ; / * 引数の数が誤っている場合は使用方法を表示 */ if (argc ! = 4 ) { fprintf (stderr, "Usage : 凵 program 凵 bits 凵 infile 凵 outfile 凵 \Ⅱ") ; return 1 ; / * 田 0 セファイルの読み込み * / if ( (wavfile = WAV-CreateFromFiIe(argv [ 2 ] ) ) = = NULL) { fprintf (stderr , t'Fai1ed 凵 tO 凵 get 凵 wav 凵 data. 凵 \ Ⅱ " ) ; return 1 ; / * 変換後の t の取得 * / wavfile—>format . bits—per—sample = atOi (argv[l] ) ; if ( (wavfile—>format . bits—per—sample ! = 8 ) 16 ) & & (wavfile—>format . bits—per—sample ! = & & (wavfile—>format . bits—per—sample ! = 24 ) & & (wavfile—>format. bits-per-sample ! = 32 ) ) { fprintf (stderr, "Wavfi1e 凵 bps 凵 must 凵 be 凵 8/16/24/32. 凵 \ n " ) ; return 1 ; / * と概を変更して保存 * / WAV-WriteToFiIe (argv [ 3 ] , / * ハンドル破棄 * / WAV—Destroy(wavfi1e) ; return 0 ; wavfile) ; 38 } 2.7 main . c main 関数が含まれる main. c は、引数処理を行ってエンコード処理とデコード処理を ALA のエンコード処理手順は、次のように要約される。 2.7.1 ALA のエンコード処理 バイナリファイルの読み書きを実行しているに過ぎない。 呼び分ける。工ンコード処理およびデコード処理は、表 2.1 , 2.2 のフォーマットに従って

4. Introduction to Lossless Audio Codec ロスレス音声コーデック -基本理論と実装-

第 2 章 / * セの上位ビットから順次出力 * 初回ループでは端数 ( 出力に必要なビット数 ) 分を埋め出力 * 2 回目以降は 8 とれ単位で出力 */ while (n—bits > = stream—>bit—count) { n—bits = n_bits stream—>bit_count ; stream—>bit—buffer ー = (uint8—t) B 工 TSTREAM_GETLOWERBITS (stream—> bit—count , va1 > > n—bits) ; if (fputc (stream—>bit—buffer, stream—>fp) return B 工 TSTREAM_APIRESULT_IOERROR ; = EOF) { 248 247 246 245 244 243 = 8 ; 242 241 240 239 238 237 72 stream—>bit_count stream—>bit_buffer = 0 ; 実装編 この while ループは、ループの度に 1 バイトの出力を行う。出力バッファ while ループを抜けた残りの bit は、リスト 2.16 に示す処理でバッファ 下位 bit から取り出す処理を行う。 た、 B 工 TSTREAM-GETLOWERBITS マクロは第二引数の値から、第一引数で指定した数だけ 数 n-bit s は出力対象の値 val の bit 位置を出力しているかを示す力ウンタとなる。ま 象の 1 バイトデータを設定し、 fputc 関数を実行している。このループにおいて引数変 stream—>bit-buffer に B 工 TSTREAM-GETLOWERBITS マクロによって取り出した出力対 stream → bit-buffer に記録され、次回の書き出し処理への備えを行う。 250 251 252 253 254 2 4.2 リスト 2.16 残った bit の記録処理 (bit_stream. c) / * 端数ビットの処理 : * 残った分をバッフアの上位ビットにセット * / assert (n—bits く = 8 ) ; stream—>bit_count n_b it s ; stream—>bit—buffer ト (uint8-t) (BITSTREAM-GETLOWERB 工 TS (n—bits , bit 単位の取得処理 stream—>bit—count) ; val) くく lbit 取得処理 lbit だけ取得を行う処理をリスト 2.17 に示す。 259 260 261 262 263 264 265 リスト 2.17 lbit の取得処理 (bit_stream. c) / * れ取得 */ BitStreamApiResu1t BitStream—GetBit (struct BitStream* stream, uint8_t* bit) int32_t ch; / * 引数チェック */ if (stream = = NULL Ⅱ bit = NULL) {

5. Introduction to Lossless Audio Codec ロスレス音声コーデック -基本理論と実装-

70 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 } 第 2 章 実装編 / * 読み込みモードでは実行不可能 * / stream—>bit—buffer ー = (uint8—t) ( 1 くく stream—>bit—count) ; if (bit ! = 0 ) { / * ビット出力バッフアに値を格納 */ stream—>bit_count— / * バイト出力するまでのカウントを減らす */ return BITSTREAM_AP 工 RESULT_INVAL 工 D—MODE ; if (stream->flags & BITSTREAM-FLAGS—FILEOPENMODE READ) { / * バッフア出力・更新 * / if (stream—>bit—count if (fputc(stream—>bit-buffer , stream->fp) return BITSTREAM-APIRESULT—IOERROR ; stream—>bit_count = 8 ; stream—>bit—buffer = 0 ; return B 工 TSTREAM_APIRESULT_OK ; = EOF) { lbit だけ出力する場合、その値は即座にファイルに書き出されず、一旦 1 バイ stre ー > bit ー co t に記録されており、このカウントが 0 になったときに始めてバイト ト分のバッファ stream->bit-buffer に蓄えられる。 bit の書き出しカウント数は 複数 bit 出力を行う処理をリスト 2.14 に示す。 複数 bit 出力処理 単位の書き出し (fputc 関数 ) が実行される。 210 211 212 213 214 215 216 217 218 219 リスト 2.14 複数 bit 出力処理 (bit-stream ・ c) * 乙の右側 ( 下位 ) れ一 ts 出力 ( 最大 6 イ t 出力可能 ) * BitStream-PutBits(stream, 3 , の , ・は次と同じ : * BitStream-PutBit(stream, プ ) , ・ BitStream—PutBit(stream, 1 ) , ・ BitStream-PutBit (stream, の , ・ BitStreamApiResu1t BitStream—PutBits (struct BitStream* stream, n—bits , uint64—t val) / * 引数チェック * / if (stream = = NULL) { て e t urn B ITS TREAM_AP IRESULT_ INVAL 工 D_ARGUMENT ; uint32_t

6. Introduction to Lossless Audio Codec ロスレス音声コーデック -基本理論と実装-

2.5 ala—coder . c 352 } 37 { 54 } Rice 符号化を行う処理をリスト 2.19 に示す。 Rice 符号化処理 に実装している。 考えればよい。 ala-coder. c では、 Rice 符号化と復号処理を 1.2.3 節で示した定義通り ALA では Golomb 符号化のパラメータを 2 の冪数に限定している為、 Rice 符号のみを 2.5.1 Rice 符号 入出力は bit 単位で行う必要があるため、 bit-stream . c に依存している。 理と、ファイルから残差を復号する処理を分担している。なお、本モジュールのファイル このモジュールは、予測によって得られた残差信号を符号化してファイルに書き出す処 2.5 ala_coder . c Ⅱー bits が少なくなるまで while ループを回し、ループの度に 1 バイト取得を行う。 反映される。処理の構造としては BitStream-PutBits とほぼ同様であり、取得 bit 数 取得データは一時変数 tmp に対して上位 bit から順に書き込まれ、最後に引数 val に 75 35 36 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 リスト 2.19 Rice 符号化処理 (ala-coder. c) static void ALACoder—PutRiceCode ( struct BitStream* strm, uint32—t rice—parameter, uint32—t val) uint32—t i , quot , rest ; assert (strm ! = NULL) ; / * 商と剰余の計算 * / quot = va1 > > ALAUti1ity—Log2CeiI(rice—parameter) ; rest = va1 & (rice—parameter ー 1 ) ; / * 商部分の出力 * / 0 ; 土く quot ; i + + ) { for (i BitStream—PutBit (strm, 0 ) ; BitStream—PutBit (strm, 1 ) ; / * 剰余部分の出力 * / BitStream-PutBits (strm, ALAUti1ity-Log2Cei1(rice—parameter) , rest) ; 符号化対象の数値 val と Rice 符号のパラメータ rice_parameter を用いて商 quot と

7. Introduction to Lossless Audio Codec ロスレス音声コーデック -基本理論と実装-

2.4 bit_stream . c 73 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 } return B 工 TSTREAM_APIRESULT_ 工 NVALID_ARGUMENT ; / * 読み込みモードでない場合は即時リターン * / if ( ! (stream->flags & BITSTREAM—FLAGS—F 工 LEOPENMODE—READ) ) { return B 工 TSTREAM_APIRESULT_ 工 NVALID_MODE ; / * 入力ビットカウントをプ減らし、バッフアの対象ビットを出力 * / if (stream—>bit—count > 0 ) { stream—>bit_count— (*bit) (stream—>bit—buffer > > stream—>bit—count) & 1 ; return B 工 TSTREAM—APIRESULT_OK ; / * プバイト読み込みとエラー処理 * / if ( ()h = fgetc (stream->fp) ) if (feof(stream → (p)) { / * ファイル終端に達した * / return BITSTREAM_APIRESULT_EOS ; } else { / * それ以外のエラー * / return BITSTREAM_AP 工 RESULT_IOERROR ; / * カウンタとバッフアの更新 * / stream—>bit_count = 7 ; (uint8-t) ch; stream—>bit_buffer / * 取得したバッフアの最上位ビットを出力 * / (*bit) (stream->bit—buffer > > 7 ) & 1 ; return BITSTREAM—APIRESULT_OK ; = EOF) { 常に読み込み予定の bit を含むデータ 1 バイト分をバッファ stream->bit-buffer に 取得しておき、バッフアに残っている bit 数のカウンタ stream->bit_count が残って いる限りはそこから lbit 取り出す。カウンタ stream → bit-count が 0 になったら次の データを fgetc 関数によって 1 バイト取得してバッファ stream->bit-buffer とカウ ンタ stream → bit-count を補充し、 lbit を取り出す。 複数 bit 取得処理 最後に複数 bit 取得を行う処理をリスト 2.18 に示す。 リスト 2.18 複数 bit 取得処理 (bit-stream. c) 302 / * n-bits 取得 ( 最大 6 イい t ) し、その値を右詰めして出力 */ 303 BitStreamApiResu1t BitStream_GetBits(struct BitStream* stream, uint32—t

8. Introduction to Lossless Audio Codec ロスレス音声コーデック -基本理論と実装-

86 第 2 章 実装編 ALA のエンコード処理手順 (main. c の do-encode 関数 ) 1. 入力の wav ファイルデータを取得する。 2. ヘッダ情報を書き出す。 に達するまで繰り返す。 3. プロックのエンコード処理を行う。以下の処理を wav ファイルデータの末尾 (f) 残差をエンコードする。 (e) 同期コードと PARCOR 係数をエンコードする。 出する。 (d) 整数データに PARCOR 格子型フィルターによる予測を行い、残差を算 (c) 整数データにプリエンファシスを適用する。 COR 係数を計算する。 double 形式のデータにプリエンファシスと窓掛けを行ってから、 PAR- (a) wav のチャンネル数がステレオ ( 2 ) 以上であれば、 S 処理を行う。 (b) ている ( リスト 2.38 ) 。 入力 wav データは整数型で取得すると同時に、解析用に高精度な double 型に変換し 入力 wav データの取得 大まかな処理内容は上記内容で十分と思われるため、細かい補足について触れていく。 既に 2.6.1 節で注意したが、 WAVFi1e 構造体に含まれる波形データは 32bit 整数型で記 ー 31 ) ; input-int32 [ch] [smpl] > > = ( 32 ー in-wav->format. bits-per_sample) ; / * 情報が失われない程度に右シフト * / input-int32 [ch] [smpl] = WAVFiIe-PCM (in-wav , smpl , (h) ; input [ch] Csmp1] = WAVFi1e—PCM (in—wav , smpl , (h) * pow ( 2 , 0 ; smpl く num—samples ; smpl + + ) { 土 0 て (smpl fO て ()h = 0 ; ch く num_channels; c れ + + ) { / * 入力データ取得 * / リスト 2.38 wav データ取得 (main. c 108 107 106 105 104 103 102 101 100 から離れるに従って精度が落ちる [ 38 ] 。 * 10 IEEE 754 の規格に従う浮動小数点数は、 0 近傍に多くの数値が含まれるため数値表現精度が高いが、 0 工ンコードするサンプル数は、リスト 2.39 に示す式で決定している。 工ンコードするサンプル数の決定 型データに 2 ー 31 を乗じた double 型のデータとして記録する。 きくなり過ぎてしまい、精度落ちの可能性がある * 10 。そのため、解析用のデータは、整数 録されている。このまま PARCOR 係数の解析を行うと ( 特に自己相関関数の ) 数値が大

9. Introduction to Lossless Audio Codec ロスレス音声コーデック -基本理論と実装-

2.6 wav . c ルは音声データを示す data チャンク以外は全て無視して処理を行う。 2.6.1 構造体定義 wav ファイルを扱うための構造体 WAVFi1e はリスト 2.31 で定義される。 83 32 33 34 35 36 リスト 2.31 wav ファイルハンドル ( wav. h ) / * 隰 / ファイルハンドル * / struct WAVFi1e { struct WAVFiIeFormat format ; / * フォーマット * / WAVPcmData** data; / * 実データ * / wav ファイルに関する操作 ( 関数 ) はこの構造体を介して行う。 WAVFi1e は、 wav ファイ ルのフォーマット情報が入った WAVFiIeFormat と、波形データ本体である WAVPcmData から構成される。 WAVFiIeFormat の定義はリスト 2.32 に示す通り。 23 24 25 26 27 28 29 30 リスト 2.32 wav ファイルフォーマット (wav. 五) / * 隰 / ファイルフォーマット * / struct WAVFiIeFormat { WAVDataFormat data—format ; / * データフォーマット * / uint32—t num—channels; / * チャンネル数 * / uint32—t sampling—rate ; / * サンプリングレート * / uint32-t bits-per-sample ; / * 量子化ビット数 * / uint32—t num-samples; / * サンプル数 * / 波形の情報を示す情報が詰まっている。波形データフォーマット WAVDataFormat は現 状 PCM フォーマットのみしか対応していない。波形データの型の実体は int32-t であ ることを踏まえると、本モジュールは整数型 ( 最大 32bit) の PCM のみサポートしてい ることに注意。 波形データへの読み書きは、リスト 2.33 の WAVFi1e-PCM を使用できる。 ( 直接配列に アクセスしても良い ) リスト 2.33 波形データアクセサ ( wav. h ) 38 / * アクセサ * / 39 #define WAVFi1e-PCM(wavfiIe , samp, (h) (wavfile->data[(ch)] [(samp)] ) サンプル位置 s p とチャンネル ch を指定してデータへのアクセスを行う。こでも 一点注意。 wav モジュールを扱う側で bit 幅を意識させないように、波形データは一律で 32bit 整数で取得される。波形が 32bit より小さい量子化 bit 数であっても、 32bit 幅に 拡張される。例えば、量子化 bit 数が 16bit の波形データにおいて、 Ox7FFF は 32bit 整 数に ( 左 16bit シフトして ) 拡張され 0X7FFF0000 で取得される。一方、 wav ファイルへ

10. Introduction to Lossless Audio Codec ロスレス音声コーデック -基本理論と実装-

2.5 ala_coder . c 131 132 133 BitStream—PutBits (strm, 16 , coder—>estimated—mean [ch] 79 me an_uint ) ; ALACODER_UINT32_TO_F 工 XED—FLOAT (mean—uint) 初期値は適当に 1 等で決め打ちしても処理としては問題ないが、推定平均値の収束を早 くするために、入力データの平均値を推定値の初期値に設定している。また、初期値は残 差の直前に記録しておく。 処理マクロについて補足する。 ALAUTIL 工 TY-S 工 NT32-T0_UINT32 マクロは符号付き整 数を符号無し整数に変換する処理を行う。 Rice 符号は正整数を対象にしているため、符 号化にあたってこの変換は必須である。マクロは ala ー utility. h において次のように定 義される。 リスト 2.24 ALAUTIL 工 TY_SINT32-TO-U 工 NT32 マクロ (ala—utility. h) 27 / * 符号付き 32 とれ数値を符号なし 32 と概数値に一意変換 * / 28 #define ALAUT 工 L 工 TY-SINT32-TO-UINT32(sint) ( ( (int32—t) (sint) く 0 ) ? ( ( ((uint32-t)(((sint) くく 1 ) ) ) ) uint32-t)((-((sint) くく 1 ) ) ー 1 ) ) ・ このマクロによって、正整数は正偶数に、負整数は正奇数に変換される。この変換は絶 対値の小さい方から大きい順に変換後の数値が並ぶため、 Rice 符号のような符号化対象 の数値の絶対値の大きさに追従して出力符号長が長くなる符号にとって都合が良い。符号 付き整数を符号なし整数に変換する手法は他にも幾つか存在し、 [ 9 ] によると、整数を符 号 bit とその絶対値に分けて符号化する方法や、符号を負数に対応させる方法が挙げられ ている。 ALACODER-UINT32-T0-F 工 XED-FLOAT マクロは整数値を固定小数化するマクロである。 マクロの定義をリスト 2.25 に示す。 リスト 2.25 整数値の固定小数化 (ala-coder. c) 13 / * 符号なし整数を固定小数に変換 * / 14 #define ALACODER-U 工 NT32—TO—F 工 XED-FLOAT ( u32 ) ( ( u32 ) くく ( ALACODER_NUM_FRACT 工 ON—PART-BITS) ) 左シフト演算によって、小数部を 0 にした状態の固定小数点数を作成している。固定小 数化する理由としては、平均推定値を更新する際、率直に整数を使うと切り捨てによる精 度落ちが無視できないためである。 符号化と推定平均値の更新処理をリスト 2.26 に示す。 135 136 137 138 139 リスト 2.26 符号化処理コア部分 (ala-coder ・ c) / * 各チャンネル毎に符号化 * / for ()h = 0 ; ch く num—channels ; c + + ) { 0 ; smpl く num—samples ; smpl + + ) { f0 て (smpl / * 符号なし整数に変換 */ uint = ALAUTIL 工 TY-S 工 NT32—TO—UINT32 (data [ch] [smpl] ) ;