File indexing completed on 2024-05-12 04:51:33
0001 /* 0002 SPDX-FileCopyrightText: 1998-2007 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "k3bmpcwrapper.h" 0007 0008 #include <QDebug> 0009 #include <QFile> 0010 0011 0012 #ifdef MPC_OLD_API 0013 mpc_int32_t read_impl( void* data, void* ptr, mpc_int32_t size ) 0014 { 0015 QFile* input = static_cast<QFile*>( data ); 0016 #else 0017 mpc_int32_t read_impl( mpc_reader* data, void* ptr, mpc_int32_t size ) 0018 { 0019 QFile* input = static_cast<QFile*>( data->data ); 0020 #endif 0021 return input->read( (char*)ptr, size ); 0022 } 0023 0024 0025 #ifdef MPC_OLD_API 0026 mpc_bool_t seek_impl( void* data, mpc_int32_t offset ) 0027 { 0028 QFile* input = static_cast<QFile*>( data ); 0029 #else 0030 mpc_bool_t seek_impl( mpc_reader* data, mpc_int32_t offset ) 0031 { 0032 QFile* input = static_cast<QFile*>( data->data ); 0033 #endif 0034 return input->seek( offset ); 0035 } 0036 0037 #ifdef MPC_OLD_API 0038 mpc_int32_t tell_impl( void* data ) 0039 { 0040 QFile* input = static_cast<QFile*>( data ); 0041 #else 0042 mpc_int32_t tell_impl( mpc_reader* data ) 0043 { 0044 QFile* input = static_cast<QFile*>( data->data ); 0045 #endif 0046 return input->pos(); 0047 } 0048 0049 #ifdef MPC_OLD_API 0050 mpc_int32_t get_size_impl( void* data ) 0051 { 0052 QFile* input = static_cast<QFile*>( data ); 0053 #else 0054 mpc_int32_t get_size_impl( mpc_reader* data ) 0055 { 0056 QFile* input = static_cast<QFile*>( data->data ); 0057 #endif 0058 return input->size(); 0059 } 0060 0061 #ifdef MPC_OLD_API 0062 mpc_bool_t canseek_impl( void* ) 0063 #else 0064 mpc_bool_t canseek_impl( mpc_reader* ) 0065 #endif 0066 { 0067 return true; 0068 } 0069 0070 0071 #ifdef MPC_FIXED_POINT 0072 static int shift_signed( MPC_SAMPLE_FORMAT val, int shift ) 0073 { 0074 if(shift > 0) 0075 val <<= shift; 0076 else if(shift < 0) 0077 val >>= -shift; 0078 return (int) val; 0079 } 0080 #endif 0081 0082 0083 K3bMpcWrapper::K3bMpcWrapper() 0084 { 0085 m_input = new QFile(); 0086 0087 m_reader = new mpc_reader; 0088 m_reader->read = read_impl; 0089 m_reader->seek = seek_impl; 0090 m_reader->tell = tell_impl; 0091 m_reader->get_size = get_size_impl; 0092 m_reader->canseek = canseek_impl; 0093 m_reader->data = m_input; 0094 0095 #ifdef MPC_OLD_API 0096 m_decoder = new mpc_decoder; 0097 #else 0098 m_decoder = 0; 0099 #endif 0100 0101 m_info = new mpc_streaminfo; 0102 } 0103 0104 0105 K3bMpcWrapper::~K3bMpcWrapper() 0106 { 0107 close(); 0108 0109 delete m_reader; 0110 #ifdef MPC_OLD_API 0111 delete m_decoder; 0112 #else 0113 if( m_decoder ) 0114 mpc_demux_exit( m_decoder ); 0115 #endif 0116 delete m_info; 0117 delete m_input; 0118 } 0119 0120 0121 bool K3bMpcWrapper::open( const QString& filename ) 0122 { 0123 close(); 0124 0125 m_input->setFileName( filename ); 0126 0127 if( m_input->open( QIODevice::ReadOnly ) ) { 0128 #ifdef MPC_OLD_API 0129 mpc_streaminfo_init( m_info ); 0130 if( mpc_streaminfo_read( m_info, m_reader ) != ERROR_CODE_OK ) { 0131 qDebug() << "(K3bMpcWrapper) Not a valid musepack file: \"" << filename << "\""; 0132 return false; 0133 } 0134 else { 0135 mpc_decoder_setup( m_decoder, m_reader ); 0136 if( !mpc_decoder_initialize( m_decoder, m_info ) ) { 0137 #else 0138 m_decoder = mpc_demux_init( m_reader ); 0139 if( !m_decoder ) { 0140 #endif 0141 qDebug() << "(K3bMpcWrapper) failed to initialize the Musepack decoder."; 0142 close(); 0143 return false; 0144 } 0145 else { 0146 #ifndef MPC_OLD_API 0147 mpc_demux_get_info( m_decoder, m_info ); 0148 #endif 0149 qDebug() << "(K3bMpcWrapper) valid musepack file. " 0150 << channels() << " Channels and Samplerate: " << samplerate() << Qt::endl; 0151 return true; 0152 } 0153 #ifdef MPC_OLD_API 0154 } 0155 #endif 0156 } 0157 else 0158 return false; 0159 } 0160 0161 0162 void K3bMpcWrapper::close() 0163 { 0164 m_input->close(); 0165 } 0166 0167 0168 int K3bMpcWrapper::decode( char* data, int max ) 0169 { 0170 // FIXME: make this a member variable 0171 MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH]; 0172 0173 #ifdef MPC_OLD_API 0174 unsigned int samples = mpc_decoder_decode( m_decoder, sample_buffer, 0, 0 ); 0175 #else 0176 unsigned int samples; 0177 mpc_frame_info frame; 0178 0179 frame.buffer = sample_buffer; 0180 mpc_demux_decode( m_decoder, &frame ); 0181 samples = frame.samples; 0182 #endif 0183 0184 if( samples*channels()*2 > (unsigned int)max ) { 0185 qDebug() << "(K3bMpcWrapper) buffer not big enough."; 0186 return -1; 0187 } 0188 0189 static const unsigned int bps = 16; 0190 static const int clip_min = -1 << (bps - 1); 0191 static const int clip_max = (1 << (bps - 1)) - 1; 0192 static const int float_scale = 1 << (bps - 1); 0193 0194 for( unsigned int n = 0; n < samples*channels(); ++n ) { 0195 int val = 0; 0196 0197 #ifdef MPC_FIXED_POINT 0198 val = shift_signed( sample_buffer[n], 0199 bps - MPC_FIXED_POINT_SCALE_SHIFT); 0200 #else 0201 val = (int)(sample_buffer[n] * float_scale); 0202 #endif 0203 0204 if( val < clip_min ) 0205 val = clip_min; 0206 else if( val > clip_max ) 0207 val = clip_max; 0208 0209 data[2*n] = (val>>8) & 0xff; 0210 data[2*n+1] = val & 0xff; 0211 } 0212 0213 return samples*channels()*2; 0214 } 0215 0216 0217 bool K3bMpcWrapper::seek( const K3b::Msf& msf ) 0218 { 0219 #ifdef MPC_OLD_API 0220 return mpc_decoder_seek_seconds( m_decoder, (double)msf.totalFrames()/75.0 ); 0221 #else 0222 return mpc_demux_seek_second( m_decoder, (double)msf.totalFrames()/75.0 ); 0223 #endif 0224 } 0225 0226 0227 K3b::Msf K3bMpcWrapper::length() const 0228 { 0229 return K3b::Msf::fromSeconds( mpc_streaminfo_get_length( m_info ) ); 0230 } 0231 0232 0233 int K3bMpcWrapper::samplerate() const 0234 { 0235 return m_info->sample_freq; 0236 } 0237 0238 0239 unsigned int K3bMpcWrapper::channels() const 0240 { 0241 return m_info->channels; 0242 } 0243