File indexing completed on 2024-05-12 04:51:32
0001 /* 0002 0003 SPDX-FileCopyrightText: 2004 Matthieu Bedouet <mbedouet@no-log.org> 0004 SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 #include "k3blibsndfiledecoder.h" 0009 #include "k3bplugin_i18n.h" 0010 0011 #include <config-k3b.h> 0012 0013 #include <QDebug> 0014 #include <QFile> 0015 #include <QStringList> 0016 0017 #include <math.h> 0018 #include <stdio.h> 0019 #include <sndfile.h> 0020 0021 K_PLUGIN_CLASS_WITH_JSON(K3bLibsndfileDecoderFactory, "k3blibsndfiledecoder.json") 0022 0023 class K3bLibsndfileDecoder::Private 0024 { 0025 public: 0026 Private(): 0027 isOpen(false), 0028 buffer(0), 0029 bufferSize(0) { 0030 format_info.name = 0; 0031 } 0032 0033 SNDFILE *sndfile; 0034 SF_INFO sndinfo; 0035 SF_FORMAT_INFO format_info; 0036 bool isOpen; 0037 float* buffer; 0038 int bufferSize; 0039 }; 0040 0041 0042 0043 K3bLibsndfileDecoder::K3bLibsndfileDecoder( QObject* parent ) 0044 : K3b::AudioDecoder( parent ) 0045 { 0046 d = new Private(); 0047 } 0048 0049 0050 K3bLibsndfileDecoder::~K3bLibsndfileDecoder() 0051 { 0052 delete d; 0053 } 0054 0055 0056 QString K3bLibsndfileDecoder::fileType() const 0057 { 0058 if( d->format_info.name ) 0059 return QString::fromLocal8Bit(d->format_info.name); 0060 else 0061 return "-"; 0062 } 0063 0064 0065 0066 bool K3bLibsndfileDecoder::openFile() 0067 { 0068 if( !d->isOpen ) { 0069 0070 cleanup(); 0071 0072 d->sndinfo.format = 0; 0073 d->sndfile = sf_open (QFile::encodeName(filename()), SFM_READ, &d->sndinfo); 0074 if ( !d->sndfile ) { 0075 qDebug() << "(K3bLibsndfileDecoder::openLibsndfileFile) : " << sf_strerror(d->sndfile); 0076 return false; 0077 } 0078 else { 0079 //retrieve infos (name, extension) about the format: 0080 d->format_info.format = d->sndinfo.format & SF_FORMAT_TYPEMASK ; 0081 sf_command (d->sndfile, SFC_GET_FORMAT_INFO, &d->format_info, sizeof (SF_FORMAT_INFO)) ; 0082 0083 d->isOpen = true; 0084 qDebug() << "(K3bLibsndfileDecoder::openLibsndfileFile) " << d->format_info.name << " file opened "; 0085 return true; 0086 } 0087 } 0088 0089 return d->isOpen; 0090 } 0091 0092 0093 bool K3bLibsndfileDecoder::analyseFileInternal( K3b::Msf& frames, int& samplerate, int& ch ) 0094 { 0095 cleanup(); 0096 0097 if( openFile() ) { 0098 // check length of track 0099 if ( d->sndinfo.frames <= 0 ) { 0100 qDebug() << "(K3bLibsndfileDecoder::analyseFileInternal) Could not determine length of file " 0101 << filename() << Qt::endl; 0102 cleanup(); 0103 return false; 0104 } 0105 else { 0106 addMetaInfo( META_TITLE, sf_get_string(d->sndfile, SF_STR_TITLE) ); 0107 addMetaInfo( META_ARTIST, sf_get_string(d->sndfile, SF_STR_ARTIST) ); 0108 addMetaInfo( META_COMMENT, sf_get_string(d->sndfile, SF_STR_COMMENT) ); 0109 0110 addTechnicalInfo( i18n("Channels"), QString::number(d->sndinfo.channels) ); 0111 addTechnicalInfo( i18n("Sampling Rate"), i18n("%1 Hz",d->sndinfo.samplerate) ); 0112 0113 frames = (unsigned long)ceil(75.0 * d->sndinfo.frames / d->sndinfo.samplerate); 0114 samplerate = d->sndinfo.samplerate; 0115 ch = d->sndinfo.channels; 0116 0117 qDebug() << "(K3bLibsndfileDecoder) successfully analysed file: " << frames << " frames."; 0118 0119 cleanup(); 0120 return true; 0121 } 0122 } 0123 else 0124 return false; 0125 } 0126 0127 0128 0129 bool K3bLibsndfileDecoder::initDecoderInternal() 0130 { 0131 cleanup(); 0132 return openFile(); 0133 } 0134 0135 0136 0137 int K3bLibsndfileDecoder::decodeInternal( char* data, int maxLen ) 0138 { 0139 if( !d->buffer ) { 0140 d->buffer = new float[maxLen]; 0141 d->bufferSize = maxLen/2; 0142 } 0143 0144 int read = (int) sf_read_float(d->sndfile, d->buffer,d->bufferSize) ; 0145 fromFloatTo16BitBeSigned( d->buffer, data, read ); 0146 read = read * 2; 0147 0148 if( read < 0 ) { 0149 qDebug() << "(K3bLibsndfileDecoder::decodeInternal) Error: " << read; 0150 return -1; 0151 } 0152 else if( read == 0 ) { 0153 qDebug() << "(K3bLibsndfileDecoder::decodeInternal) successfully finished decoding."; 0154 return 0; 0155 } 0156 else 0157 return read; 0158 } 0159 0160 0161 0162 bool K3bLibsndfileDecoder::seekInternal( const K3b::Msf& pos) 0163 { 0164 return ( sf_seek( d->sndfile, pos.pcmSamples(), SEEK_SET ) == 0 ); 0165 } 0166 0167 0168 0169 0170 void K3bLibsndfileDecoder::cleanup() 0171 { 0172 if( d->isOpen ) { 0173 qDebug() << "(K3bLibsndfileDecoder) cleaning up."; 0174 sf_close( d->sndfile ); 0175 d->isOpen = false; 0176 } 0177 } 0178 0179 0180 0181 /********************************************************/ 0182 0183 0184 K3bLibsndfileDecoderFactory::K3bLibsndfileDecoderFactory( QObject* parent, const QVariantList& ) 0185 : K3b::AudioDecoderFactory( parent) 0186 { 0187 } 0188 0189 0190 K3bLibsndfileDecoderFactory::~K3bLibsndfileDecoderFactory() 0191 { 0192 } 0193 0194 0195 K3b::AudioDecoder* K3bLibsndfileDecoderFactory::createDecoder( QObject* parent ) const 0196 { 0197 return new K3bLibsndfileDecoder( parent ); 0198 } 0199 0200 0201 bool K3bLibsndfileDecoderFactory::canDecode( const QUrl& url ) 0202 { 0203 SF_INFO infos; 0204 infos.format = 0; 0205 SNDFILE* sndfile = sf_open (QFile::encodeName(url.toLocalFile()), SFM_READ, &infos); 0206 0207 //is it supported by libsndfile? 0208 if ( !sndfile ) { 0209 qDebug() << "(K3bLibsndfileDecoder) " << sf_strerror(sndfile); 0210 return false; 0211 } 0212 else if ( infos.format ) { 0213 0214 //retrieve infos (name) about the format: 0215 SF_FORMAT_INFO format_info; 0216 format_info.format = infos.format & SF_FORMAT_TYPEMASK ; 0217 sf_command (sndfile, SFC_GET_FORMAT_INFO, &format_info, sizeof (format_info)) ; 0218 0219 qDebug() << "(K3bLibsndfileDecoder) " << format_info.name << " file === OK === "; 0220 sf_close( sndfile ); 0221 return true; 0222 } 0223 else { 0224 qDebug() << "(K3bLibsndfileDecoder) " << url.toLocalFile() << "not supported"; 0225 sf_close( sndfile ); 0226 return false; 0227 } 0228 return false; 0229 } 0230 0231 #include "k3blibsndfiledecoder.moc" 0232 0233 #include "moc_k3blibsndfiledecoder.cpp"