📄 taklibxx.h
字号:
#ifndef __TAKLIBXX_H__
#define __TAKLIBXX_H__
/**
* \file taklibxx.h
* Low-level C++ wrapper for the TAK decoder.
* \author Holger Stenger
*/
#ifndef __cplusplus
#error TAKLIB++ must be compiled as C++
#endif
#include "tak_deco_lib.h"
namespace taklibxx
{
class tak_library
{
public:
static TtakResult get_library_version(TtakInt32 &p_version, TtakInt32 &p_compatible_version)
{
return tak_GetLibraryVersion(&p_version, &p_compatible_version);
}
};
/**
* Wrapper to access basic functions of the TAK seekable stream decoder (SSD).
*/
class tak_ssd_ptr_raw
{
private:
TtakSeekableStreamDecoder m_ptr;
public:
tak_ssd_ptr_raw() {m_ptr = 0;}
~tak_ssd_ptr_raw() {reset();}
bool is_empty() const {return m_ptr == 0;}
void reset() {if (m_ptr != 0) tak_SSD_Destroy(m_ptr); m_ptr = 0;}
bool is_decoder_valid()
{
PFC_ASSERT(m_ptr != 0);
return tak_SSD_Valid(m_ptr) != tak_False;
}
void attach(TtakSeekableStreamDecoder p_ptr) {reset(); m_ptr = p_ptr;}
TtakSeekableStreamDecoder detach() {TtakSeekableStreamDecoder ptr = m_ptr; m_ptr = 0; return ptr;}
bool create_from_file(const char * p_path, const TtakSSDOptions &p_options, TSSDDamageCallback p_callback, void * p_callback_data)
{
reset();
m_ptr = tak_SSD_Create_FromFile(p_path, &p_options, p_callback, p_callback_data);
return m_ptr != 0;
}
bool create_from_stream(TtakStreamIoInterface * p_stream, void * p_stream_data, const TtakSSDOptions &p_options, TSSDDamageCallback p_callback, void * p_callback_data)
{
reset();
m_ptr = tak_SSD_Create_FromStream(p_stream, p_stream_data, &p_options, p_callback, p_callback_data);
return m_ptr != 0;
}
TtakResult get_stream_info(Ttak_str_StreamInfo & p_info)
{
PFC_ASSERT(m_ptr != 0);
return tak_SSD_GetStreamInfo(m_ptr, &p_info);
}
TtakResult get_stream_encoder_info(Ttak_str_MetaEncoderInfo &p_encoder_info)
{
PFC_ASSERT(m_ptr != 0);
return tak_SSD_GetEncoderInfo(m_ptr, &p_encoder_info);
}
TtakResult seek(TtakInt64 p_sample_pos)
{
PFC_ASSERT(m_ptr != 0);
return tak_SSD_Seek(m_ptr, p_sample_pos);
}
TtakResult read_audio(void * p_buffer, TtakInt32 p_samples, TtakInt32 & p_samples_read)
{
PFC_ASSERT(m_ptr != 0);
return tak_SSD_ReadAudio(m_ptr, p_buffer, p_samples, &p_samples_read);
}
TtakInt32 get_last_frame_bitrate()
{
PFC_ASSERT(m_ptr != 0);
return tak_SSD_GetCurFrameBitRate(m_ptr);
}
TtakAPEv2Tag get_tag()
{
PFC_ASSERT(m_ptr != 0);
return tak_SSD_GetAPEv2Tag(m_ptr);
}
};
class tak_tag_raw
{
private:
TtakAPEv2Tag m_ptr;
public:
tak_tag_raw() {m_ptr = 0;}
~tak_tag_raw() {reset();}
bool is_empty() {return m_ptr != 0;}
void reset() {m_ptr = 0;}
void attach(TtakAPEv2Tag p_ptr) {reset(); m_ptr = p_ptr;}
TtakAPEv2Tag detach() {TtakAPEv2Tag ptr = m_ptr; m_ptr = 0; return ptr;}
bool is_tag_valid()
{
PFC_ASSERT(m_ptr != 0);
return tak_APE_Valid(m_ptr) != tak_False;
}
};
/**
* Template class that adds convenience methods to a TAK SSD wrapper.
* Usage: tak_ssd_ptr_helper<tak_ssd_ptr_without_helper_methods>
*/
template <class T>
class tak_ssd_ptr_helper : public T
{
public:
bool create_from_file(const char * p_path, TtakInt32 p_flags = 0, TtakCpuOptions p_cpu_options = tak_Cpu_Any)
{
TtakSSDOptions options;
options.Cpu = p_cpu_options;
options.Flags = p_flags;
return T::create_from_file(p_path, options, 0, 0);
}
bool create_from_stream(TtakStreamIoInterface * p_stream, void * p_stream_data, TtakInt32 p_flags = 0, TtakCpuOptions p_cpu_options = tak_Cpu_Any)
{
TtakSSDOptions options;
options.Cpu = p_cpu_options;
options.Flags = p_flags;
return T::create_from_stream(p_stream, p_stream_data, options, 0, 0);
}
};
/**
* Template class that extends the seeking range to all reachable positions.
* The raw TAK SSD does not allow seeking to the position after the last sample.
* It can only reach this position through decoding. The wrapper makes this
* position a valid seek target.
* Usage: tak_ssd_ptr_eos_seek_fix<tak_ssd_ptr_with_normal_seek_range>
*/
template <class T>
class tak_ssd_ptr_eos_seek_fix : public T
{
private:
bool m_is_virtual_eof;
TtakInt64 m_sample_count;
public:
tak_ssd_ptr_eos_seek_fix()
{
m_is_virtual_eof = false;
m_sample_count = -1;
}
TtakResult seek(TtakInt64 p_sample_position)
{
PFC_ASSERT(!is_empty());
TtakResult result = tak_res_Ok;
if (m_sample_count == -1)
{
Ttak_str_StreamInfo info;
TtakResult res = get_stream_info(info);
m_sample_count = info.Sizes.SampleNum;
}
if (p_sample_position >= m_sample_count)
{
m_is_virtual_eof = true;
}
else
{
m_is_virtual_eof = false;
result = T::seek(p_sample_position);
}
return result;
}
TtakResult read_audio(void * p_buffer, TtakInt32 p_samples, TtakInt32 & p_samples_read)
{
PFC_ASSERT(!is_empty());
TtakResult result = tak_res_Ok;
if (m_is_virtual_eof)
{
p_samples_read = 0;
}
else
{
result = T::read_audio(p_buffer, p_samples, p_samples_read);
}
return result;
}
};
#ifdef _FOOBAR2000_H_
/**
* Template class that outputs trace information on the foobar2000 console
* Usage: tak_ssd_ptr_trace<tak_ssd_ptr_where_method_calls_should_be_traced>
*/
template <class T, char const * NAME = 0>
class tak_ssd_ptr_trace : public T
{
private:
class trace_formatter : public console::formatter
{
public:
trace_formatter(const char * p_method, bool p_leaving)
{
if (NAME != 0)
*this << "(" << NAME << ") ";
*this << (p_leaving ? "leaving " : "entering ") << p_method;
}
};
public:
bool create_from_file(const char * p_path, const TtakSSDOptions &p_options, TSSDDamageCallback p_callback, void * p_callback_data)
{
trace_formatter("create_from_file", false);
bool result = T::create_from_file(p_path, p_options, p_callback, p_callback_data);
trace_formatter("create_from_file", true)
<< ": result = " << (result ? "true" : "false");
return result;
}
bool create_from_stream(TtakStreamIoInterface * p_stream, void * p_stream_data, const TtakSSDOptions &p_options, TSSDDamageCallback p_callback, void * p_callback_data)
{
trace_formatter("create_from_stream", false);
bool result = T::create_from_stream(p_stream, p_stream_data, p_options, p_callback, p_callback_data);
trace_formatter("create_from_stream", true)
<< ": result = " << (result ? "true" : "false");
return result;
}
TtakResult get_stream_info(Ttak_str_StreamInfo & p_info)
{
trace_formatter("get_stream_info", false);
TtakResult result = T::get_stream_info(p_info);
trace_formatter("get_stream_info", true)
<< ": result = " << result;
return result;
}
TtakResult get_stream_encoder_info(Ttak_str_EncoderInfo &p_encoder_info)
{
trace_formatter("get_stream_encoder_info", false);
TtakResult result = T::get_stream_encoder_info(p_encoder_info);
trace_formatter("get_stream_encoder_info", true)
<< ": result = " << result;
return result;
}
TtakResult seek(TtakInt64 p_sample_pos)
{
trace_formatter("seek", false)
<< ": sample = " << p_sample_pos;
TtakResult result = T::seek(p_sample_pos);
trace_formatter("seek", true)
<< ": result = " << result;
return result;
}
TtakResult read_audio(void * p_buffer, TtakInt32 p_samples, TtakInt32 & p_samples_read)
{
trace_formatter("read_audio", false)
<< ": requested samples = " << p_samples;
TtakResult result = T::read_audio(p_buffer, p_samples, p_samples_read);
trace_formatter("read_audio", true)
<< ": result = " << result
<< ", delivered samples = " << p_samples_read;
return result;
}
TtakInt32 get_last_frame_bitrate()
{
trace_formatter("get_last_frame_bitrate", false);
TtakInt32 result = T::get_last_frame_bitrate();
trace_formatter("get_last_frame_bitrate", true)
<< ": result = " << result;
return result;
}
TtakAPEv2Tag get_tag()
{
trace_formatter("get_tag", false);
TtakAPEv2Tag result = T::get_tag();
trace_formatter("get_tag", true)
<< ": result = " << ((result == 0) ? "<null>" : "<non-null>");
return result;
}
};
/**
* Template class that adds foobar2000 specific call tracking to methods.
* Usage: tak_ssd_ptr_trackcall<tak_ssd_ptr_without_call_tracking>
*/
template <class T>
class tak_ssd_ptr_trackcall : public T
{
public:
bool create_from_file(const char * p_path, const TtakSSDOptions &p_options, TSSDDamageCallback p_callback, void * p_callback_data)
{
TRACK_CALL_TEXT("tak_ssd::create_from_file");
return T::create_from_file(p_path, p_options, p_callback, p_callback_data);
}
bool create_from_stream(TtakStreamIoInterface * p_stream, void * p_stream_data, const TtakSSDOptions &p_options, TSSDDamageCallback p_callback, void * p_callback_data)
{
TRACK_CALL_TEXT("tak_ssd::create_from_stream");
return T::create_from_stream(p_stream, p_stream_data, p_options, p_callback, p_callback_data);
}
TtakResult get_stream_info(Ttak_str_StreamInfo & p_info)
{
TRACK_CALL_TEXT("tak_ssd::get_stream_info");
return T::get_stream_info(p_info);
}
TtakResult get_stream_encoder_info(Ttak_str_MetaEncoderInfo &p_encoder_info)
{
TRACK_CALL_TEXT("tak_ssd::get_stream_encoder_info");
return T::get_stream_encoder_info(p_encoder_info);
}
TtakResult seek(TtakInt64 p_sample_pos)
{
TRACK_CALL_TEXT("tak_ssd::seek");
return T::seek(p_sample_pos);
}
TtakResult read_audio(void * p_buffer, TtakInt32 p_samples, TtakInt32 & p_samples_read)
{
TRACK_CALL_TEXT("tak_ssd::read_audio");
return T::read_audio(p_buffer, p_samples, p_samples_read);
}
TtakInt32 get_last_frame_bitrate()
{
TRACK_CALL_TEXT("tak_ssd::get_last_frame_bitrate");
return T::get_last_frame_bitrate();
}
TtakAPEv2Tag get_tag()
{
TRACK_CALL_TEXT("tak_ssd::get_tag");
return T::get_tag();
}
};
#endif
} // namespace taklibxx
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -