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

0001 /*
0002     SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "k3bwavefilewriter.h"
0007 #include <QDebug>
0008 
0009 K3b::WaveFileWriter::WaveFileWriter()
0010     : m_outputStream( &m_outputFile )
0011 {
0012 }
0013 
0014 
0015 K3b::WaveFileWriter::~WaveFileWriter()
0016 {
0017     close();
0018 }
0019 
0020 
0021 bool K3b::WaveFileWriter::open( const QString& filename )
0022 {
0023     close();
0024 
0025     m_outputFile.setFileName( filename );
0026 
0027     if( m_outputFile.open( QIODevice::ReadWrite ) ) {
0028         m_filename = filename;
0029 
0030         writeEmptyHeader();
0031 
0032         return true;
0033     }
0034     else {
0035         return false;
0036     }
0037 }
0038 
0039 
0040 void K3b::WaveFileWriter::close()
0041 {
0042     if( isOpen() ) {
0043         if( m_outputFile.pos() > 0 ) {
0044             padTo2352();
0045 
0046             // update wave header
0047             updateHeader();
0048 
0049             m_outputFile.close();
0050         }
0051         else {
0052             m_outputFile.close();
0053             m_outputFile.remove();
0054         }
0055     }
0056 
0057     m_filename = QString();
0058 }
0059 
0060 
0061 bool K3b::WaveFileWriter::isOpen()
0062 {
0063     return m_outputFile.isOpen();
0064 }
0065 
0066 
0067 const QString& K3b::WaveFileWriter::filename() const
0068 {
0069     return m_filename;
0070 }
0071 
0072 
0073 void K3b::WaveFileWriter::write( const char* data, int len, Endianess e )
0074 {
0075     if( isOpen() ) {
0076         if( e == LittleEndian ) {
0077             m_outputStream.writeRawData( data, len );
0078         }
0079         else {
0080             if( len % 2 > 0 ) {
0081                 qDebug() << "(K3b::WaveFileWriter) data length ("
0082                          << len << ") is not a multiple of 2! Cannot swap bytes." << Qt::endl;
0083                 return;
0084             }
0085 
0086             // we need to swap the bytes
0087             char* buffer = new char[len];
0088             for( int i = 0; i < len-1; i+=2 ) {
0089                 buffer[i] = data[i+1];
0090                 buffer[i+1] = data[i];
0091             }
0092             m_outputStream.writeRawData( buffer, len );
0093 
0094             delete [] buffer;
0095         }
0096     }
0097 }
0098 
0099 
0100 void K3b::WaveFileWriter::writeEmptyHeader()
0101 {
0102     static const unsigned char riffHeader[] =
0103         {
0104             0x52, 0x49, 0x46, 0x46, // 0  "RIFF"
0105             0x00, 0x00, 0x00, 0x00, // 4  wavSize
0106             0x57, 0x41, 0x56, 0x45, // 8  "WAVE"
0107             0x66, 0x6d, 0x74, 0x20, // 12 "fmt "
0108             0x10, 0x00, 0x00, 0x00, // 16
0109             0x01, 0x00, 0x02, 0x00, // 20
0110             0x44, 0xac, 0x00, 0x00, // 24
0111             0x10, 0xb1, 0x02, 0x00, // 28
0112             0x04, 0x00, 0x10, 0x00, // 32
0113             0x64, 0x61, 0x74, 0x61, // 36 "data"
0114             0x00, 0x00, 0x00, 0x00  // 40 byteCount
0115         };
0116 
0117     m_outputStream.writeRawData( (const char*) riffHeader, 44 );
0118 }
0119 
0120 
0121 void K3b::WaveFileWriter::updateHeader()
0122 {
0123     if( isOpen() ) {
0124 
0125         m_outputFile.flush();
0126 
0127         qint32 dataSize( m_outputFile.pos() - 44 );
0128         qint32 wavSize(dataSize + 44 - 8);
0129         char c[4];
0130 
0131         // jump to the wavSize position in the header
0132         if( m_outputFile.seek( 4 ) ) {
0133             c[0] = (wavSize   >> 0 ) & 0xff;
0134             c[1] = (wavSize   >> 8 ) & 0xff;
0135             c[2] = (wavSize   >> 16) & 0xff;
0136             c[3] = (wavSize   >> 24) & 0xff;
0137             m_outputStream.writeRawData( c, 4 );
0138         }
0139         else
0140             qDebug() << "(K3b::WaveFileWriter) unable to seek in file: " << m_outputFile.fileName();
0141 
0142         if( m_outputFile.seek( 40 ) ) {
0143             c[0] = (dataSize   >> 0 ) & 0xff;
0144             c[1] = (dataSize   >> 8 ) & 0xff;
0145             c[2] = (dataSize   >> 16) & 0xff;
0146             c[3] = (dataSize   >> 24) & 0xff;
0147             m_outputStream.writeRawData( c, 4 );
0148         }
0149         else
0150             qDebug() << "(K3b::WaveFileWriter) unable to seek in file: " << m_outputFile.fileName();
0151 
0152         // jump back to the end
0153         m_outputFile.seek( m_outputFile.size() );
0154     }
0155 }
0156 
0157 
0158 void K3b::WaveFileWriter::padTo2352()
0159 {
0160     int bytesToPad = ( m_outputFile.pos() - 44 ) % 2352;
0161     if( bytesToPad > 0 ) {
0162         qDebug() << "(K3b::WaveFileWriter) padding wave file with " << bytesToPad << " bytes.";
0163 
0164         char* c = new char[bytesToPad];
0165         memset( c, 0, bytesToPad );
0166         m_outputStream.writeRawData( c, bytesToPad );
0167         delete [] c;
0168     }
0169 }
0170 
0171 
0172 int K3b::WaveFileWriter::fd() const
0173 {
0174     return m_outputFile.handle();
0175 }