⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tak_lib_cpp.cpp

📁 foo_input_tak-0.4.2-20080408-src tak文件识别代码
💻 CPP
字号:
#include "stdafx.h"
#include "tak_lib_cpp.h"

#ifdef _DEBUG
//#define TRACE_IO_INTERFACE
#endif

class format_tak_version
{
	pfc::string_formatter data;
public:
	explicit format_tak_version(TtakInt32 p_version)
	{
		data << pfc::format_int((p_version >> 16) & 0xff)
			<< "." << pfc::format_int((p_version >> 8) & 0xff)
			<< "." << pfc::format_int(p_version& 0xff);
	}

	operator char const *() {return data;}
};


namespace tak_lib_cpp
{
	inline TtakBool tak_bool_cast(bool p_val) {return p_val ? tak_True : tak_False;}

	class exception_io_tak_ssd : public std::exception
	{
		char m_what[tak_ErrorStringSizeMax];
	public:
		exception_io_tak_ssd(TtakResult p_result)
		{
			tak_SSD_GetErrorString(p_result, m_what, sizeof(m_what));
		};

		virtual const char * what() const
		{
			return m_what;
		};
	};

	TtakStreamIoInterface tak_stream_interface_impl_file::g_io_interface;

	TtakBool tak_stream_interface_impl_file::CanRead(void * p_userdata)
	{
		tak_stream_interface_impl_file * _this = static_cast<tak_stream_interface_impl_file *>(p_userdata);
		return tak_bool_cast(_this->m_file.is_valid());
	}

	TtakBool tak_stream_interface_impl_file::CanWrite(void * p_userdata)
	{
		tak_stream_interface_impl_file * _this = static_cast<tak_stream_interface_impl_file *>(p_userdata);
		return tak_bool_cast(_this->m_file.is_valid());
	}

	TtakBool tak_stream_interface_impl_file::CanSeek(void * p_userdata)
	{
		tak_stream_interface_impl_file * _this = static_cast<tak_stream_interface_impl_file *>(p_userdata);
		return tak_bool_cast(_this->m_file->can_seek());
	}

	TtakBool tak_stream_interface_impl_file::Read(void * p_userdata, void * p_buffer, TtakInt32 p_bytes, TtakInt32 * p_read)
	{
		tak_stream_interface_impl_file * _this = static_cast<tak_stream_interface_impl_file *>(p_userdata);
#ifdef TRACE_IO_INTERFACE
		console::formatter trace;
#endif
		try
		{
#ifdef TRACE_IO_INTERFACE
			trace << "Read(this, buffer, " << p_bytes << ")";
#endif
			t_size read = _this->m_file->read(p_buffer, p_bytes, abort_callback_impl());
#ifdef TRACE_IO_INTERFACE
			trace << " succeeded, read " << read << " bytes";
#endif
			if (p_read != 0)
				*p_read = read;
			return tak_True;
		}
		catch (const std::exception &exc)
		{
#ifdef TRACE_IO_INTERFACE
			trace << " failed, exception: " << exc;
#else
			exc; // avoid warning
#endif
			return tak_False;
		}
	}

	TtakBool tak_stream_interface_impl_file::Write(void * p_userdata, const void * p_buffer, TtakInt32 p_bytes)
	{
		tak_stream_interface_impl_file * _this = static_cast<tak_stream_interface_impl_file *>(p_userdata);
		try
		{
			_this->m_file->write(p_buffer, p_bytes, abort_callback_impl());
			return tak_True;
		}
		catch (std::exception)
		{
			return tak_False;
		}
	}

	TtakBool tak_stream_interface_impl_file::Flush(void * p_userdata)
	{
		tak_stream_interface_impl_file * _this = static_cast<tak_stream_interface_impl_file *>(p_userdata);
		try
		{
			// Null operation.
			return tak_True;
		}
		catch (std::exception)
		{
			return tak_False;
		}
	}

	TtakBool tak_stream_interface_impl_file::Truncate(void * p_userdata)
	{
		tak_stream_interface_impl_file * _this = static_cast<tak_stream_interface_impl_file *>(p_userdata);
		try
		{
			_this->m_file->set_eof(abort_callback_impl());
			return tak_True;
		}
		catch (std::exception)
		{
			return tak_False;
		}
	}

	TtakBool tak_stream_interface_impl_file::Seek(void * p_userdata, TtakInt64 p_position)
	{
		tak_stream_interface_impl_file * _this = static_cast<tak_stream_interface_impl_file *>(p_userdata);
#ifdef TRACE_IO_INTERFACE
		console::formatter trace;
#endif
		try
		{
#ifdef TRACE_IO_INTERFACE
			trace << "Seek(this, " << p_position << ")";
#endif
			_this->m_file->seek(p_position, abort_callback_impl());
#ifdef TRACE_IO_INTERFACE
			trace << " succeeded";
#endif
			return tak_True;
		}
		catch (const std::exception &exc)
		{
#ifdef TRACE_IO_INTERFACE
			trace << " failed, exception: " << exc;
#else
			exc; // avoid warning
#endif
			return tak_False;
		}
	}

	TtakBool tak_stream_interface_impl_file::GetLength(void * p_userdata, TtakInt64 * p_length)
	{
		tak_stream_interface_impl_file * _this = static_cast<tak_stream_interface_impl_file *>(p_userdata);
		try
		{
			*p_length = _this->m_file->get_size(abort_callback_impl());
			return tak_True;
		}
		catch (std::exception)
		{
			return tak_False;
		}
	}

	TtakStreamIoInterface * tak_stream_interface_impl_file::g_get_io_interface_ptr()
	{
		static bool g_initialized = false;
		if (!g_initialized)
		{
			g_io_interface.CanRead = &CanRead;
			g_io_interface.CanSeek = &CanSeek;
			g_io_interface.CanWrite = &CanWrite;
			g_io_interface.Flush = &Flush;
			g_io_interface.GetLength = &GetLength;
			g_io_interface.Read = &Read;
			g_io_interface.Seek = &Seek;
			g_io_interface.Truncate = &Truncate;
			g_io_interface.Write = &Write;

			g_initialized = true;
		}
		return &g_io_interface;
	}

	tak_stream_interface_impl_file::tak_stream_interface_impl_file(service_ptr_t<file> p_file)
	{
		m_file = p_file;
	}

	tak_stream_interface_impl_file::~tak_stream_interface_impl_file()
	{
	}

#ifdef _DEBUG
	tak_seekable_decoder::tak_seekable_decoder(const char * p_filename)
	{
		m_decoder.create_from_file(p_filename, tak_ssd_opt_BufferInput);

		if (m_decoder.is_empty())
			throw exception_io("TAK decoder could not be created");

		if (!m_decoder.is_decoder_valid())
			throw exception_io("TAK decoder is in error state");

		TtakResult res = m_decoder.get_stream_info(m_info);
		if (res != tak_res_Ok)
			throw exception_io_tak_ssd(res);

		res = m_decoder.get_stream_encoder_info(m_encoder_info);
		m_encoder_info_valid = (res == tak_res_Ok);
	}
#endif

	tak_seekable_decoder::tak_seekable_decoder(service_ptr_t<file> p_file, TtakInt32 p_cpu_opt_flags)
	{
		m_file_callback = new tak_stream_interface_impl_file(p_file);

		m_decoder.create_from_stream(
			tak_stream_interface_impl_file::g_get_io_interface_ptr(),
			m_file_callback.get_ptr(),
			tak_ssd_opt_BufferInput,
			p_cpu_opt_flags);

		if (m_decoder.is_empty())
			throw exception_io("TAK decoder could not be created");

		if (!m_decoder.is_decoder_valid())
			throw exception_io("TAK decoder is in error state");

		TtakResult res = m_decoder.get_stream_info(m_info);
		if (res != tak_res_Ok)
			throw exception_io_tak_ssd(res);

		res = m_decoder.get_stream_encoder_info(m_encoder_info);
		m_encoder_info_valid = (res == tak_res_Ok);
	}

	tak_seekable_decoder::~tak_seekable_decoder()
	{
	}

	void tak_seekable_decoder::seek(TtakInt64 p_sample)
	{
		TtakResult res = m_decoder.seek(p_sample);
		if (res != tak_res_Ok)
			throw exception_io_tak_ssd(res);
	}

	t_size tak_seekable_decoder::decode(void * p_data, t_size p_samples)
	{
		TtakInt32 read = 0;

		TtakResult res = m_decoder.read_audio(p_data, p_samples, read);
		if (res != tak_res_Ok)
			throw exception_io_tak_ssd(res);

		return read;
	}

	t_uint32 tak_seekable_decoder::get_channel_count()
	{
		return m_info.Audio.ChannelNum;
	}

	t_uint32 tak_seekable_decoder::get_sample_rate()
	{
		return m_info.Audio.SampleRate;
	}

	t_uint64 tak_seekable_decoder::get_sample_count()
	{
		return m_info.Sizes.SampleNum;
	}

	t_uint32 tak_seekable_decoder::get_bits_per_sample()
	{
		return m_info.Audio.SampleBits;
	}

	t_uint32 tak_seekable_decoder::get_frame_size()
	{
		return m_info.Sizes.FrameSizeInSamples;
	}

	void tak_seekable_decoder::get_info(file_info & p_info)
	{
		p_info.info_set_int("bitspersample", m_info.Audio.SampleBits);
		p_info.info_set_int("channels", m_info.Audio.ChannelNum);
		p_info.info_set_int("samplerate", m_info.Audio.SampleRate);

		p_info.set_length(audio_math::samples_to_time(m_info.Sizes.SampleNum, m_info.Audio.SampleRate));

		//TtakResult result = tak_res_Ok;
		//char codec_name[tak_CodecNameSizeMax];
		//result = tak_GetCodecName(m_info.Encoder.Codec, codec_name, sizeof(codec_name));

		p_info.info_set("codec", "TAK");

		if (m_encoder_info_valid)
		{
			pfc::string8_fastalloc profile;
			if (m_encoder_info.Version <= 0x010001)
			{
				switch (m_encoder_info.Preset)
				{
				case 0:
					profile = "turbo";
					break;
				case 1:
					profile = "fast";
					break;
				case 2:
					profile = "normal";
					break;
				case 3:
					profile = "high";
					break;
				case 4:
					profile = "extra";
					break;
				default:
					profile << m_info.Encoder.Profile;
					break;
				}
			}
			else if (m_encoder_info.Version <= 0x010002)
			{
				switch (m_encoder_info.Preset)
				{
				case 0:
					profile = "turbo";
					break;
				case 1:
					profile = "fast";
					break;
				case 2:
					profile = "normal";
					break;
				case 3:
					profile = "high";
					break;
				case 4:
					profile = "extra";
					break;
				case 5:
					profile = "insane";
					break;
				default:
					profile << m_info.Encoder.Profile;
					break;
				}
			}
			else
			{
				profile << m_info.Encoder.Profile;
			}

			switch (m_encoder_info.Evaluation)
			{
			case tak_PresetEval_Standard:
				// no additional text
				break;
			case tak_PresetEval_Extra:
				profile << " extra";
				break;
			case tak_PresetEval_Max:
				profile << " max";
				break;
			default:
				break;
			}

			p_info.info_set("codec_profile", profile);

			p_info.info_set("tool", pfc::string_formatter() << "TAK encoder " << format_tak_version(m_encoder_info.Version));
		}
		else if (m_info.Encoder.Codec == 0)
		{
			switch (m_info.Encoder.Profile)
			{
			case 0:
				p_info.info_set("codec_profile", "turbo");
				break;
			case 1:
				p_info.info_set("codec_profile", "fast");
				break;
			case 2:
				p_info.info_set("codec_profile", "normal");
				break;
			case 3:
				p_info.info_set("codec_profile", "high");
				break;
			case 4:
				p_info.info_set("codec_profile", "extra");
				break;
			default:
				p_info.info_set_int("codec_profile", m_info.Encoder.Profile);
				break;
			}
		}

#ifdef _DEBUG
		p_info.info_set_int("framesize", m_info.Sizes.FrameSizeInSamples);

		switch (m_info.Sizes.FrameSize)
		{
		case tak_str_FrameSizeType_94_ms:
			p_info.info_set_int("framesizems", 94);
			break;
		case tak_str_FrameSizeType_125_ms:
			p_info.info_set_int("framesizems", 125);
			break;
		case tak_str_FrameSizeType_188_ms:
			p_info.info_set_int("framesizems", 188);
			break;
		case tak_str_FrameSizeType_250_ms:
			p_info.info_set_int("framesizems", 250);
			break;
		}
#endif
	}

	t_int32 tak_seekable_decoder::get_last_frame_bitrate()
	{
		TtakInt32 result = m_decoder.get_last_frame_bitrate();
		return result;
	}


} // namespace tak_lib_cpp

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -