概要 †libflac++とは †flacを扱いやすくするためのC++ライブラリ。 ダウンロード †ここから落としてくる。 ライセンス †ライブラリ †New BSD ライセンス(修正BSD) この記事 †使用方法 †基本的にオーバーライドして使う模様 #define FLAC__NO_DLL をソースに追加。 デコーダ †class m_Decoder : public FLAC::Decoder::Stream { public: m_Decoder(FILE *f_) : FLAC::Decoder::Stream(), f(f_) { buffer.clear(); } vector<int32_t> buffer; uint64_t getTotalSample() { return totalSamples; } unsigned int getSampleRate() { return sampleRate; } unsigned int getChannels() { return channels; } unsigned int getBitPerSeconds() { return bps; } protected: FILE *f; virtual ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]); virtual ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes); virtual void metadata_callback(const ::FLAC__StreamMetadata *metadata); virtual void error_callback(::FLAC__StreamDecoderErrorStatus status); private: m_Decoder(const m_Decoder&); m_Decoder&operator=(const m_Decoder&); FLAC__uint64 totalSamples = 0; unsigned int sampleRate = 0; unsigned int channels = 0; unsigned int bps = 0; }; 関数のオーバーライド †基本的にコールバックが呼ばれる。 write_callback †FLACをデコードしたRAWデータが出てくる場所 ::FLAC__StreamDecoderWriteStatus m_Decoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 *const buffer[]) { for (unsigned int i = 0; i < frame->header.blocksize; i++) { for (unsigned int channels = 0; channels < frame->header.channels; channels++) { this->buffer.push_back(buffer[channels][i]); } } return ::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } read_callback †ファイルを読むときに呼び出される場所。 ちゃんと書けばstream系も使える。 ::FLAC__StreamDecoderReadStatus m_Decoder::read_callback(FLAC__byte buffer[], size_t *bytes) { const size_t size = *bytes; if (feof(f)){ *bytes = 0; return FLAC__StreamDecoderReadStatus::FLAC__STREAM_DECODER_READ_STATUS_ABORT; } else if (size > 0) { *bytes = ::fread(buffer, 1, size, f); if (*bytes == 0){ if (feof(f)) return FLAC__StreamDecoderReadStatus::FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; else { return FLAC__StreamDecoderReadStatus::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; } } else { return FLAC__StreamDecoderReadStatus::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; } } else return FLAC__StreamDecoderReadStatus::FLAC__STREAM_DECODER_READ_STATUS_ABORT; } metadata_callback †メタデータが出てくる場所。 void m_Decoder::metadata_callback(const ::FLAC__StreamMetadata *metadata) { if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { totalSamples = metadata->data.stream_info.total_samples; sampleRate = metadata->data.stream_info.sample_rate; channels = metadata->data.stream_info.channels; bps = metadata->data.stream_info.bits_per_sample; } } error_callback †エラーが発生した時に呼ばれる。確かサンプルからコピった。 void m_Decoder::error_callback(::FLAC__StreamDecoderErrorStatus status) { fprintf(stderr, "Got error callback: %s\n", FLAC__StreamDecoderErrorStatusString[status]); } コード †#include <FLAC++/all.h> #include <vector> #include "m_Decoder.h" using namespace FLAC; using namespace std; static FLAC__uint64 total_samples = 0; static unsigned sample_rate = 0; static unsigned channels = 0; static unsigned bps = 0; int main(void){ FILE *fread; fopen_s(&fread, "data.flac", "rb"); m_Decoder decode(fread); decode.set_md5_checking(true); FLAC__StreamDecoderInitStatus initResult = decode.init(); if (initResult != FLAC__STREAM_DECODER_INIT_STATUS_OK) { fprintf(stderr, "ERROR : FLAC Init Error."); return 0; } decode.process_until_end_of_metadata(); // Getting metadeta... int sample = 0; vector<int32_t> RAWData; while(total_samples > sample){ decode.process_single(); for (int i=0; i<decode.buffer.size(); i++){ RAWData.push_back(decode.buffer[i]); sample++; } decode.buffer.clear(); } return 0; } イメージこんな感じ。 process_until_end_of_stream()もあるけど、全部デコードしちゃうから効果音とか短いのならいいけど長いのは時間かかる。 実際に実行してないから動くかわからない |