///////////////////////////////////////////////////////////////////////////// ////////////// THE LOSSLESS TRUE AUDIO CODEC C++ LIBRARY V2.3 /////////////// ///////////////////////////////////////////////////////////////////////////// This package contains a full-futured codec library for realtime encoding and decoding of True Audio (TTA) files. The library has a 3 interface classes, which provides a possibility to work in applications of any complexity. For maintenance of namespace wholeness, all functions and library classes are transferred out to the separate namespace, named tta. For using this library in advanced applications the tta_encoder, tta_decoder and tta_exception interface classes can be used. //////////////////////////// TTA decoder class ////////////////////////////// ///////////////////////////////////////////////////////////////////////////// The tta_decoder class is intended for decoding of the TTA audio files. The tta_decoder class constructor accepts the 'iocb' callbacks structure as a function parameter. The 'iocb' structure must be initialized before use. Good sample code of this library usage can be found in 'console' folder of the source code package. tta_decoder(fileio *io); The 'init' function initializes the decoder and fills the info structure retrieving the data from the file header. 'password' should be provided (not a null string) when the original TTA audio file is encrypted. The encrypted data will be decoded correctly only if the right password is set. void init(TTA_info *info, uint64_t pos, const std::string& password); The 'frame_reset' function is intended to reinitialize the decoder for reading data from new data source e.g. for decoding the frame data directly from the memory buffer. void frame_reset(uint32_t frame, fileio *io); The 'process_stream' function can be used to get a chunk of the decompressed data. This function accepts requested count of samples as a parameter and returns the decompressed data into the 'output' buffer. The count of actually decoded samples is returned as a function value. The 'tta_callback' is a function parameter, intended for the extension of possibilities of the user program. It can be used to get a statistics of the decoding process. int process_stream(uint8_t *output, uint32_t req_count, TTA_CALLBACK tta_callback); The 'process_frame' function can be used to decode one TTA frame of 'in_bytes' size into the 'output' buffer of 'out_bytes' size. int process_frame(uint32_t in_bytes, uint8_t *output, uint32_t out_bytes); The 'set_position' function allows to jump to different parts of the audio track playback. Function accepts the time position in seconds where playback has to start, and returns the actual time position of start of the next audio frame as a 'new_pos' parameter. void set_position(uint32_t seconds, uint32_t *new_pos); The 'get_rate' function returns the dynamic bit-rate of compressed data stream in Kbps. This function can be used in case of separate processing of each data frame. In other cases it's better to use the tta_callback function. int get_rate(); //////////////////////////// TTA encoder class ////////////////////////////// ///////////////////////////////////////////////////////////////////////////// The tta_encoder class is intended for coding PCM data with into the output TTA file. The tta_encoder class constructor accepts the 'fileio*' pointer as a function parameter. tta_encoder(fileio *io); The 'init' function will initialize the encoder with stream parameters from previously filled "info" structure. The 'pos' parameter of this function specifies the count of bytes to skip from the beginning of the output file if required. if 'password' is given (not a null string), the output data will be password protected. void init(TTA_info *info, uint64_t pos, const std::string& password); The 'frame_reset' function is intended to reinitialize the encoder for reading from new data source e.g. for encoding the frame data directly from the memory buffer. void frame_reset(uint32_t frame, fileio *io); The 'process_stream' function can be used to compress a chunk of the input data. The function accepts the chunk of PCM audio data of 'in_bytes' size from 'input' buffer. The 'tta_callback' is a function parameter, intended for the extension of possibilities of the user program. It can be used to get a statistics of the decoding process. void process_stream(uint8_t *input, uint32_t in_bytes, TTA_CALLBACK tta_callback); The 'process_frame' function can be used to produce one TTA frame. The function accepts the chunk of PCM audio data of 'in_bytes' size from 'input' buffer. void process_frame(uint8_t *input, uint32_t in_bytes); The 'finalize' function is intended to finalize the encoding process. This function must be called when you're finished encoding. void finalize(); The 'get_rate' function returns the dynamic bit-rate of compressed data stream in Kbps. This function can be used in case of separate processing of each data frame. In other cases it's better to use the tta_callback function. int get_rate(); ////////////////////////////// TTA exceptions /////////////////////////////// ///////////////////////////////////////////////////////////////////////////// If an error occurs, the both of tta_encoder and tta_decoder classes generates exceptions of the tta_exception type. The error code can be retrieved by code() function of the exception value. This function returns the code which has a TTA_CODEC_STATUS type. Description of the TTA error codes: TTA_NO_ERROR - no known errors found TTA_OPEN_ERROR - can't open file TTA_FORMAT_ERROR - not compatible file format TTA_FILE_ERROR - file is corrupted TTA_READ_ERROR - can't read from input file TTA_WRITE_ERROR - can't write to output file TTA_SEEK_ERROR - file seek error TTA_MEMORY_ERROR - insufficient memory available TTA_PASSWORD_ERROR - password protected file TTA_NOT_SUPPORTED - unsupported architecture //////// Sample for building the TTA decoder on Sigma Designs EM86XX //////// ///////////////////////////////////////////////////////////////////////////// #include <libtta/libtta.h> using namespace std; using namespace tta; typedef struct { RMuint32 number_of_channels; RMuint32 sample_rate; RMuint32 bits_per_sample; RMuint32 bytes_per_sample; RMuint32 total_count_of_samples; RMuint32 sample_size; RMuint64 track_duration; } tta_context; static tta_decoder *TTA; static tta_context t_info; static RMuint32 seek_skip = 0; // count of samples to skip after seek class tta_file_io : public fileio { private: HANDLE m_handle; public: tta_file_io(HANDLE handle); ~tta_file_io(); int32_t Read(uint8_t *buffer, uint32_t size) override; int32_t Write(uint8_t *buffer, uint32_t size) override; int64_t Seek(int64_t offset) override; }; tta_file_io::tta_file_io(HANDLE handle) : m_handle(handle) {} tta_file_io::~tta_file_io() {} int32_t tta_file_io::Read(uint8_t *buffer, uint32_t size) { int32_t result; if (tta_read(m_handle, buffer, size, result)) return result; return 0; } int32_t tta_file_io::Write(uint8_t *buffer, uint32_t size) { int32_t result; if (tta_write(m_handle, buffer, size, result)) return result; return 0; } int64_t tta_file_io::Seek(int64_t offset) { return tta_seek(m_handle, offset); } ///////////////////////// 1. Decoder initialization ///////////////////////// RMstatus rmtta_file_init(RMfile f_handle) { TTA_info info; if (!f_handle) return RM_ERROR; RMMemset(&t_info, 0, sizeof(tta_context)); tta_file_io io(f_handle); try { TTA = new tta_decoder(&io); TTA->init(&info, 0, ""); } catch (tta_exception ex) { RMDBGLOG((ENABLE, "rmtta_error: %d\n", ex.code()); if (TTA) delete TTA; // cleanup return RM_ERROR; } // TTA->info structure contains now all of required information: t_info.number_of_channels = info.nch; t_info.sample_rate = info.sps; t_info.bits_per_sample = info.bps; t_info.total_count_of_samples = info.samples; t_info.bytes_per_sample = (info.bps + 7) / 8; t_info.sample_size = t_info.bytes_per_sample * t_info.number_of_channels; // The track duration (in ms) can be easily calculated as t_info.track_duration = RMuint64(t_info.total_count_of_samples / t_info.sample_rate * 1000); return RM_OK; } ///////////////////////////// 3. File seeking /////////////////////////////// RMstatus rmtta_file_seek(RMuint32 seconds) { if (!TTA->seek_allowed) return RM_ERROR; RMuint32 frame_start = 0; try { TTA->set_position(seconds, &frame_start); } catch (tta_exception ex) { RMDBGLOG((ENABLE, "rmtta_error: %d\n", ex.code()); return RM_ERROR; } // We need to skip some samples from start of the frame if required seek_skip = RMuint32((seconds - frame_start) * t_info.sample_rate + 0.5); return RM_OK; } /////////////////////// 4. Reading the data from file /////////////////////// RMstatus rmtta_file_read(RMuint8 *buffer, RMuint32 length, RMuint32 *size_returned) { if (!TTA) return RM_ERROR; RMuint32 buffer_length = length / t_info.sample_size; RMuint32 samples_returned = 0; RMuint32 eos_flag = 0; // end of stream flag try { while (seek_skip && !eos_flag) { if (seek_skip >= buffer_length) { samples_returned = TTA->process_stream(buffer, buffer_length); seek_skip -= samples_returned; } else { samples_returned = TTA->process_stream(buffer, seek_skip); seek_skip = 0; } if (!samples_returned) eos_flag = 1; } if (!eos_flag) { samples_returned = TTA->process_stream(buffer, buffer_length); if (!samples_returned) eos_flag = 1; } } catch (tta_exception ex) { RMDBGLOG((ENABLE, "rmtta_error: %d\n", ex.code()); delete TTA; // cleanup return RM_ERROR; } *size_returned = samples_returned * t_info.sample_size; if (eos_flag) return RM_ERRORENDOFFILE; return RM_OK; } ////////////////////////////// Contributors ///////////////////////////////// ///////////////////////////////////////////////////////////////////////////// Listed in chronological order: Aleksander Djuric, Pavel Zhilin, Tamir Barak, Noam Koenigstein, Kazuki Oikawa, Christophe Paris, Eugene Okhotsky, Yoshihisa Uchida, LM Poh, Scott Watson. ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// Copyright (c) 1999-2015 Aleksander Djuric. All rights reserved. For the latest in news and downloads, please visit the official True Audio project site: http://www.true-audio.com/