File indexing completed on 2024-07-14 04:43:23

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"