File indexing completed on 2025-04-20 04:27:27
0001 /* 0002 0003 SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 #include "k3bwavedecoder.h" 0008 #include "k3bplugin_i18n.h" 0009 0010 #include <config-k3b.h> 0011 0012 #include <QDebug> 0013 #include <QFile> 0014 0015 0016 K_PLUGIN_CLASS_WITH_JSON(K3bWaveDecoderFactory, "k3bwavedecoder.json") 0017 0018 static unsigned short le_a_to_u_short( unsigned char* a ) { 0019 return ((unsigned short) 0020 ((a[0] & 0xFF) | 0021 (a[1] << 8 & 0xFF00)) ); 0022 } 0023 0024 static unsigned long le_a_to_u_long( unsigned char* a ) { 0025 return ((unsigned long) 0026 ((a[0] & 0xFF) | 0027 (a[1] << 8 & 0xFF00) | 0028 (a[2] << 16 & 0xFF0000) | 0029 (a[3] << 24 & 0xFF000000)) ); 0030 } 0031 0032 0033 /** 0034 * Returns the length of the wave file in bytes 0035 * Otherwise 0 is returned. 0036 * leave file seek pointer past WAV header. 0037 */ 0038 static unsigned long identifyWaveFile( QFile& f, int* samplerate = 0, int* channels = 0, int* samplesize = 0 ) 0039 { 0040 typedef struct { 0041 unsigned char ckid[4]; 0042 unsigned char cksize[4]; 0043 } chunk_t; 0044 0045 typedef struct { 0046 unsigned char wave[4]; 0047 } riff_chunk; 0048 0049 typedef struct { 0050 unsigned char fmt_tag[2]; 0051 unsigned char channels[2]; 0052 unsigned char sample_rate[4]; 0053 unsigned char av_byte_rate[4]; 0054 unsigned char block_size[2]; 0055 unsigned char bits_per_sample[2]; 0056 } fmt_chunk; 0057 0058 static const char WAV_RIFF_MAGIC[] = "RIFF"; // Magic for file format 0059 static const char WAV_WAVE_MAGIC[] = "WAVE"; // Magic for Waveform Audio 0060 static const char WAV_FMT_MAGIC[] = "fmt "; // Start of Waveform format 0061 static const char WAV_DATA_MAGIC[] = "data"; // Start of data chunk 0062 0063 chunk_t chunk; 0064 riff_chunk riff; 0065 fmt_chunk fmt; 0066 0067 0068 // read riff chunk 0069 if( f.read( (char*)&chunk, sizeof(chunk) ) != sizeof(chunk) ) { 0070 qDebug() << "(K3bWaveDecoder) unable to read from " << f.fileName(); 0071 return 0; 0072 } 0073 if( qstrncmp( (char*)chunk.ckid, WAV_RIFF_MAGIC, 4 ) ) { 0074 qDebug() << "(K3bWaveDecoder) " << f.fileName() << ": not a RIFF file."; 0075 return 0; 0076 } 0077 0078 // read wave chunk 0079 if( f.read( (char*)&riff, sizeof(riff) ) != sizeof(riff) ) { 0080 qDebug() << "(K3bWaveDecoder) unable to read from " << f.fileName(); 0081 return 0; 0082 } 0083 if( qstrncmp( (char*)riff.wave, WAV_WAVE_MAGIC, 4 ) ) { 0084 qDebug() << "(K3bWaveDecoder) " << f.fileName() << ": not a WAVE file."; 0085 return 0; 0086 } 0087 0088 0089 // read fmt chunk 0090 if( f.read( (char*)&chunk, sizeof(chunk) ) != sizeof(chunk) ) { 0091 qDebug() << "(K3bWaveDecoder) unable to read from " << f.fileName(); 0092 return 0; 0093 } 0094 if( qstrncmp( (char*)chunk.ckid, WAV_FMT_MAGIC, 4 ) ) { 0095 qDebug() << "(K3bWaveDecoder) " << f.fileName() << ": could not find format chunk."; 0096 return 0; 0097 } 0098 if( f.read( (char*)&fmt, sizeof(fmt) ) != sizeof(fmt) ) { 0099 qDebug() << "(K3bWaveDecoder) unable to read from " << f.fileName(); 0100 return 0; 0101 } 0102 if( le_a_to_u_short(fmt.fmt_tag) != 1 || 0103 le_a_to_u_short(fmt.channels) > 2 || 0104 ( le_a_to_u_short(fmt.bits_per_sample) != 16 && 0105 le_a_to_u_short(fmt.bits_per_sample) != 8 ) ) { 0106 qDebug() << "(K3bWaveDecoder) " << f.fileName() << ": wrong format:" << Qt::endl 0107 << " format: " << le_a_to_u_short(fmt.fmt_tag) << Qt::endl 0108 << " channels: " << le_a_to_u_short(fmt.channels) << Qt::endl 0109 << " samplerate: " << le_a_to_u_long(fmt.sample_rate) << Qt::endl 0110 << " bits/sample: " << le_a_to_u_short(fmt.bits_per_sample) << Qt::endl; 0111 return 0; 0112 } 0113 0114 int sampleRate = le_a_to_u_long(fmt.sample_rate); 0115 int ch = le_a_to_u_short(fmt.channels); 0116 int sampleSize = le_a_to_u_short(fmt.bits_per_sample);; 0117 if( samplerate ) 0118 *samplerate = sampleRate; 0119 if( channels ) 0120 *channels = ch; 0121 if( samplesize ) 0122 *samplesize = sampleSize; 0123 0124 // skip all other (unknown) format chunk fields 0125 if( !f.seek( f.pos() + le_a_to_u_long(chunk.cksize) - sizeof(fmt) ) ) { 0126 qDebug() << "(K3bWaveDecoder) " << f.fileName() << ": could not seek in file."; 0127 return 0; 0128 } 0129 0130 0131 // find data chunk 0132 bool foundData = false; 0133 while( !foundData ) { 0134 if( f.read( (char*)&chunk, sizeof(chunk) ) != sizeof(chunk) ) { 0135 qDebug() << "(K3bWaveDecoder) unable to read from " << f.fileName(); 0136 return 0; 0137 } 0138 0139 // skip chunk data of unknown chunk 0140 if( qstrncmp( (char*)chunk.ckid, WAV_DATA_MAGIC, 4 ) ) { 0141 qDebug() << "(K3bWaveDecoder) skipping chunk: " << (char*)chunk.ckid; 0142 if( !f.seek( f.pos() + le_a_to_u_long(chunk.cksize) ) ) { 0143 qDebug() << "(K3bWaveDecoder) " << f.fileName() << ": could not seek in file."; 0144 return 0; 0145 } 0146 } 0147 else 0148 foundData = true; 0149 } 0150 0151 // found data chunk 0152 unsigned long size = le_a_to_u_long(chunk.cksize); 0153 if( f.pos() + size > (unsigned long)f.size() ) { 0154 qDebug() << "(K3bWaveDecoder) " << f.fileName() << ": file length " << f.size() 0155 << " does not match length from WAVE header " << f.pos() << " + " << size 0156 << " - using actual length." << Qt::endl; 0157 size = (f.size() - f.pos()); 0158 } 0159 0160 return size; 0161 } 0162 0163 0164 class K3bWaveDecoder::Private { 0165 public: 0166 Private() 0167 : buffer(0), 0168 bufferSize(0) { 0169 } 0170 0171 QFile file; 0172 0173 long headerLength; 0174 int sampleRate; 0175 int channels; 0176 int sampleSize; 0177 unsigned long size; 0178 unsigned long alreadyRead; 0179 0180 char* buffer; 0181 int bufferSize; 0182 }; 0183 0184 0185 K3bWaveDecoder::K3bWaveDecoder( QObject* parent ) 0186 : K3b::AudioDecoder( parent ), 0187 d( new Private ) 0188 { 0189 } 0190 0191 0192 K3bWaveDecoder::~K3bWaveDecoder() 0193 { 0194 } 0195 0196 0197 int K3bWaveDecoder::decodeInternal( char* _data, int maxLen ) 0198 { 0199 int read = 0; 0200 0201 maxLen = qMin( maxLen, (int)(d->size - d->alreadyRead) ); 0202 0203 if( d->sampleSize == 16 ) { 0204 read = d->file.read( _data, maxLen ); 0205 if( read > 0 ) { 0206 d->alreadyRead += read; 0207 0208 if( read % 2 > 0 ) { 0209 qDebug() << "(K3bWaveDecoder) data length is not a multiple of 2! Cutting data."; 0210 read -= 1; 0211 } 0212 0213 // swap bytes 0214 char buf; 0215 for( int i = 0; i < read; i+=2 ) { 0216 buf = _data[i]; 0217 _data[i] = _data[i+1]; 0218 _data[i+1] = buf; 0219 } 0220 } 0221 } 0222 else { 0223 if( !d->buffer ) { 0224 d->buffer = new char[maxLen/2]; 0225 d->bufferSize = maxLen/2; 0226 } 0227 0228 read = d->file.read( d->buffer, qMin(maxLen/2, d->bufferSize) ); 0229 d->alreadyRead += read; 0230 0231 // stretch samples to 16 bit 0232 from8BitTo16BitBeSigned( d->buffer, _data, read ); 0233 0234 read *= 2; 0235 } 0236 0237 return read; 0238 } 0239 0240 0241 bool K3bWaveDecoder::analyseFileInternal( K3b::Msf& frames, int& samplerate, int& channels ) 0242 { 0243 // handling wave files is very easy... 0244 if( initDecoderInternal() ) { 0245 0246 // 0247 // d->size is the number of bytes in the wave file 0248 // 0249 unsigned long size = d->size; 0250 if( d->sampleRate != 44100 ) 0251 size = (int)((double)size * 44100.0 / (double)d->sampleRate); 0252 0253 if( d->sampleSize == 8 ) 0254 size *= 2; 0255 if( d->channels == 1 ) 0256 size *= 2; 0257 0258 // 0259 // we pad to a multiple of 2352 bytes 0260 // (the actual padding of zero data will be done by the K3b::AudioDecoder class) 0261 // 0262 if( (size%2352) > 0 ) 0263 size = (size/2352) + 1; 0264 else 0265 size = size/2352; 0266 0267 frames = size; 0268 samplerate = d->sampleRate; 0269 channels = d->channels; 0270 return true; 0271 } 0272 else 0273 return false; 0274 } 0275 0276 0277 bool K3bWaveDecoder::initDecoderInternal() 0278 { 0279 cleanup(); 0280 0281 d->file.setFileName( filename() ); 0282 if( !d->file.open( QIODevice::ReadOnly ) ) { 0283 qDebug() << "(K3bWaveDecoder) could not open file."; 0284 return false; 0285 } 0286 0287 // skip the header 0288 d->size = identifyWaveFile( d->file, &d->sampleRate, &d->channels, &d->sampleSize ); 0289 if( d->size <= 0 ) { 0290 qDebug() << "(K3bWaveDecoder) no supported wave file."; 0291 cleanup(); 0292 return false; 0293 } 0294 0295 d->headerLength = d->file.pos(); 0296 d->alreadyRead = 0; 0297 0298 return true; 0299 } 0300 0301 0302 bool K3bWaveDecoder::seekInternal( const K3b::Msf& pos ) 0303 { 0304 return( d->file.seek( d->headerLength + (pos.totalFrames()*2352) ) ); 0305 } 0306 0307 0308 void K3bWaveDecoder::cleanup() 0309 { 0310 if( d->file.isOpen() ) 0311 d->file.close(); 0312 } 0313 0314 0315 QString K3bWaveDecoder::fileType() const 0316 { 0317 return i18n("WAVE"); 0318 } 0319 0320 0321 QStringList K3bWaveDecoder::supportedTechnicalInfos() const 0322 { 0323 return QString( i18n("Channels") + ';' + 0324 i18n("Sampling Rate") + ';' + 0325 i18n("Sample Size") ).split( ';' ); 0326 } 0327 0328 0329 QString K3bWaveDecoder::technicalInfo( const QString& name ) const 0330 { 0331 if( name == i18n("Channels") ) 0332 return QString::number(d->channels); 0333 else if( name == i18n("Sampling Rate") ) 0334 return i18n("%1 Hz",d->sampleRate); 0335 else if( name == i18n("Sample Size") ) 0336 return i18np("1 bit","%1 bits",d->sampleSize); 0337 else 0338 return QString(); 0339 } 0340 0341 0342 K3bWaveDecoderFactory::K3bWaveDecoderFactory( QObject* parent, const QVariantList& ) 0343 : K3b::AudioDecoderFactory( parent ) 0344 { 0345 } 0346 0347 0348 K3bWaveDecoderFactory::~K3bWaveDecoderFactory() 0349 { 0350 } 0351 0352 0353 K3b::AudioDecoder* K3bWaveDecoderFactory::createDecoder( QObject* parent ) const 0354 { 0355 return new K3bWaveDecoder( parent ); 0356 } 0357 0358 0359 bool K3bWaveDecoderFactory::canDecode( const QUrl& url ) 0360 { 0361 QFile f( url.toLocalFile() ); 0362 if( !f.open( QIODevice::ReadOnly ) ) { 0363 qDebug() << "(K3bWaveDecoder) could not open file " << url.toLocalFile(); 0364 return false; 0365 } 0366 0367 return (identifyWaveFile( f ) > 0); 0368 } 0369 0370 0371 0372 #include "k3bwavedecoder.moc" 0373 0374 #include "moc_k3bwavedecoder.cpp"