音频demo:使用开源项目LibFLAC来将PCM格式数据和FLAC无损压缩格式相互进行编解码

1、README

a. 移植步骤

源码下载地址:https://github.com/xiph/flac/releases

tar xzf flac-1.4.3.tar.gz
cd flac-1.4.3/
./autogen.sh
./configure --prefix=$PWD/_install --enable-static --disable-shared
make -j8
make install
tree _install/ -h
b. demo使用方法
编译
$ make clean && make
rm -rf pcm2flac flac2pcm out*
gcc main_pcm2flac.c -I./include -lFLAC -L./libs -lm -o pcm2flac
gcc main_flac2pcm.c -I./include -lFLAC -L./libs -lm -o flac2pcm
编码
$ ./pcm2flac 
Usage: 
         ./pcm2flac <in-pcm-file> <sample-rate> <bits per sample> <channels> <out-flac-file>
Examples: 
         ./pcm2flac ./audio/test_16000_16_1.pcm 16000 16 1 out1.flac
         ./pcm2flac ./audio/test_44100_16_2.pcm 44100 16 2 out2.flac
解码
Usage: 
         ./flac2pcm <in-flac-file> <out-pcm-file>
Examples: 
         ./flac2pcm ./audio/out1.flac out_16000_16_1.pcm
         ./flac2pcm ./audio/out2.flac out_44100_16_2.pcm
c. 参考文章
d. demo使用日志
编码

如果是双声道,那么一个采样点就包含16bit*2channels等于4个字节,单通道就是2个字节(16bit),那么,文件大小/一个采样点的字节数=总的采样点数。

另外,从日志里看,这里1帧(frame)是由4096个采样点编码而成,那么我们程序里每次读取1024个采样点传递进去并不是直接进行编码的。

$ ls -l audio/
total 6088
-rw-rw-r-- 1 lin lin  437838 6月  11 21:10 out1.flac
-rw-rw-r-- 1 lin lin 1621374 6月  11 21:10 out2.flac
-rw-rw-r-- 1 lin lin  640000 6月  11 16:27 test_16000_16_1.pcm
-rw-rw-r-- 1 lin lin 3528000 6月  11 20:23 test_44100_16_2.pcm
$ 
$ ./pcm2flac ./audio/test_16000_16_1.pcm 16000 16 1 out1.flac
It will encode a PCM file as [file size: 640000] [total samples: 320000] [sample rate: 16000] - [bits per sample: 16] - [channels: 1] !
wrote 5318 bytes, 4096/320000 samples, 2/79 frames
wrote 9345 bytes, 8192/320000 samples, 2/79 frames
wrote 13453 bytes, 12288/320000 samples, 3/79 frames
wrote 17821 bytes, 16384/320000 samples, 4/79 frames
wrote 22198 bytes, 20480/320000 samples, 5/79 frames
wrote 27175 bytes, 24576/320000 samples, 6/79 frames
wrote 33137 bytes, 28672/320000 samples, 7/79 frames
wrote 39056 bytes, 32768/320000 samples, 8/79 frames
wrote 44756 bytes, 36864/320000 samples, 9/79 frames
wrote 50595 bytes, 40960/320000 samples, 10/79 frames
wrote 56557 bytes, 45056/320000 samples, 11/79 frames
wrote 63043 bytes, 49152/320000 samples, 12/79 frames
wrote 69089 bytes, 53248/320000 samples, 13/79 frames
wrote 75846 bytes, 57344/320000 samples, 14/79 frames
wrote 81958 bytes, 61440/320000 samples, 15/79 frames
wrote 87419 bytes, 65536/320000 samples, 16/79 frames
wrote 92602 bytes, 69632/320000 samples, 17/79 frames
wrote 97864 bytes, 73728/320000 samples, 18/79 frames
wrote 103342 bytes, 77824/320000 samples, 19/79 frames
wrote 108532 bytes, 81920/320000 samples, 20/79 frames
wrote 113797 bytes, 86016/320000 samples, 21/79 frames
wrote 120079 bytes, 90112/320000 samples, 22/79 frames
wrote 125751 bytes, 94208/320000 samples, 23/79 frames
wrote 131919 bytes, 98304/320000 samples, 24/79 frames
wrote 137624 bytes, 102400/320000 samples, 25/79 frames
wrote 143249 bytes, 106496/320000 samples, 26/79 frames
wrote 149302 bytes, 110592/320000 samples, 27/79 frames
wrote 155021 bytes, 114688/320000 samples, 28/79 frames
wrote 160210 bytes, 118784/320000 samples, 29/79 frames
wrote 165215 bytes, 122880/320000 samples, 30/79 frames
wrote 170107 bytes, 126976/320000 samples, 31/79 frames
wrote 174884 bytes, 131072/320000 samples, 32/79 frames
wrote 179605 bytes, 135168/320000 samples, 33/79 frames
wrote 184281 bytes, 139264/320000 samples, 34/79 frames
wrote 188811 bytes, 143360/320000 samples, 35/79 frames
wrote 193357 bytes, 147456/320000 samples, 36/79 frames
wrote 197303 bytes, 151552/320000 samples, 37/79 frames
wrote 201058 bytes, 155648/320000 samples, 38/79 frames
wrote 207450 bytes, 159744/320000 samples, 39/79 frames
wrote 214081 bytes, 163840/320000 samples, 40/79 frames
wrote 220053 bytes, 167936/320000 samples, 41/79 frames
wrote 225452 bytes, 172032/320000 samples, 42/79 frames
wrote 230626 bytes, 176128/320000 samples, 43/79 frames
wrote 237118 bytes, 180224/320000 samples, 44/79 frames
wrote 242759 bytes, 184320/320000 samples, 45/79 frames
wrote 249391 bytes, 188416/320000 samples, 46/79 frames
wrote 255973 bytes, 192512/320000 samples, 47/79 frames
wrote 261699 bytes, 196608/320000 samples, 48/79 frames
wrote 267705 bytes, 200704/320000 samples, 49/79 frames
wrote 273581 bytes, 204800/320000 samples, 50/79 frames
wrote 279489 bytes, 208896/320000 samples, 51/79 frames
wrote 285062 bytes, 212992/320000 samples, 52/79 frames
wrote 291205 bytes, 217088/320000 samples, 53/79 frames
wrote 297068 bytes, 221184/320000 samples, 54/79 frames
wrote 302728 bytes, 225280/320000 samples, 55/79 frames
wrote 307865 bytes, 229376/320000 samples, 56/79 frames
wrote 313116 bytes, 233472/320000 samples, 57/79 frames
wrote 318420 bytes, 237568/320000 samples, 58/79 frames
wrote 323566 bytes, 241664/320000 samples, 59/79 frames
wrote 328424 bytes, 245760/320000 samples, 60/79 frames
wrote 333121 bytes, 249856/320000 samples, 61/79 frames
wrote 337973 bytes, 253952/320000 samples, 62/79 frames
wrote 344265 bytes, 258048/320000 samples, 63/79 frames
wrote 350878 bytes, 262144/320000 samples, 64/79 frames
wrote 357328 bytes, 266240/320000 samples, 65/79 frames
wrote 363638 bytes, 270336/320000 samples, 66/79 frames
wrote 370207 bytes, 274432/320000 samples, 67/79 frames
wrote 375974 bytes, 278528/320000 samples, 68/79 frames
wrote 381269 bytes, 282624/320000 samples, 69/79 frames
wrote 386678 bytes, 286720/320000 samples, 70/79 frames
wrote 392988 bytes, 290816/320000 samples, 71/79 frames
wrote 400124 bytes, 294912/320000 samples, 72/79 frames
wrote 406608 bytes, 299008/320000 samples, 73/79 frames
wrote 413317 bytes, 303104/320000 samples, 74/79 frames
wrote 419545 bytes, 307200/320000 samples, 75/79 frames
wrote 425148 bytes, 311296/320000 samples, 76/79 frames
wrote 430510 bytes, 315392/320000 samples, 77/79 frames
wrote 437052 bytes, 319488/320000 samples, 78/79 frames
   state: FLAC__STREAM_ENCODER_OK
wrote 437838 bytes, 320000/320000 samples, 79/79 frames
encoding: succeeded
   state: FLAC__STREAM_ENCODER_UNINITIALIZED
./audio/test_16000_16_1.pcm -> out1.flac: Success!
$ 
$  ./pcm2flac ./audio/test_44100_16_2.pcm 44100 16 2 out2.flac
It will encode a PCM file as [file size: 3528000] [total samples: 882000] [sample rate: 44100] - [bits per sample: 16] - [channels: 2] !
wrote 6858 bytes, 4096/882000 samples, 2/216 frames
wrote 11921 bytes, 8192/882000 samples, 2/216 frames
wrote 18879 bytes, 12288/882000 samples, 3/216 frames
wrote 24793 bytes, 16384/882000 samples, 4/216 frames
wrote 31126 bytes, 20480/882000 samples, 5/216 frames
wrote 37532 bytes, 24576/882000 samples, 6/216 frames
wrote 43425 bytes, 28672/882000 samples, 7/216 frames
wrote 50210 bytes, 32768/882000 samples, 8/216 frames
wrote 56439 bytes, 36864/882000 samples, 9/216 frames
wrote 62129 bytes, 40960/882000 samples, 10/216 frames
wrote 69469 bytes, 45056/882000 samples, 11/216 frames
wrote 75834 bytes, 49152/882000 samples, 12/216 frames
wrote 82229 bytes, 53248/882000 samples, 13/216 frames
wrote 89065 bytes, 57344/882000 samples, 14/216 frames
wrote 95800 bytes, 61440/882000 samples, 15/216 frames
wrote 102536 bytes, 65536/882000 samples, 16/216 frames
wrote 109214 bytes, 69632/882000 samples, 17/216 frames
wrote 116265 bytes, 73728/882000 samples, 18/216 frames
wrote 124616 bytes, 77824/882000 samples, 19/216 frames
wrote 132645 bytes, 81920/882000 samples, 20/216 frames
wrote 140175 bytes, 86016/882000 samples, 21/216 frames
wrote 147662 bytes, 90112/882000 samples, 22/216 frames
wrote 154911 bytes, 94208/882000 samples, 23/216 frames
wrote 162076 bytes, 98304/882000 samples, 24/216 frames
wrote 169290 bytes, 102400/882000 samples, 25/216 frames
wrote 176480 bytes, 106496/882000 samples, 26/216 frames
wrote 183555 bytes, 110592/882000 samples, 27/216 frames
wrote 190913 bytes, 114688/882000 samples, 28/216 frames
wrote 198080 bytes, 118784/882000 samples, 29/216 frames
wrote 206022 bytes, 122880/882000 samples, 30/216 frames
wrote 213876 bytes, 126976/882000 samples, 31/216 frames
wrote 222047 bytes, 131072/882000 samples, 32/216 frames
wrote 230677 bytes, 135168/882000 samples, 33/216 frames
wrote 238791 bytes, 139264/882000 samples, 34/216 frames
wrote 246886 bytes, 143360/882000 samples, 35/216 frames
wrote 254563 bytes, 147456/882000 samples, 36/216 frames
wrote 263643 bytes, 151552/882000 samples, 37/216 frames
wrote 273869 bytes, 155648/882000 samples, 38/216 frames
wrote 282268 bytes, 159744/882000 samples, 39/216 frames
wrote 290151 bytes, 163840/882000 samples, 40/216 frames
wrote 297752 bytes, 167936/882000 samples, 41/216 frames
wrote 305124 bytes, 172032/882000 samples, 42/216 frames
wrote 312254 bytes, 176128/882000 samples, 43/216 frames
wrote 319121 bytes, 180224/882000 samples, 44/216 frames
wrote 325896 bytes, 184320/882000 samples, 45/216 frames
wrote 332538 bytes, 188416/882000 samples, 46/216 frames
wrote 339206 bytes, 192512/882000 samples, 47/216 frames
wrote 345880 bytes, 196608/882000 samples, 48/216 frames
wrote 352383 bytes, 200704/882000 samples, 49/216 frames
wrote 359824 bytes, 204800/882000 samples, 50/216 frames
wrote 367211 bytes, 208896/882000 samples, 51/216 frames
wrote 373769 bytes, 212992/882000 samples, 52/216 frames
wrote 381000 bytes, 217088/882000 samples, 53/216 frames
wrote 387656 bytes, 221184/882000 samples, 54/216 frames
wrote 394393 bytes, 225280/882000 samples, 55/216 frames
wrote 401500 bytes, 229376/882000 samples, 56/216 frames
wrote 408441 bytes, 233472/882000 samples, 57/216 frames
wrote 415171 bytes, 237568/882000 samples, 58/216 frames
wrote 423435 bytes, 241664/882000 samples, 59/216 frames
wrote 432680 bytes, 245760/882000 samples, 60/216 frames
wrote 440701 bytes, 249856/882000 samples, 61/216 frames
wrote 448100 bytes, 253952/882000 samples, 62/216 frames
wrote 455401 bytes, 258048/882000 samples, 63/216 frames
wrote 462701 bytes, 262144/882000 samples, 64/216 frames
wrote 472414 bytes, 266240/882000 samples, 65/216 frames
wrote 481221 bytes, 270336/882000 samples, 66/216 frames
wrote 489509 bytes, 274432/882000 samples, 67/216 frames
wrote 497310 bytes, 278528/882000 samples, 68/216 frames
wrote 504814 bytes, 282624/882000 samples, 69/216 frames
wrote 512669 bytes, 286720/882000 samples, 70/216 frames
wrote 520577 bytes, 290816/882000 samples, 71/216 frames
wrote 528375 bytes, 294912/882000 samples, 72/216 frames
wrote 536032 bytes, 299008/882000 samples, 73/216 frames
wrote 544172 bytes, 303104/882000 samples, 74/216 frames
wrote 552246 bytes, 307200/882000 samples, 75/216 frames
wrote 559632 bytes, 311296/882000 samples, 76/216 frames
wrote 566922 bytes, 315392/882000 samples, 77/216 frames
wrote 574093 bytes, 319488/882000 samples, 78/216 frames
wrote 580970 bytes, 323584/882000 samples, 79/216 frames
wrote 587300 bytes, 327680/882000 samples, 80/216 frames
wrote 593719 bytes, 331776/882000 samples, 81/216 frames
wrote 600181 bytes, 335872/882000 samples, 82/216 frames
wrote 606396 bytes, 339968/882000 samples, 83/216 frames
wrote 612662 bytes, 344064/882000 samples, 84/216 frames
wrote 618967 bytes, 348160/882000 samples, 85/216 frames
wrote 625201 bytes, 352256/882000 samples, 86/216 frames
wrote 631440 bytes, 356352/882000 samples, 87/216 frames
wrote 637761 bytes, 360448/882000 samples, 88/216 frames
wrote 643816 bytes, 364544/882000 samples, 89/216 frames
wrote 650384 bytes, 368640/882000 samples, 90/216 frames
wrote 656575 bytes, 372736/882000 samples, 91/216 frames
wrote 662745 bytes, 376832/882000 samples, 92/216 frames
wrote 669712 bytes, 380928/882000 samples, 93/216 frames
wrote 675969 bytes, 385024/882000 samples, 94/216 frames
wrote 682037 bytes, 389120/882000 samples, 95/216 frames
wrote 688092 bytes, 393216/882000 samples, 96/216 frames
wrote 694048 bytes, 397312/882000 samples, 97/216 frames
wrote 700636 bytes, 401408/882000 samples, 98/216 frames
wrote 706679 bytes, 405504/882000 samples, 99/216 frames
wrote 712382 bytes, 409600/882000 samples, 100/216 frames
wrote 717892 bytes, 413696/882000 samples, 101/216 frames
wrote 723301 bytes, 417792/882000 samples, 102/216 frames
wrote 728847 bytes, 421888/882000 samples, 103/216 frames
wrote 734156 bytes, 425984/882000 samples, 104/216 frames
wrote 739274 bytes, 430080/882000 samples, 105/216 frames
wrote 746880 bytes, 434176/882000 samples, 106/216 frames
wrote 756767 bytes, 438272/882000 samples, 107/216 frames
wrote 766891 bytes, 442368/882000 samples, 108/216 frames
wrote 775996 bytes, 446464/882000 samples, 109/216 frames
wrote 784668 bytes, 450560/882000 samples, 110/216 frames
wrote 792922 bytes, 454656/882000 samples, 111/216 frames
wrote 801492 bytes, 458752/882000 samples, 112/216 frames
wrote 809356 bytes, 462848/882000 samples, 113/216 frames
wrote 816866 bytes, 466944/882000 samples, 114/216 frames
wrote 824192 bytes, 471040/882000 samples, 115/216 frames
wrote 831114 bytes, 475136/882000 samples, 116/216 frames
wrote 837942 bytes, 479232/882000 samples, 117/216 frames
wrote 844678 bytes, 483328/882000 samples, 118/216 frames
wrote 852778 bytes, 487424/882000 samples, 119/216 frames
wrote 861523 bytes, 491520/882000 samples, 120/216 frames
wrote 870124 bytes, 495616/882000 samples, 121/216 frames
wrote 877961 bytes, 499712/882000 samples, 122/216 frames
wrote 885433 bytes, 503808/882000 samples, 123/216 frames
wrote 892823 bytes, 507904/882000 samples, 124/216 frames
wrote 900258 bytes, 512000/882000 samples, 125/216 frames
wrote 908603 bytes, 516096/882000 samples, 126/216 frames
wrote 918817 bytes, 520192/882000 samples, 127/216 frames
wrote 928288 bytes, 524288/882000 samples, 128/216 frames
wrote 937156 bytes, 528384/882000 samples, 129/216 frames
wrote 945565 bytes, 532480/882000 samples, 130/216 frames
wrote 953499 bytes, 536576/882000 samples, 131/216 frames
wrote 960935 bytes, 540672/882000 samples, 132/216 frames
wrote 968090 bytes, 544768/882000 samples, 133/216 frames
wrote 975740 bytes, 548864/882000 samples, 134/216 frames
wrote 985130 bytes, 552960/882000 samples, 135/216 frames
wrote 993246 bytes, 557056/882000 samples, 136/216 frames
wrote 1001069 bytes, 561152/882000 samples, 137/216 frames
wrote 1008631 bytes, 565248/882000 samples, 138/216 frames
wrote 1016261 bytes, 569344/882000 samples, 139/216 frames
wrote 1024244 bytes, 573440/882000 samples, 140/216 frames
wrote 1032388 bytes, 577536/882000 samples, 141/216 frames
wrote 1039786 bytes, 581632/882000 samples, 142/216 frames
wrote 1047190 bytes, 585728/882000 samples, 143/216 frames
wrote 1055030 bytes, 589824/882000 samples, 144/216 frames
wrote 1062862 bytes, 593920/882000 samples, 145/216 frames
wrote 1070573 bytes, 598016/882000 samples, 146/216 frames
wrote 1078334 bytes, 602112/882000 samples, 147/216 frames
wrote 1085813 bytes, 606208/882000 samples, 148/216 frames
wrote 1093283 bytes, 610304/882000 samples, 149/216 frames
wrote 1100145 bytes, 614400/882000 samples, 150/216 frames
wrote 1108373 bytes, 618496/882000 samples, 151/216 frames
wrote 1116195 bytes, 622592/882000 samples, 152/216 frames
wrote 1123450 bytes, 626688/882000 samples, 153/216 frames
wrote 1130454 bytes, 630784/882000 samples, 154/216 frames
wrote 1137457 bytes, 634880/882000 samples, 155/216 frames
wrote 1144441 bytes, 638976/882000 samples, 156/216 frames
wrote 1151327 bytes, 643072/882000 samples, 157/216 frames
wrote 1157846 bytes, 647168/882000 samples, 158/216 frames
wrote 1164613 bytes, 651264/882000 samples, 159/216 frames
wrote 1171889 bytes, 655360/882000 samples, 160/216 frames
wrote 1179003 bytes, 659456/882000 samples, 161/216 frames
wrote 1186194 bytes, 663552/882000 samples, 162/216 frames
wrote 1192913 bytes, 667648/882000 samples, 163/216 frames
wrote 1199511 bytes, 671744/882000 samples, 164/216 frames
wrote 1206029 bytes, 675840/882000 samples, 165/216 frames
wrote 1212386 bytes, 679936/882000 samples, 166/216 frames
wrote 1218772 bytes, 684032/882000 samples, 167/216 frames
wrote 1225041 bytes, 688128/882000 samples, 168/216 frames
wrote 1231422 bytes, 692224/882000 samples, 169/216 frames
wrote 1237651 bytes, 696320/882000 samples, 170/216 frames
wrote 1245053 bytes, 700416/882000 samples, 171/216 frames
wrote 1254712 bytes, 704512/882000 samples, 172/216 frames
wrote 1263045 bytes, 708608/882000 samples, 173/216 frames
wrote 1273075 bytes, 712704/882000 samples, 174/216 frames
wrote 1282054 bytes, 716800/882000 samples, 175/216 frames
wrote 1291524 bytes, 720896/882000 samples, 176/216 frames
wrote 1302024 bytes, 724992/882000 samples, 177/216 frames
wrote 1311828 bytes, 729088/882000 samples, 178/216 frames
wrote 1321254 bytes, 733184/882000 samples, 179/216 frames
wrote 1330171 bytes, 737280/882000 samples, 180/216 frames
wrote 1338987 bytes, 741376/882000 samples, 181/216 frames
wrote 1348433 bytes, 745472/882000 samples, 182/216 frames
wrote 1358436 bytes, 749568/882000 samples, 183/216 frames
wrote 1367462 bytes, 753664/882000 samples, 184/216 frames
wrote 1375580 bytes, 757760/882000 samples, 185/216 frames
wrote 1383306 bytes, 761856/882000 samples, 186/216 frames
wrote 1390483 bytes, 765952/882000 samples, 187/216 frames
wrote 1397478 bytes, 770048/882000 samples, 188/216 frames
wrote 1404200 bytes, 774144/882000 samples, 189/216 frames
wrote 1410618 bytes, 778240/882000 samples, 190/216 frames
wrote 1416946 bytes, 782336/882000 samples, 191/216 frames
wrote 1423099 bytes, 786432/882000 samples, 192/216 frames
wrote 1431069 bytes, 790528/882000 samples, 193/216 frames
wrote 1439434 bytes, 794624/882000 samples, 194/216 frames
wrote 1447284 bytes, 798720/882000 samples, 195/216 frames
wrote 1455480 bytes, 802816/882000 samples, 196/216 frames
wrote 1465232 bytes, 806912/882000 samples, 197/216 frames
wrote 1476564 bytes, 811008/882000 samples, 198/216 frames
wrote 1486541 bytes, 815104/882000 samples, 199/216 frames
wrote 1495732 bytes, 819200/882000 samples, 200/216 frames
wrote 1504701 bytes, 823296/882000 samples, 201/216 frames
wrote 1513423 bytes, 827392/882000 samples, 202/216 frames
wrote 1522877 bytes, 831488/882000 samples, 203/216 frames
wrote 1532922 bytes, 835584/882000 samples, 204/216 frames
wrote 1541847 bytes, 839680/882000 samples, 205/216 frames
wrote 1550105 bytes, 843776/882000 samples, 206/216 frames
wrote 1557923 bytes, 847872/882000 samples, 207/216 frames
wrote 1565203 bytes, 851968/882000 samples, 208/216 frames
wrote 1572329 bytes, 856064/882000 samples, 209/216 frames
wrote 1579009 bytes, 860160/882000 samples, 210/216 frames
wrote 1585557 bytes, 864256/882000 samples, 211/216 frames
wrote 1592689 bytes, 868352/882000 samples, 212/216 frames
wrote 1601002 bytes, 872448/882000 samples, 213/216 frames
wrote 1610714 bytes, 876544/882000 samples, 214/216 frames
wrote 1618694 bytes, 880640/882000 samples, 215/216 frames
   state: FLAC__STREAM_ENCODER_OK
wrote 1621374 bytes, 882000/882000 samples, 216/216 frames
encoding: succeeded
   state: FLAC__STREAM_ENCODER_UNINITIALIZED
./audio/test_44100_16_2.pcm -> out2.flac: Success!
解码
$ ls -l audio/
total 6088
-rw-rw-r-- 1 lin lin  437838 6月  11 21:10 out1.flac
-rw-rw-r-- 1 lin lin 1621374 6月  11 21:10 out2.flac
-rw-rw-r-- 1 lin lin  640000 6月  11 16:27 test_16000_16_1.pcm
-rw-rw-r-- 1 lin lin 3528000 6月  11 20:23 test_44100_16_2.pcm
$ 
$ ./flac2pcm ./audio/out1.flac out_16000_16_1.pcm
sample rate    : 16000 Hz
channels       : 1
bits per sample: 16
total samples  : 320000
decoding: succeeded
   state: FLAC__STREAM_DECODER_END_OF_STREAM
$ 
$ ./flac2pcm ./audio/out2.flac out_44100_16_2.pcm
sample rate    : 44100 Hz
channels       : 2
bits per sample: 16
total samples  : 882000
decoding: succeeded
   state: FLAC__STREAM_DECODER_END_OF_STREAM
e. demo目录架构
$ tree
.
├── audio
│   ├── out1.flac
│   ├── out2.flac
│   ├── test_16000_16_1.pcm
│   └── test_44100_16_2.pcm
├── docs
│   ├── FLAC文件格式详解-优快云博客.mhtml
│   └── FLAC 格式详解 - 刘文涛 - 博客园.pdf
├── include
│   ├── FLAC
│   │   ├── all.h
│   │   ├── assert.h
│   │   ├── callback.h
│   │   ├── export.h
│   │   ├── format.h
│   │   ├── metadata.h
│   │   ├── ordinals.h
│   │   ├── stream_decoder.h
│   │   └── stream_encoder.h
│   └── FLAC++
│       ├── all.h
│       ├── decoder.h
│       ├── encoder.h
│       ├── export.h
│       └── metadata.h
├── libs
│   ├── libFLAC.a
│   └── libFLAC++.a
├── main_flac2pcm.c
├── main_pcm2flac.c
├── Makefile
├── opensource
│   └── flac-1.4.3.tar.gz
└── README.md

2、主要代码片段

main_pcm2flac.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include "FLAC/ordinals.h"
#include "FLAC/stream_encoder.h"
#include "FLAC/metadata.h"

#define READSIZE 1024

#ifndef PRIu64
#define PRIu64 "lu"
#endif

static int total_samples = 0;

void progress_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data);


int main(int argc, char *argv[])
{
    /* 输入PCM文件相关信息 */
    char *in_pcm_file_name = NULL;
    FILE *fpPcm = NULL;
    int sample_rate = 0;
    int bits_per_sample = 0;
    int channels = 0;
    unsigned char *buffer = NULL; // fixbug: 这里需要用 unsigned char 类型或者 FLAC__uint8 ,否则音频有问题
    /* 输出FLAC文件相关信息 */
    char *out_flac_file_name = NULL;
    FLAC__bool ok = true;
    FLAC__StreamEncoder *encoder = NULL;
	FLAC__StreamEncoderInitStatus init_status;
	FLAC__StreamMetadata *metadata[2];
	FLAC__StreamMetadata_VorbisComment_Entry entry;
    //static FLAC__int32 pcm[READSIZE/*samples*/ * 2/*channels*/];
    int32_t *pcm = NULL; // 这里可以用 uint32_t 或者 FLAC__int32

    /* 检查参数 */
    if(argc != 6)
    {
        printf("Usage: \n"
                "\t %s <in-pcm-file> <sample-rate> <bits per sample> <channels> <out-flac-file>\n"
                "Examples: \n"
                "\t %s ./audio/test_16000_16_1.pcm 16000 16 1 out1.flac\n"
                "\t %s ./audio/test_44100_16_2.pcm 44100 16 2 out2.flac\n"
                , argv[0], argv[0], argv[0]);
        return -1;
    }
    in_pcm_file_name = argv[1];
    sample_rate = atoi(argv[2]);
    bits_per_sample = atoi(argv[3]);
    channels = atoi(argv[4]);
    out_flac_file_name = argv[5];
    /* calc audio sample cnt */
    int filesize = 0;
    struct stat statbuff;
    int ret = stat((const char *)in_pcm_file_name, &statbuff);
    if(ret == 0)
    {
        filesize = statbuff.st_size;
    }
    else
    {
        fprintf(stderr, "stat file error(%s).\n", in_pcm_file_name);
        return -1;
    }
    total_samples = filesize/(bits_per_sample/8)/channels; // 同一时间多个通道算一个采样点
    printf("It will encode a PCM file as [file size: %d] [total samples: %d] [sample rate: %d] - [bits per sample: %d] - [channels: %d] !\n", 
            filesize, total_samples, sample_rate, bits_per_sample, channels);
    buffer = (unsigned char *)calloc(READSIZE*(bits_per_sample/8)*channels, 1);
    pcm = (int32_t *)calloc(READSIZE*channels*sizeof(int32_t), 1);

    /* 打开pcm文件 */
    fpPcm = fopen(in_pcm_file_name, "rb");
    if(fpPcm == NULL)
    {
        perror("open pcm file failed!");
        return -1;
    }

	/* allocate the encoder */
    if((encoder = FLAC__stream_encoder_new()) == NULL) {
        fprintf(stderr, "ERROR: allocating encoder\n");
        fclose(fpPcm);
        return 1;
    }

    ok &= FLAC__stream_encoder_set_verify(encoder, true);
    ok &= FLAC__stream_encoder_set_compression_level(encoder, 5);
    ok &= FLAC__stream_encoder_set_channels(encoder, channels);
    ok &= FLAC__stream_encoder_set_bits_per_sample(encoder, bits_per_sample);
    ok &= FLAC__stream_encoder_set_sample_rate(encoder, sample_rate);
    ok &= FLAC__stream_encoder_set_total_samples_estimate(encoder, total_samples);

    /* now add some metadata; we'll add some tags and a padding block */
	if(ok) {
        if((metadata[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) == NULL ||
           (metadata[1] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == NULL ||
            /* there are many tag (vorbiscomment) functions but these are convenient for this particular use: */
            !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "ARTIST", "Some Artist") ||
            !FLAC__metadata_object_vorbiscomment_append_comment(metadata[0], entry, /*copy=*/false) || /* copy=false: let metadata object take control of entry's allocated string */
            !FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "YEAR", "2024") ||
            !FLAC__metadata_object_vorbiscomment_append_comment(metadata[0], entry, /*copy=*/false))
        {
            fprintf(stderr, "ERROR: out of memory or tag error\n");
            ok = false;
		}
        else
        {
			metadata[1]->length = 1234; /* set the padding length */
			ok = FLAC__stream_encoder_set_metadata(encoder, metadata, 2);
        }
	}

    /* initialize encoder */
    if(ok) {
        init_status = FLAC__stream_encoder_init_file(encoder, out_flac_file_name, progress_callback, /*client_data=*/NULL);
        if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
            fprintf(stderr, "ERROR: initializing encoder: %s\n", FLAC__StreamEncoderInitStatusString[init_status]);
            ok = false;
        }
    }

    if(ok) {
        size_t left = (size_t)total_samples;
        while(ok && left) {
            size_t need = (left>READSIZE? (size_t)READSIZE : (size_t)left);
            if(fread(buffer, channels*(bits_per_sample/8), need, fpPcm) != need) {
                fprintf(stderr, "ERROR: reading from PCM file\n");
                ok = false;
            }
            else {
                /* convert the packed little-endian 16-bit PCM samples into an interleaved FLAC__int32 buffer for libFLAC */
                size_t i;
                for(i = 0; i < need*channels; i++) {
                    /* inefficient but simple and works on big- or little-endian machines */
                    pcm[i] = (FLAC__int32)(((FLAC__int16)(FLAC__int8)buffer[2*i+1] << 8) | (FLAC__int16)buffer[2*i]);
                }
                /* feed samples to encoder */
                ok = FLAC__stream_encoder_process_interleaved(encoder, pcm, need);
            }
            left -= need;
        }
    }

    fprintf(stderr, "   state: %s\n", FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder)]);
    ok &= FLAC__stream_encoder_finish(encoder);

    fprintf(stderr, "encoding: %s\n", ok? "succeeded" : "FAILED");
    fprintf(stderr, "   state: %s\n", FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder)]);

    /* now that encoding is finished, the metadata can be freed */
    FLAC__metadata_object_delete(metadata[0]);
    FLAC__metadata_object_delete(metadata[1]);
    FLAC__stream_encoder_delete(encoder);

    /* 关闭文件 */
    fclose(fpPcm);
    if(buffer)
        free(buffer);
    if(pcm)
        free(pcm);

    printf("%s -> %s: Success!\n", in_pcm_file_name, out_flac_file_name);

    return 0;
}


void progress_callback(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
{
	(void)encoder, (void)client_data;

	fprintf(stdout, "wrote %" PRIu64 " bytes, %" PRIu64 "/%u samples, %u/%u frames\n", bytes_written, samples_written, total_samples, frames_written, total_frames_estimate);
}

main_flac2pcm.c
#include <stdio.h>
#include <stdlib.h>

#include "FLAC/ordinals.h"
#include "FLAC/stream_decoder.h"
#include "FLAC/metadata.h"

#ifndef PRIu64
#define PRIu64 "lu"
#endif

static FLAC__uint64 total_samples = 0;
static unsigned sample_rate = 0;
static unsigned channels = 0;
static unsigned bps = 0;

void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);


int main(int argc, char *argv[])
{
    /* 输入FLAC文件相关信息 */
    char *in_flac_file_name = NULL;
    FLAC__bool ok = true;
    FLAC__StreamDecoder *decoder = NULL;
    FLAC__StreamDecoderInitStatus init_status = 0;
    /* 输出PCM文件相关信息 */
    char *out_pcm_file_name = NULL;
    FILE *fp_out_pcm = NULL;

    /* 检查参数 */
    if(argc != 3)
    {
        printf("Usage: \n"
                "\t %s <in-flac-file> <out-pcm-file>\n"
                "Examples: \n"
                "\t %s ./audio/out1.flac out_16000_16_1.pcm\n"
                "\t %s ./audio/out2.flac out_44100_16_2.pcm\n"
                , argv[0], argv[0], argv[0]);
        return -1;
    }
    in_flac_file_name = argv[1];
    out_pcm_file_name = argv[2];

    if((fp_out_pcm = fopen(out_pcm_file_name, "wb")) == NULL) {
        fprintf(stderr, "ERROR: opening %s for output\n", out_pcm_file_name);
        return 1;
    }

    if((decoder = FLAC__stream_decoder_new()) == NULL) {
        fprintf(stderr, "ERROR: allocating decoder\n");
        fclose(fp_out_pcm);
        return 1;
    }

    (void)FLAC__stream_decoder_set_md5_checking(decoder, true);

    init_status = FLAC__stream_decoder_init_file(decoder, in_flac_file_name, write_callback, metadata_callback, error_callback, /*client_data=*/fp_out_pcm);
    if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
        fprintf(stderr, "ERROR: initializing decoder: %s\n", FLAC__StreamDecoderInitStatusString[init_status]);
        ok = false;
    }

    if(ok) {
        ok = FLAC__stream_decoder_process_until_end_of_stream(decoder);
        fprintf(stderr, "decoding: %s\n", ok? "succeeded" : "FAILED");
        fprintf(stderr, "   state: %s\n", FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(decoder)]);
    }

    FLAC__stream_decoder_delete(decoder);
    fclose(fp_out_pcm);

    return 0;
}


static FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 x)
{
    return
        fputc(x, f) != EOF &&
        fputc(x >> 8, f) != EOF
    ;
}
static FLAC__bool write_little_endian_int16(FILE *f, FLAC__int16 x)
{
    return write_little_endian_uint16(f, (FLAC__uint16)x);
}



void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
{
    (void)decoder, (void)client_data;

    /* print some stats */
    if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
        /* save for later */
        total_samples = metadata->data.stream_info.total_samples;
        sample_rate = metadata->data.stream_info.sample_rate;
        channels = metadata->data.stream_info.channels;
        bps = metadata->data.stream_info.bits_per_sample;

        fprintf(stderr, "sample rate    : %u Hz\n", sample_rate);
        fprintf(stderr, "channels       : %u\n", channels);
        fprintf(stderr, "bits per sample: %u\n", bps);
        fprintf(stderr, "total samples  : %" PRIu64 "\n", total_samples);
    }
}

FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
{
    (void)decoder;

    FILE *fp_out_pcm = (FILE*)client_data;

    if(total_samples == 0) {
        fprintf(stderr, "ERROR: this example only works for FLAC files that have a total_samples count in STREAMINFO\n");
        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
    }
    if(bps != 16) {
        fprintf(stderr, "ERROR: this example only supports 16bit streams\n");
        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
    }
    if(frame->header.channels == 1 && buffer [0] == NULL) {
        fprintf(stderr, "ERROR: buffer [0] is NULL\n");
        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
    }
    if(frame->header.channels == 2 && buffer [1] == NULL) {
        fprintf(stderr, "ERROR: buffer [1] is NULL\n");
        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
    }

    /* write decoded PCM samples */
    for(int i = 0; i < frame->header.blocksize; i++)
    {
        for(int channel_index = 0; channel_index < frame->header.channels; channel_index++)
        {
            if(!write_little_endian_int16(fp_out_pcm, (FLAC__int16)buffer[channel_index][i]))
            {
                fprintf(stderr, "ERROR: write channel(%d) error\n", channel_index);
                return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
            }
        }
    }

    return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}

void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
{
    (void)decoder, (void)client_data;

    fprintf(stderr, "Got error callback: %s\n", FLAC__StreamDecoderErrorStatusString[status]);
}

3、demo下载地址(任选一个)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

R-QWERT

你的鼓励是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值