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