- UID
- 1
- 精华
- 积分
- 76361
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
1、什么是libFLAC?
libFLAC是用于操作FLAC文件的C开源工具。
libFLAC的官网:https://xiph.org/flac/
2、什么是FLAC?
FLAC是一种针对声音文件的无损压缩算法。压缩比略低于AAC,但是压缩和解压的速度很理想。使用FLAC压缩的无损音乐,体积将比没有经过压缩的无损音乐小很多(取决于音乐的平均音量。通常体积能减少到原文件的50%左右)。
相比较MP3有损压缩格式而言,FLAC能保留100%的音质。对于广大音乐爱好者而言,相对于MP3,FLAC是更好的选择。
libFLAC的源码请大家到libFLAC的官网下载。点此进入官方下载页面。
我这里有备用的下载地址。如果大家无法到官网下载libFLAC的源码,大家可以来我这里下载1.3.0版。强烈建议大家去官网下载最新版。
flac-1.3.0.tar.xz
(1.03 MB, 下载次数: 29)
首先我们下载libFLAC的源码。然后用VS打开它的FLAC.sln这个文件。我用的是VS2012,因此出现了提示升级工程的对话框。我就将工程文件升级为VS2012的版本了。
看左边有很多工程。其中需要留意的是这几个工程:
C语言工程:
libFLAC_dynamic:编译它你能得到libFLAC.dll。这个DLL导出的函数可以帮你完成对FLAC文件的编码和解码的操作。
libFLAC_static:编译它,你能得到libFLAC.lib。当你既想操作FLAC文件,又不想让自己的程序依赖libFLAC.dll的时候,你可以使用它。
C++工程:
libFLAC++_dynamic:C++版的libFLAC.dll。功能和C语言版的一样,但是它是C++风格的,适合C++使用。
libFLAC++_static:C++版的libFLAC.lib。
这些是libFLAC的核心部分。当你展开它你会发现以下的文件:
这些文件是用NASM语法编写的汇编代码,用NASM编译,然后和C语言程序配合进行FLAC的编码和解码的。注意这是PC平台上的x86汇编。32位的。
我编译这个工程的时候NASM产生了“nasm.h:83: warning: COFF section names limited to 8 characters: truncating”这样的警告。意思是nasm.h第83行给段起名的时候超过了8个字符的长度,超出部分被截去。
这样的警告一般不会导致什么严重的错误,除非你为了编这个程序定义了各种奇怪的段,然后一不小心就冲突了。而这样的错误一般会被链接器发现,从而提示你进行修正。所以目前可以无视。
libFLAC的源码出现了NASM汇编代码,而且在很多地方出现了_asm内联汇编的语句,看似影响了移植性,其实这只是libFLAC用于优化代码运行效率的手段。
我们只需把C语言的预定义部分加上FLAC__NO_ASM,就能使其把原本用_asm内联汇编语句实现的部分用C代替了,从而保证了移植性。
本来libFLAC的源码里面附带的工程文件的配置是只有Win32平台编译的配置的。经过我的一系列处理(去掉NASM的部分使其不参与编译,然后通过调整预处理来使其不使用内联汇编)之后我编译出了64位的libFLAC.lib(静态链接库)。大家可以在这里下载。
x86:
libFLAC_static_1_3_0_x86.7z
(176.17 KB, 下载次数: 12, 售价: 1 个宅币)
x64:
libFLAC_static_1_3_0_x64.7z
(194.76 KB, 下载次数: 6, 售价: 2 个宅币)
要使用libFLAC进行C语言编程进行FLAC文件编码和解码,我们首先需要两样东西:编译时用到的头文件(.H)和链接时用到的库文件(.LIB,无论是动态DLL还是静态LIB)。
库文件请下载上面的。头文件,则在你刚下载的libFLAC的源码的include文件夹的FLAC文件夹内。
为了便于大家学习,我将头文件打包上传了。点此下载->
FLAC.7z
(43.25 KB, 下载次数: 14)
头文件都是放在FLAC文件夹里面的。首先你把FLAC文件夹拷到你的工程文件夹。然后配置好你的工程,让它链接你的库文件。键人在此就不赘述了。
0x1:解码程序怎么写?
首先你需要包含一个头文件:#include"FLAC/stream_decoder.h"
FLAC的使用是围绕一个结构体进行的:FLAC__StreamDecoder *pDecoder;//FLAC解码器对象
FLAC是面向对象编程的思路。FLAC__StreamDecoder就是它所指的对象。首先我们需要调用FLAC__stream_decoder_new()来取得这个对象。
pDecoder=FLAC__stream_decoder_new();
if(!pDecoder)
{
fprintf(stderr,"初始化FLAC解码器失败!\n");
return;
}
取得的pDecoder就是我们所说的FLAC解码器对象了。切记在用完了pDecoder之后要记得把它删掉,否则就会占用内存。调用FLAC__stream_decoder_delete(pDecoder);就可以把它占用的部分删掉了。
然后就是它的初始化工作了。有以下几种初始化的函数可供选择:
FLAC__stream_decoder_init_stream:由用户自行将FLAC文件的内容输入,然后取得解码得到的波形数据。
FLAC__stream_decoder_init_ogg_stream:由用户自行将ogg FLAC文件的内容输入,然后取得解码得到的波形数据。
FLAC__stream_decoder_init_FILE:用户提供打开了FLAC文件的FILE*,然后FLAC解码器会自动从文件流读入数据,再解码。
FLAC__stream_decoder_init_ogg_FILE:用户提供打开了ogg FLAC文件的FILE*,然后FLAC解码器会自动从文件流读入数据,再解码。
FLAC__stream_decoder_init_file:用户只需提供FLAC文件的路径,FLAC解码器自动打开文件进行解码。
FLAC__stream_decoder_init_ogg_file:用户只需提供ogg FLAC文件的路径,FLAC解码器自动打开文件进行解码。
(PS.什么是ogg FLAC?)
这些函数都是以回调函数的方式运作的。用户只需提供回调函数,然后让它解码,最后等它调用你的回调函数就能取得解码的数据了。
我这里把这几个函数的原型贴出来。- /** Initialize the decoder instance to decode native FLAC streams.
- *
- * This flavor of initialization sets up the decoder to decode from a
- * native FLAC stream. I/O is performed via callbacks to the client.
- * For decoding from a plain file via filename or open FILE*,
- * FLAC__stream_decoder_init_file() and FLAC__stream_decoder_init_FILE()
- * provide a simpler interface.
- *
- * This function should be called after FLAC__stream_decoder_new() and
- * FLAC__stream_decoder_set_*() but before any of the
- * FLAC__stream_decoder_process_*() functions. Will set and return the
- * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA
- * if initialization succeeded.
- *
- * \param decoder An uninitialized decoder instance.
- * \param read_callback See FLAC__StreamDecoderReadCallback. This
- * pointer must not be \c NULL.
- * \param seek_callback See FLAC__StreamDecoderSeekCallback. This
- * pointer may be \c NULL if seeking is not
- * supported. If \a seek_callback is not \c NULL then a
- * \a tell_callback, \a length_callback, and \a eof_callback must also be supplied.
- * Alternatively, a dummy seek callback that just
- * returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED
- * may also be supplied, all though this is slightly
- * less efficient for the decoder.
- * \param tell_callback See FLAC__StreamDecoderTellCallback. This
- * pointer may be \c NULL if not supported by the client. If
- * \a seek_callback is not \c NULL then a
- * \a tell_callback must also be supplied.
- * Alternatively, a dummy tell callback that just
- * returns \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED
- * may also be supplied, all though this is slightly
- * less efficient for the decoder.
- * \param length_callback See FLAC__StreamDecoderLengthCallback. This
- * pointer may be \c NULL if not supported by the client. If
- * \a seek_callback is not \c NULL then a
- * \a length_callback must also be supplied.
- * Alternatively, a dummy length callback that just
- * returns \c FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED
- * may also be supplied, all though this is slightly
- * less efficient for the decoder.
- * \param eof_callback See FLAC__StreamDecoderEofCallback. This
- * pointer may be \c NULL if not supported by the client. If
- * \a seek_callback is not \c NULL then a
- * \a eof_callback must also be supplied.
- * Alternatively, a dummy length callback that just
- * returns \c false
- * may also be supplied, all though this is slightly
- * less efficient for the decoder.
- * \param write_callback See FLAC__StreamDecoderWriteCallback. This
- * pointer must not be \c NULL.
- * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This
- * pointer may be \c NULL if the callback is not
- * desired.
- * \param error_callback See FLAC__StreamDecoderErrorCallback. This
- * pointer must not be \c NULL.
- * \param client_data This value will be supplied to callbacks in their
- * \a client_data argument.
- * \assert
- * \code decoder != NULL \endcode
- * \retval FLAC__StreamDecoderInitStatus
- * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful;
- * see FLAC__StreamDecoderInitStatus for the meanings of other return values.
- */
- FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream(
- FLAC__StreamDecoder *decoder,
- FLAC__StreamDecoderReadCallback read_callback,
- FLAC__StreamDecoderSeekCallback seek_callback,
- FLAC__StreamDecoderTellCallback tell_callback,
- FLAC__StreamDecoderLengthCallback length_callback,
- FLAC__StreamDecoderEofCallback eof_callback,
- FLAC__StreamDecoderWriteCallback write_callback,
- FLAC__StreamDecoderMetadataCallback metadata_callback,
- FLAC__StreamDecoderErrorCallback error_callback,
- void *client_data
- );
- /** Initialize the decoder instance to decode Ogg FLAC streams.
- *
- * This flavor of initialization sets up the decoder to decode from a
- * FLAC stream in an Ogg container. I/O is performed via callbacks to the
- * client. For decoding from a plain file via filename or open FILE*,
- * FLAC__stream_decoder_init_ogg_file() and FLAC__stream_decoder_init_ogg_FILE()
- * provide a simpler interface.
- *
- * This function should be called after FLAC__stream_decoder_new() and
- * FLAC__stream_decoder_set_*() but before any of the
- * FLAC__stream_decoder_process_*() functions. Will set and return the
- * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA
- * if initialization succeeded.
- *
- * \note Support for Ogg FLAC in the library is optional. If this
- * library has been built without support for Ogg FLAC, this function
- * will return \c FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER.
- *
- * \param decoder An uninitialized decoder instance.
- * \param read_callback See FLAC__StreamDecoderReadCallback. This
- * pointer must not be \c NULL.
- * \param seek_callback See FLAC__StreamDecoderSeekCallback. This
- * pointer may be \c NULL if seeking is not
- * supported. If \a seek_callback is not \c NULL then a
- * \a tell_callback, \a length_callback, and \a eof_callback must also be supplied.
- * Alternatively, a dummy seek callback that just
- * returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED
- * may also be supplied, all though this is slightly
- * less efficient for the decoder.
- * \param tell_callback See FLAC__StreamDecoderTellCallback. This
- * pointer may be \c NULL if not supported by the client. If
- * \a seek_callback is not \c NULL then a
- * \a tell_callback must also be supplied.
- * Alternatively, a dummy tell callback that just
- * returns \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED
- * may also be supplied, all though this is slightly
- * less efficient for the decoder.
- * \param length_callback See FLAC__StreamDecoderLengthCallback. This
- * pointer may be \c NULL if not supported by the client. If
- * \a seek_callback is not \c NULL then a
- * \a length_callback must also be supplied.
- * Alternatively, a dummy length callback that just
- * returns \c FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED
- * may also be supplied, all though this is slightly
- * less efficient for the decoder.
- * \param eof_callback See FLAC__StreamDecoderEofCallback. This
- * pointer may be \c NULL if not supported by the client. If
- * \a seek_callback is not \c NULL then a
- * \a eof_callback must also be supplied.
- * Alternatively, a dummy length callback that just
- * returns \c false
- * may also be supplied, all though this is slightly
- * less efficient for the decoder.
- * \param write_callback See FLAC__StreamDecoderWriteCallback. This
- * pointer must not be \c NULL.
- * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This
- * pointer may be \c NULL if the callback is not
- * desired.
- * \param error_callback See FLAC__StreamDecoderErrorCallback. This
- * pointer must not be \c NULL.
- * \param client_data This value will be supplied to callbacks in their
- * \a client_data argument.
- * \assert
- * \code decoder != NULL \endcode
- * \retval FLAC__StreamDecoderInitStatus
- * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful;
- * see FLAC__StreamDecoderInitStatus for the meanings of other return values.
- */
- FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_stream(
- FLAC__StreamDecoder *decoder,
- FLAC__StreamDecoderReadCallback read_callback,
- FLAC__StreamDecoderSeekCallback seek_callback,
- FLAC__StreamDecoderTellCallback tell_callback,
- FLAC__StreamDecoderLengthCallback length_callback,
- FLAC__StreamDecoderEofCallback eof_callback,
- FLAC__StreamDecoderWriteCallback write_callback,
- FLAC__StreamDecoderMetadataCallback metadata_callback,
- FLAC__StreamDecoderErrorCallback error_callback,
- void *client_data
- );
- /** Initialize the decoder instance to decode native FLAC files.
- *
- * This flavor of initialization sets up the decoder to decode from a
- * plain native FLAC file. For non-stdio streams, you must use
- * FLAC__stream_decoder_init_stream() and provide callbacks for the I/O.
- *
- * This function should be called after FLAC__stream_decoder_new() and
- * FLAC__stream_decoder_set_*() but before any of the
- * FLAC__stream_decoder_process_*() functions. Will set and return the
- * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA
- * if initialization succeeded.
- *
- * \param decoder An uninitialized decoder instance.
- * \param file An open FLAC file. The file should have been
- * opened with mode \c "rb" and rewound. The file
- * becomes owned by the decoder and should not be
- * manipulated by the client while decoding.
- * Unless \a file is \c stdin, it will be closed
- * when FLAC__stream_decoder_finish() is called.
- * Note however that seeking will not work when
- * decoding from \c stdout since it is not seekable.
- * \param write_callback See FLAC__StreamDecoderWriteCallback. This
- * pointer must not be \c NULL.
- * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This
- * pointer may be \c NULL if the callback is not
- * desired.
- * \param error_callback See FLAC__StreamDecoderErrorCallback. This
- * pointer must not be \c NULL.
- * \param client_data This value will be supplied to callbacks in their
- * \a client_data argument.
- * \assert
- * \code decoder != NULL \endcode
- * \code file != NULL \endcode
- * \retval FLAC__StreamDecoderInitStatus
- * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful;
- * see FLAC__StreamDecoderInitStatus for the meanings of other return values.
- */
- FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE(
- FLAC__StreamDecoder *decoder,
- FILE *file,
- FLAC__StreamDecoderWriteCallback write_callback,
- FLAC__StreamDecoderMetadataCallback metadata_callback,
- FLAC__StreamDecoderErrorCallback error_callback,
- void *client_data
- );
- /** Initialize the decoder instance to decode Ogg FLAC files.
- *
- * This flavor of initialization sets up the decoder to decode from a
- * plain Ogg FLAC file. For non-stdio streams, you must use
- * FLAC__stream_decoder_init_ogg_stream() and provide callbacks for the I/O.
- *
- * This function should be called after FLAC__stream_decoder_new() and
- * FLAC__stream_decoder_set_*() but before any of the
- * FLAC__stream_decoder_process_*() functions. Will set and return the
- * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA
- * if initialization succeeded.
- *
- * \note Support for Ogg FLAC in the library is optional. If this
- * library has been built without support for Ogg FLAC, this function
- * will return \c FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER.
- *
- * \param decoder An uninitialized decoder instance.
- * \param file An open FLAC file. The file should have been
- * opened with mode \c "rb" and rewound. The file
- * becomes owned by the decoder and should not be
- * manipulated by the client while decoding.
- * Unless \a file is \c stdin, it will be closed
- * when FLAC__stream_decoder_finish() is called.
- * Note however that seeking will not work when
- * decoding from \c stdout since it is not seekable.
- * \param write_callback See FLAC__StreamDecoderWriteCallback. This
- * pointer must not be \c NULL.
- * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This
- * pointer may be \c NULL if the callback is not
- * desired.
- * \param error_callback See FLAC__StreamDecoderErrorCallback. This
- * pointer must not be \c NULL.
- * \param client_data This value will be supplied to callbacks in their
- * \a client_data argument.
- * \assert
- * \code decoder != NULL \endcode
- * \code file != NULL \endcode
- * \retval FLAC__StreamDecoderInitStatus
- * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful;
- * see FLAC__StreamDecoderInitStatus for the meanings of other return values.
- */
- FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_FILE(
- FLAC__StreamDecoder *decoder,
- FILE *file,
- FLAC__StreamDecoderWriteCallback write_callback,
- FLAC__StreamDecoderMetadataCallback metadata_callback,
- FLAC__StreamDecoderErrorCallback error_callback,
- void *client_data
- );
- /** Initialize the decoder instance to decode native FLAC files.
- *
- * This flavor of initialization sets up the decoder to decode from a plain
- * native FLAC file. If POSIX fopen() semantics are not sufficient, (for
- * example, with Unicode filenames on Windows), you must use
- * FLAC__stream_decoder_init_FILE(), or FLAC__stream_decoder_init_stream()
- * and provide callbacks for the I/O.
- *
- * This function should be called after FLAC__stream_decoder_new() and
- * FLAC__stream_decoder_set_*() but before any of the
- * FLAC__stream_decoder_process_*() functions. Will set and return the
- * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA
- * if initialization succeeded.
- *
- * \param decoder An uninitialized decoder instance.
- * \param filename The name of the file to decode from. The file will
- * be opened with fopen(). Use \c NULL to decode from
- * \c stdin. Note that \c stdin is not seekable.
- * \param write_callback See FLAC__StreamDecoderWriteCallback. This
- * pointer must not be \c NULL.
- * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This
- * pointer may be \c NULL if the callback is not
- * desired.
- * \param error_callback See FLAC__StreamDecoderErrorCallback. This
- * pointer must not be \c NULL.
- * \param client_data This value will be supplied to callbacks in their
- * \a client_data argument.
- * \assert
- * \code decoder != NULL \endcode
- * \retval FLAC__StreamDecoderInitStatus
- * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful;
- * see FLAC__StreamDecoderInitStatus for the meanings of other return values.
- */
- FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file(
- FLAC__StreamDecoder *decoder,
- const char *filename,
- FLAC__StreamDecoderWriteCallback write_callback,
- FLAC__StreamDecoderMetadataCallback metadata_callback,
- FLAC__StreamDecoderErrorCallback error_callback,
- void *client_data
- );
- /** Initialize the decoder instance to decode Ogg FLAC files.
- *
- * This flavor of initialization sets up the decoder to decode from a plain
- * Ogg FLAC file. If POSIX fopen() semantics are not sufficient, (for
- * example, with Unicode filenames on Windows), you must use
- * FLAC__stream_decoder_init_ogg_FILE(), or FLAC__stream_decoder_init_ogg_stream()
- * and provide callbacks for the I/O.
- *
- * This function should be called after FLAC__stream_decoder_new() and
- * FLAC__stream_decoder_set_*() but before any of the
- * FLAC__stream_decoder_process_*() functions. Will set and return the
- * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA
- * if initialization succeeded.
- *
- * \note Support for Ogg FLAC in the library is optional. If this
- * library has been built without support for Ogg FLAC, this function
- * will return \c FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER.
- *
- * \param decoder An uninitialized decoder instance.
- * \param filename The name of the file to decode from. The file will
- * be opened with fopen(). Use \c NULL to decode from
- * \c stdin. Note that \c stdin is not seekable.
- * \param write_callback See FLAC__StreamDecoderWriteCallback. This
- * pointer must not be \c NULL.
- * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This
- * pointer may be \c NULL if the callback is not
- * desired.
- * \param error_callback See FLAC__StreamDecoderErrorCallback. This
- * pointer must not be \c NULL.
- * \param client_data This value will be supplied to callbacks in their
- * \a client_data argument.
- * \assert
- * \code decoder != NULL \endcode
- * \retval FLAC__StreamDecoderInitStatus
- * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful;
- * see FLAC__StreamDecoderInitStatus for the meanings of other return values.
- */
- FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_file(
- FLAC__StreamDecoder *decoder,
- const char *filename,
- FLAC__StreamDecoderWriteCallback write_callback,
- FLAC__StreamDecoderMetadataCallback metadata_callback,
- FLAC__StreamDecoderErrorCallback error_callback,
- void *client_data
- );
复制代码 大家可以通过看注释来了解它们的使用方式。
刚才只是初始化的设定而已。设置好初始化的操作以后,你要做的就是让libFLAC帮你解码。
有以下几种方式可以启动它的解码过程:
FLAC__stream_decoder_process_single:解码一个块,得到一个块的数据。
FLAC__stream_decoder_process_until_end_of_metadata:一直解码,直到元数据(metadata)的结尾。
FLAC__stream_decoder_process_until_end_of_stream:一直解码,直到流的结尾(整个文件解码完)
当你调用上面三个函数中的一个的时候,libFLAC就会开始帮你解码,调用你提供的回调函数,把解码得到的数据提供给你。
其中可以用于辅助解码的函数如下:
FLAC__stream_decoder_skip_single_frame:跳过一个块。
FLAC__stream_decoder_seek_absolute:定位到某一个样本处。
详细的来自头文件的信息:- /** Decode one metadata block or audio frame.
- * This version instructs the decoder to decode a either a single metadata
- * block or a single frame and stop, unless the callbacks return a fatal
- * error or the read callback returns
- * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM.
- *
- * As the decoder needs more input it will call the read callback.
- * Depending on what was decoded, the metadata or write callback will be
- * called with the decoded metadata block or audio frame.
- *
- * Unless there is a fatal read error or end of stream, this function
- * will return once one whole frame is decoded. In other words, if the
- * stream is not synchronized or points to a corrupt frame header, the
- * decoder will continue to try and resync until it gets to a valid
- * frame, then decode one frame, then return. If the decoder points to
- * a frame whose frame CRC in the frame footer does not match the
- * computed frame CRC, this function will issue a
- * FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH error to the
- * error callback, and return, having decoded one complete, although
- * corrupt, frame. (Such corrupted frames are sent as silence of the
- * correct length to the write callback.)
- *
- * \param decoder An initialized decoder instance.
- * \assert
- * \code decoder != NULL \endcode
- * \retval FLAC__bool
- * \c false if any fatal read, write, or memory allocation error
- * occurred (meaning decoding must stop), else \c true; for more
- * information about the decoder, check the decoder state with
- * FLAC__stream_decoder_get_state().
- */
- FLAC_API FLAC__bool FLAC__stream_decoder_process_single(FLAC__StreamDecoder *decoder);
- /** Decode until the end of the metadata.
- * This version instructs the decoder to decode from the current position
- * and continue until all the metadata has been read, or until the
- * callbacks return a fatal error or the read callback returns
- * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM.
- *
- * As the decoder needs more input it will call the read callback.
- * As each metadata block is decoded, the metadata callback will be called
- * with the decoded metadata.
- *
- * \param decoder An initialized decoder instance.
- * \assert
- * \code decoder != NULL \endcode
- * \retval FLAC__bool
- * \c false if any fatal read, write, or memory allocation error
- * occurred (meaning decoding must stop), else \c true; for more
- * information about the decoder, check the decoder state with
- * FLAC__stream_decoder_get_state().
- */
- FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_metadata(FLAC__StreamDecoder *decoder);
- /** Decode until the end of the stream.
- * This version instructs the decoder to decode from the current position
- * and continue until the end of stream (the read callback returns
- * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM), or until the
- * callbacks return a fatal error.
- *
- * As the decoder needs more input it will call the read callback.
- * As each metadata block and frame is decoded, the metadata or write
- * callback will be called with the decoded metadata or frame.
- *
- * \param decoder An initialized decoder instance.
- * \assert
- * \code decoder != NULL \endcode
- * \retval FLAC__bool
- * \c false if any fatal read, write, or memory allocation error
- * occurred (meaning decoding must stop), else \c true; for more
- * information about the decoder, check the decoder state with
- * FLAC__stream_decoder_get_state().
- */
- FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__StreamDecoder *decoder);
- /** Skip one audio frame.
- * This version instructs the decoder to 'skip' a single frame and stop,
- * unless the callbacks return a fatal error or the read callback returns
- * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM.
- *
- * The decoding flow is the same as what occurs when
- * FLAC__stream_decoder_process_single() is called to process an audio
- * frame, except that this function does not decode the parsed data into
- * PCM or call the write callback. The integrity of the frame is still
- * checked the same way as in the other process functions.
- *
- * This function will return once one whole frame is skipped, in the
- * same way that FLAC__stream_decoder_process_single() will return once
- * one whole frame is decoded.
- *
- * This function can be used in more quickly determining FLAC frame
- * boundaries when decoding of the actual data is not needed, for
- * example when an application is separating a FLAC stream into frames
- * for editing or storing in a container. To do this, the application
- * can use FLAC__stream_decoder_skip_single_frame() to quickly advance
- * to the next frame, then use
- * FLAC__stream_decoder_get_decode_position() to find the new frame
- * boundary.
- *
- * This function should only be called when the stream has advanced
- * past all the metadata, otherwise it will return \c false.
- *
- * \param decoder An initialized decoder instance not in a metadata
- * state.
- * \assert
- * \code decoder != NULL \endcode
- * \retval FLAC__bool
- * \c false if any fatal read, write, or memory allocation error
- * occurred (meaning decoding must stop), or if the decoder
- * is in the FLAC__STREAM_DECODER_SEARCH_FOR_METADATA or
- * FLAC__STREAM_DECODER_READ_METADATA state, else \c true; for more
- * information about the decoder, check the decoder state with
- * FLAC__stream_decoder_get_state().
- */
- FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder);
- /** Flush the input and seek to an absolute sample.
- * Decoding will resume at the given sample. Note that because of
- * this, the next write callback may contain a partial block. The
- * client must support seeking the input or this function will fail
- * and return \c false. Furthermore, if the decoder state is
- * \c FLAC__STREAM_DECODER_SEEK_ERROR, then the decoder must be flushed
- * with FLAC__stream_decoder_flush() or reset with
- * FLAC__stream_decoder_reset() before decoding can continue.
- *
- * \param decoder A decoder instance.
- * \param sample The target sample number to seek to.
- * \assert
- * \code decoder != NULL \endcode
- * \retval FLAC__bool
- * \c true if successful, else \c false.
- */
- FLAC_API FLAC__bool FLAC__stream_decoder_seek_absolute(FLAC__StreamDecoder *decoder, FLAC__uint64 sample);
复制代码 回调函数的原型详见libFLAC的头文件。里面有非常详细的介绍。你只需在VS里把光标放到这些函数类型上然后按下F12就能看到所有的信息。
不过为了便于理解,我把这些回调函数的原型也复制了过来。这样大家就不用亲自去按F12看信息了。直接看我的帖子就行。- /** Signature for the read callback.
- *
- * A function pointer matching this signature must be passed to
- * FLAC__stream_decoder_init*_stream(). The supplied function will be
- * called when the decoder needs more input data. The address of the
- * buffer to be filled is supplied, along with the number of bytes the
- * buffer can hold. The callback may choose to supply less data and
- * modify the byte count but must be careful not to overflow the buffer.
- * The callback then returns a status code chosen from
- * FLAC__StreamDecoderReadStatus.
- *
- * Here is an example of a read callback for stdio streams:
- * \code
- * FLAC__StreamDecoderReadStatus read_cb(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
- * {
- * FILE *file = ((MyClientData*)client_data)->file;
- * if(*bytes > 0) {
- * *bytes = fread(buffer, sizeof(FLAC__byte), *bytes, file);
- * if(ferror(file))
- * return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
- * else if(*bytes == 0)
- * return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
- * else
- * return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
- * }
- * else
- * return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
- * }
- * \endcode
- *
- * \note In general, FLAC__StreamDecoder functions which change the
- * state should not be called on the \a decoder while in the callback.
- *
- * \param decoder The decoder instance calling the callback.
- * \param buffer A pointer to a location for the callee to store
- * data to be decoded.
- * \param bytes A pointer to the size of the buffer. On entry
- * to the callback, it contains the maximum number
- * of bytes that may be stored in \a buffer. The
- * callee must set it to the actual number of bytes
- * stored (0 in case of error or end-of-stream) before
- * returning.
- * \param client_data The callee's client data set through
- * FLAC__stream_decoder_init_*().
- * \retval FLAC__StreamDecoderReadStatus
- * The callee's return status. Note that the callback should return
- * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM if and only if
- * zero bytes were read and there is no more data to be read.
- */
- typedef FLAC__StreamDecoderReadStatus (*FLAC__StreamDecoderReadCallback)(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
- /** Signature for the seek callback.
- *
- * A function pointer matching this signature may be passed to
- * FLAC__stream_decoder_init*_stream(). The supplied function will be
- * called when the decoder needs to seek the input stream. The decoder
- * will pass the absolute byte offset to seek to, 0 meaning the
- * beginning of the stream.
- *
- * Here is an example of a seek callback for stdio streams:
- * \code
- * FLAC__StreamDecoderSeekStatus seek_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
- * {
- * FILE *file = ((MyClientData*)client_data)->file;
- * if(file == stdin)
- * return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
- * else if(fseeko(file, (off_t)absolute_byte_offset, SEEK_SET) < 0)
- * return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
- * else
- * return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
- * }
- * \endcode
- *
- * \note In general, FLAC__StreamDecoder functions which change the
- * state should not be called on the \a decoder while in the callback.
- *
- * \param decoder The decoder instance calling the callback.
- * \param absolute_byte_offset The offset from the beginning of the stream
- * to seek to.
- * \param client_data The callee's client data set through
- * FLAC__stream_decoder_init_*().
- * \retval FLAC__StreamDecoderSeekStatus
- * The callee's return status.
- */
- typedef FLAC__StreamDecoderSeekStatus (*FLAC__StreamDecoderSeekCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
- /** Signature for the tell callback.
- *
- * A function pointer matching this signature may be passed to
- * FLAC__stream_decoder_init*_stream(). The supplied function will be
- * called when the decoder wants to know the current position of the
- * stream. The callback should return the byte offset from the
- * beginning of the stream.
- *
- * Here is an example of a tell callback for stdio streams:
- * \code
- * FLAC__StreamDecoderTellStatus tell_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
- * {
- * FILE *file = ((MyClientData*)client_data)->file;
- * off_t pos;
- * if(file == stdin)
- * return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
- * else if((pos = ftello(file)) < 0)
- * return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
- * else {
- * *absolute_byte_offset = (FLAC__uint64)pos;
- * return FLAC__STREAM_DECODER_TELL_STATUS_OK;
- * }
- * }
- * \endcode
- *
- * \note In general, FLAC__StreamDecoder functions which change the
- * state should not be called on the \a decoder while in the callback.
- *
- * \param decoder The decoder instance calling the callback.
- * \param absolute_byte_offset A pointer to storage for the current offset
- * from the beginning of the stream.
- * \param client_data The callee's client data set through
- * FLAC__stream_decoder_init_*().
- * \retval FLAC__StreamDecoderTellStatus
- * The callee's return status.
- */
- typedef FLAC__StreamDecoderTellStatus (*FLAC__StreamDecoderTellCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
- /** Signature for the length callback.
- *
- * A function pointer matching this signature may be passed to
- * FLAC__stream_decoder_init*_stream(). The supplied function will be
- * called when the decoder wants to know the total length of the stream
- * in bytes.
- *
- * Here is an example of a length callback for stdio streams:
- * \code
- * FLAC__StreamDecoderLengthStatus length_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
- * {
- * FILE *file = ((MyClientData*)client_data)->file;
- * struct stat filestats;
- *
- * if(file == stdin)
- * return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
- * else if(fstat(fileno(file), &filestats) != 0)
- * return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
- * else {
- * *stream_length = (FLAC__uint64)filestats.st_size;
- * return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
- * }
- * }
- * \endcode
- *
- * \note In general, FLAC__StreamDecoder functions which change the
- * state should not be called on the \a decoder while in the callback.
- *
- * \param decoder The decoder instance calling the callback.
- * \param stream_length A pointer to storage for the length of the stream
- * in bytes.
- * \param client_data The callee's client data set through
- * FLAC__stream_decoder_init_*().
- * \retval FLAC__StreamDecoderLengthStatus
- * The callee's return status.
- */
- typedef FLAC__StreamDecoderLengthStatus (*FLAC__StreamDecoderLengthCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
- /** Signature for the EOF callback.
- *
- * A function pointer matching this signature may be passed to
- * FLAC__stream_decoder_init*_stream(). The supplied function will be
- * called when the decoder needs to know if the end of the stream has
- * been reached.
- *
- * Here is an example of a EOF callback for stdio streams:
- * FLAC__bool eof_cb(const FLAC__StreamDecoder *decoder, void *client_data)
- * \code
- * {
- * FILE *file = ((MyClientData*)client_data)->file;
- * return feof(file)? true : false;
- * }
- * \endcode
- *
- * \note In general, FLAC__StreamDecoder functions which change the
- * state should not be called on the \a decoder while in the callback.
- *
- * \param decoder The decoder instance calling the callback.
- * \param client_data The callee's client data set through
- * FLAC__stream_decoder_init_*().
- * \retval FLAC__bool
- * \c true if the currently at the end of the stream, else \c false.
- */
- typedef FLAC__bool (*FLAC__StreamDecoderEofCallback)(const FLAC__StreamDecoder *decoder, void *client_data);
- /** Signature for the write callback.
- *
- * A function pointer matching this signature must be passed to one of
- * the FLAC__stream_decoder_init_*() functions.
- * The supplied function will be called when the decoder has decoded a
- * single audio frame. The decoder will pass the frame metadata as well
- * as an array of pointers (one for each channel) pointing to the
- * decoded audio.
- *
- * \note In general, FLAC__StreamDecoder functions which change the
- * state should not be called on the \a decoder while in the callback.
- *
- * \param decoder The decoder instance calling the callback.
- * \param frame The description of the decoded frame. See
- * FLAC__Frame.
- * \param buffer An array of pointers to decoded channels of data.
- * Each pointer will point to an array of signed
- * samples of length \a frame->header.blocksize.
- * Channels will be ordered according to the FLAC
- * specification; see the documentation for the
- * <A HREF="../format.html#frame_header">frame header</A>.
- * \param client_data The callee's client data set through
- * FLAC__stream_decoder_init_*().
- * \retval FLAC__StreamDecoderWriteStatus
- * The callee's return status.
- */
- typedef FLAC__StreamDecoderWriteStatus (*FLAC__StreamDecoderWriteCallback)(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
- /** Signature for the metadata callback.
- *
- * A function pointer matching this signature must be passed to one of
- * the FLAC__stream_decoder_init_*() functions.
- * The supplied function will be called when the decoder has decoded a
- * metadata block. In a valid FLAC file there will always be one
- * \c STREAMINFO block, followed by zero or more other metadata blocks.
- * These will be supplied by the decoder in the same order as they
- * appear in the stream and always before the first audio frame (i.e.
- * write callback). The metadata block that is passed in must not be
- * modified, and it doesn't live beyond the callback, so you should make
- * a copy of it with FLAC__metadata_object_clone() if you will need it
- * elsewhere. Since metadata blocks can potentially be large, by
- * default the decoder only calls the metadata callback for the
- * \c STREAMINFO block; you can instruct the decoder to pass or filter
- * other blocks with FLAC__stream_decoder_set_metadata_*() calls.
- *
- * \note In general, FLAC__StreamDecoder functions which change the
- * state should not be called on the \a decoder while in the callback.
- *
- * \param decoder The decoder instance calling the callback.
- * \param metadata The decoded metadata block.
- * \param client_data The callee's client data set through
- * FLAC__stream_decoder_init_*().
- */
- typedef void (*FLAC__StreamDecoderMetadataCallback)(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
- /** Signature for the error callback.
- *
- * A function pointer matching this signature must be passed to one of
- * the FLAC__stream_decoder_init_*() functions.
- * The supplied function will be called whenever an error occurs during
- * decoding.
- *
- * \note In general, FLAC__StreamDecoder functions which change the
- * state should not be called on the \a decoder while in the callback.
- *
- * \param decoder The decoder instance calling the callback.
- * \param status The error encountered by the decoder.
- * \param client_data The callee's client data set through
- * FLAC__stream_decoder_init_*().
- */
- typedef void (*FLAC__StreamDecoderErrorCallback)(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
复制代码 那么到最后,我来总结一下解码器的写法:
1、取得解码器对象。FLAC__StreamDecoder *pDecoder=FLAC__stream_decoder_new();
2、初始化解码器。用以下的几个函数中的一个来完成。其实就是告诉libFLAC,要解码的数据的来源,以及解码得到的数据的去向。
FLAC__stream_decoder_init_stream
FLAC__stream_decoder_init_ogg_stream
FLAC__stream_decoder_init_FILE
FLAC__stream_decoder_init_ogg_FILE
FLAC__stream_decoder_init_file
FLAC__stream_decoder_init_ogg_file
3、开始解码过程。调用以下的函数来实现。
FLAC__stream_decoder_process_single:解码一个块。
FLAC__stream_decoder_process_until_end_of_metadata:解码全部metadata块。
FLAC__stream_decoder_process_until_end_of_stream:解码全部块。
4、完成解码后清理用过的内存。
FLAC__stream_decoder_delete(pDecoder);
就这些。 |
|