File indexing completed on 2024-04-28 04:49:29
0001 /* 0002 SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef _K3B_AUDIO_DECODER_H_ 0008 #define _K3B_AUDIO_DECODER_H_ 0009 0010 #include "k3bplugin.h" 0011 #include "k3bmsf.h" 0012 #include "k3b_export.h" 0013 #include <QUrl> 0014 0015 0016 namespace K3b { 0017 /** 0018 * Abstract streaming class for all the audio input. 0019 * Has to output data in the following format: 0020 * MSBLeft LSBLeft MSBRight LSBRight (big endian byte order) 0021 * 0022 * Instances are created by AudioDecoderFactory 0023 **/ 0024 class LIBK3B_EXPORT AudioDecoder : public QObject 0025 { 0026 Q_OBJECT 0027 0028 public: 0029 explicit AudioDecoder( QObject* parent = 0 ); 0030 ~AudioDecoder() override; 0031 0032 /** 0033 * Set the file to decode. Be aware that one cannot rely 0034 * on the file length until analyseFile() has been called. 0035 */ 0036 void setFilename( const QString& ); 0037 0038 /** 0039 * Since this may take a while depending on the filetype it is best 0040 * to run it in a separate thread. 0041 * 0042 * This method will also call initDecoder(). 0043 * 0044 * \sa AudioFielAnalyzerJob 0045 */ 0046 bool analyseFile(); 0047 0048 /** 0049 * @return true if the file was successfully analysed by analyseFile. 0050 */ 0051 bool isValid() const; 0052 0053 /** 0054 * Initialize the decoding. 0055 * Normally there is no need to call this as analyseFile already does so. 0056 */ 0057 bool initDecoder(); 0058 0059 /** 0060 * initialize the decoding. 0061 * @param startOffset the number of frames to skip at the beginning of the file. 0062 * 0063 * This is the same as calling: initDecoder() and seek(startOffset) 0064 */ 0065 bool initDecoder( const Msf& startOffset ); 0066 0067 enum MetaDataField { 0068 META_TITLE, 0069 META_ARTIST, 0070 META_SONGWRITER, 0071 META_COMPOSER, 0072 META_COMMENT 0073 }; 0074 0075 /** 0076 * This should at least support "Title" and "Artist" 0077 * 0078 * the default implementation returns the infos set via @p addMetaInfo 0079 * and uses KFileMetaData if none was set 0080 */ 0081 virtual QString metaInfo( MetaDataField ); 0082 0083 /** 0084 * The filetype is only used for informational purposes. 0085 * It is not necessary but highly recommended to implement this method 0086 * as it enhances usability. 0087 * @return The filetype of the decoded file. 0088 */ 0089 virtual QString fileType() const { return QString(); } 0090 0091 /** 0092 * This method may be reimplemented to provide technical information about 0093 * the file. It should return localized strings. 0094 * 0095 * the default implementation returns the infos set via @p addTechnicalInfo 0096 */ 0097 virtual QStringList supportedTechnicalInfos() const; 0098 0099 /** 0100 * The framework will call this method with all strings returned by the 0101 * supportedTechnicalInfos() method. It should return localized strings. 0102 * 0103 * the default implementation returns the infos set via @p addTechnicalInfo 0104 */ 0105 virtual QString technicalInfo( const QString& ) const; 0106 0107 /** 0108 * returns -1 on error, 0 when finished, length of data otherwise 0109 * takes care of padding 0110 * calls decodeInternal() to actually decode data 0111 * 0112 * Fill the data buffer with maximal maxLen bytes. 0113 */ 0114 int decode( char* data, int maxLen ); 0115 0116 /** 0117 * Cleanup after decoding like closing files. 0118 * Be aware that this is the counterpart to @p initDecoder(). 0119 * 0120 * There might happen multiple calls to initDecoder() and cleanup(). 0121 */ 0122 virtual void cleanup(); 0123 0124 /** 0125 * Seek to the position pos. 0126 * Decoding is started new. That means that the data will be padded to 0127 * length() - pos. 0128 * returns true on success; 0129 */ 0130 bool seek( const Msf& pos ); 0131 0132 /** 0133 * Be aware that one cannot rely 0134 * on the file length until analyseFile() has been called. 0135 */ 0136 virtual Msf length() const { return m_length; } 0137 0138 const QString& filename() const { return m_fileName; } 0139 0140 // some helper methods 0141 static void fromFloatTo16BitBeSigned( float* src, char* dest, int samples ); 0142 static void from16bitBeSignedToFloat( char* src, float* dest, int samples ); 0143 static void from8BitTo16BitBeSigned( char* src, char* dest, int samples ); 0144 0145 protected: 0146 /** 0147 * Use this method if using the default implementation of @p metaInfo 0148 */ 0149 void addMetaInfo( MetaDataField, const QString& ); 0150 0151 /** 0152 * Use this method if using the default implementation of @p technicalInfo 0153 * and @p supportedTechnicalInfos. 0154 */ 0155 void addTechnicalInfo( const QString&, const QString& ); 0156 0157 /** 0158 * This will be called once before the first call to decodeInternal. 0159 * Use it to initialize decoding structures if necessary. 0160 * 0161 * There might happen multiple calls to initDecoder() and cleanup(). 0162 */ 0163 virtual bool initDecoderInternal() = 0; 0164 0165 /** 0166 * This method should analyze the file to determine the exact length, 0167 * the samplerate in Hz, and the number of channels. The framework takes care of 0168 * resampling and converting mono to stereo data. 0169 * This method may be time consuming. 0170 */ 0171 virtual bool analyseFileInternal( Msf& length, int& samplerate, int& channels ) = 0; 0172 0173 /** 0174 * fill the already allocated data with maximal maxLen bytes of decoded samples. 0175 * The framework will take care of padding or cutting the decoded data as well 0176 * as resampling to 44100 Hz and converting mono samples to stereo. 0177 */ 0178 virtual int decodeInternal( char* data, int maxLen ) = 0; 0179 0180 virtual bool seekInternal( const Msf& ) { return false; } 0181 0182 private: 0183 int resample( char* data, int maxLen ); 0184 0185 QString m_fileName; 0186 Msf m_length; 0187 0188 class Private; 0189 Private* d; 0190 }; 0191 0192 0193 /** 0194 * PluginFactory that needs to be subclassed in order to create an 0195 * audio decoder. 0196 * We need this because K3b uses multiple AudioDecoders of the same type at the 0197 * same time. 0198 */ 0199 class LIBK3B_EXPORT AudioDecoderFactory : public Plugin 0200 { 0201 Q_OBJECT 0202 0203 public: 0204 explicit AudioDecoderFactory( QObject* parent = 0 ) 0205 : Plugin( parent ) { 0206 } 0207 0208 ~AudioDecoderFactory() override { 0209 } 0210 0211 QString category() const override { return "AudioDecoder"; } 0212 0213 QString categoryName() const override; 0214 0215 /** 0216 * K3b uses this flag to decide which plugins to test first 0217 * when searching for an audio decoder. 0218 * 0219 * Decoders that are specialized on one format are favored over 0220 * multi-format-decoders. 0221 */ 0222 virtual bool multiFormatDecoder() const { return false; } 0223 0224 /** 0225 * This is the most important method of the AudioDecoderFactory. 0226 * It is used to determine if a certain file can be decoded by the 0227 * decoder this factory creates. 0228 * It is important that this method does not work lazy since it will 0229 * be called with urls to every kind of files and if it returns true 0230 * a decoder of this type is used for the file. 0231 */ 0232 virtual bool canDecode( const QUrl& filename ) = 0; 0233 0234 virtual AudioDecoder* createDecoder( QObject* parent = 0 ) const = 0; 0235 0236 /** 0237 * Searching for an audiodecoder for @p filename. 0238 * 0239 * It first searches the single format decoder and the multiformat decoder. 0240 * 0241 * @returns a newly created decoder on success and 0 when no decoder could be found. 0242 */ 0243 static AudioDecoder* createDecoder( const QUrl& url ); 0244 }; 0245 } 0246 0247 #endif